Процессор Intel в защищенном режиме #6 — Архив WASM.RU
Prelude
Спешу всех порадовать – в самых ближайших выпусках мы начнем непосредственно программировать и использовать все полученные знания на практике. Знаний у нас пока немного, но достаточно для реализации простых действий. Поэтому настоятельно рекомендую ознакомиться со всеми выпусками рассылки (архив лежит здесь: http://subscribe.ru/archive/comp.soft.prog.intelpm). Подписчикам, которые внимательно читают все выпуски с самого начала, не помешает все же еще раз бегло пробежаться по оным (тогда на практике не возникнет лишних вопросов).
СТРАНИЧНАЯ АДРЕСАЦИЯ
Ну вот, наконец-то мы добрели и до страничной адресации (не прошло и месяца . Стоит отметить, что подписчики, у которых не возникло проблем с сегментной адресацией также легко и просто освоят страничную.
Прежде всего, нужно понять очень важную вещь: при использовании страничной адресации структуры из сегментной адресации (как то – таблицы дескрипторов, селекторы, регистры таблиц дескрипторов) НИКУДА НЕ ДЕВАЮТСЯ! Все остается на своих местах! Так в чем же тогда заключается страничная адресация? Где же она себя проявляет?
ВАЖНЫЙ МОМЕНТ: ЕДИНСТВЕННОЕ МЕСТО, ГДЕ СТРАНИЧНАЯ АДРЕСАЦИЯ ДЕЙСТВИТЕЛЬНО ВКЛИНИВАЕТСЯ В ПРОЦЕСС РАБОТЫ ПРОЦЕССОРА – ПРИ ПЕРЕВОДЕ ЛИНЕЙНОГО АДРЕСА В ФИЗИЧЕСКИЙ! Вот в этом вся соль! ЭТИМ НУЖНО ПРОНИКНУТЬСЯ!
Придется немного прокрутить пленку назад. Вспомни три понятия: логический, линейный и физический адрес. Логический адрес – это некий абстрактный, на деле ничего не значащий адрес, грубо говоря, CS:EIP – это и есть логический адрес, в самом деле, что он может нам сообщить? Ничего. Только то, что если мы вытащим из CS поле индекс, а затем по этому полю найдем в таблице дескрипторов соотв. дескриптор, а затем к базе из этого дескриптора прибавим EIP – то вот только тогда получим ЛИНЕЙНЫЙ адрес. При использовании сегментной адресации физический адрес совпадает с линейным (физический – это адрес который проц выставляет уже на адресную шину). Т.е. при сегментной адресации проц просто берет линейный адрес и без выкрутасов выставляет на адресную шину. При использовании страничной адресации именно на этапе перевода линейного адреса в физический в действие вступают новые силы, о коих и будет поведано ниже...
При использовании страничной адресации линейный адрес не совпадает с физическим, как в случае с сегментной адресацией. Т.е. мы имеем дело с виртуальной памятью. Процессор делит линейное адресное пространство на страницы фиксированного размера (длиной 4Кб, 2Мб или 4Мб), которые, в свою очередь, уже отображаются в физической памяти (или на диске). Когда программа (или задача) обращается к памяти через логический адрес, процессор переводит его в линейный и затем, используя механизму страничной адресации, переводит его в соответсвтующий физический адрес. Если страницы в данный момент нет в физической памяти, то возникает исключение #PF. Это по сути кульминационный момент: обработчик этого исключения (#PF) должен выполнить соответствующие манипуляции по устранению данной проблемы, т.е. подгрузить страницу с харда (или наоборот – скинуть ненужную страницу на диск).
Вообщем, все знают что такое своп-файл в винде? Вот по сути это и есть те самые странички памяти на харде, которые после возникновения #PF должны быть загружены в оперативку (или наоборот). По сути - #PF это не есть нечто ужасное и недопустимое (как #GP). НАОБОРОТ! #PF «нам строить и жить помогает!!!» Без него вообще ничего бы и не получилось по сути то дела!
Как только страница была благополучно водворена на место, то выполнение прерванной проги продолжается с той самой инструкции, которая вызвала #PF. А кстати, какая инструкция может вызвать #PF? Да в принципе любая, которая так или иначе обращается к памяти...
Страничная организация отличается от сегментной еще и тем, что все страницы имеют фиксированный размер (в сегментной размер сегментов абсолютно произволен). Также при сегментной адресации все сегменты обязательно должны присутствовать непосредственно в оперативе, а при страничной возможна ситуация, когда кусок сегмента находится в памяти, а другой кусок фактически того же сегмента – на харде (т.е. другими словами – часть страниц сегмента находится в оперативе, а часть – валяется в то же время на харде).
Проц всегда, где это возможно, облегчает себе жизнь. Вспомни про «теневую» часть сегментного регистра. Также и в случае со страничной адресацией – страницы, к которым проц чаще всего обращается кэшируются в процессоре, в области, которая называется буфер с ассоциативной выборкой (TLB - Table lookaside buffer). Т.е. не все такие страницы целиком, а только записи, которые необходимы для доступа к ним (см. ниже).
Несколько слов по поводу TLB. Начиная с P6 процев сущестувуют кэши специально для записей, описывающих код и данные, также разные кэши для 4Кб и для 4Мб страниц. Инструкция CPUID позволяет определить размер этих самых TLB в твоем проце. Чем они больше – тем быстрее соответственно будет работать проц. В отличии от теневой части сегментного регистра, куда мы не могли лезть руками и вообще не имели никакого доступа к ней, в TLB мы можем кое что изменять (естественно только в том случае, если мы на самом крутом уровне привилегий, на нулевом). Для этого существует команда INVLPG и др. приемы, на которых не стоит заострять внимания (если кому интересно в подробностях – пишите).
Итак, страничная организация непосредственно в проце управляется тремя флажками:
- Флаг PG (paging): бит 31 в регистре CR0. Появился в 386 проце.
- Флаг PSE (page size extensions): бит 4 в регистре CR4. Появлися в пнях.
- PAE (physical address extension) flag: бит 5 в регистре CR4. Появился в пентиум pro процах.
Теперь подробнее. Флаг PG разрешает страничную адресацию. Сразу после установки его в единицу страничная адресация включена.
Флаг PSE, если его установить, позволяет использовать страницы больших размеров (4Мб и 2Мб). Если сброшен – страницы имеют размер 4Кб.
Флаг PAE позволяет расширить физический адрес до 36 бит (стандартно он 32-х битный). Данный флаг можно использовать ТОЛЬКО в режиме страничной адресации. Узнать, поддерживает ли твой проц данное расширение можно по 17 биту в EDX после CPUID).
Кстати, использовать 36-разрядную адресацию можно как с помощью PAE-флага, так и с помощью PSE-флага, это два разных метода, мы их рассмотрим дальше.
Каталоги и таблицы страниц.
Ну все, хватит лирики, пора приступать к делу. При трансляции линейного адреса в физический (при включенной страничной адресации) процессор использует 4 структуры данных:
1. Каталог страниц – массив 32-битных записей (PDE – page- directory entry), к-рые хранятся в 4Кб странице. Напоминает таблицу дескрипторов, не так ли? А сколько 32-битных записей помещается в 4Кб? Правильно, 1024 штуки. Т.е. всего 1024 PDE- шки...
2. Таблица страниц – массив 32-битных записей (PTE – page-table entry), которые также все расположены в одной 4Кб странице. Т.е. PTE-шек тоже может быть всего 1024 штуки. Забегая вперед – для 2Мб и 4Мб страниц таблица страниц вообще никак не используется – все решают только PDE-шки.
3. Сама страница – 4Кб, 2Мб или 4Мб кусок памяти
4. Указатель на каталог страниц – массив 64-битных записей, каждая из которых указывает на каталог страниц. Эта структура данных используется процем только при использовании 36-битной адресации.
Все эти таблицы позволяют обращаться к 4Кб или к 4Мб страницам при 32-х битной адресации и к 4Кб, 2Мб или 4Мб страницам при 36-битной адресации. Смотри на таблицу, какие флаги на что влияют:
Непонятно тут может быть только одно – что за колонка PSE-36? Дело в том, что этот режим работы (PSE-36) появился только в третьих пнях, а доступен он или нет можно узнать посредством CPUID. Как видишь, при использовании PSE-36 механизма доступны только страницы размером 4Мб. Фактически таким макаром можно адресовать 64 Gb физического адресного пространства.
Конечно, на первый взгляд получается несколько туманно и путано, столько флажков, какие то разрядности, но на самом деле все довольно четко и логично, просто надо вникнуть, а потом задать вопросы ).
Вообщем, расклад таков: при страничной организации существуют 3 способа адресации: 32-х разрядная, 36-разрядная с использованием флага PAE и 36-разрядная с использованием флага PSE.
Для начала рассмотрим самую простую и наглядную – 32-х разрядную адресацию. Все о чем пойдет дальше речь – справедливо только для нее.
Линейная адресная трансляция (4Кб страницы)
Обязательно дождитесь загрузки картинки! (Кто не хочет – пишите, вышлю по мылу). Вот она, механизма:
И что мы видим? А видим мы следующее: линейный адрес (тот самый, который получается в результате сложения базы сегмента со смещением при сегментной организации) при страничной организации с 4Кб страницами делится на три части:
- Номер записи в каталоге страниц: биты 22-31.
- Номер записи в таблице страниц: биты 12-21.
- Смещение в самой 4Кб странице: биты 0-11.
Для справки: в регистре CR3 (см. рисунок) только биты 12-31 содержат смещение каталога страниц в памяти. Где же младшие 12? А они ВСЕГДА равны нулю. Т.е. как не верти, а расположить каталог страниц ниже 4 Кб не удастся... Подумай над этим ).
На самом деле, может создаться ошибочное мнение, что каталог страниц – один единственный, и указывает на него регистр CR3 (как в случае с глобальной таблицей дескрипторов и регистром GDTR, помнишь?). На самом же деле все обстоит совсем не так, каталогов страниц может быть несколько, даже у каждой задачи свой, а регистр CR3 меняется после переключения задачи (подробнее – в выпуске, про переключение задач).
Линейная адресная трансляция (4Мб страницы)
Помнишь, чуть выше я упоминал, что для 4Мб страниц никакой таблицы страниц не существует? Смотри, как это выглядит в реале:
Видишь, фактически за счет размера страниц мы ничего не теряем и опять же, можем адресовать 4Gb, как и в случае с 4Кб страницами. 4Мб размер страницы получается в случае установки флагов PSE и PS. Флаг PSE ты уже знаешь где (в CR4), а что за флаг PS? А флаг PS находится непосредственно в записи каталога страниц. Увидишь его в следующем выпуске.
В случае 4Мб страниц линейный адрес делится на ДВЕ части:
- Номер записи в каталоге страниц (биты 22-31)
- Смещение в самой 4Мб-странице (биты 0-21)
РЕГИСТР CR3
Еще раз: младшие 12 бит ВСЕ ВРЕМЯ РАВНЫ НУЛЮ (их вообще то и нет даже на картинке по сути, флаги PCD и PWT не входят в эти младшие 12 бит, а существуют сами по себе. Все что не обозначено – зарезервировано.
PCD-флаг (page level cache disabled) – четвертый бит, контролирует кэширование каталога страниц. Если он установлен, то кэширование не происходит. Если сброшен – каталог страниц может кэшироваться. Этот флаг влияет только на L1 и L2 (внутренние кэши процессора). Процессор игнорирует этот флаг, если страничная адресация отключена (флаг PG в CR0 сброшен) или если вообще отключен кэш (флаг CD в CR0).
PWT-флаг (page-level writes transparent) – третий бит, controls the write-through or write-back caching policy of the current page directory . Переведи лучше сам... Также влияет только на L1 и L2 и зависит от PG и CD.
Регистр CR3 (главным образом, хранящий начало каталога страниц текущей задачи) также называют PDBR (page directory base register). Если мы собираемся использовать страничную адресацию, мы должны загрузить этот регистр в процессе инициализации. Загрузить его можно либо непосредственно командой mov, либо он сам загрузиться при переключении задач.
Может возникнуть ситуация, когда каталог страниц в момент переключения отсутствует в физической памяти, поэтому ОС перед переключением задачи должна устранить это недоразумение. Каталог страниц должен находится в памяти столько времени, сколько активна задача, использующая этот каталог страниц.
На сегодня все. В следующем выпуске познакомимся с структурами записей в каталоге и таблице страниц.
p.s. данный выпуск, как никакой другой, покажется тебе затуманенным и неясным. На самом деле это нормально. Главное – не заострять внимания на флажочках и битиках, а уловить общую суть – при страничной адресации линейный адрес распадается на n-частей (на 3 в случае 4Кб страниц и на 2 в случае 4Мб страниц), каждая из этих частей выполняет свою роль, и т.д.
p.p.s. есть ли среди подписчиков люди, серьезно занимающиеся демо- мейкерством (glide, 3D и т.п.)? Прошу откликнуться, есть одна бредовая идейка. © Broken Sword
Процессор Intel в защищенном режиме #6
Дата публикации 15 окт 2002