Поддержка сегментного способа организации виртуальной памяти
Как мы уже знаем, для организации эффективной и надежной работы вычислительной системы в мультипрограммном режиме необходимо иметь соответствующие аппаратные механизмы, поддерживающие независимость адресных пространств каждой задачи и в то же время позволяющие организовать обмен данными и разделение кода. Для этого желательно выполнить следующие два требования:
106_______________ Глава 4. Особенности архитектуры микропроцессоров i80x86
- чтобы у каждого вычислительного процесса было собственное (личное, локальное) адресное пространство, никак не пересекающееся с адресными пространствами других процессов;
- чтобы существовало общее (разделяемое) адресное пространство.
Для удовлетворения этих требований в микропроцессорах i80x86 реализован сегментный способ распределения памяти. Помимо того в этих микропроцессорах может быть задействована и страничная трансляция. Поскольку для каждого сегмента нужен дескриптор, устройство управления памятью поддерживает соответствующую информационную структуру. Формат дескриптора сегмента приведен на рис. 4.3.
Первое (младшее) двойное слово дескриптора Рис. 4.3. Дескриптор сегмента
Поля дескриптора (базовый адрес, поле предела) размещены в дескрипторе не непрерывно, а в разбивку, потому что, во-первых, разработчики постарались минимизировать количество перекрестных соединений в полупроводниковой структуре микропроцессора, а во-вторых, чтобы обеспечить полную совместимость1 микропроцессоров (предыдущий микропроцессор i80286 работал с 16-разрядным кодом и тоже поддерживал сегментный механизм реализации виртуальной памяти). Необходимо заметить, что формат дескриптора сегмента, изображенный на рис. 4.3, справедлив только для случая нахождения соответствующего сегмента в оперативной памяти. Если же бит присутствия в поле прав доступа равен нулю (сегмент отсутствует в памяти), то все биты, за исключением поля прав доступа, считаются неопределенными и могут использоваться системными программистами (для указания адреса сегмента во внешней памяти) произвольным образом.
Локальное адресное пространство задачи определяется через таблицу LDT (Local Descriptor Table). У каждой задачи может быть свое локальное адресное пространство. Общее, или глобальное, адресное пространство определяется через таблицу GDT (Global Descriptor Table). Само собой, что работу с этими таблицами (их заполнение и последующую модификацию) должна осуществлять операционная система. Доступ к таблицам LDT и GDT со стороны прикладных задач должен быть исключен.
При переключении микропроцессора в защищенный режим он начинает совершенно другим образом, чем в реальном режиме, вычислять физические адреса команд и
1 Естественно, совместимость обеспечена только «снизу вверх», то есть программы, разработанные для предыдущих версий микропроцессора, должны выполняться на последующих без какой-либо переделки.
Адресация в 32-разрядных микропроцессорах j80x86_________________________ 107
операндов. Прежде всего, содержимое сегментных регистров начинает интерпретироваться иначе: считается, что там содержится не адрес начала, а номер соответствующего сегмента. Для того чтобы подчеркнуть этот факт, сегментные регистры CS, SS, DS, ES, FS, GS начинают даже называть иначе — селекторами сегментов. При этом каждый селекторный регистр разбивается на три поля (рис. 4.4).
- Поле индекса (Index) — старшие 13 битов (3-15) определяет собственно номер
сегмента (его индекс в соответствующей таблице дескрипторов).
- Поле индикатора таблицы сегментов (Table Index, TI) — бит с номером 2 определяет часть виртуального адресного пространства (общее или принадлежащее только данной задаче). Если TI=0, то поле индекса указывает на элемент в глобальной таблице дескрипторов (GDT), то есть идет обращение к общей памяти. Если TI = 1, то идет обращение к локальной области памяти текущей задачи; это пространство описывается локальной таблицей дескрипторов (LDT).
- Поле уровня привилегий идентифицирует запрашиваемый уровень привилегий
(Requested Privilege Level, RPL).
Рис. 4.4. Селектор сегмента
Операционная система в процессе своего запуска инициализирует многие регистры, и прежде всего GDTR. Этот регистр содержит начальный адрес глобальной таблицы дескрипторов (GDT) и ее размер. Как мы уже знаем, в GDT содержатся дескрипторы глобальных сегментов и системные дескрипторы.
Для манипулирования задачами операционные системы поддерживают информационную структуру, которую мы уже раньше называли как дескриптор задачи (см. главу 1). Микропроцессоры с архитектурой IA32 поддерживают работу с наиболее важной частью дескриптора задачи, которая меньше всего зависит от операционной системы. Эта инвариантная часть дескриптора, с которой и работает микропроцессор, названа сегментом состояния задачи (Task State Segment, TSS). Перечень полей TSS показан на рис. 4.5. Видно, что этот сегмент содержит в основном контекст задачи. Процессор получает доступ к этой структуре с помощью регистра задачи (Task Register, TR).
Регистр TR содержит индекс (селектор) элемента в GDT. Этот элемент представляет собой дескриптор сегмента TSS. Дескриптор заносится в теневую часть регистра (см. рис. 4.2). К рассмотрению TSS мы еще вернемся, а сейчас заметим, что в одном из полей TSS содержится указатель (селектор) на локальную таблицу дескрипторов данной задачи. При переходе процессора с одной задачи на другую содержимое поля LDTR заносится микропроцессором в одноименный регистр. Инициализировать регистр TR можно и явным образом.
Итак, регистр LDTR содержит селектор, указывающий на один из дескрипторов таблицы GDT. Этот дескриптор заносится микропроцессором в теневую часть регистра LDTR и описывает таблицу LDT для текущей задачи. Теперь, когда у нас
108_______________ Глава 4. Особенности архитектуры микропроцессоров j80x86
определены как глобальная, так и локальная таблица дескрипторов, можно рассмотреть процесс определения линейного адреса1. Для примера рассмотрим процесс получения адреса команды. Адреса операндов определяются по аналогии, но задействованы будут другие регистры.
Рис. 4.5. Сегмент состояния задачи
Микропроцессор анализирует бит TI селектора кода и, в зависимости от его значения, извлекает из таблицы GDT или LDT дескриптор сегмента кода с номером (индексом), который равен полю индекса (биты 3-15 селектора на рис. 4.4). Этот дескриптор заносится в теневую (скрытую) часть регистра CS. Далее микропроцессор сравнивает значение регистра EIP (Extended Instruction Pointer — расширенный указатель команды) с полем размера сегмента, содержащегося в извлеченном дескрипторе, и если смещение относительно начала сегмента не превышает размера предела, то значение EIP прибавляется к значению поля начала сегмента, и мы получаем искомый линейный адрес команды. Линейный адрес — это одна из форм виртуального адреса. Исходный двоичный виртуальный адрес, вычисляе-
1 В микропроцессорах i80x86 линейным называется адрес, полученный в результате преобразования виртуального адреса формата (S, d) в 32-разрядный адрес.
Адресация в 32-разрядных микропроцессорах i80x86_________________________ 109
мый в соответствии с используемой схемой адресации, преобразуется в линейный. В свою очередь, линейный адрес будет либо равен физическому (если страничное преобразование отключено), либо путем страничной трансляции преобразуется в физический адрес. Если же смещение из регистра EIP превышает размер сегмента кода, то эта аварийная ситуация вызывает прерывание, и управление должно передаваться супервизору операционной системы.
Рис. 4.6. Процесс получения линейного адреса команды
110_______________ Глава 4. Особенности архитектуры микропроцессоров j80x86
Рассмотренный нами процесс получения линейного адреса иллюстрирует рис. 4.6. Стоит отметить, что поскольку межсегментные переходы происходят нечасто, то, как правило, определение линейного адреса заключается только в сравнении значения EIP с полем предела сегмента и в прибавлении смещения к началу сегмента. Все необходимые данные уже находятся в микропроцессоре, и операция получения линейного адреса происходит очень быстро.
Итак, линейный адрес может считаться физическим адресом, если не включен режим страничной трансляции адресов. К сожалению, аппаратных средств микропроцессора для поддержки рассмотренного способа двойной трансляции виртуальных адресов в физические явно недостаточно. При наличии большого количества небольших сегментов, из которых состоят программы, это приводит к заметному замедлению в работе процессора. В самом деле, теневой регистр при каждом селекторе имеется в единственном экземпляре, и при переходе на другой сегмент требуется вновь находить и извлекать соответствующий дескриптор сегмента, а это отнимает время. Страничный же способ трансляции виртуальных адресов, как мы знаем, имеет немало достоинств. Поэтому в защищенном режиме работы, при котором всегда действует описанный выше механизм определения линейных адресов, может быть включен еще и страничный механизм.