Особенности архитектуры процессоров 386, 486 и Pentium . Часть 2.

2.4. Прерывания и исключения

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

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

Аппаратные прерывания подразделяются на маскируемые и немаскируемые. Процессор может воспринимать прерывания после выполнения каждой команды, длинные строковые команды имеют для восприятия прерываний специальные окна.

Маскируемые прерывания вызываются переходом в высокий уровень сигнала на входе INTR (Interrupt Request) при установленном флаге разрешения (IF==1). В этом случае процессор сохраняет в стеке регистр флагов, сбрасывает флаг IF и вырабатывает два следующих друг за другом (back to back) цикла подтверждения прерывания, в которых генерируются управляющие сигналы INTA# (Interrupt Acknowledge). Высокий уровень сигнала INTR должен сохраняться по крайней мере до подтверждения прерывания. Первый цикл подтверждения холостой, по второму импульсу внешний контроллер прерываний передает по шине номер вектора, обслуживающего данный тип аппаратного прерывания. Прерывание с полученным номером вектора выполняется процессором так же, как и программное. Обработка текущего прерывания может быть в свою очередь прервана немаскируемым прерыванием, а если обработчик установит флаг IF, то и другим маскируемым аппаратным прерыванием.

Немаскируемые прерывания выполняются независимо от состояния флага IF по сигналу NMI (Non Mascable Interrupt). Высокий уровень на этом входе вызовет прерывание с типом (вектором) 2, которое выполняется так же, как и маскируемое. Его обработка не может прерываться под действием сигнала на входе NMI до выполнения команды IRET.

Исключения (Exceptions) подразделяются на отказы, ловушки и аварийные завершения.

Отказ (fault) — это исключение, которое обнаруживается и обслуживается до выполнения инструкции, вызывающей ошибку. После обслуживания этого исключения управление возвращается снова на ту же инструкцию (включая все префиксы), которая вызвала отказ. Отказы, использующиеся в системе виртуальной памяти, позволяют, например, подкачать с диска в оперативную память затребованную страницу или сегмент.

Ловушка (trap) — это исключение, которое обнаруживается и обслуживается после выполнения инструкции, его вызывающей. После обслуживания этого исключения управление возвращается на инструкцию, следующую за вызвавшей ловушку. К классу ловушек относятся и программные прерывания.

Аварийное завершение (abort) — это исключение, которое не позволяет точно установить инструкцию, его вызвавшую. Оно используется для сообщения о серьезной ошибке, такой как аппаратная ошибка или повреждение системных таблиц.

Набор и обработка исключений реального и защищенного режимов различны. Под исключения Intel резервирует векторы 0-31 в таблице прерываний, однако в PC часть из них перекрывается системными прерываниями BIOS и DOS.

Процедура, обслуживающая прерывание или исключение, определяется по таблице с помощью номера восьмибитного указателя (вектора) прерывания. Указатель для программных прерываний задается командой, для маскируемых аппаратных прерываний вводится от внешнего контроллера во втором цикле INTA#, немаскируемое прерывание имеет фиксированный вектор, а исключения генерируют и передают вектор внутри процессора.

Каждому номеру (0-255) прерывания или исключения соответствует элемент в таблице дескрипторов прерываний IDT (Interrupt Descriptor Table). В реальном режиме таблица прерываний содержит двойные слова дальние адреса обслуживающих процедур и после сброса располагается, начиная с нулевых адресов. Командой LIDT можно изменять ее положение в пределах первого мегабайта, а размер (03FFh) может быть уменьшен до 007Fh. При попытке обслуживания прерывания с номером, выходящим за заданный размер таблицы, генерируется исключение типа 8. В защищенном режиме таблица IDT содержит 8-байтные дескрипторы прерываний, может иметь размер от 32 до 256 дескрипторов и располагаться в любом месте физической памяти.

Анализ условий обслуживания прерываний и исключений выполняется в следующем порядке (по убыванию приоритета):

