
- •3. Работа процессоров в защищенном и реальном режимах
- •3.1 Сегментация памяти в защищенном режиме
- •3.2. Страничная организация памяти
- •3.3. Защита памяти
- •3.4. Многозадачность
- •3.13. Структура сегмента tss
- •3.5. Реализация режима виртуального 8086 (v86)
- •3.6. Функционирование процессора в реальном режиме
- •4. Реализация прерываний и исключений. Обеспечение тестирования и
- •4.1. Виды прерываний и исключений, реализация их обслуживания
- •4.2. Обработка прерываний в реальном и защищенном режимах
- •4.3. Причины возникновения исключений [1,4]
- •4.4. Реализация и обслуживание виртуальных прерываний
- •4.5. Реализация прерываний в мультипроцессорных системах
- •4.6. Средства обеспечения отладки
- •4.7. Реализация тестирования и контроля функционирования
- •5. Режим системного управления работой процессора. Инициализация, мониторинг производительности и обмен по системной шине
- •5.1. Режим системного управления (smm)
- •5.2. Инициализация и реализация энергосберегающих режимов
- •5.3. Метки реального времени и мониторинг производительности
- •Оглавление
3. Работа процессоров в защищенном и реальном режимах
Процессоры семейства Р6, Р7 как и другие микропроцессоры 80x86, имеют два основных рабочих режима: защищенный и реальный.
Наиболее полно возможности процессора реализуются при работе в защищенном режиме. При этом обеспечивается физическая адресация памяти объемом до 2 32 =4 Гбайт и доступ к виртуальной памяти объемом до 2 46 =64 Гбайт. Помимо сегментации памяти в защищенном режиме может быть реализована страничная организация. Этот режим позволяет использовать дополнительные команды, введенные для поддержки многозадачных операционных систем. Кроме того, обеспечивается защита пользовательских программ друг от друга и от операционной системы, предотвращающая возможное взаимное вмешательство в их работу.
При работе в реальном режиме возможности микропроцессора существенно ограничиваются: сокращается до 1 Мбайт объем адресуемой памяти, исключаются основные механизмы защиты, не реализуется страничная организация памяти и многозадачное функционирование систем. Этот режим обычно используется либо как промежуточный для перехода в защищенный режим после инициализации микропроцессорной системы, либо для более быстрого выполнения программ, написанных для микропроцессоров 8086, 80186. По сравнению с ними процессоры Р6 в реальном режиме имеют более широкий набор выполняемых команд и обеспечивают обработку 32-разрядных операндов.
Быстрое выполнение программ, написанных для микропроцессоров 8086, вместе с обеспечением защиты памяти, страничной организации и многозадачности достигается при работе процессора в режиме виртуального 8086, который является вариантом защищенного режима.
В настоящей главе подробно рассматривается функционирование процессоров Р6 в защищенном режиме (сегментация, страничная организация памяти, многозадачность), особенности реализации реального режима и режима виртуального 8086.
3.1 Сегментация памяти в защищенном режиме
При работе процессора в защищенном режиме каждый из сегментов команд, данных, стека характеризуется соответствующими параметрами, которые определяют локализацию данного сегмента в общем пространстве адресуемой памяти и правила обращения к нему. Параметры сегмента представляются в виде 8-байтной структуры данных, называемой дескриптором. При адресации памяти процессор использует дескриптор для того, чтобы определить разрешено ли обращение к данному сегменту, вычислить адрес ячейки памяти и проверить, находится ли этот адрес в пределах выбранного сегмента.
Дескрипторы сегментов хранятся в памяти в виде массивов данных, которые сформированы в виде таблиц. Таблицы могут иметь размеры от 8 байт до 64 Кбайт, то есть содержать до 8192 дескрипторов. Имеется три типа таблиц дескрипторов:
• GDT - глобальная таблица дескрипторов;
• LDT - локальная таблица дескрипторов;
• IDT - таблица дескрипторов прерываний.
Таблица GDT содержит дескрипторы, которые могут использоваться системой при выполнении различных задач. Таблицы LDT содержат дескрипторы сегментов, используемых при решении данной задачи. Количество создаваемых таблиц LDT определяется операционной системой и зависит от числа выполняемых задач. Общее количество таблиц LDT может достигать 8192. В принципе, каждая задача может иметь отдельную LDT, которая включает дескрипторы сегментов, используемых при ее решении. В случае совместного использования сегментов таблицы LDT могут полностью или частично перекрывать друг друга. Таблица IDT обеспечивает выполнение процедур обслуживания исключений (прерываний). В данной главе описывается адресация памяти в защищенном режиме, которая обеспечивается с помощью таблиц GDT и LDT.
Обращение к необходимому дескриптору в таблице осуществляется с помощью селектора, загружаемого в соответствующий сегментный регистр: СS, DS, SS, ЕS, FS или GS. Селектор представляет собой 16-разрядный указатель, который имеет три поля (рис. 3.1).
Поле RPL (биты 0-1) определяет уровень привилегий запроса (request privilege level). Это двухразрядный код, указывающий допустимый уровень защиты сегмента, который может быть выбран с помощью данного селектора.
Поле TI (бит 2) служит индикатором таблицы. Его значение указывает выбираемую таблицу: GDT при TI = 0, LDT при TI = 1.
Поле INDEX (биты 3-15) служит индексом для выбора одного из 8192 дескрипторов, содержащихся в таблице.
15 3 2 1 0
INDEX |
TI |
RPL |
Рис. 3.1. Формат селектора
Каждой из таблиц GDT, LDT, IDT соответствует определенный регистр: GDTR, LDTR, IDTR.
Регистр GDTR содержит 48 разрядов (см. рис.1.6), из которых 32 старших разряда задают базовый адрес таблицы дескрипторов, а 16 младших разрядов указывают границу таблицы.
Регистр LDTR (см. рис.1.6) содержит 16-разрядный селектор, определяющий размещение в GDT дескриптора используемой таблицы LDT. Поле INDEX в этом указателе содержит смещение, которое используется для формирования адреса дескриптора таблицы LDT, выбираемого из GDT. Дескриптор LDT содержит 32-разрядный базовый адрес используемой LDT, ее 16-разрядную границу и атрибуты, определяющие права доступа к таблице. При загрузке в LDTR селектора таблицы LDT соответствующий дескриптор выбирается из GDT и хранится во внутреннем программно недоступном регистре процессора — "теневом" регистре LDTR (рис.3.2).
Рис 3.2. Выборка дескрипторов из таблиц GDT и LDT
Загрузка регистров GDTR, LDTR из памяти, а также сохранение в памяти их содержимого реализуется с помощью команд LGTR, LLDT и SGDT, SLDT. Загрузка селекторов в регистры сегментов данных DS, ES, FS, GS, SS производится командами LDS, LES, LFS, LGS, LSS. Регистр СS является программно недоступным, поэтому прямая загрузка в него (или выгрузка) селекторов для выбора сегментов программ невозможна. Начальное содержимое СS устанавливается при инициализации системы и затем изменяется программно при выполнении команд межсегментных вызовов и переходов CALL, JUMP и при переключении задач.
Если селектор, загруженный в сегментный регистр CS, SS, DS, ES, FS или GS, обращается к таблице GDT (бит ТI=0) или LDT (бит TI=1), то его индекс, служит в качестве относительного адреса (смещения) для формирования адреса дескриптора в данной таблице (рис.3.2). При этом индекс сдвигается на три разряда влево, то есть умножается на 8 (на число байтов в дескрипторе). Это смещение сравнивается с границей таблицы, хранящейся в GDTR или "теневом" регистре LDTR. Если смещение превышает границу, то есть выходит за пределы таблицы GDTR, то вырабатывается прерывание типа #GP ("нарушение защиты"). Если нарушения границы нет, то смещение прибавляется к содержащемуся в GDTR базовому адресу, в результате чего образуется адрес младшего байта выбираемого дескриптора. При обращении к таблице LDTR проверяются также права доступа к данной таблице, которые устанавливаются так же, как для выбираемых сегментов.
Селектор с нулевым значением полей INDEX и TI (разряды 2-15, рис.3.1) называется нуль индикатором. Он обеспечивает обращение к первому дескриптору в таблице GDT (нуль-дескриптор). Загрузка такого селектора в регистр СS или SS для выборки сегмента команд или стека вызывает исключение типа #GP ("нарушение общей защиты"). Так как при инициализации системы обычно производится установка нулевых начальных значений дескрипторов и селекторов, то данное исключение предотвращает возможность запуска рабочих программ до загрузки операционной системой необходимых сегментов и дескрипторов.
Таким образом, в защищенном режиме программно задается логический адрес ячеек памяти, хранящих команды или данные, который состоит из селектора и относительного адреса. С помощью селектора и таблиц GDT, LDT процессор производит выборку соответствующего дескриптора. Затем формируется линейный адрес ячейки памяти путем сложения базового адреса, содержащегося в дескрипторе, и относительного адреса, образуемого в соответствии с используемым способом адресации (рис. 3.3). Линейный адрес определяет местоположение ячейки в линейном адресном пространстве, которое может быть разбито на отдельные страницы при введении страничной организации памяти.
Если при работе процессора не используется страничная организация памяти (бит 32 в регистре управления CR0.РG=0), то полученный линейный адрес является физическим адресом для выбора требуемой ячейки памяти.
При выполнении программ, написанных для процессоров 80386, 80486, Pentium, Р6,P7 базовый и относительный адреса содержат по 32 разряда. При работе в режиме виртуального 8086 в качестве базового адреса используется селектор, сдвинутый влево на 4 разряда. Таким образом, базовый адрес имеет 20 разрядов. В этом режиме используется 16-разрядный относительный адрес, а формируемый линейный адрес содержит 20 разрядов.
Иногда при работе микропроцессорной системы сегментации памяти не требуется. В этом случае необходимо загрузить все регистры сегментов селекторами дескрипторов, имеющих нулевые базовые адреса и задающие размеры сегментов по 4 Гбайт. В результате каждый из сегментов использует полное адресное пространство, то есть сегментация подавляется. При этом может быть реализована страничная организация памяти.
Рис 3,3 Формирование линейного адреса
В таблицах GDT, LDT могут размещаться следующие виды дескрипторов: дескрипторы сегментов команд, дескрипторы сегментов данных, системные дескрипторы.
Формат дескриптора (в общем виде) представлен на рис. 3.4, где 32-разрядный базовый адрес сегмента (база ВА31-0) и 20-разрядная граница сегмента (L19-0) размещены по частям в различных байтах дескриптора.
Граница сегмента L указывает максимальное допустимое значение относительного адреса, которое может использоваться при обращении к сегменту. Величина (L+1) определяет размер сегмента в байтах или страницах. Обращение к ячейке памяти, находящейся за границей данного сегмента, вызывает исключение типа #GP.
Помимо базового адреса и границы сегмента дескрипторы задают ряд других важных его атрибутов, состав которых зависит от вида сегмента. Отдельные биты байта 6 дескриптора определяют следующие атрибуты сегмента.
Байт 8 Байт 7 Байт 6 Байт 5
31 24 23 22 21 20 19 16 15 14 13 12 11 8 7 0
Базовый Адрес ВА31-24 |
G |
D / B |
0 |
A V L |
Граница L19-16 |
P |
DPL |
S |
TYPE |
Базовый Адрес ВА2316 |
Базовый адрес ВА15-0 |
Граница сегмента L15-0 |
Рис.3.4. Общий формат дескриптора
Бит дробности G указывает, в каких единицах задан размер сегмента: в байтах при G=0 или страницах объемом по 4 Кбайт при G=1.
Таким образом, сегмент может иметь размер до 2 20 =1 Мбайт при
G=0 или до 2 32 =4 Гбайта при G=1.
Бит разрядности по умолчанию D/B для сегментов команд определяет разрядность формируемого относительного адреса и выбираемого операнда: 16 разрядов при D/В=0, 32 разряда при D/В=1. Если производится обращение к сегменту стека (при выполнении команд типа РUSН, РОР, CALL), то при D/В=0 используется регистр SР и 16-разрядные, а при D/В=1 — регистр ЕSР и 32-разрядные данные. Для расширяемых вниз сегментов данных (сегменты со стековой адресацией) бит D/В определяет их верхнюю границу: М=FFFFh при D/В=0 или М=FFFFFFFFh при D/В=1. Для системных дескрипторов этот бит должен иметь нулевое значение.
Бит 5 в байте 6 всегда должен иметь нулевое значение, а бит 4
(AVL) может принимать значение, устанавливаемое пользователем или
операционной системой.
Байт 5 дескриптора определяет права доступа к выбираемому сегменту. В зависимости от вида сегмента байт доступа имеет различные форматы (рис. 3.5), хотя назначение ряда полей (битов) остается одинаковым. Одинаковое назначение имеют следующие биты и поля.
Бит присутствия Р определяет наличие соответствующего сегмента в памяти. Если Р=0 (сегмент отсутствует), то данный дескриптор не используется для формирования адресов, то есть соответствующие байты дескриптора не загружаются в регистры, хранящие базовый адрес и размер сегмента. Поэтому содержимое этих байтов может быть установлено произвольно. Если в регистр сегмента поступает селектор дескриптора, имеющего Р=0, то процессор переходит к обработке соответствующего исключения #NР ("отсутствие сегмента").
Поле DPL. (биты 6-5) указывает уровень защиты сегмента (уровень привилегий дескриптора). В зависимости от соотношения значений DPL и RPL задаваемого в младших битах селектора (рис. 3.1), разрешается или запрещается обращение к данному сегменту. Таким образом, обеспечивается требуемый уровень защиты сегмента.
Системный бит S определяет вид выбираемого сегмента . При S=1 дескриптор обеспечивает обращение к сегментам программ (кодов) или данных (включая стек). Системные дескрипторы, имеющие значение S=0, служат для обращения к таблицам LDT, сегментам состояния задачи ТSS или шлюзам для входа в другие задачи или программы, включая программы обслуживания исключений и прерываний.
Форматы байта доступа для дескрипторов сегментов программ и данных (рис. 3.5,а,б) отличаются значениями бита 3, который имеет значение "1" для сегментов программ и "0" для сегментов данных.
a)
7 6 5 4 3 2 1 0
P |
DPL |
S=1 |
1 |
C |
R |
A |
б)
7 6 5 4 3 2 1 0
P |
DPL |
S=1 |
0 |
E |
W |
A |
в)
7 6 5 4 3 0
P |
DPL |
S=1 |
TYPE |
Рис. 3.5. Формат байта доступа для дескрипторов сегментов
Программ (а), данных (б) и системных дескрипторов (в).
Бит обращения А устанавливается в единицу при обращении к сегменту, то есть при загрузке соответствующего селектора в сегментный регистр. Этот бит периодически проверяется операционной системой, реализующей виртуальную память, которая таким образом выявляет невостребованные сегменты, имеющие А=0. Сегменты, долгое время остающиеся невостребованными, выводятся из оперативной памяти на магнитный диск, освобождая место для других сегментов.
Назначение битов 1 и 2 байта доступа зависит от типа сегмента.
Бит разрешения считывания R вводится для сегмента программ и разрешает при R=1 производить считывание его содержимого. При R=0 допускается только выборка содержимого этого сегмента для выполнения через регистр СS. Попытка считывания сегмента в этом случае вызовет исключение типа #GP. Отметим, что прерывание этого типа возникает также при попытке записи в сегмент программ независимо от значения бита R. Таким образом, запрещается запись в сегмент программ. Если возникает необходимость внести изменение в этот сегмент, то можно создать сегмент данных с разрешением записи (W=1), занимающий то же адресное пространство, что и модифицируемый сегмент программ. После внесения изменений в созданный сегмент данных можно обратиться к нему как к сегменту программ, загрузив селектор этого сегмента в регистр СS.
Бит подчиненности С определяет дополнительные правила обращения, которые обеспечивают защиту сегментов программ: при С=0 обращение к данному сегменту разрешается только программам, имеющим уровень привилегии CPL (значение поля RPL в регистре CS) такой же, как значение поля DPL в дескрипторе сегмента; при С=1 допускается обращение к данному сегменту программ, имеющих CPL>=DPL.
Бит разрешения записи W вводится для сегментов данных.
Разрешает (при W=1) или запрещает (при W=0) изменение содержимого этих сегментов. При W=0 разрешается только считывание данных, а при попытке записи реализуется исключение типа #GP.
Бит направления расширения Е определяет размещение сегмента данных относительно заданной границы сегмента. При Е=0 (расширение вверх) данные в сегменте размещаются от базового адреса ВА, задающего нижний предел сегмента до верхнего предела, определяемого суммой базового адреса и границы сегмента: (ВА+L). Таким образом, сегмент размещается вниз от границы — в направлении уменьшения адресов до базового.
При Е=1 (расширение вниз) данные располагаются, начиная с адреса (ВА+L+1), определяющего нижний предел сегмента. Остальные ячейки размещаются в направлении возрастания адресов (вниз от границы) до верхнего предела, задаваемого адресом (ВА+М). Верхний предел сегмента в этом случае равен базовому адресу, увеличенному на М=FFFFh (размер сегмента до 64 Кбайт) или на М=FFFFFFFFh (размер сегмента до 4 Гбайт) в зависимости от значения бита разрядности D/В в байте 6 дескриптора (рис.3.4). Размер сегмента будет равен (М-L), и его максимальное значение достигается, когда заданная граница L=0. Отметим, что для сегментов с расширением вниз значения битов дробности и разрядности должны быть равными: G = D/В.
Таким образом, при расширении вверх (бит Е=0) относительный адрес выбираемой ячейки должен быть меньше или равен границе сегмента, при расширении вниз (бит Е=1) относительный адрес должен быть
больше границы сегмента.
Формат байта доступа для системных дескрипторов (S=0) приведен на рис. 3.5,в. Поле ТУРЕ определяет тип системного дескриптора в соответствии с табл. 3.1. Можно выделить три основных класса системных дескрипторов.
Дескрипторы таблиц LDT обеспечивают обращение к локальной таблице дескрипторов для выбора сегментов, используемых при выполнении текущей программы.
Дескрипторы сегментов ТSS используются при переключении задач в многозадачном режиме. При этом бит 3 поля ТУРЕ байта доступа указывает, решается ли вызываемая задача с использованием 16- или 32-разрядных адресов и данных. Бит В в байте доступа сегмента ТSS называется битом занятости и указывает является ли вызываемый сегмент занятым (соответствующая задача находится в процессе выполнения) или доступным (задача еще не поступила на выполнение). Переключение на занятую задачу вызывает исключение типа #GР ("нарушение защиты"). Отметим, что дескрипторы LDT и ТSS всегда должны иметь значение бита разрядности D/В=0 (рис. 3.4).
Таблица 3.1. Типы системных дескрипторов
-
TYPE
Тип системного дескриптора
0000
0001
0010
0011
0100
0101
0110
0111
1000
1001
1010
1011
1100
1101
1110
1111
Резервировано
TSS, 16-разр.(доступен)
LDT
TSS, 16-разр.(занят)
Шлюз вызова подпрограммы 16-разр.
Шлюз вызова задачи
Шлюз вызова прерываний 16-разр.
Шлюз вызова ловушки, 16-разр.
Резервировано
TSS, 32-разр.(доступен)
Резервировано
TSS, 32-разр.(занят)
Шлюз вызова подпрограммы, 32-разр.
Резервировано
Шлюз вызова прерываний, 32-разр.
Шлюз вызова ловушки, 32-разр.
Дескрипторы шлюзов используются для реализации специальных правил доступа при обращении к программам и задачам, а также при обработке прерываний и ловушек
Дескрипторы сегментов, использующих 16-разрядные адреса и операнды при размере сегментов до 1 Мбайт (значения битов G=D/В=0) , имеют нулевые значения байтов 5 и 6 дескриптора (рис.3.4). Такие дескрипторы использовались в 16-разрядных микропроцессорах 80286. Остальные биты и поля дескрипторов для процессоров 80286 полностью соответствуют форматам, приведенным на рис.3.4, 3.5. Поэтому процессоры семейства Р6, как и более ранние модели, обеспечивают полную программную совместимость с 16-разрядным микропроцессором 80286, выполняя сегменты команд (программы), написанные для 80286, без какой-либо модификации. Отличие состоит только в разрядности базового адреса, которая для 80286 равна 24 битам (ВА23-0 в байтах 2, 3, 4 дескриптора), и границе сегмента, которая не должна превышать 64 Кбайт (L15-0 в байтах О, 1 дескриптора). Дробность и разрядность для этих сегментов устанавливается байтами G, D/В дескриптора, которые имеют нулевое значение.
Если системные дескрипторы имеют нулевые значения старших байтов 6,7 дескриптора (дескрипторы, аналогичные используемым для процессора 80286), то старший бит в поле ТУРЕ байта доступа (рис.3.5,в) всегда должен иметь нулевое значение. При этом допускается использование только тех типов системных дескрипторов, которые указаны в восьми верхних строках табл.3.1.