Аппаратная поддержка виртуальной памяти на примере микропроцессоров семейства Intel Pentium. Механизмы преобразования адресов

Средства поддержки сегментации памяти

Средства поддержки механизмов виртуальной памяти в процессоре Pentium позволяют отображать виртуальное адресное пространство на физическую память размером максимум в 4 Гбайт (этот максимум определяется использованием 32-разрядных адресов при работе с оперативной памятью).

Процессор может поддерживать как сегментную модель распределения памяти, так и сегментно-страничную. Средства сегментации образуют верхний уровень средств управления виртуальной памятью процессора Pentium, а средства страничной организации — нижний уровень. Это означает, что сегментные средства работают всегда, а средства страничной организации могут быть как включены, так и выключены путем установки однобитного признака РЕ (Paging Enable) в регистре CRO процессора. В зависимости от того, включены ли средства страничной организации, изменяется смысл процедуры преобразования адресов, которая выполняется средствами сегментации. Сначала рассмотрим случай работы средств сегментации при отключенном механизме управления страницами.

Виртуальное адресное пространство

При работе процессора Pentium в сегментном режиме в распоряжении программиста имеется виртуальное адресное пространство, представляемое совокупностью сегментов.

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

Рис. 7.4.1. Формат дескриптора сегмента данных или кода

Структура дескриптора, которая поддерживается в процессоре Pentium, сложилась исторически. Многое в ней связано с обеспечением совместимости с предыдущими процессорами семейства х86. Именно этим объясняется то, что базовый адрес сегмента представлен в дескрипторе в виде трех частей, а размер сегмента занимает два поля.

Ниже перечислены основные поля дескриптора.

§ База — базовый адрес сегмента (32 бита).

§ Размер — размер сегмента (24 бита).

§ G (Granularity) — единица измерения размера сегмента, один бит. Если G=0, то размер задан в байтах и тогда сегмент не может быть больше 64 Кбайт, если 0=1, то размер сегмента измеряется в страницах по 4 Кбайт.

§ Байт доступа (5-й байт дескриптора) содержит информацию, которая используется для принятия решения о возможности или невозможности обращения к данному сегменту. Бит Р (Present) определяет, находится ли соответствующий сегмент в данный момент в памяти (Р=1) или он выгружен на диск (Р=0). Поле DPL (Descriptor Privilege Level) содержит данные об уровне привилегий, необходимом для доступа к сегменту. Остальные пять битов байта доступа зависят от типа сегмента и определяют способ, которым можно использовать данный сегмент (то есть читать, писать, выполнять). Различаются три основных типа сегментов:

§ сегмент данных;

§ кодовый сегмент;