1) проверка на исключение (ловушка) отладки (типа 1) по выполненной инструкции (пошаговый режим через флаг TF или точка останова по данным через регистры отладки);

2) проверка на исключение (отказ) отладки (типа 1) по последующей инструкции (точка останова по инструкции через регистр отладки);

3) немаскируемое прерывание (аппаратное по входу NMI);

4) маскируемое прерывание (аппаратное по входу INTR при IF==1);

5) проверка на исключение (отказ) сегментации (типа 11 или 13) при выборке следующей инструкции;

6) проверка на исключение (отказ) страницы (типа 14) при выборке следующей инструкции;

7) проверка на отказ декодирования следующей инструкции (типа 6 или 13);

8) для операции WAIT проверка TS и МР (исключение 7, если TS-1 и МР-1);

9) для операции ESCAPE (к мат. сопроцессору) проверка ЕМ и TS (исключение 7, если ЕМ=1 или TS=l);

10) для операции WAIT или ESCAPE проверка на исключение 16 от сопроцессора;

11) проверка на отказ сегментации (1.1, 1.2, 13) и страницы (14) для. операндов, используемых в инструкции.

Двойной отказ (Double Fault) — исключение 8 — возникает, когда при обработке исключения, связанного с сегментацией (10, 11, 12 или 13), процессор обнаруживает исключение, отличное от отказа страницы (14). Также двойной отказ возникает, если при отработке исключения отказа страницы (типа 14) обнаруживается исключение другого типа. В этом случае тоже исполняется исключение 8.

Если во время обслуживания исключения отказа страницы произойдет еще один отказ страницы, то происходит отключение (Shutdown) процессора. Во время отключения никакие новые инструкции не выполняются. Из этого состояния процессор можно вывести только аппаратно сигналом NMI, оставляя его в защищенном режиме, или сигналом RESET, переводящим процессор в реальный режим.

Прерывания и исключения процессора, работающего в защищенном режиме, приведены в табл. 4. Исключения реального режима, отличающиеся от защищенного, приведены в табл. 5.

 

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

Номер

Функция

Тип

0

Переполнение при делении на 0

Fault

1

Исключение отладки

Fault/Trap

2

Немаскируемое прерывание (NMI)

NMI

3

Прерывание отладки (INT 3)

Trap

4

Прерывание по переполнению (INTO)

Trap

5

Прерывание по контролю диапазона (BOUND)

Fault

6

Недопустимый код операции

Fault

7

Сопроцессор недоступен или переключалась задача

Fault

8*

Двойной отказ

Abort

9

Нарушение границы сегмента сопроцессором (только 386/387)

Fault

10**

Недопустимый сегмент состояния задачи

Fault

11**

Сегмент отсутствует

Fault

12*

Нарушение границы сегмента стека или сегмент стека отсутствует

Fault

13*

Общее нарушение защиты

Fault

14**

Отказ страницы

Fault

15

Зарезервирован

 

 

16

Исключение сопроцессора

Fault

17**

Контроль выравнивания (486+)

Fault

18-31

Зарезервированы

 

 

0-255

Программные прерывания INT n

Trap

* В реальном режиме имеют другое назначение (см. табл. 5).

** В реальном режиме не возникают, но возможны в V86.

 

Таблица 5. Исключения реального режима

Номер

Функция

8

Вектор прерывания не попадает в таблицу

12

Нарушение границы сегмента стека

13

Нарушение границы сегмента данных или кода

При отработке исключения в защищенном режиме процессор сохраняет в стеке слово кода ошибки (Error Code). Если оно отлично от нуля, то оно содержит селектор дескриптора, с которым связана ошибка.

2.5. Начальный сброс и самотестирование

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

FLAGS = 0002h и биты VM и RF его расширения обнуляются;

в регистре CR0 обнуляются биты PG, TS, ЕМ, МР и РЕ;

CS = F000h (база устанавливается FFFF0000h, лимит - 0FFFFh);

EIP – 0000FFF0h;

DS - ES = SS = FS = GS = 0000h.

Регистр DH после сброса содержит идентификатор процессора Component Id (03-386, 04-486, 05-Pentium, 06-Pentium Pro или Pentium II), DL - номер модели (Revision Id).

Только после сброса и до первой команды межсегментного перехода или вызова на шине адреса в реальном режиме биты А[20:31] в циклах выборки команд имеют единичное значение. Из этого следует, что по крайней мере на начальный период времени после сигнала RESET компьютер должен иметь образ BIOS в адресах FFFFFFF0-FFFFFFFFh, в то время как в PC на 8086/88 ROM BIOS располагалась под границей первого мегабайта (FFFFFh), a AT-286 имели образ под границей 16-го мегабайта (FFFFFFh). Перемещение BIOS из первого мегабайта памяти в режиме нормальной работы невозможно, поскольку векторы прерываний, ссылающиеся на сервисы BIOS, в реальном режиме могут адресоваться только к памяти в диапазоне адресов 0-OFFFFFh (0-10FFEF при открытом вентиле Gate A20).

Если во время спада сигнала RESET на определенном входе процессора удерживать низкий уровень сигнала, процессор начнет выполнять внутренний тест BIST (Built-in Self-Test). Тест для 386-го и 486-го процессоров выполняется примерно за 2 тактов, что занимает десятки миллисекунд. По окончании самотестирования процессор начинает работу, как после обычного сброса, а регистр ЕАХ содержит сигнатуру результата тестирования. Об успешном выполнении теста свидетельствует нулевое значение сигнатуры.

2.6. Ввод-вывод

Как и 8086, 32-разрядные процессоры позволяют адресовать до 64К однобайтных или 32 К двухбайтных регистров в пространстве, отдельном от памяти. Дополнительно имеется возможность обращения к 32-битным портам. При операциях ввода-вывода линии А[16:31] не используются. Адрес устройства задается либо в команде (только младший байт, старший — нулевой), либо берется из регистра DX (полный 16-битный адрес). Команды ввода-вывода вызывают шинные циклы с активными сигналами IORD#, 10WR#. Строковые команды обеспечивают блочный ввод-вывод со скоростью, превышающей аналогичные операции со стандартным контроллером DMA. В адресном пространстве ввода-вывода область 0F8-0FF зарезервирована для использования сопроцессором (при обращении к сопроцессору 386 выставляет единицу на линии А31 шины адреса, что используется для упрощения дешифрации адресов).

В защищенном режиме инструкции ввода-вывода являются привилегированными. Это означает, что они могут исполняться задачами только с определенным уровнем привилегий, определяемым полем IOPL регистра флагов или битовой картой разрешения ввода-вывода (I/O Permission Bitmap), хранящейся в сегменте состояния задачи. Несанкционированная попытка выполнения этих инструкций вызовет исключение 13 — нарушение защиты (сообщение “General Protection Error”).

2.7. Основные понятия защищенного режима

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

Основным защищаемым ресурсом является память, в которой хранятся коды, данные и различные системные таблицы (например, таблица прерываний). Защищать требуется и совместно используемую аппаратуру, обращение к которой обычно происходит через операции ввода-вывода и прерывания. В защищенном режиме процессор 80286 аппаратно реализует многие функции защиты, необходимые для построения супервизора многозадачной ОС, поддерживая и механизм виртуальной памяти.

Защита памяти основана на использовании сегментации. Сегмент это блок адресного пространства памяти определенного назначения. К элементам сегмента возможно обращение с помощью различных инструкций процессора, использующих разные режимы адресации для формирования адреса в пределах сегмента. Максимальный размер сегмента для процессоров 8086 и 80286 составлял 64 Кб, в 32-разрядных процессорах этот предел отодвигается до 4 Гб. Сегменты памяти выделяются задачам операционной системой, но в реальном режиме любая задача может переопределить значение сегментных регистров, задающих положение сегмента в пространстве памяти, и “залезть” в чужую область данных или кода. В защищенном режиме сегменты тоже распределяются операционной системой, но прикладная программа сможет использовать только разрешенные для нее сегменты памяти, выбирая их с помощью селекторов из предварительно сформированных таблиц дескрипторов сегментов. Селекторы представляют собой 16-битные указатели, загружаемые в сегментные регистры процессора.

Дескрипторы — это структуры данных, используемые для определения свойств программных элементов (сегментов, вентилей и таблиц). Дескриптор определяет положение элемента в памяти, размер занимаемой им области (лимит), его назначение и характеристики защиты. Защита памяти с помощью сегментации не позволяет:

• использовать сегменты не по назначению (например, пытаться трактовать область данных как коды инструкций);

• нарушать права доступа (пытаться модифицировать сегмент, предназначенный только для чтения, обращаться к сегменту, не имея достаточных привилегий, и т. п.);

• адресоваться к элементам, выходящим за лимит сегмента;

• изменять содержимое таблиц дескрипторов (то есть параметров сегментов), не имея достаточных привилегий.

Защищенный режим предоставляет средства переключения задач. Состояние каждой задачи (значение всех связанных с ней регистров процессора) может быть сохранено в специальном сегменте состояния задачи (TSS), на который указывает селектор в регистре задачи. При переключении задач достаточно загрузить новый селектор в регистр задачи, и состояние предыдущей задачи автоматически сохранится в ее TSS, а в процессор загрузится состояние новой (возможно, и ранее прерванной) задачи и начнется (продолжится) ее выполнение.

Четырехуровневая иерархическая система привилегий предназначена для управления использованием привилегированных инструкций и доступом к дескрипторам. Уровни привилегий нумеруются от 0 до 3, нулевой уровень соответствует максимальным (неограниченным) возможностям доступа и отводится для ядра операционной системы. Уровень 3 имеет самые ограниченные права и обычно предоставляется прикладным задачам. Систему защиты обычно изображают в виде концентрических колец, соответствующих уровням привилегий (рис. 4.), а сами уровни привилегий иногда называют кольцами защиты. Сервисы, предоставляемые задачам, могут находиться в разных кольцах защиты. Передача управления между задачами контролируется вентилями (Gate), проверяющими правила использования уровней привилегий. Через вентили задачи могут получить доступ только к разрешенным им сервисам других сегментов.

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

Дескрипторы и привилегии являются основой системы защиты: дескрипторы определяют структуры элементов (без которых невозможно их использование), а привилегии определяют возможность доступа к дескрипторам и выполнения привилегированных инструкций. Любое нарушение защиты приводит к возникновению специальных исключений, обрабатываемых ядром операционной системы.

Механизм виртуальной памяти позволяет любой задаче использовать логическое адресное пространство размером до 64 Тб (16К сегментов по 4 Гб). Для этого каждый сегмент в своем дескрипторе имеет специальный бит, который указывает на присутствие данного сегмента в оперативной памяти в текущий момент времени. Неиспользуемый сегмент может быть выгружен из оперативной во внешнюю память (например, дисковую), о чем делается пометка в его дескрипторе. На освободившееся место из внешней памяти может восстанавливаться содержимое другого сегмента (этот процесс называется свопингом, или подкачкой), и в его дескрипторе делается пометка о присутствии. При обращении задачи к отсутствующему сегменту процессор вырабатывает соответствующее исключение, обработчик которого и заведует виртуальной памятью в операционной системе. После подкачки страницы (сегмента) выполнение задачи продолжается, так что виртуализация памяти для прикладных задач прозрачна (если не принимать во внимание задержку, вызванную подкачкой).

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

 

 

2.8. Сегментация

Сегментация — метод управления памятью, на котором основано построение защиты. Сегмент является средством объединения областей памяти с общими атрибутами. Информация о свойствах сегмента хранится в 8-байтной структуре данных, называемой дескриптором. Все дескрипторы хранятся в таблицах, обращение к которым аппаратно поддерживается процессором. Процессор может обращаться только к тем сегментам памяти, для которых имеются дескрипторы в таблицах.

Таблицы дескрипторов

Существуют три типа таблиц дескрипторов — локальная таблица дескрипторов LDT (Local Descriptor Table), глобальная таблица дескрипторов GDT (Global Descriptor Table) и таблица дескрипторов прерываний IDT (Interrupt Descriptor Table). Размеры таблиц могут находиться в пределах 8 байт — 64 Кбайт, что соответствует числу элементов в таблице от 1 до 8К.

С каждой из этих таблиц связан соответствующий регистр процессора . Регистры GDTR и IDTR имеют программно-доступное 16-битное поле лимита, задающее размер таблицы, и 32-битное (у 80286 — 24-битное) поле базового адреса, определяющее положение таблицы в пространстве линейных (у 80286 — физических) адресов памяти. У регистра LDTR программно доступно только 16-битное поле селектора, по которому из GDT автоматически загружаются программно-невидимые поля базового адреса и лимита.

Команды загрузки регистров таблиц LGDT, LIDT и LLDT являются привилегированными (выполняются только на уровне 0). Команды LGDT и LIDT загружает из памяти 6-байтное поле, содержащее базовый адрес и лимит локальной таблицы. Команду LLDT загружает только селектор, ссылающийся на дескриптор, содержащий базовый адрес и лимит локальной таблицы дескрипторов.

Глобальная таблица (GDT) содержит дескрипторы, доступные всем задачам. Она может содержать дескрипторы любых типов, кроме дескрипторов прерываний и ловушек. Локальная таблица (LDT) может быть собственной для каждой задачи, она может содержать только дескрипторы сегментов, вентилей задачи и вызовов. Сегмент недоступен задаче, если его дескриптора нет в текущий момент ни в GDT, ни в LDT.

Выбор таблицы (локальная или глобальная) определяется по значению бита TI селектора, а положение (номер) дескриптора задается 13-битным полем INDEX селектора. При ссылке на дескриптор, выходящий за лимит таблицы, возникает исключение типа 13.

Таблица дескрипторов прерываний, используемая в защищенном режиме, может содержать описания до 256 прерываний. Таблица может содержать только вентили задач, прерываний и ловушек. Базовый адрес и лимит таблицы загружается привилегированной командой LIDT (аналогично LGDT). Размер IDT должен быть не менее 256 байт для того, чтобы в нее поместились все зарезервированные прерывания процессора. Ссылка на элементы IDT происходит по командам INT, аппаратным прерываниям и исключениям процессора. При возникновении прерывания или исключения, дескриптор которого выходит за лимит таблицы, вырабатывается исключение 8.

Дескрипторы

Дескрипторы имеют 8-байтный формат как для 16-разрядных (80286), так и для 32-разрядных процессоров. Назначение дескриптора определяется полями байта управления доступом. Дескрипторы 16-и 32-разрядных процессоров отличаются разрядностью поля базового адреса (24 и 32 бит) и трактовкой поля лимита, которое должно обеспечивать размер сегмента до 64 Кб или 4 Гб соответственно. Два старших байта у дескрипторов 80286 всегда нулевые (по требованиям совместимости со старшими процессорами, объявленным при выпуске 80286), что позволяет их отличать и корректно использовать, выполняя 16-битные приложения защищенного режима на 32-битных процессорах.

Два старших байта дескрипторов 32-битных процессоров содержат расширения полей BASE и LIMIT, бит дробности G (Granularity), определяющий, в каких единицах задан лимит: G=0 — в байтах, G=1 — в страницах по 4К (что и обеспечивает максимальную длину в 4 Гб).

Пятый байт любого дескриптора определяет его тип и управляет доступом (Access rights byte - байт управления доступом).

Дескрипторы сегментов кода и данных определяют базовый адрес, размер сегмента, права доступа (чтение, чтение/запись, только исполнение кода или исполнение/чтение), а для систем с виртуальной памятью еще и присутствие сегмента в физической памяти.

