Обработка прерываний и исключений в защищенном режиме IA-32

В оглавлении перечислены более-менее в логическом порядке статьи об экспериментах с разработкой ОС.

Пришла пора продолжить серию постов об экспериментах с разработкой Операционной Системы. У меня есть загрузчики, есть билд-система для сборки ядра. Есть заготовка экранных функций. Загрузчик загружает ядро в память по адресу 0x10000, переводит процессор в защищенный режим и передает управление на ядро. Ядро в данный момент просто выводит на экран несколько отладочных сообщений в цикле. Эдакий сферический конь в вакууме. Работает этот «конь» недолго. Дело в том, что у компьютера по-умолчанию настроены ряд прерываний. В частности таймер. Это прерывание вызывается весьма часто. В момент старта компьютер работает в реальном режиме. И прерывания обрабатываются обработчиками прерываний реального режима. Таблица прерываний реального режима находится в адресах 0 — 0x400.

В защищённом режиме, прерывания обрабатываются по-другому. У меня кода обработки прерываний пока нет, поэтому первое же прерывание приводит мою тестовую систему к перезагрузке.

Об обработке прерываний есть статья James Molloy: http://www.jamesmolloy.co.uk/tutorial_html/4.-The%20GDT%20and%20IDT.html. Есть ещё другие материалы, но я планирую для начала обратиться к первоисточникам. К документации Intel.


Прерывания и исключения — обзор

Прерывания и исключения — события, означающие что где-то в системе
(оборудовании) или внутри текущей выполняющейся программы или
задачи возникло состояние, требующее немедленного внимания
процессора. Обычно прерывания и исключения приводят к принудительной
передачи управления от текущей выполняемой программы или задачи к
специальной программной процедуре или задаче, называемой
обработчиком прерывания или обработчиком исключения. Действие,
выполняемое процессором в ответ на прерывание или исключение
называют обработка прерывания или исключения (servicing or handling the
interrupt or exception).

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

Исключения возникают когда процессор определяет возникновение ошибки
(detects error condition) в процессе выполнения инструкции. Например —
деление на ноль. Процессор определяет разнообразные error conditions
включая нарушения защиты (protection violations), ошибки страниц (page
faults), internal machine faults. Архитектура процессоров Pentium 4, Intel Xeon,
P6 family и Pentium позволяет генерацию machine-check excheption при
возникновении внутренних аппаратных ошибок (hardware errors) или
ошибок шины (bus errors).

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


Вектора прерываний и исключений

Для упорядочивания обработки исключений и прерываний, каждому
отдельному исключению и каждому прерыванию (interrupt condition),
требующему специальной обработки процессором, назначается уникальный
идентификатор, называемый номером вектора (vector number). Процессор
использует vector number (номер), назначенный исключению или
прерыванию как индекс в таблице дескрипторов прерываний (interrupt
descriptor table IDT). Таблица содержит адреса (entry point) обработчиков
исключений или прерываний.

Разрешенный диапозон для vector numbers от 0 до 255. Номера от 0 до 31
зарезервированы в Intel 64 и IA-32 архитектурах для architecturedefined
прерываний и исколючений. Не все из vector numbers в этом диапозоне
имеют назначенную функцию. Неназначенные vector numbers в этом
диапозоне зарезервированы. Не используйте эти зарезервированные
номера.

Vector numbers в диапозоне от 32 до 255 отведены под user-defined
прерывания и не зарезервированы Intel 64 и IA-32 архитектурами. Эти
прерывания в основном предназначены для внешних устройств ввода-
вывода.


Источники прерываний

Процессор получает прерывания из 2-х источников:
— Внешние (аппаратно генерируемые) прерывания.
— Программно-генерируемые прерывания.

Внешние (аппаратные) прерывания

Внешние прерывания получаются через контакты процессора или через
локальный контроллер прерываний APIC. Главные контакты, означающие
состояние прерывания на процессорах Pentium 4, Intel Xeon, P6 family и
Pentium — LINT[1:0] pins, соединенные с локальным APIC. Когда локальный
APIC включен, LINT[1:0] pins, могут быть запрограммированы с помощью
APIC local vector table (LVT), на ассоциацию с любым процессорным
исключением или вектором прерывания.

Когда локальный APIC является глобальным/аппаратные прерывания
запрещены, тогда эти контакты конфигурируются как INTR и NMI контакты,
соответственно. Сигнал на контакте INTR сигнализирует процессору, что
внешнее прерывание возникло. Процессор читает из системной шины
inerrupt vector, предоставляемый внешним контроллером прерываний,
таким как 8259A. Сигнал на контакте NMI говорит процессору, что
немаскируемое прерывание (NMI), назначенное на вектор прерывания 2.


Прерывания и исключения защищенного режима

