Protected Mode
Содержание
Node:Top,
Next:Introduction,
Up:(dir)
Содержание
Этот документ возник в результате DJGPP e-mail-подписки "protected mode".
Документ включает детальную информацию о защищенном режиме.
Node:Introduction,
Next:RM Addressing,
Previous:Top,
Up:Top
1 Введение в защищенный режим
Node:Quick look,
Next:Advantages,
Up:Introduction
1.1 Краткий обзор Protected Mode
Что такое Защищенный Режим?
80386+ обеспечивает такие фичи , как защита памяти , виртуальная память ,
многозадачность , совместимость с предыдущими версиями процессоров .
8086 работает только в одном режиме - реальном. При разработке 286
инженеры интел хотели убить 2 зайцев - обеспечить совместимость с 8086
и придать ему новые преимущества.
Поэтому 286 поддерживает 2 режима - реальный и защищенный.
Программы , разработанные для 8086 , не могут работать в защищенном режиме.
386 имеет все преимущества 8086 и 286 и новые качества.
Режим по умолчанию остается прежним - реальный.
Защищенный режим 386 имеет отличия.
Он лучше защищен , чем в 286.
Он также поддерживает 3-й режим - Virtual 8086 (V86) mode.
В V86 mode программы , выполняемые в защищенном режиме , могут симулировать реальный режим.
Это позволяет например досовским программам работать в защищенном режиме
в обычном порядке .
Node:Advantages,
Previous:Quick look,
Up:Introduction
1.2 Преимущества использования Protected Mode
Доступ к 4 гигам памяти -
Это наиболее существенная разница между защищенным и реальным режимом.
Виртуальная память -
Специальный модуль - Memory Management Unit (MMU) на 386
реализует механизм виртуальной памяти.
Трансляция адресов -
Блок MMU транслирует реальные физические адреса.
Например , вам нужно скопировать адреса в видео-памяти начиная с сегмента
800H (CGA) в буффер данных вашей программы,а потом скопировать их обратно.
Программы работают с логическими адресами.
386 конвертирует их в 32-битные линейные (не-сегментная адресация).
Затем MMU конвертирует эти линейные адреса в физические.
Если рассматривать реальный режим , то например :
адрес B800:0010 - это логический адрес , тогда линейный адрес - это B8010H ,
в реальном режиме он же есть и физический , поскольку здесь MMU не работает.
Улучшенная сегментация -
В реальном режиме все сегменты - 64-килобитные и порядок расположения у них фиксированный.
В защищенном режиме сегмент может состоять из одного байта , а может быть быть и на 4 гига.
Сегменты могут начинаться с произвольного адреса.
Программист обязан здесь указывать назначение каждого сегмента.
Если программа попытается записать данные в сегмент кода , будет сгенерирована ошибка.
Защита памяти -
В 386 память защищена.Например , пользовательский процесс не в состоянии что-либо записать
в память , которую использует сама операционная система.
Защита на уровне процессов -
Программы могут быть защищены относительно друг друга.
Они не имеют доступа к данным друг друга , в то время как операционная система имеет
доступ ко всем процессам.
32-битные регистры -
Основные регистры в 386 теперь 32-битные.К имени регистра добавляется префикс Е.
Добавлены 2 новых сегментных регистра - FS и GS.
Программы реального режима могут также использовать 32-битные регистры ,
но не могут использовать их для индексации.
Использование 32-битных регистров само по себе делает код более компактным,
оптимизируя его по размеру.
Режимы адресации -
В реальном режиме адреса можно формировать с помощью 4-х регистров -BX,BP,SI,DI.
В защищенном режиме любой регистр может быть адресом.
Индекс может быть смасштабирован как 2.4 или 8-кратный.
Что позволяет писать что-то типа :
MOV EBX,[EDI][EAX*8]+2.
Многозадачность -
386 может делать одномоментный слепок состояния своих регистров
и переключиться на другую задачу - context switch.
И делает его всего одна инструкция.
Hardware debugging -
386 может реализовать пошаговый break-point кода и данных.
Node:RM Addressing,
Next:80386 Registers,
Previous:Introduction,
Up:Top
2 Адресация в Real Mode
В 8086 память организована побайтно.
Если число бит не кратно 8 и равно например 2 байтам ,
то информация будет храниться так : младший байт будет сохранен в младшем по адресу байте памяти.
Т.е. например слово B800H : сначала 00H , потом B8H.
Интеловские процессоры используют сегментированную модель памяти.
Сегмент - кусок памяти. Сегментов может быть много.
В реальном режиме каждый сегмент по размеру равен 64 кб ,
и всего их может быть 65536 штук.
Адрес каждого сегмента тут кратен 16 байтам , поэтому общее количество памяти
не может быть более меетра - 65536 * 16 = 1048576 = 1MB.
И 8086 и 8088 имею всего 1MB адресов.
286, 386+ могут иметь больше , но 286 не ко всем имеет прямой доступ.
Сегменты пронумерованы - от 0000H до FFFFH.
Поскольку размер сегмента фиксирован , нам достаточно знать смещение - offset -
для определения адресного байта.
В 8086 полный адрес состоит из сегмента и смещения.
Если например сегмент 0040H и смещение 0102H,
мы пишем 0040:0102.
Поскольку сегмент кратен 16 байтам (10H) ,
адрес 0000:0010 идентичен 0001:0000.
Сегментный адрес хранится в перервернутом виде - например , 0040:1234 :
34 12 40 00
Для конвертации сегментного адреса в линейный нужно умножить значение сегмента на 16
(10H) и добавить смещение :
0040 * 10 + 0000 = 00400
0000 * 0 + 0400 = 00400
0020 * 10 + 0200 = 00400
В данном случае мы имеем дело с одним и тем же адресом.
Node:80386 Registers,
Next:RM Vector Table,
Previous:RM Addressing,
Up:Top
3 Регистры в 80386
386 имеет 4 основных регистра , флаговый , 6 сегментных , 2 индексных ,
2 стековых , базовый , указатель на текущую команду.
Также имеются :
GDTR (Global Descriptor Table Register)
IDTR (Interrupt Descriptor Table Register)
LDTR (Local Descriptor Table Register)
TR (Task Register)
CR0-CR3 (Control Registers)
DR0-DR7 (Debug Registers)
Следующая картинка показывает их отличия .
Node:RM Vector Table,
Next:Hardware Interrupts,
Previous:80386 Registers,
Up:Top
4 Real Mode Vector Table
8086 имеет 256 прерываний. Их адреса расположены в памяти начиная с адреса 0000:0000
в специальной таблице прерываний.
Каждый адрес в этой таблице имеет длину 4 байта ,
куда умещается сегмент+смещение.
На таблицу прерываний отведено 1024 байта - 1 килобайт.
Если процессор получает например 2-е прерывание (INT 2),
происходит следующее:записывается специальный флаг ,
регистры CS и IP пишутся в стек ,
берется адрес в ячейке 0000:0008 и выполняется процедура прерывания ISR по этому адресу ,
после чего оттуда происходит возврат в результате команды IRET.
Node:Hardware Interrupts,
Next:Keyboard,
Previous:RM Vector Table,
Up:Top
5 Hardware Interrupts
hardware interrupt - специальный сигнал от I/O-устройства процессору.
Процессор немедленно останавливается и начинает обрабатывать прерывание.
После обработки команды возобновляются.
Такие прерывания могут прийти от различных устройств.
Например , отклавиатуры , часов , принтера , портов , диска и т.д.
Некоторые прерывания может генерировать сам процессор.
Например INT 0 возникает при делении на ноль.
Программируемый контролер - 8259 Programmable Interrupt Controller (PIC)
обслуживает все hardware interruptrs.
Таблица ниже показывает hardware interrupts для реального режима и соответствующие
генерируемые PIC interrupt request inputs (IRQ).
Стандартные номера IRQ не совпадают с номерами прерываний.
Их можно вообще по-своему перепрограммировать .
PIC также контролирует приоритет прерываний.
Например , часы (IRQ 0) имеют наивысший приоритет, чем клавиатура (IRQ 1).
Схема приоритетов может быть перепрограммирована.
Interrupt | IRQ Number | Description
| 00H | - | Divide by zero or divide overflow
| 02H | - | NMI (Non-maskable Interrupt)
| 04H | - | Overflow (generated by INTO)
| 08H | 0 | System timer
| 09H | 1 | Keyboard
| 0AH | 2 | Interrupt from second PIC
| 0BH | 3 | COM2
| 0CH | 4 | COM1
| 0DH | 5 | LPT2
| 0EH | 6 | Floppy Disk
| 0FH | 7 | LPT1
| 70H | 8 | Real Time Clock
| 71H | 9 | General I/O
| 72H | 10 | General I/O
| 73H | 11 | General I/O
| 74H | 12 | General I/O
| 75H | 13 | Coprocessor
| 76H | 14 | Hard Disk
| 77H | 15 | General I/O
|
Прерывания можно запретить с помощтю команды CLI
Node:Keyboard,
Next:Selectors and Descriptors,
Previous:Hardware Interrupts,
Up:Top
6 Клавиатура и A20
Исторически так повелось , что AT-шные материнские платы реализовали шину A20
через контроллер клавиатуры . Контроллер блокирует эту шину.
Разблокировать или заблокировать ее можно специальной командой.
Доступ к расширенной памяти доступен через гейт A20 независимо от того ,
в реальном мы режиме или защищенном.
Node:Selectors and Descriptors,
Next:Protected Mode Privileges,
Previous:Keyboard,
Up:Top
7 Селекторы и дескрипторы
Node:Segment Selectors,
Next:Tables,
Up:Selectors and Descriptors
7.1 Селекторы
Сегменты - ключ к понимаю защищенного режима.
Сегментные селекторы в защищенном режиме имеют 16-битную длину.
Селектор в защищенном режиме - это не адрес самого сегмента ,
это смещение в таблице.
Значение селектора , хранящееся в регистре , есть индекс в таблице сегментных дескрипторов.
Каждый дескриптор определяет один сегмент , его тип и другие парметры сегмента.
Селектор включает 3 специальных поля.
Нижние 2 бита (RPL) отвечают за механизм защиты.
Следующий бит - TI, определяет саму таблицу дескрипторов.
3 сегментных таблицы:
- Global Descriptor Table (GDT)
- Interrupt Descriptor Table (IDT)
- Local Descriptor Table (LDT)
Сегментный селектор может ссылаться либо на GDT , либо на LDT , но не на IDT.
Если TI = 0 - это таблица GDT. Если TI = 1 - LDT .
Node:Tables,
Next:Descriptors,
Previous:Segment Selectors,
Up:Selectors and Descriptors
7.2 Таблицы в Protected Mode
Любая дескрипторная таблица может хранить 8192 дескрипторов. Индексные биты - INDEX -
(биты с 15 по 3) в селекторе определяют дескриптор.
Регистры GDTR и IDTR определяют расположение таблиц GDT и IDT.
Он состоит из 32-битного адреса и 16-битного ограничения.
Т.е. эти 2 регистра 48-битные.
GDT - единая глобальная таблица для всех процессов.
Регистр LDTR определяет расположение LDT.
В отличие от GDT, каждая задача имеет свою собственную LDT.
В LDTR сегментный сеектор глобальной таблицы , который указывает на LDT.
Таблица прерываний IDT в защищенном режиме аналогична таблице прерываний в реальном режиме.
Как правило , она состоит из 256 прерываний.
Следующий рисунок показывает формат дескрипторной таблицы.
Node:Descriptors,
Previous:Tables,
Up:Selectors and Descriptors
7.3 Дескрипторы
В сегментном дескрипторе представляют интерес бит P (bit 47) , в случае если он равен нулю , означает создание виртуального сегмента.
Если программа попытается его использовать,возникнет ошибка.
После этого операционная система загружает сегмент с диска.
Если бит Р=0 , биты 0-39 48-63 могут иметь произвольные значения.
Другой интересный бит - A (bit 40).
Если он равен 1 , значит в сегмент можно писать.
Для определения размера сегмента используется бит G (bit 55).
Если бит G равен нулю , сегмент может иметь размер от одного байта до одного метра.
Если бит G равен 1 , сегмент может иметь размер от 4 килобайт до 4 гигабайт.
Можно создать 2 дескриптора , которые указывают на одну и ту же область памяти.
Например , можно загрузить данные сегмент и стартовать с него же.
Такой процесс называется aliasing.
Первый слот в GDT зарезервирован. Это нулевой селектор.
Node:Protected Mode Privileges,
Next:Multitasking,
Previous:Selectors and Descriptors,
Up:Top
8 Привилегии защищенного режима
Каждая программа имеет свой уровень привилегии - PL, от 0 до 3.
Уровень PL0 позволяет выполнять любой код и иметь доступ к любым данным.
Уровень PL3 не может выполнять определенные инструкции и иметь доступ к данным
более привилегированных программ. Каждый дескриптор имеет свой
Descriptor Privilege Level (DPL).
Иерархия привилегий очень важна в современных операционных системах.
В них ядро как правило выполняется с уровнем PL0.
Некоторые части операционной системы могут работать с уровнем PL1.
Драйвера могут работать в PL2.
Пользовательские программы работают в PL3.
Уровень PL0 может выполнить следующие инструкции:
•HLT
•CLTS
•LGDT
•LIDT
•LLDT
•LTR
•LMSW
•MOV (to/from control/debug/test registers)
На 486 :
•INVD
•WBINVD
•INVLPG
На Pentium и выше :
•RDMSR
•WRMSR
•RDTSC
Поле IOPL (2 бита) флагового регистра позволяет операционной системе контролировать I/O.
Если IOPL=0 , только PL0 может выполнять I/O.
Если IOPL=3 , все программы могут выполнять I/O.
Только PL0 может модифицировать IOPL.
Уровень привилегий программы эквивалентен селекторному полю RPL регистра CS.
Модифицировать это поле из программы нельзя.
8.1 Доступ к данным
При загрузке сегментов данных (DS, ES, FS or GS) проверяются поля DPL , CPL , RPL.
При загрузке регистра SS поля DPL и CPL должны быть равны.
Node:Multitasking,
Next:Exceptions,
Previous:Protected Mode Privileges,
Up:Top
9 Многозадачность
На самом деле программы выполняются не одновременно , а последовательно.
Для поддержки многозадачности используется регистр Task State Segments (TSS) .
Он указывает на буфер , который должен быть как минимум разамеров 104 байта.
Он также может быть использован для прерываний.
TSS оперирует с GDT.
В этом буфере хранится содержимое регистров при переключении задач.
Процесс записи и чтения содержимого регистров из этого буфера критичен по времени
и потому очень быстр.
386 поддерживает т.н. nested tasks.
Для их управления используется бит NT флагового регистра.
При вызове "calls" селектор TSS вызываемой задачи сохраняется
в специальном поле , при этом бит NT=1.
При возвращении срабатывает инструкция IRET.
Имеется указатель на область памяти обьемом 8К - I/O bitmap.
Каждый бит в нем соответствует порту I/O.
Если задача пытается сделать I/O , проверяются CPL и IOPL.
Если CPL меньше или равно IOPL , прерывание разрешено.
В противном случае происходит проверка бита.
Если бит равен нулю,доступ к порту разрешен.
bitmap должен оканчиваться на 0FFh.
Node:Exceptions,
Next:MMU,
Previous:Multitasking,
Up:Top
10 Исключения 80386
386 поддерживает 256 прерываний. Таблица IDT может иметь их 8192.
IDT может включать trap gates, interrupt gates , task gates.
trap gate срабатывает при возникновении исключения.
interrupt gate отключает остальные прерывания.
Прерывания могут быть вызваны со стороны PIC.
Прерывания также могут быть сгенерированы процессором.
Процессор генерирует 386 исключений , которые могут быть классифицированы как
faults, traps , aborts.
fault - несмертельная исправляемая ошибка.При этом CS:EIP указывает на инструкцию,
которая вызвала fault. Большинство faults известны как "General Protection Fault (GPF)".
Trap как правило вызывается софтом.
В основном это инструкции INT и INTO.
Abort - серьезная ошибка. Например Double Fault и FPU Overrun - это aborts.
Таблица исключений:
Exception (#num) Type
| Divide Error (0) Fault
| Debug (1) F/Trap
| Breakpoint (3) Trap
| Overflow (4) Trap
| Bounds Check (5) Fault
| Bad Opcode (6) Fault
| No Coprocessor (7) Fault
| Double Fault (8) Abort
| Coprocessor Overrun (9) Abort
| Invalid TSS Segment (0A) Fault
| Segment not Present (0B) Fault
| Stack Fault (0C) Fault
| General Protection Fault (0D) Fault
| Page Fault (0E) Fault
| Coprocessor Error (10) Fault
|
Node:MMU,
Next:V86 Mode,
Previous:Exceptions,
Up:Top
11 Memory Management Unit (MMU)
386 имеет 2 фичи для управления памятью :
- Segmentation
- Paging
Paging позволяет реализовать механизм
виртуальной памяти , который используется большинством операционных систем.
Для реализации paging, нужно установить бит 31 регистра CR0.
Также необходимо проинициализировать Page Directory Entries и Page Table Entries,
PDEs и PTEs.
PDEs и PTEs - это таблицы для конвертации логических адресов в физические.
Только уровень PL0 может активизировать MMU.
Пользовательские программы о существовании MMU не знают.
MMU использует 2 типа таблиц для перевода адресов - Page Directory Entry и Page table Entries.
Одна PDE соответствует 4 метрам памяти.
PDE включает указатель на начало page table.
PTE используется для раздачи пермишинов 4-килобайтным блокам внутри одной 4-метровой PDE.
PTEs также включает физический адрес.
PDE включает Physical Address самой page tables.
Для перевода линейного адреса в физический , MMU берет биты 22-31 у линейного адреса.
Биты 12-21 используются для выбора одного из 1024 PTE.
Нижние 12 бит формируют младшие биты физического адреса.
Регистр CR3 хранит базовый адрес PDE.Он еще называется PDBR (Page Directory Base
Register)
Node:V86 Mode,
Next:Interrupt Handling,
Previous:MMU,
Up:Top
12 Virtual 8086 (V86/VM86) Mode
В этом режиме 386 ведет себя также , как и 8086 , с небольшими исключениями.
Здесь не выполняются инструкции LGDT, LIDT, LLDT, SLDT, ARPL, LAR, LSL,
LTR, VERR, VERW, INVD, WBINVD, WRMSR, RDMSR, и т.д.
MMU активен.
Задачи выполняются так , как и реальном режиме.
Нужно установить бит VM флагового регистра.
Это можно сделать из PL0.
Выполнение программ в этом режиме быстрее , чем в реальном.
Задача может иметь доступ к 1 метру памяти.
Задача всегда выполняется в PL3.
Задача может делать I/O , если IOPL=3.
Node:Interrupt Handling,
Next:Working in Protected Mode,
Previous:V86 Mode,
Up:Top
13 Управление прерываниями в Protected Mode
Управление прерываниями - важная часть любой операционной системы.
Без этого с любой системой может произойти чио угодно.
Управление прерываниями , генерируемыми железом , в V86 более комплексное.
Фактически это управление в защищенном режиме.
Перед вызовом обработчика прерываний сегментные регистры обнуляются.
Структура стека VM68 показана ниже :
Когда происходит General Protection Fault ,
программа может быть остановлена , или вызвана инструкция типа CLI , STI.
Node:Working in Protected Mode,
Next:Protected Mode Tutorial,
Previous:Interrupt Handling,
Up:Top
14 Работа в Protected Mode
Для этого сначала нужно переключиться в защищенный режим.
Для этого :
- Setup the Global Descriptor Table (GDT)
- Setup the Interrupt Descriptor Table (IDT)
- Reprogram the PICs so that they generate different interrupts
- Setup the TSS
- Setup Page Tables and CR3 (perhaps you may not require this)
- Set bit 0 of CR0
- Load the Task Register (TR)
- Jump to the TSS selector
Инициализация GDT и IDT проста.
Для этого нужно создать таблицу и загрузить регистр GDTR.
|