Жмакин А.П. Архитектура ЭВМ (2006) (1186252), страница 30
Текст из файла (страница 30)
Общая реакция процессора на прерывания или особые случаи состоит в сохранении минимального контекста прерываемой программы (в стеке — адрес возврата и, может быть, некоторую дополнительную информацию), идентификации источника прерывания или особого случая и передаче управления соответствующему обработчику (программе, подпрограмме, задаче). Однако имеются принципиальные различия по формированию сохраняемого контекста.
При возникновении нарушений в стек обработчика особого случая в качестве адреса возврата включается CS : EIP команды, вызвавшей нарушение.
При распознавании ловушки (к ним относятся и большинство внешних прерываний) процессор включает в стек адрес возврата, относящийся к следующей за ловушкой команде.
Наконец, при авариях содержательный адрес возврата отсутствует, поэтому рестарт задачи при авариях невозможен.
Принцип реализации прерываний (внешних) и особых случаев (внутренних) в микропроцессорах фирмы Intel сохранился практически неизменным с МП 8086.
В 8086 сигналы запросов на обработку прерываний формировались либо аппаратурой контроля процессора (внутренние прерывания), либо поступали из внешней среды на входы процессора INTR или NMI. При обнаружении (разрешенного) запроса в стек помещались текущие значения FLAGS, CS и IP.
В процессе идентификации источника запроса ему ставился в соответствие восьмиразрядный двоичный код п — вектор прерывания, причем за каждым внутренним прерыванием и за внешним NMI жестко закреплялся свой вектор, а для запросов, поступивших по входу INTR, реализовывалась процедура ввода вектора с внешней шины. Далее, определенный вектор прерывания рассматривался как номер строки таблицы, располагающейся с нулевого физического адреса памяти. Четырехбайтовыми элементами этой таблицы были адреса CS : IP точек входа в подпрограммы — обработчики прерываний. Таким образом, в системе поддерживалось до 256 различных обработчиков прерываний, причем векторы 0—31 резервировались за внутренними прерываниями (и NMI), а остальные — для внешних прерываний.
При идентификации источника запроса INTR выполняются следующие действия (при условии, что флаг IF* 1, иначе запрос INTR игнорируется):
1. Генерируется два цикла шины для ввода вектора внешнего прерывания.
2. Помещается в стек содержимое регистра FLAGS.
3. Помещается в стек содержимое регистра CS.
4. Помещается в стек содержимое регистра IP.
5. Сбрасывается в 0 флаг разрешения внешних прерываний IF, запрещая восприятие новых запросов по входу INTR до явной установки флага IF в 1 командой sti.
6. По значению вектора п обращаются к л-му элементу таблицы векторов прерываний и из нее загружаются новые значения регистров CS : IP.
7. Начинается выполнения обработчика прерывания с точки входа, определяемой CS : IP.
Сохраненное в стеке старое содержимое регистров CS : IP образует адрес возврата. Когда обработчик прерываний заканчивает свои действия, он должен выполнить команду возврата iret, которая, извлекая из стека содержимое FLAGS, CS, IP, возвращает управление прерванной программе.
Механизм реализации внешних и внутренних прерываний МП 80486 и Pentium в R-режиме аналогичен описанному выше, однако в Р-режиме он значительно усовершенствован:
□ таблица векторов прерываний трансформирована в дескрипторную таблицу прерываний IDT (рис. 7.13);
□ более сложен процесс перехода к обработчику прерывания или особого случая;
□ обработчику передается дополнительная информация о причине возникновения особого случая.
Механизм передачи управления обработчику особого случая (прерывания) соответствует обычному способу передачи управления через шлюз вызова. При этом процессор аппаратно включает в стек значения EFLAGS, CS : EIP (адрес возврата) прерываемой программы и, кроме того, в некоторых случаях — КОд ошибки и текущие значения SS, ESP (последние — при смене привилегий).
Точное значение адреса возврата зависит от того, является ли особый случай нарушением, ловушкой или аварией. Первые 32 вектора зарезервированы за особыми случаями Р-режима (табл. 7.1).
7.3.1. Дескрипторная таблица прерываний
Дескрипторная таблица прерываний IDT является прямой заменой таблицы векторов прерываний процессора 8086. Она должна определять 256 обработчиков прерываний и особых случаев, поэтому ее максимальный размер составляет 256 х 8 = 2048 байтов. Таблица ЮТ может находиться в любой области памяти, процессор локализует ее с помощью 48-битного регистра IDTR, который содержит базовый адрес и предел таблицы. Таблицу не рекомендуется объявлять короче максимального размера, т. к. любое обращение за пределы таблицы вызывает нарушение общей защиты, а вектор внешнего прерывания, вообще говоря, может иметь любое значение в диапазоне 00—FFh.
В таблице IDT разрешается применять только три вида дескрипторов: шлюз ловушки, шлюз прерывания и шлюз задачи (но не дескриптор TSS). Шлюзы прерывания и ловушки имеют большое сходство со шлюзом вызова (см. рис. 7.9). Единственное отличие состоит в отсутствии в этих шлюзах 5-битового поля счетчика WC, которое в шлюзе вызова определяет число параметров, передаваемых в вызываемую подпрограмму через стек. Соответствующее поле в шлюзах прерывания и ловушки зарезервировано.
Напомним, что шлюз вызова (а также ловушки и прерывания) содержит селектор сегмента кода и смещение внутри него, которые однозначно определяют точку передачи управления. Шлюз задачи содержит лишь селектор сегмента состояния задачи TSS (разумеется, каждый дескриптор содержит и байт доступа).
После локализации сегмента кода обработчика особого случая и включения информации в стек, выполнение начинается с той команды, которая определяется смещением в шлюзе ловушки. Обработчик действует до тех пор, пока не достигнет команды iret. По этой команде процессор извлекает из стека адрес возврата и содержимое регистра флажков (а также 48-битный указатель внешнего стека, если при обработке особого случая происходила смена уровней привилегий).
Если особый случай вызывается через шлюз прерывания, процессор сбрасывает флаг разрешения прерывания IF после включения в стек адреса возврата и содержимое регистра флажков, но до выполнения первой команды обработчика. При переходе через шлюз ловушки никакие флаги не изменяются.
Обработка особого случая через шлюз задачи аналогична действию команды far call, приводящей к переключению задачи. Однако здесь невозможен прямой переход через дескриптор TSS, а требуется промежуточный шлюз задачи. С дескриптором шлюза задачи ассоциируется уровень привилегий, который не должен быть выше уровня привилегий прерываемой задачи. По существу, прерываемая задача как бы выполняет команду far call вызова другой задачи через шлюз задачи, и здесь действуют стандартные правила защиты по привилегиям.
Обработка особого случая через шлюз задачи, т. е. в другой задаче, имеет определенные преимущества:
□ автоматически сохраняется весь контекст прерванной задачи;
О обработчик особого случая не может исказить прерванную задачу, т. к. он полностью изолирован от нее;
□ обработчик прерывания может работать на любом уровне привилегий и в заведомо правильной среде; он может иметь свое локальное адресное пространство благодаря наличию отдельной локальной дескрипторной таблицы (при необходимости).
К недостаткам применения шлюза задачи для вызова обработчика можно отнести:
□ замедленную реакцию процессора на особый случай;
□ в шлюзе задачи невозможно определить начальную точку выполнения задачи;
□ сложность получения информации о прерванной задаче.
Переключение задачи, инициируемое особым случаем, производит вложение задачи обработчика в прерванную задачу. Старая задача остается занятой, а новая — обработчик особого случая — отмечается как занятая, причем в ней будет установлен флажок NT и загружено поле обратной связи. Состояние флага IF в новой задаче не меняется и определяется тем значением бита регистра EFLAGS, которое хранилось в TSS. Поэтому, если обработчик особого случая через шлюз задачи предназначен для обработки внешних прерываний, следует в TSS установить IF = 0, "аппаратно" запретив внешние прерывания на время работы обработчика, или пока он явно не установит IF = 1.
7.3.2. Учет уровня привилегий
Все особые случаи должны обрабатываться через шлюзы. В дескрипторах шлюзов всех трех типов, содержащихся в IDT, имеется поле уровня привилегий дескриптора DPL, определяющее минимальный уровень привилегий, необходимый для использования шлюза. Для обработчиков прерываний рекомендуется устанавливать DPL = 3, чтобы обработка особого случая не зависела от уровня привилегий текущей задачи.
Шлюзы ловушек или прерываний должны передавать управление сегменту кода с более высоким или равным уровнем привилегий. Обработчику не разрешается работать на уровне привилегий, который ниже уровня прерываемой задачи (если, конечно, он не является отдельной задачей). Из-за непредсказуемости возникновения прерываний и особых случаев требуется гарантировать невозможность нарушения правил защиты по привилегиям при обработке особого случая. Этого можно достичь двумя способами:
□ определить все обработчики особых случаев, не вызывающие переключения задачи, в сегментах кода с уровнем привилегий 0; такие обработчики будут действовать всегда, независимо от значения CPL программы;
□ определить все обработчики особых случаев, не вызывающие переключения задачи, в подчиненные сегменты кода.
7.3.3. Код ошибки
В некоторых особых случаях процессор включает в стек 4 байта кода ошибки (error code), причем действительными являются только 2 младших байта, остальные включаются лишь для выравнивания стека. Когда процессор обнаруживает
□ недействительный сегмент TSS:
□ нарушение неприсутствия;
□ нарушение стека;
□ нарушение общей защиты,
он включает в стек обработчика особого случая информацию, идентифицирующую "виновный" дескриптор.
Формат кода ошибки напоминает селектор, т. к. большинство особых случаев связано с ошибками дескрипторов и содержит следующие поля:
□ биты [15:3] — индекс (номер строки дескрипторной таблицы);
□ бит [2] — TI, как и в других селекторах, определяет принадлежность дескриптора к локальной (TI = 1) или глобальной (TI = 0) дескрипторной таблице;
□ бит [1] — I. Если I = 1, то индекс в старших битах [15:3] кода ошибки относится к дескрипторной таблице прерываний ЮТ;
П бит [0] — EXT = 1 означает, что особый случай был вызван аппаратным прерыванием (внешним) или возник, когда процессор обрабатывал другой особый случай.
Если процессор не может сформировать содержательный код ошибки, он включает в стек код, равный 0.
Помимо кода ошибки в некоторых особых случаях дополнительная диагностическая информация находится в других регистрах процессора. Например, при страничном нарушении в регистре CR2 содержится линейный адрес, преобразование которого привело к ошибке. Обработчик этого особого случая может обратиться к соответствующим элементам PDE и РТЕ. Для особого случая отладки полезная информация содержится в регистре состояния отладки DR6.
7.3.4. Описание особых случаев
Далее приводится краткое описание действий процессора х86 при возникновении особых случаев [3].
Ошибка деления (0) — автоматически формируется, когда в команде div или idiv делитель равен нулю или частное слишком велико для получателя (AL/AX/EAX).
Отладка (1)— формируется в следующих случаях (может быть нарушением или ловушкой):
□ нарушение контрольной точки по адресу команд;
□ ловушка контрольной точки по адресу данных;
□ нарушение общей защиты;
□ ловушка покомандной работы (флаг TF =1);