Для дескриптора сегмента данных (Е=0, S=l) слово лимита трактуется по-разному в зависимости от направления расширения.

В сегмент кода (Е==1, S=1) запись невозможна, лимит указывает на его последний байт, а биты поля.

Системные сегменты предназначены для хранения локальных таблиц дескрипторов LDT (Local Descriptor Table) и состояния задач TSS (Task State Segment). Их дескрипторы определяют базовый адрес, лимит сегмента (1-64 Кб), права доступа (чтение, чтение/запись, только исполнение кода или исполнение/чтение) и присутствие сегмента в физической памяти (для систем с виртуальной памятью).

В байте управления доступом у этих дескрипторов бит S=0. Бит Р определяет действительность (P=l) или недействительность (Р=О) содержимого сегмента. Поле уровня привилегий DPL используется только в дескрипторах сегментов состояния задач. Поскольку обращение к локальным дескрипторам возможно только по привилегированным командам, поле DPL для дескрипторов таблиц не используется. Поле TYPE (1-3, 9-В) определяет тип сегмента:

0, 8 - недопустимо;

1 - доступный сегмент состояния задачи 80286 (Available TSS);

2 - таблица локальных дескрипторов (LDT);

3 - занятый сегмент состояния задачи 80286 (Busy TSS);

9 - доступный сегмент состояния задачи 386+ (Available TSS);

А - не определено (зарезервировано);

В - занятый сегмент состояния задачи 386+ (Busy TSS). Межсегментная передача управления непосредственно (командами JMP, CALL, INT, RET и IRET) возможна только к сегментам кода с тем же уровнем привилегий либо к подчиненным сегментам, уровень привилегий которых выше, чем CPL (при этом CPL не изменяется). Для переходов с изменением уровня привилегий используются вентили (Gate), иногда называемые шлюзами. Для каждого способа косвенной межсегментной передачи управления имеются соответствующие вентили, их использование позволяет процессору автоматически выполнять контроль защиты. Вентили вызова (Call Gates) используются для вызовов процедур со сменой уровня привилегий, вентили задач (Task Gates) используются для переключения задач, вентили прерываний (Interrupt Gates) и ловушек (Trap Gates) определяют процедуры обслуживания прерываний. Вентили вызова позволяют автоматически копировать заданное число слов из старого стека в новый. Вентили прерываний отличаются от вентилей ловушек только тем, что они запрещают прерывания (сбрасывают IF), а вентили ловушек не запрещают. Для каждого типа вентилей используются соответствующие дескрипторы вентилей (Gate Descriptors).

В байте управления доступом у этих дескрипторов бит S==0. Бит Р определяет действительность (P=l) или недействительность (Р=0) содержимого сегмента. Поле DPL задает уровень привилегий. Поле TYPE (4-7) определяет тип вентиля:

4 — вентиль вызова 80286 (Call Gate),

5 — вентиль задачи 80286 (Task Gate),

6 — вентиль прерывания 80286 (Interrupt Gate),

7 — вентиль ловушки 80286 (Trap Gate),

С — вентиль вызова 386+ (Call Gate),

D — вентиль задачи 386+ (Task Gate),

E — вентиль прерывания 386+ (Interrupt Gate),

F — вентиль ловушки 386+ (Trap Gate).

Поле WORD COUNT используется только в ключах вызовов и определяет число слов из стека вызывающего процесса, автоматически копируемых в стек вызываемой процедуры. Для сегментов 80286 слова 16-битные, для 386+ слова 32-битные.

Слово DESTINATION SELECTOR для вентилей вызова, прерываний и ловушек задает селектор целевого сегмента кода, а для вентиля задачи — селектор целевого TSS.

Слово DESTINATION OFFSET задает смещение (адрес) точки входа в целевом сегменте.

При использовании вентилей может возникнуть исключение 13, которое означает, что селектор указывает на некорректный тип дескриптора. При попытке использования недействительного вентиля (Р=0, 8) возникает исключение 11.

 

Категория: