Переключение процессоров Intel из реального в защищенный режим и обратно.
Все
процессоры Intel, начиная с i80286 и до последних включительно, по включению
электропитания (после начального "сброса") работают в режиме
реального адреса (реальном режиме). Обычно реальный режим используется либо как
промежуточный для перехода в защищенный режим после инициализации
микропроцессорной системы, либо для более быстрого выполнения программ,
написанных для микропроцессоров 8086, 80186, но, по сравнению с 8086, 80186,
современные микропроцессоры в реальном режиме имеют более широкий набор выполняемых
команд и возможность обработки 32-разрядных операндов.
Переключение процессора в защищенный режим из реального осуществляется загрузкой в регистр CR0
(рис. 1) слова с единичным значением бита РЕ (Protect Enable). Для
совместимости с ПО для 80286 бит РЕ может быть установлен также инструкцией
LMSW. До переключения в памяти должны быть проинициализированы необходимые
таблицы дескрипторов IDT и GDT. Сразу после включения защищенного режима
процессор имеет CPL = 0.
Для всех процессоров ( начиная
с 32-разрядных) рекомендуется выполнять следующую последовательность действий
для переключения в защищенный режим:
1.
Запретить маскируемые прерывания сбросом флага IF, а возникновение
немаскируемых прерываний блокировать внешней логикой. Программный код на время
"переходного периода" должен гарантировать отсутствие исключений и не
использовать программных прерываний. Это требование вызвано сменой механизма
вызова обработчиков прерываний.
2.
Загрузить в GDTR базовый адрес GDT (инструкцией LGDT).
3.
Инструкцией MOV CR0 установить флаг РЕ, а если требуется страничное управление
памятью, то и флаг PG.
4. Сразу
после этого должна выполняться команда межсегментного перехода (JMP Far) или
вызова (CALL Far) для очистки очереди инструкций, декодированных в реальном
режиме, и выполнения сериализации процессора. Если включается страничное
преобразование, то коды инструкций MOV CR0 и JMP или CALL должны находиться в
странице, для которой физический адрес совпадает с логическим (для кода,
которому передается управление, это требование не предъявляется).
5. Если
планируется использование локальной таблицы дескрипторов, инструкцией LLDT
загрузить селектор сегмента для LDT в регистр LDTR.
6.
Инструкцией LTR загрузить в регистр задач селектор TSS для начальной задачи
защищенного режима.
7.
Перезагрузить сегментные регистры (кроме CS), содержимое которых еще относится
к реальному режиму, или выполнить переход или вызов другой задачи (при этом
перезагрузка регистров произойдет автоматически). В неиспользуемые сегментные
регистры загружается нулевое значение селектора.
8.
Инструкцией LIDT загрузить в регистр IDTR адрес и лимит IDT - таблицы
дескрипторов прерываний защищенного режима.
9.
Разрешить маскируемые и немаскируемые аппаратные прерывания.
Переключение процессора из защищенного
режима в реальный возможно не только
через аппаратный сброс, как это было у 80286, но и сбросом бита РЕ в CR0. При
этом для корректного перехода, согласно документации на процессоры, должны
выполняться следующие действия.
1.
Запретить маскируемые прерывания флагом IF, немаскируемые - внешней схемой.
2. Если
включена страничная трансляция, то необходимо обеспечить равенство линейных и
физических адресов для текущего исполняемого кода (перейти на такую страницу),
а также для таблиц GDT и IDT. Обнулить бит PG в регистре CR0 и загрузить нули в
CR3 для очистки кэш-буфера TLB.
3.
Передать управление читаемому сегменту с лимитом 64 Кбайт.
4.
Загрузить в сегментные регистры SS, DS, ES, FS и GS селектор дескриптора
(ненулевой), в котором установлен лимит 64 Кбайт, байтовая дробность (G = 0),
расширяемость вверх (Е = 0), доступность записи (W = 1) и присутствие (Р = 1).
Если сегментные регистры не перезагружать, исполнение будет продолжаться с
атрибутами, унаследованными от защищенного режима (шаги 3 и 4 предназначены для
загрузки программно-недоступных регистров дескрипторов сегментов параметрами
стандартного реального режима. Однако вместо них можно создать и
"нереальный" (Unreal, по Р. Коллинзу) режим, отличающийся от реального
возможностью доступа к сегментам большого - до 4 Гбайт - размера).
5.
Инициализировать таблицу векторов прерываний реального режима (в пределах
первого мегабайта) и указать на нее инструкцией LIDT.
6.
Сбросить бит РЕ для перехода в реальный режим.
7. Выполнить
дальний переход на программу реального режима, что сбросит очередь инструкций,
декодированных в защищенном режиме, и загрузит соответствующие права доступа к
сегменту кода.
8.
Загрузить корректные значения в сегментные регистры и указатель стека.
9.
Разрешить прерывания.
После
этого загружаются остальные регистры. Процессор теперь работает в реальном
режиме, по умолчанию с 16-разрядными адресами и данными.
Рис. 1.
Регистр CR0.