Vector No. Mnemonic Description Type Error Code Source
0 #DE Divide Error Fault No DIV и IDIV инструкции
1 #DB RESERVED Fault/Trap No For Intel use only
2 NMI Interrupt Interrupt No Nonmaskable externel
interrupt
3 #BP Breakpoint Trap No INT 3 instruction
4 #OF Overflow Trap No INT0 instruction
5 #BR BOUND Range Exceeded Fault No BOUND instruction
6 #UD Invalid Opcode (Undefined
Opcode)
Fault No UD2 instruction or reserved
opcode
7 #NM Device Not Available (No
Math Coprocessor)
Fault No Floating-point or WIT/FWAIT
instruction
8 #DF Double Fault Abort Yes (zero) Any instruction that can
generate an exception, an NMI, or an INTR.
9 Coprocessor Segment Overrun
(reserved)
Fault No Floating-point instruction
10 #TS Invalid TSS Fault Yes Task switch or TSS access.
11 #NP Segment Not Present Fault Yes Loading segment registers or
accessing system segments.
12 #SS Stack-Segment Fault Fault Yes Stack operations and SS
register loads
13 #GP General Protection Fault Yes Any memory reference and
other protection checks
14 #PF Page Fault Fault Yes Any memory reference
15 (Intel reserved. Do not use) Fault No
16 #MF x87 FPU Floating-Point Error
(Math Fault)
Fault No x87 FPU floating-point or
WAIT/FWAIT instruction
17 #AC Alignment Check Fault Yes(Zero) Any data reference in memory
18 #MC Machine Check Abort No Error codes (if any) and
source are model dependant
19 #XM SIMD Floating-Point Exception Fault No SSE/SSE2/SSE3 floating point
instructions
20-31 Intel reserved. Do not use.
32-255 User Defined ( Non
reserved)
Interrupts
Interrupt External interrupt or INT n
instruction

Внутренний контроллер прерываний процессора localAPIC обычно соединен с
системным контроллером прерываний I/O APIC. Внешние прерывания
полученные через контакты системного контроллера прерываний I/O APIC
могут быть направлены на внутренний контроллер прерываний local APIC
через системную шину (Pentium 4, Intel Core Duo, Intel Core 2, Intel® Atom™,
and Intel Xeon processors) или через APIC serial bus (P6 family and Pentium
processors). Внешний контроллер прерываний I/O APIC определяет vector
number прерывания и шлёт этот номер внутреннему контроллеру
процессора (local APIC). Когда система включает множество процессоров,
процессоры могут также слать прерывания один другому посредством
системной шины (Pentium 4, Intel Core Duo, Intel Core 2, Intel Atom, and
Intel Xeon processors) или посредством APIC serial bus (P6 family and
Pentium processors).

Контакты LINT[1:0] не доступны в процессорах Intel486 и ранних
процессорах Pentium не имеющих встроенного внутреннего local APIC. Эти
процессоры имеют специальные жестко назначенные контакты NMI и INTR.
В системах с такими процессорами прерывания обычно генерируются
системным контроллером прерываний (8259A), с посылкой прерываний
через контакт INTR.

Заметьте, что несколько других контактов на процессоре могут приводить
к возникновению процессорного прерывания. Однако эти прерывания не
обрабатываются механизмом обработки прерываний и исключений
описанным здесь. Эти контакты включают: RESET#, FLUSH#, STPCLK#,
SMI#, R/S#, and INIT#. Есть ли они у конкретного процессора, зависит от
реализации конкретной модели. Функции контактов описаны в технических
описаниях прилагаемых к конкретным процессорам. Контакт SMI#
описывается в главе 26 «System Management».


Маскируемые аппаратные прерывания

Любое внешнее прерывание доставленное процессору посредством
контакта INTR или через внутренний local APIC называется маскируемым
аппаратным прерыванием. Через Маскируемые аппаратные прерывания
доставленные через контакт INTR могут быть любыми в диапозоне 0 — 255.
Прерывания доставленные через внутренний local API могут быть векторами
в диапозоне 16 — 255.

Флаг IF регистра EFLAGS позволяет маскировать всю группу маскируемых
аппаратных прерываний. При получении прерываний с векторами от 0 до
15 через внутренний local APIC, APIC сообщает (indicates) получение
неверного вектора прерывания.


Источники исключений

Процессор получает исключения из трех источников:
— Обнаруживаемые процессором Program-Error exceptions
— Программно генерируемые исключения
— Machine-check exceptions.

Program-Error Exceptions

Процессор генерирует одно или более исключений при обнаружении
программных ошибок в процессе выполнении приложения, кода
операционной системы или executive. Архитектуры Intel64 и IA-32
определяют vector number для каждого processor-detectable exception.
Исключения подразделяются на faults, traps и aborts.

Программно-генерируемые исключения

Инструкции INTO, INT3 и BOUND позволяют программную генерацию
исключений. Эти инструкции позволяют выполнение проверки условий в
местах выполнения потока инструкций. Например INT 3 вызывает
генерацию breakpoint exception. Инструкция INT n может быть использована
для эмуляции исключений в программах, но есть ограничение. Если INT n
вызывает вектор для одного из architecturally-defined исключений,
процессор генерирует прерывание на корректный вектор (для доступа
к обработчику исключения) но не кладет код ошибки на стек. В отличии
от аппаратно-генерируемое исключения нормально сохраняющего на стеке
код ошибки. Обработчик исключения будет пытаться взять
код ошибки со стека при обработке исключения. Но, так как код ошибки
не был сохранён в стеке, вместо кода ошибки из стека будет извлечён
EIP (на месте пропущенного кода ошибки). Это приведёт к возврату из
обработчика по неверному адресу. (Т.о. нельзя с помощью INT n
обращаться к обработчикам аппаратно-генерируемых исключений).

Machine-Check Exceptions

Процессоры семейств P6 family и Pentium предоставляют внутренние и
внешние machine-check механизмы для проверки операций внутреннего
аппаратного чипа и транзакций шины. Эти механизмы — implementation
dependent (непереносимы). Когда процессор обнаруживает machinecheck
ошибку, процессор сигнализирует об ошибке с помощью machine-check
exception (vector 18) и возвращает код ошибки.

Классификация исключений

Исключения подразделяются на faults, traps и aborts в зависимости от
пути их поступления или в зависимости от возможности рестара
инструкции вызвавшей исключение без потери работоспособности
(continuity) программы или задачи.

Продолжение здесь…

Оставьте комментарий