Что такое isr windows

Interrupts

Часть 1 — Прерывания, ISR, IRQ,PIC

Что такое прерывание ?

Интел учит нас , что прерывания останавливают ход программы при возникновении внешних событий или ошибок.

Как происходит прерывание ? Оно может быть сгенерировано железом. Его можно также вызвать программно. Например , при нажатии клавиши прерывание поступает в процессор. Процессор останавливает выполняемый код и вызывает функцию , которая будет читать порт 0x60(keyboard’s output port). Эта же функция потом должна вернуть контроль. Программный код может вызвать прерывание путем вызова инструкции ‘int

Разрешение и запрещение прерываний выполняется с помощтю команд ‘cli'(disable) и ‘sti'(enable).

Где используются прерывания ?

Дисководы , звуковые карты , сетевые карты также используют прерывания.
PIT(Programable Interrupt Timer) генерит прерывания со специальным интервалом , что полезно при реализации многозадачности.

Пользовательские программы могут использовать прерывния. Например , в досе с помощью прерываний выводятся сообщения на экран. В биосе есть специальные прерывания для пользовательских программ , с помощью которых можно переключаться между графическими режимами.

Что такое ISR?

ISR(Interrupt Service Routine) — это код , выполняемый в результате прерывания. Каждому прерыванию должна соответствовать своя ISR.

Написание ISR

Во первых , нужно сохранить в стеке содержимое регистров SS, EIP, ESP, CS . Затем в указатель стека положить адрес нужной ISR. После чего будет выполнен ее код вплоть до инструкции ‘iret’, которая восстановит вышеуказанные регистры .

Небольшой кусок на NASM :

IRQ(Interrupt Request) — прерывание , генерируемое железом.

16 IRQ для PC пронумерованы от 0 до 15.
PIC(Programable Interrupt Controller) ловит эти прерывания с помощью 2-х блоков по 8 IRQ каждое. IRQ пересекаются с исключениями , поэтому их номера нужно переназначать.

PIC — шлюз между IRQ и CPU

Когда случается хардварное прерывание , много чего может произойти. Для лучшей совместимости устройств и различных платформ , при генерации прерывания устройство посылает минимум необходимой информации на PIC(Programable Interrupt Controller). PIC вычисляет номер прерывания и сигнализирует процессору об этом. После чего процессор останавливает поток выполняемых инструкций и вызывает соответствующую процедуру прерывания.

Часть 2 — Exceptions

Что такое исключение ?

Исключение — это событие , возникающее тогда , когда выясняется , что в выполняемом коде заложена ошибка. Например , это может быть деление на ноль , попытка доступа к несуществующему сегменту .

Существуют таблица стандартных интеловских исключений.

0 Divide Error
1 Debug Exceptions
2 Intel reserved
3 Breakpoint
4 Overflow
5 Bounds Check
6 Invalid Opcode
7 Coprocessor Not Available
8 Double Fault
9 Coprocessor Segment Overrun
10 Invalid TSS
11 Segment Not Present
12 Stack Exception
13 General Protection Exception(Triple Fault)
14 Page Fault
15 Intel reserved
16 Coprocessor Error
Читайте также:  Elite dangerous steam linux

Что должна делать ISR , обрабатывающая исключение ?

Рассмотрим конкретный пример обратки исключения — деления на ноль. Этот пример со смешанным кодом на си и ассемблере.

C function — interrupt_0:

Фактически на каждое исключение нужно иметь отдельную функцию .

Exception Interrupt 14 — Page Fault

Если вы будете использовать paging , вам понадобится это исключение. Если вы попытаетесь получить доступ к странице , которая промаркирована как not-present, процессор сгенерирует это исключение.

Часть 3 — IDT

Что такое IDT?

IDT(Interrupt Descriptor Table) это массив дескрипторов (каждый длиной 8 байт) , который необходим для того , чтобы привязать прерывания и исключения к нужным ISR. IDT может хранить максимум 256 дескрипторов. Не обязательно инициализировать все 256 дескрипторов. Достаточно только те , которые вы собираетесь использовать. Инструкция LIDT инициализирует этот массив.

IDT Descriptor Format

Дескриптор IDT имеет 8-байтную длину.

31 15 14 12 7 4 0
Offset 31-16(word) Present(1 bit) DPL(2 bits) 01110(5 bits) 000(3 bits) Not Used 4
Selector31-16(word) Offset 15-0(word) 0

Несколько слов о бите Present , поле DPL , селекторе и смещении :
Present: 0 = not present, 1 = present. Если Present =0 , будет сгенерировано исключение.
DPL: Descriptor Privilege Level, 00 = ring0, 01 = ring1, 10 = ring2, 11 = ring3
Selector: Кодовый селектор , который будет использовать ISR
Offset: Адрес самой ISR.

Теперь посмотрим на реальный дескриптор. Установим DPL = ring0, present = 1, selector = 0x10, offset= 0x200000.

31 15 14 12 7 4 0
0x20 1 00 01110 000 00000 4
0x10 0x0000 0

Переведем это на NASM:

Теперь осталось сказать процессору , как воспользоваться всем этим.

Загрузка IDT с помощью LIDT

Мы загружаем IDT с помощью инструкции LIDT . LIDT в качестве параметра имеет указатель на структуру , которая описывает IDT, в которой содержится начальный адрес и число дескрипторов.

31 15 0
Limit 15-0(word) 4
Base 31-0(double word) 0

Base: адрес самой IDT
Limit: длина IDT в байтах

Теперь рассмотрим пример с IDT , в которой 3 дескриптора :

2 метки — start_of_idt и end_of_idt , дадут нам возможность вычислить IDT pointer.

31 15 0
end_of_idt — start_of_idt — 1 4
start_of_idt 0

Переведем указатель на NASM:

И наконец сама загрузка :

Все в кучу

Теперь соберем все вместе и построим IDT , которая будет отлавливать 16 прерываний и передавать их в ISR , которая будет расположена по адресу 0x200000(окромя прерываний 2 и 15 — которые зарезервированы Intel).

Введение в драйверы устройств ввода/вывода

Обработка ISR и IST для драйверов устройств

Большинство периферийных устройств могут генерировать прерывания, чтобы получить обслуживание от операционной системы. Некоторыми примерами устройств, которые могут использовать прерывания, являются платы ПК, встроенные таймеры, устройства аудио-ввода, клавиатуры, сенсорные экраны, последовательные порты, и устройства указатели. Почти любой тип периферийного устройства может использовать прерывания в качестве основного метода инициирования действий ОС по обслуживанию.

Так как эти периферийные устройства могут вызывать или сигнализировать о прерываниях, их драйверы устройств должны обрабатывать прерывания, чтобы обслужить свои устройства. Физические прерывания (IRQ) являются аппаратными линиями связи, по которым устройства могут посылать сигналы прерываний в микропроцессор. Логические прерывания (SYSINTR) являются отображением IRQ, которое определяет OAL.

Читайте также:  Windows 10 final beta

Когда обрабатывается прерывание, имеет место определенная последовательность событий. Необходимо написать для драйвера устройства запрос на обслуживание прерывания ( ISR ) и поток обслуживания прерывания ( IST ), помня о следующей последовательности событий.

  1. Когда происходит прерывание, микропроцессор переходит к обработчику исключительных ситуаций ядра.
  2. Обработчик исключительных ситуаций отключает все прерывания равного или более низкого приоритета микропроцессора, и затем вызывает соответствующий ISR для запроса физического прерывания (IRQ).
  3. ISR возвращает логическое прерывание в форме идентификатора прерывания обработчику прерываний и, обычно, маскирует прерывание устройства уровня платы.
  4. Обработчик прерываний снова включает все прерывания в микропроцессоре, за исключением текущего прерывания, которое остается замаскированным на плате, и затем сигнализирует о соответствующем событии IST .
  5. IST планируется, обрабатывает оборудование, и затем заканчивает обработку прерывания.
  6. IST вызывает функцию InterruptDone , которая в свою очередь вызывает в OAL функцию OEMInterruptDone .

Функция OEMInterruptDone снова включает текущее прерывание. Драйвер устройства должен выполнить при загрузке следующие действия:

  • Регистрирует свой ISR в ядре. Драйвер должен зарегистрировать свой ISR в ядре, если драйвер не использует общую функцию OAL ISR для обработки своего прерывания. Драйвер должен зарегистрировать свой ISR в ядре, чтобы ядро вызывало ISR , когда происходит соответствующее физическое прерывание. Отобразить IRQ в SYSINTR в функции OEMInit из OAL. -или- Драйвер шины, который загружает драйвер, должен отобразить IRQ в SYSINTR , что делается в случае драйвера шины PCI.
  • Если драйвер не устанавливает ISR , любые прерывания, сгенерированные устройством, обрабатываются используемым по умолчанию ISR , который устанавливается OAL в OEMInit .

Процесс регистрации обработчика прерываний регистрирует событие, которое ассоциируется с системным прерыванием SYSINTR . После загрузки драйвера устройства драйвер создает поток службы прерываний ( IST ), а затем вызывает InterruptInitialize для регистрации события. IST может затем использовать функцию WaitForSingleObject для ожидания этого события и регистрации его в обработчике прерываний. IST регистрируется для одного или нескольких логических прерываний ( SYSINTR ).

Если для определенного драйвера используется реализация компании Microsoft модельного драйвера устройства (MDD), вам не нужно будет писать код для регистрации прерывания. Слой MDD драйвера регистрирует драйвер для прерываний. Если создается монолитный драйвер, нужно реализовать код для регистрации IST драйвера в обработчике прерываний. Для этого используется функция CreateEvent для создания события и функция InterruptInitialize для соединения события с SYSINTR .

Если драйвер устройства должен остановить обработку прерывания, то драйвер может использовать функцию InterruptDisable . Когда драйвер вызывает эту функцию, обработчик прерываний удаляет ассоциацию между IST и указанным логическим прерыванием. Обработчик прерываний выполняет это, вызывая функцию OEMInterruptDisable для отключения прерывания. Драйвер, если понадобиться, может позже снова зарегистрироваться для прерывания.

Могут возникать ситуации, когда требуется передать информацию между процедурой службы прерываний ( ISR ) и потоком службы прерываний ( IST ). Например, потому что вызов IST всякий раз, когда приходит запрос прерывания (IRQ), является длительным процессом, можно спроектировать ISR с буферизацией данных IRQ перед вызовом IST .

Читайте также:  Изменение настроек биоса windows

ISR будет возвращать SYSINTR_NOP , пока буфер не будет заполнен, а затем вернет соответствующий идентификатор SYSINTR , когда ISR будет готова для выполнения IST . Во время выполнения IST она может выбирать данные, которые буферизировала ISR .

Для передачи данных между ISR и IST :

  1. Зарезервируйте физическую память для ISR в файле Config. bib . Config. bib содержит несколько примеров резервирования физической памяти для последовательного и отладочного драйверов.
  2. Используйте зарезервированную память в вызове ISR . Так как ISR выполняется в режиме ядра, ISR может обращаться к зарезервированной памяти для буферизации данных.

Вызовите функцию MmMapIoSpace в IST для отображения физической памяти в виртуальные адреса.

Функция MMMapIoSpace вызывает функции VirtualAlloc и VirtualCopy для отображения физической памяти в адреса виртуальной памяти, к которой может обращаться IST .

Можно также вызывать функции VirtualAlloc и VirtualCopy непосредственно. Например, можно выделить память вне пространства виртуальной памяти процесса, вызывая VirtualAlloc с параметрами, заданными следующим образом:

  • dwSize >= 2 MB
  • flAllocationType задается как MEM_RESERVE
  • flProtect задается как PAGE_NOACCESS

В Windows Embedded CE устанавливаемая ISR может легко использовать данные совместно с IST , так как память может распределяться динамически, вместо резервирования в файле Config. bib . Поток службы прерываний ( IST ) является потоком, который выполняет большую часть обработки прерываний. ОС пробуждает IST , когда ОС получает прерывание для обработки. Иначе IST находится в спящем режиме. IST для клавиатуры, сенсорного экрана, мыши, и драйвера дисплея должны вызывать функцию SetKMode(TRUE) , чтобы позволить GWES писать в общую кучу памяти.

Чтобы ОС пробудила IST , IST должна ассоциировать объект события с идентификатором прерывания. Используйте функцию CreateEvent для создания объекта события. После обработки прерывания IST должна ждать следующий сигнал прерывания . Этот вызов обычно делается в цикле.

Когда происходит аппаратное прерывание, ядро сигнализирует о событии от имени ISR , и затем IST выполняет необходимые операции В/В на устройстве для сбора данных и их обработки. Когда обработка прерывания завершается, IST должна информировать ядро, чтобы снова включить аппаратное прерывание.

Обычно потоки IST выполняются с приоритетом выше нормального. Они могут задать для себя более высокий приоритет перед регистрацией своего события в ядре, вызывая функцию CeSetThreadPriority . Таблица 9.3 показывает функции, которые обычно использует IST .

Таблица 9.3. Функции, используемые в IST
Функция Описание
InterruptInitialize Соединяет событие с идентификатором прерывания ISR .
WaitForSingleObject Возвращает управление, когда указанный объект находится в сигнальном состоянии или когда истекает интервал перерыва.
InterruptDone Инструктирует ядро о повторном включении аппаратного прерывания, связанного с этим потоком.

Следующий список содержит примеры того, что IST может сделать при запуске:

  • Создать структуру для хранения значений прерываний.
  • Использовать CreateEvent в качестве триггера IST .
  • Прочитать значения IRQ и SysIntr из реестра и позволить OAL отобразить IRQ в значение SYSINTR перед загрузкой драйвера.
  • Сохранить указатель для созданного потока.

Следующий пример кода драйвера устройства клавиатуры PS/2 из ..\WINCE600\Public\Common\OAK\Drivers\Keybd\Ps2_8042\Ps2keybd.cpp показывает типичную IST .

Следующий образец кода показывает реализацию функции KeybdIstLoop .

Оцените статью