§ системный сегмент (GDT, TSS и т. п

Дескрипторы сегментов объединяются в таблицы. Процессор Pentium для управления памятью поддерживает два типа таблиц дескрипторов сегментов:

§ глобальная таблица дескрипторов (Global Descriptor Table, GDT), которая предназначена для описания сегментов операционной системы и общих сегментов для всех прикладных процессов, например сегментов межпроцессного взаимодействия;

§ локальная таблица дескрипторов (Local Descriptor Table, LDT), которая содержит дескрипторы сегментов отдельного пользовательского процесса.

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

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

Рис. 7.4.2. Формат регистра GDTR

Процесс обращается к физической памяти по виртуальному адресу, представляющему собой пару (селектор, смещение). Селектор однозначно определяет виртуальный сегмент, к которому относится искомый адрес, то есть он может интерпретироваться как номер сегмента, а смещение, как это и следует из его названия, фиксирует положение искомого адреса относительно начала сегмента. Смещение задается в машинной инструкции, а селектор помещается в один из сегментных регистров процессора. Под смещение отводится 32 бита, что обеспечивает максимальный размер сегмента 4 Гбайт (232).

Селектор извлекается из одного из шести 16-разрядных сегментных регистров процессора (CS, SS, DS, ES, FS или GS) в зависимости от типа команды и стадии ее выполнения — выборки кода команды или данных. Например, при обращении к памяти во время выборки следующей команды используется селектор из сегментного регистра кода CS, а при записи результатов в сегмент данных процесса селекторы извлекаются из сегментных регистров данных DS или ES, если же данные записываются в стек по команде PUSH, то механизм виртуальной памяти извлекает селектор из сегментного регистра стека SS, и т. п.

Рис. 7.4.3. Формат селектора

Селектор состоит из трех полей (рис. 7.4.3):

§ индекса, который задает последовательный номер дескриптора в таблице GDT или LDT (13 бит);

§ указателя типа используемой таблицы дескрипторов: GDT или LDT (1 бит);

§ требуемого уровня привилегий — RPL (2 бита), это поле используется механизмом защиты данных, который будет рассмотрен ниже.

Виртуальное адресное пространство процесса складывается из всех сегментов, описанных в общей для всех процессов таблице GDT, и сегментов, описанных в его собственной таблице LDT. Разрядность поля индекса определяет максимальное число глобальных и локальных сегментов процесса — по 8 Кбайт (213) сегментов каждого типа, всего 16 Кбайт сегментов. С учетом максимального размера сегмента — 4 Гбайт — каждый процесс при чисто сегментной организации виртуальной памяти (без включения страничного механизма) может работать в вирту-;алъном адресном пространстве в 64 Тбайт.

Каждый дескриптор в таблицах GDT и LDT имеет размер 8 байт, поэтому максимальный размер каждой из этих таблиц — 64 Кбайт (8 байт х 8 Кбайт дескрипторов).

Из приведенного описания видно, что процессор Pentium обеспечивает поддержку работы ОС в двух отношениях:

§ поддерживает работу виртуальной памяти за счет быстрого аппаратного способа преобразования виртуального адреса в физический;

§ обеспечивает защиту данных и кодов различных приложений.

Преобразование адресов

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

Рис. 7.4.4. Механизм преобразования виртуального адреса в физический при работе процессора в сегментном режиме

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

1. Значение селектора указывает механизму преобразования адресов, что виртуальный адрес относится к сегменту, описываемому в таблице GDT. Местонахождение таблицы GDT система определяет из регистра GDTR, в котором хранится полный 32-битный базовый физический адрес таблицы. Процессор складывает базовый адрес таблицы, взятый из регистра GDTR, со сдвинутым на 3 разряда влево (умножение на 8 в соответствии с числом байтов в одном дескрипторе сегмента) значением поля индекса из селектора. Результатом является физический адрес дескриптора сегмента, к которому относится заданный виртуальный адрес.

2. По вычисленному адресу процессор извлекает из памяти дескриптор нужного сегмента.

3. Выполняется проверка возможности выполнения заданной операции доступа по заданному виртуальному адресу:

§ сначала процессор определяет правильность адреса, сравнивая смещение, заданное в виртуальном адресе, с размером сегмента, извлеченным из регистра LDTR (в случае выхода адреса за границы сегмента происходит прерывание);

§ затем процессор проверяет права доступа задачи к данному сегменту памяти;

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

4. Если все три условия выполнены, то доступ по заданному виртуальному адресу разрешен. Выполняется преобразование виртуального адреса в физический путем сложения базового адреса сегмента, извлеченного из дескриптора, и смещения, заданного в инструкции. Выполняется заданная операция над элементом физической памяти по этому адресу.

В случае когда селектор в виртуальном адресе указывает не на таблицу GDT, a на таблицу LDT, процедура вычисления физического адреса несколько усложняется. Это связано с тем, что регистр LDTR в отличие от GDTR указывает на размещение таблицы сегментов не прямо, а косвенно. В LDTR содержится индекс дескриптора сегмента LDT. Поэтому в процедуре преобразования адресов появляется дополнительный этап — определение базового адреса таблицы LDT. На основании базового адреса таблицы GDT, взятого из регистра GDTR, и селектора, взятого из регистра LDTR, вычисляется смещение в таблице GDT, которое и является адресом дескриптора сегмента LDT.

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

Таким образом, для использования сегментного механизма процессора Pentium операционной системе необходимо сформировать таблицы GDT и LDT, загрузить их память (для начала достаточно загрузить только таблицу GDT), загрузить указатели на эти таблицы в регистры GDTR и LDTR и выключить страничную поддержку.

Операционная система может отказаться от использования средств сегментации процессора Pentium, в таком случае ей достаточно назначить каждому процессу только по одному сегменту и занести в соответствующие таблицы LDT по одному дескриптору. Виртуальное адресное пространство задачи будет состоять из одного сегмента длиной максимум в 4 Гбайт. Поскольку выгрузка процессов на диск будет осуществляться целиком, виртуальная память вырождается в таком частном случае в свопинг.

Защита данных при сегментной организации памяти

Процессор Pentium при работе в сегментном режиме предоставляет операционной системе следующие средства, направленные на обеспечение защиты процессов друг от друга.

§ Процессор Pentium поддерживает для каждого процесса отдельную таблицу дескрипторов сегментов LDT. Эта таблица формируется операционной системой на этапе создания процесса. После активизации процесса в регистр LDTR заносится адрес (селектор) его таблицы LDT. Тем самым система делает недоступным для процесса локальные сегменты других процессов, описанные в их таблицах LDT.

§ Вместе с тем таблица GDT, в которой хранятся дескрипторы сегментов операционной системы, а также сегменты, используемые несколькими процессами совместно, доступна всем процессам, а следовательно, не защищена от их несанкционированного вмешательства. Для решения этой проблемы в процессоре Pentium предусмотрена поддержка системы безопасности на основе привилегий. Каждый сегмент памяти наделяется атрибутами безопасности, которые характеризуют степень защищенности данного сегмента. Процессы также наделяются атрибутами безопасности, которые в этом случае характеризуют степень привилегированности процесса. Уровень привилегий процесса определяется уровнем привилегий его кодового сегмента. Доступ к сегменту регулируется в зависимости от его защищенности и уровня привилегированности запроса. Это позволяет защитить от несанкционированного доступа сегменты GDT, а также обеспечить дифференцированный доступ к локальным сегментам процесса.

§ Само по себе наличие отдельных таблиц дескрипторов для каждого процесса еще не обеспечивает надежной защиты процессов друг от друга. Действительно, что мешает одному пользовательскому процессу изменить содержимое регистра LDTR так, чтобы он указывал на таблицу другого процесса? Аналогично никакие значения атрибутов безопасности не смогут защитить от несанкционированного доступа сегменты, описанные в таблице GDT, если процесс имеет возможность по своей инициативе устанавливать желаемый уровень привилегий для себя. Поэтому необходимым элементом защиты является наличие аппаратных ограничений в наборе инструкций, разрешенных для выполнения процессу. Некоторые инструкции, имеющие критически важное значение для функционирования системы, такие, например, как останов процессора, загрузка регистра GDTR, загрузка регистра LDTR, являются привилегированными как раз по этой причине — процесс может выполнять их, только обладая наивысшим уровнем привилегий.

§ Еще одним механизмом защиты, поддерживаемым в процессоре Pentium, является ограничение на способ использования сегмента. В зависимости от того, к какому типу относится сегмент — сегмент данных, кодовый сегмент или системный сегмент, — некоторые действия по отношению к нему могут быть запрещены. Например, в кодовый сегмент нельзя записывать какие-либо данные, а сегменту данных нельзя передать управление, даже если загрузить его селектор в регистр CS.

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

Рис. 7.4.5. Кольца защиты

Система защиты манипулирует несколькими переменными, характеризующими уровень привилегий:

§ DPL (Descriptor Privilege Level) — уровень привилегий дескриптора, задается полем DPL в дескрипторе сегмента;

§ RPL (Requested Privilege Level) — запрашиваемый уровень привилегий, задается полем RPL селектора сегмента;

§ CPL (Current Privilege Level) — текущий уровень привилегий выполняемого кода, задается полем RPL селектора кодового сегмента;

§ EPL (Effective Privilege Level) — эффективный уровень привилегий запроса.

Под запросом здесь понимается любое обращение к памяти независимо от того, произошло ли оно при выполнении кода, оформленного в виде процесса, или вне рамок процесса, как это бывает при выполнении кодов ОС.

Поле уровня привилегий является частью двух информационных структур — дескриптора и селектора. В том и другом случае оно задается двумя битами: 00, 01, 10 и 11, характеризуя четыре степени привилегированности, от самой низкой 11 до самой высокой 00.

Уровни привилегий назначаются дескрипторам и селекторам. Во время загрузки операционной системы в память, а также при создании новых процессов операционная система назначает процессу сегменты кода и данных, генерирует дескрипторы этих сегментов и помещает их в таблицы GDT или LDT. Конкретные значения уровней привилегий DPL и RPL задаются операционной системой и транслятором либо по умолчанию, либо на основании указаний программиста. Значения DPL и RPL определяют возможности создаваемого процесса.

Уровень привилегий дескриптора DPL является в некотором смысле первичной характеристикой, которая «переносится» на соответствующие сегменты и запросы. Сегмент обладает тем уровнем привилегий, который записан в поле DPL его дескриптора. DPL определяет степень защищенности сегмента. Уровень привилегий сегмента данных учитывается системой защиты, когда она принимает решения о возможности выполнения для этого сегмента чтения или записи. Уровень привилегий кодового сегмента используется системой защиты при проверке возможности чтения или выполнения кода для данного сегмента.

Уровень привилегий кодового сегмента определяет не только степень защищенности этого сегмента, но и текущий уровень привилегий CPL всех запросов к памяти (на чтение, запись или выполнение), которые возникнут при выполнении этого кодового сегмента. Другими словами, уровень привилегий кодового сегмента DPL характеризует текущий уровень привилегий GPL выполняемого кода. При запуске кода на выполнение значение DPL из дескриптора копируется в поле RPL селектора кодового сегмента, загружаемого в регистр сегмента команд CS. Значение поля RPL кодового сегмента, собственно, и является текущим уровнем привилегий выполняемого кода, то есть уровнем CPL.

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

Во время приостановки процесса его текущий уровень привилегий сохраняется в контексте, роль которого в процессоре Pentium играет системный сегмент состояния задачи (Task State Segment, TSS). Если какой-либо процесс имеет несколько кодовых сегментов с разными уровнями привилегий, то поле RPL регистра CS позволяет узнать значение текущего уровня привилегий процесса. Заметим, что пользовательский процесс не может изменить значение поля привилегий в дескрипторе, так как необходимые для этого инструкции ему недоступны. В дальнейшем уровень привилегий процесса может измениться только в случае передачи управления другому кодовому сегменту путем использования особого дескриптора — шлюза.

Контроль доступа процесса к сегментам данных осуществляется на основе сопоставления эффективного уровня привилегий EPL запроса и уровня привилегий DPL дескриптора сегмента данных. Эффективный уровень привилегий учитывает не только значение CPL, но и значение запрашиваемого уровня привилегий для конкретного сегмента, к которому выполняется обращение. Перед тем как обратиться к сегменту данных, выполняемый код загружает селектор, указывающий на этот сегмент, в один из регистров сегментов данных: DS, ES, FS или GS. Значение поля RPL данного селектора задает уровень запрашиваемых привилегий. Эффективный уровень привилегий выполняемого кода EPL определяется как максимальное (то есть худшее) из значений текущего и запрашиваемого уровней привилегий:

EPL=max{CPL.RPL}

Выполняемый код может получить доступ к сегменту данных для операций чтения или записи, если его эффективный уровень привилегий не ниже (а в арифметическом смысле «не больше») уровня привилегий дескриптора этого сегмента:

max{CPL.RPL) <= DPL

Уровень привилегий дескриптора DPL определяет степень защищенности сегмента. Значение DPL говорит о том, каким эффективным уровнем привилегий должен обладать запрос, чтобы получить доступ к данному сегменту. Например, если дескриптор имеет DPL=2, то к нему разрешено обращаться всем процессам, имеющим уровень привилегий EPL, равный 0, 1 или 2, а для процессов с EPL, равным 3, доступ запрещен.

Правило вычисления эффективного уровня привилегий показывает, что он не может быть выше уровня привилегий кодового сегмента. Поэтому загрузка в регистр DS (или любой другой сегментный регистр данных) селектора с высоким уровнем привилегий (например, с RPL = 0) при низком значении уровня CPL (например, 3) ничего нового не даст — если сегмент данных, на который указывает DS, имеет высокий уровень привилегий (например, 1), то в доступе к нему будет отказано (так как EPL будет равен max {3,0}, то есть 3). По этой причине команды загрузки сегментных регистров не являются привилегированными.

Если запрос обращен к сегменту данных, обладающему более высоким, чем EPL, уровнем привилегий, то происходит прерывание.

Задавая в поле RPL селекторов, ссылающихся на сегменты данных, различные значения, программист может управлять доступом выполняемого кода к этим сегментам. Так, при RPL=0 эффективный уровень привилегий будет всецело определяться только текущим уровнем привилегий CPL. А если поместить в селектор RPL=3, то это означает снижение эффективного уровня привилегий до самого низкого значения, при котором процессу разрешен доступ только к наименее защищенным сегментам с DPL=3.

Контроль доступа процесса к сегменту стека позволяет предотвратить доступ низкоуровневого кода к данным, выработанным высокоуровневым кодом, и помещенным в стек, например к локальным переменным процедуры. Доступ к сегменту стека разрешается только в том случае, когда уровень EPL кода совпадает с уровнем DPL сегмента стека, то есть коду разрешается работать только со стеком своего уровня привилегий. Использование одного и того же стека для процедур разного уровня привилегий может привести к тому, что низкоуровневая процедура, получив управление после возврата из вызванной ею высокоуровневой процедуры (обратная последовательность вызова процедур в процессоре Pentium запрещена, что рассматривается ниже), может прочитать из стекового сегмента записываемые туда во время работы высокоуровневой процедуры данные. Так как в ходе выполнения процесса уровень привилегий его кода может измениться, то для каждого уровня привилегий используется отдельный сегмент стека.

Контроль доступа процесса к кодовому сегменту производится путем сопоставления уровня привилегий дескриптора этого кодового сегмента DPL с текущим уровнем привилегий выполняемого кода CPL. В зависимости от того, какой способ обращения к кодовому сегменту используется, выполняется внутрисегментная или межсегментная передача управления, вызывается подчиненный или неподчиненный сегмент — по-разному формулируются правила контроля доступа. Эти вопросы будут рассмотрены в разделе «Средства вызова процедур и задач».

Осуществляя контроль доступа к сегменту, аппаратура процессора учитывает не только уровень привилегий, но и «легитимность» способа использования данного сегмента.

Способ, с помощью которого разрешено осуществлять доступ к сегменту того или иного типа, определяется несколькими битами байта доступа дескриптора сегмента. Как уже было сказано, старший, седьмой бит байта доступа является признаком Р присутствия сегмента в памяти, а шестой и пятый биты отведены для хранения уровня привилегий DPL. На рис.7.4.6 показаны оставшиеся пять битов байта доступа, смысл которых зависит от типа сегмента.

Рис. 7.4.6. Признаки, задающие тип сегмента и права доступа

Поле S занимает 1 бит и определяет, является ли сегмент системным (5=0) или сегментом кода или данных (S=l).

Системные сегменты предназначены для хранения служебной информации операционной системы. Примерами системных сегментов являются сегменты, хранящие таблицы LDT, или рассматриваемые ниже сегменты состояния задачи TSS. Конкретный тип системного сегмента указывается в четырех младших битах байта доступа, например, если это поле содержит значение 2, это означает, что данный дескриптор описывает сегмент LDT.

Признак Е позволяет отличить сегмент данных (Е=0) от сегмента кода (Е=1). Для сегмента данных определяются следующие поля:

§ ED (Expand Down) — направления распространения сегмента (ED=0 для обычного сегмента данных, распространяющегося в сторону увеличения адресов, Е0=1 для стекового сегмента данных, распространяющегося в сторону уменьшения адресов);

§ W (Writeable) — бит разрешения записи в сегмент (при W=l запись разрешена, при W=0 — запрещена);

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

Если признак W запрещает запись в сегмент данных, то разрешается только чтение сегмента. Выполнение сегмента данных запрещено всегда, независимо от значения признака W.

Для сегмента кода используются следующие признаки:

§ С (Conforming) — бит подчинения, определяет возможность вызова кода на выполнение из других сегментов; при С=1 (подчиненный сегмент) сегмент может выполняться в том случае, если текущий уровень привилегий вызывающего процесса CPL не выше уровня привилегий DPL данного кодового сегмента, то есть в арифметическом смысле CPL > DPL; после передачи управления новый кодовый сегмент начинает выполняться с уровнем привилегий вызвавшего сегмента, то есть с более низкими или теми же привилегиями; при С=0 (неподчиненный сегмент) код может быть выполнен только при CPL=DPL;

§ R (Readable) — бит разрешения (R=l) или запрета (R=0) чтения из кодового сегмента;

§ A (Accessed) — признак обращения, имеет смысл, аналогичный полю А сегмента данных.

Если признак R запрещает чтение кодового сегмента, то разрешается только его выполнение. Запись в кодовый сегмент запрещена всегда, независимо от значения признака R.

Выполнение многих операций в процессоре Pentium сопровождается проверкой их допустимости для данного типа сегмента. Первый этап проверки выполняется при загрузке селекторов в сегментные регистры. Так, диагностируется ошибка, если в сегментный регистр CS загружается селектор, ссылающийся на дескриптор сегмента данных, и наоборот, если в регистр сегмента данных DS загружается селектор, указывающий на дескриптор кодового сегмента. Ошибка возникает также, если в регистр стекового сегмента загружается селектор, ссылающийся на дескриптор сегмента данных, который допускает только чтение.

Вторым этапом является проверка ссылок операндов во время выполнения команд записи или чтения. Прерывания происходят в следующих случаях:

§ делается попытка прочитать данные из кодового сегмента, который допускает только выполнение;

§ делается попытка записать данные по адресу, принадлежащему кодовому сегменту;

§ делается попытка записать данные в сегмент данных, который допускает только чтение.

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

Сегментно-страничный механизм

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

Виртуальное адресное пространство процесса при сегментно-страничном режиме работы процессора ограничивается размером 4 Гбайт. В этом пространстве определены виртуальные сегменты процесса (рис. 7.4.7). Так как теперь все виртуальные сегменты разделяют одно виртуальное адресное пространство, то возможно их наложение, поскольку процессор не контролирует такие ситуации, оставляя эту проблему ОС.

Рис. 7.4.7. Работа сегментного механизма в сегментно-страничном режиме

Для реализации механизма управления страницами как физическое, так и виртуальное адресные пространства разбиты на страницы размером 4 Кбайт (начиная с модели Pentium в процессорах Intel существует возможность использования страниц и по 4 Мбайт, но дальнейшее изложение ориентируется на традиционный размер страницы в 4 Кбайт). Всего в виртуальном адресном пространстве в сегментно-страничном режиме насчитывается 1 Мбайт (220) страниц. Несмотря на наличие нескольких виртуальных сегментов, все виртуальное адресное пространство задачи имеет общее разбиение на страницы, так что нумерация виртуальных страниц сквозная.

Виртуальный адрес по-прежнему представляет собой пару: селектор, который определяет номер виртуального сегмента, и смещение внутри этого сегмента. Преобразование виртуального адреса выполняется в два этапа: сначала работает сегментный механизм, а затем результат его работы поступает на вход страничного механизма, который и вычисляет искомый физический адрес.

Работа сегментного механизма в данном случае во многом повторяет его работу при отключенном страничном механизме. На основании значения индекса в селекторе Выбирается нужный дескриптор из таблицы GDT или LDT. Из дескриптора извлекается базовый адрес сегмента и складывается со смещением. Дескрипторы и таблицы имеют ту же структуру. Однако имеется и принципиальное отличие, оно состоит в интерпретации содержимого поля базового адреса в дескрипторах сегментов. Если раньше дескриптор сегмента содержал базовый адрес сегмента в физической памяти и при сложении этого адреса со смещением из виртуального адреса получался физический адрес, то теперь дескриптор содержит базовый адрес сегмента в виртуальном адресном пространстве, и в результате его сложения со смещением получается линейный виртуальный адрес.

Результирующий линейный 32-разрядный виртуальный адрес передается страничному механизму для дальнейшего преобразования. Исходя из того что размер страницы равен 4 Кбайт (212), в адресе можно легко выделить номер виртуальной страницы (старшие 20 разрядов) и смещение в странице (младшие 12 разрядов). Как известно, для отображения виртуальной страницы в физическую достаточно построить таблицу страниц, каждый элемент которой — дескриптор виртуальной страницы — содержал бы номер соответствующей ей физической страницы и ее атрибуты. В процессоре Pentium так и сделано, и структура дескриптора страницы показана на рис. 8.5.8. Двадцать разрядов, в которых находится номер страницы, могут интерпретироваться и как базовый адрес страницы в памяти, который необходимо дополнить 12 нулями, так как младшие 12 разрядов базового адреса страницы всегда равны нулю. Кроме номера страницы дескриптор страницы содержит также следующие поля, близкие по смыслу соответствующим полям дескриптора сегмента:

§ Р — бит присутствия страницы в физической памяти;

§ W — бит разрешения записи в страницу;

§ U — бит пользователь/супервизор;

§ А — признак имевшего место доступа к странице;

§ D — признак модификации содержимого страницы;

§ PWT и PCD — управляют механизмом кэширования страниц (введены начиная с процессора i486);

§ AVL — резерв для нужд операционной системы (AVaiLable for use).

Рис. 7.4.8 Формат дескриптора страницы

При небольшом размере страницы процессора Pentium относительно размеров адресных пространств таблица страниц должна занимать в памяти весьма значительное место — 4 байт х 1 Мбайт = 4 Мбайт. Это слишком много для нынешних моделей персональных компьютеров, поэтому в процессоре Pentium используется деление всей таблицы страниц на части — разделы по 1024 дескриптора. Размер раздела выбран так, чтобы один раздел занимал одну физическую страницу (1024 х 4 байт - 4 Кбайт). Таким образом таблица страниц делится на 1024 раздела.

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

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

Рис. 7.4.9. Преобразование линейного виртуального адреса в физический адрес

Поле номера виртуальной страницы (старшие 20 разрядов) делится на две равные части по 10 разрядов — поле номера раздела и поле номера страницы в разделе. На основании заданного в регистре CR3 номера физической страницы, хранящей таблицу разделов, и смещения в этой странице, задаваемого полем номера раздела, процессор находит дескриптор виртуальной страницы раздела. В соответствии с атрибутами этого дескриптора определяются права доступа к странице, а также наличие ее в физической памяти. Если страницы нет в оперативной памяти, то происходит прерывание, в результате которого операционная система должна выполнить загрузку требуемой страницы в память. После того как страница (содержащая нужный раздел) загружена, из нее извлекается дескриптор страницы данных, номер которой указан в линейном виртуальном адресе. И наконец, на основании базового адреса страницы, полученного из дескриптора, и смещения, заданного в линейном виртуальном адресе, вычисляется искомый физический адрес.

Таким образом, при доступе к странице в процессоре используется двухуровневая схема адресации страниц, которая хотя и замедляет преобразование, но позволяет использовать страничный механизм для таблицы страниц, что существенно уменьшает объем физической памяти, требуемой для ее хранения. Для ускорения преобразования адресов в блоке управления страницами используется ассоциативная память, в которой каптируются 32 дескриптора активно используемых страниц, что позволяет по номеру виртуальной страницы быстро извлекать номер физической страницы без обращения к таблицам разделов и страниц.



Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



double arrow
Сейчас читают про: