Лабораторная работа по MCFG: когда тайное становится явным

Известно, что организация PCI SIG, раз­ра­ба­ты­ва­ю­щая сис­тем­ные ши­ны ком­пью­те­р­ов, пре­до­став­ля­ет до­ступ к стан­дар­там и дру­гой до­ку­мен­та­ции тол­ько для за­ре­ги­стрирован­ных чле­нов. Для не­боль­ших ком­па­ний и част­ных лиц, сто­и­мость та­кой ре­гист­ра­ции мо­жет ока­зать­ся «не­подъ­ем­ной», осо­бен­но ес­ли ин­фор­ма­ция нуж­на для ис­сле­до­ва­тель­ских работ, сро­ки оку­па­е­мос­ти ко­то­рых труд­но про­гно­зи­ро­вать.

PCI Special Interest Group

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

Существует и другой путь. Очевидно, что архитектура, схемотехника и прог­рам­мные модели контроллеров шин и кон­фи­гу­ра­ци­он­ных регистров чипсетов ма­те­ринских плат строятся в соответствии со стандартами PCI SIG. Подробная до­ку­мен­та­ция на многие чипсеты доступна для свободной загрузки, например [9-11] и [14-15]. На­пом­ним, что со­вре­мен­ные про­цес­со­ры, построенные на основе ар­хи­тек­тур AMD64 и Intel Core i7, со­дер­жат контроллер опе­ра­тив­ной па­мя­ти, блоки кон­фи­гу­ра­ци­он­ных регистров и ряд других узлов, ранее раз­ме­ща­е­мых в составе Се­вер­но­го моста чип­се­та, архитектура которых также нормируется стандартами PCI SIG. Опи­са­ние данных устройств можно найти в [5-8] и [12-13].

Предлагаемый материал посвящен исследованию механизма MCFG (memory-map­ped configuration), пред­у­смат­ри­ва­ю­ще­му доступ к кон­фи­гу­ра­ци­он­ному про­стран­ству посредством окна в пространстве памяти. Этот механизм ис­поль­зу­ет­ся в системах с шинами PCI-X и PCI Express. Напомним, что в системах, под­дер­жи­ва­ю­щих только «старую» шину PCI (включая варианты PCI+AGP), для доступа к кон­фи­гу­ра­ци­он­ному про­ст­ран­ст­ву используются порты ввода-вывода с ад­ре­сами 0CF8h и 0CFCh, работа с которыми поддерживается сер­вис­ны­ми фун­к­ци­я­ми PCIBIOS.

Историческая справка

Очевидно, что все устройства, совместимые со спецификацией Plug and Play и под­дер­жи­вающие про­грам­мное уп­рав­ле­ние назначением системных ресурсов дол­жны иметь две группы регистров. Операционные регистры, пред­наз­на­че­ны для выполнения устройством своих обязанностей и используются во время ра­бо­че­го сеанса. Кон­фи­гу­ра­ци­он­ные регистры, пред­наз­на­че­ны для под­го­тов­ки ус­трой­ства к работе и наз­на­че­ния устройству системных ре­сур­сов (диапазона пор­тов, памяти, номеров линий запросов на прерывание и ка­на­лов DMA). Раз­ра­бот­чики спе­ци­фи­ка­ции PCI приняли решение выделить отдельное кон­фи­гу­ра­ци­он­ное пространство для размещения кон­фи­гу­ра­ци­он­ных ре­гист­ров.

Архитектура x86 поддерживает всего лишь два адресуемых пространства — па­мять и ввод-вывод. Каких-ли­бо спе­ци­аль­ных процессорных инструкций для до­сту­па к кон­фи­гу­ра­ци­он­ному пространству не существует, по­э­то­му чтение и за­пись регистров этого пространства базируется на использовании специальных окон в про­странствах ввода-вывода и памяти. Главным предметом рас­смот­ре­ния в дан­ной статье является усо­вер­шен­ство­ван­ный механизм доступа MCFG (memory-map­ped configuration), используемый в системах с шиной PCI Express.

Порты CONFIG_ADDRESS, CONFIG_DATA

Перед рассмотрением механизма MCFG, уместно вспомнить, как работает его предшественник — «старый» ме­тод до­сту­па, использующий порты с адресами 0CF8h и 0CFCh (32-битные CONFIG­_ADDRESS и CONFIG­_DATA). Для чтения заданного кон­фи­гу­ра­ци­он­ного ре­гист­ра программа записывает его 32-битный адрес в CONFIG­_ADDRESS, затем счи­ты­ва­ет порт CONFIG­_DATA. Для записи в регистр, его адрес также за­пи­сы­ва­ет­ся в порт CONFIG­_ADDRESS, а дан­ные для записи — в порт CONFIG­_DATA.

32-битный адрес регистра содержит его координаты в кон­фи­гу­ра­ци­он­ном пространстве: биты [0-7] = адрес ре­гист­ра, биты [8-10] = адрес функции, биты [11-15] = адрес устройства, биты [16-23] = адрес шины, биты [24-30] за­ре­зер­ви­ро­ва­ны, бит 31 должен быть установлен в "1" для разрешения цикла обращения к за­дан­но­му устройству. Из пе­ре­чис­лен­ных разрядностей следует, что можно ад­ре­со­вать максимум 256 регистров на функцию, 8 функций на устройство, 32 ус­трой­ства на шину, 256 шин. Записываемый адрес регистра всегда кра­тен 4, то есть два его младших бита нулевые и он задает базовый адрес 32-битного слова, которое может быть прочитано инструкцией IN EAX,DX или записано ин­ст­рук­ци­ей OUT DX,EAX по адресу CONFIG_DATA (0CFCh).

Напомним, что, как и в пространствах памяти и портов, в кон­фи­гу­ра­ци­он­ном пространстве адресуемым эле­мен­том является 1 байт, а посредством 32-битного ре­гист­ра CONFIG_DATA доступно 4 байта. Поэтому, если не­об­хо­ди­ма ин­ди­ви­ду­аль­ная адресация байтов или 16-битных слов внутри 32-битного слова, ис­поль­зу­ют­ся 8 и 16-битные формы указанных инструкций. При этом в зависимости от рас­по­ложения требуемого байта внутри 32-битного слова, адрес при обращении к регистру CONFIG­_DATA может принимать значения 0CFCh,...,0CFFh. Под­роб­ности в [2].

Функции PCI BIOS

Для доступа к кон­фи­гу­ра­ци­он­ному пространству были разработаны сервисные функции PCIBIOS. Модуль PCIBIOS входит в состав BIOS материнской платы. Номенклатура функций PCIBIOS обеспечивает 8, 16 и 32-бит­ные операции чтения и записи, а также сканирование шины с поиском устройств, удовлетворяющих за­дан­ным критериям, генерацию специальных циклов и ряд дополнительных функ­ций. Процедуры PCIBIOS ис­поль­зу­ют CONFIG­_ADDRESS и CONFIG­_DATA и являются программным интерфейсом между ОС и ука­зан­ны­ми портами. Подробности в [1].

Memory-mapped Configuration Space

Технология MCFG использует метод плоского доступа к кон­фи­гу­ра­ци­он­ному пространству, при котором все ре­гист­ры устройств доступны внутри окна раз­мером до 256 Мегабайт, расположенного в адресном про­ст­ран­ст­ве памяти. До­пол­ни­тель­ным новшеством является использование 4КБ ре­гист­ро­вых блоков для каждой PCI-функции, вместо 256-байтных. Очевидно, что для на­пи­са­ния программы, использующей эту технологию, нам требуется от­ве­тить на два во­про­са: как определить базовый адрес и размер окна, и по какому прин­ци­пу вну­три не­го ад­ре­су­ют­ся ячей­ки?

Базовый адрес и размер окна декларируется в ACPI таблице с сигнатурой MCFG. Процедуры де­тек­ти­ро­ва­ния под­держ­ки ACPI и поиска заданной таблицы опи­саны в [4] и рассмотрены ниже, при описании работы про­г­рам­мы. Таб­ли­ца со­дер­жит 36-байтный заголовок и основной блок. Заголовок содержит сигнатуру таблицы, байт контрольной суммы, длину таблицы, информацию о поставщике таблицы и компиляторе, с помощью ко­то­ро­го она создана. На­зна­че­ние по­лей за­го­лов­ка нормировано спецификацией ACPI, одинаково для всех ACPI таблиц и описано в [4]. Основной блок таб­ли­цы MCFG начинается с 8-байтного поля, обыч­но со­дер­жа­ще­го нули. Точные сведения о назначении этого поля от­сут­ст­ву­ют. Да­лее располагается последовательность де­скрип­то­ров, описывающая окна для доступа в кон­фи­гу­ра­ци­он­ное пространство. Платформы типовых пер­со­наль­ных компьютеров поддерживают только одно окно и, сле­до­ва­тель­но, таб­ли­ца MCFG бу­дет содержать один дескриптор. Количество дескрипторов можно определить, прочитав дли­ну таб­ли­цы из заголовка. Она указана с учетом длины заголовка. Формат дескриптора показан в Таблице 1.

Формат дескриптора таблицы MCFG, описывающего окно для доступа в конфигурационное пространство

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

Существует альтернативный путь определения базового адреса без ис­поль­зо­ва­ния ACPI – прямое счи­ты­ва­ние ре­гист­ров чип­сета. Но при этом потребуется на­пи­сать раздельные процедуры поддержки под каждый чип­сет, так как ар­хи­тек­ту­ра ин­те­ре­су­ющих нас регистров не стандартизована. Например, чип­сет Intel 915, а имен­но Северный мост Intel 82915 поддерживает регистр PCIEXBAR (PCI Ex­press Range Base Address Re­gis­ter), имеющий координаты в кон­фи­гу­ра­ци­он­ном пространстве Bus=0, Device=0, Function=0, Register=48h. Ре­гистр 32-битный, доступен для чтения и за­пи­си. Его значение численно равно базовому фи­зи­чес­ко­му ад­ре­су окна доступа в кон­фи­гу­ра­ци­он­ное пространство. Под­роб­нос­ти в [14]. Инициализация этого регистра вхо­дит в обязанности BIOS.

Северный мост Intel 82915 поддерживает PCIEXBAR-регистр с координатами в кон­фи­гу­ра­ци­он­ном пространстве Bus=0, Device=0, Function=0, Register=48h; регистр 32-битный, доступен для чтения и записи

 

Мы рассмотрели методы определения базового адреса 256-мегабайтного ок­на. Далее рассмотрим ад­ре­са­цию внутри окна. Напомним, что иерархия кон­фи­гу­ра­ци­он­ного пространства предусматривает 256 шин, 32 уст­рой­ст­ва на шину, 8 функций на устройство, 4096 байт регистров на функцию. Отсюда следует размер окна: 256 x 32 x 8 x 4096 = 268435456 байт = 256 Мбайт.

Боль­шин­ст­во платформ используют менее 256 шин, поэтому в целях эко­но­мии адресного пространства, раз­мер окна может быть сокращен и выбран в со­от­вет­ствии с реальным количеством шин. Адрес байта вну­т­ри окна формируется в соответствии с иерархией кон­фи­гу­ра­ци­он­ного пространства. Биты адреса 0-27, вы­би­ра­ю­щие байт в пределах 256МБ-окна используются согласно таблице 2.

Формирование адреса в пределах 256-мегабайтного окна

Формализуем сказанное. Для доступа к регистру кон­фи­гу­ра­ци­он­ного про­стран­ства с заданными ко­ор­ди­на­та­ми Bus, Device, Function, Register, требуется об­ра­тить­ся по адресу

Address = MCFG_Base+1048576 * Bus+32768*Device+4096*Function+Register

где MCFG_Base — базовый адрес окна, полученный методами, рассмотренными выше (посредством ACPI или прямым чтением регистров чип­се­та).

Почти все современные платформы, использующие механизм MCFG, также под­дер­жи­ва­ют порты CONFIG_ADDRESS, CONFIG_DATA и функции PCIBIOS в це­лях совместимости со «старым» программным обес­пе­че­ни­ем. При этом, ис­поль­зуя «старый» протокол можно обратиться только к 256 младшим ре­гист­рам 4-ки­ло­байт­ных регистровых блоков «новых» устройств.

Заслуживает отдельного рассмотрения еще один аспект. Напомним, что при об­ращении к оперативной па­мя­ти, про­цес­сор оп­ти­ми­зи­ру­ет по­сле­до­ва­тель­ность шин­ных циклов с целью повышения производительности. Оп­ти­ми­за­ция такого ро­да вклю­чает в себя кэширование, отложенную запись, объединение не­сколь­ких цик­лов чтения или записи малой разрядности в один цикл большей разрядности и т.п. Очевидно, что все эти дей­ст­вия, допустимые для опе­ра­тив­ной памяти, не­допустимы при работе с регистрами устройств, ото­бра­жен­ны­ми на память. Здесь по­сле­до­ва­тель­ность вы­пол­не­ния и разрядности шинных циклов должны стро­го со­от­вет­ствовать порядку, пред­пи­сан­но­му про­г­рам­мой.

Что произойдет, если, например, будет кэширован регистр, отражающий из­ме­не­ние состояния некоторого уст­рой­ст­ва? Процессор, после выполнения первого цикла чтения из устройства, при всех повторных считываниях будет брать ко­пию ре­гистра, сохраненную в кэш-памяти, без повторного обращения к устройству (в чем, собственно, и состоит смысл кэширования). Если состояние устройства из­ме­нит­ся, процессор этого «не заметит», так как читает информацию из сво­ей кэш-памяти, а не из устройства.

Избежать проблем, подобных рассмотренной, помогают регистры MTRR (Memory Type Range Registers), вхо­дя­щие в состав процессора и позволяющие назначать различные статусы заданным регионам адресного про­ст­ран­ст­ва па­мя­ти. При этом кэширование и другая оптимизация разрешаются или запрещаются в за­ви­си­мос­ти от статуса региона, к которому обращается процессор. Вопросы ор­га­ни­за­ции регистров, ото­бра­жен­ных на память (Memory-Mapped I/O) рас­смот­ре­ны в ранее опубликованной статье «Устройства сис­тем­ной поддержки». Ис­сле­до­ва­тель­ская работа №7.

Описание работы программы

Как и в ранее опубликованных статьях данного цикла, в целях монопольного и беспрепятственного вза­и­мо­дей­ст­вия про­г­рам­мы с обо­ру­до­ва­ни­ем при работе с предлагаемым примером, автор применил древнюю тех­но­ло­гию отладки под DOS. Аргументация такого шага и рекомендации по организации рабочего места при­ве­де­ны в ранее опуб­ли­ко­ван­ной статье «64-битный режим под DOS». Ис­сле­до­ва­тельская работа №1.

Ассемблерный пример демонстрирует чтение 4-ки­ло­байт­ного блока кон­фи­гу­ра­ци­он­ных регистров устройства с ко­ор­ди­на­тами Bus=0, Device=0, Function=0. В большинстве платформ данные координаты имеет блок кон­фи­гу­ра­ци­он­ных регистров Северного моста. Работа программы не за­ви­сит от содержимого читаемой об­лас­ти. Если по указанным ко­ор­ди­на­там ус­трой­ство отсутствует, все прочитанные байты будут равны FFh. Программа вы­во­дит шест­над­ца­те­рич­ный дамп ре­гист­ро­во­го блока.

Состав программы доступа к конфигурационным регистрам

Рассмотрим выполнение программы чтения кон­фи­гу­ра­ци­он­ного пространства с использованием механизма MCFG. Нумерация пунктов приведенного ниже ал­го­рит­ма соответствует нумерации пунктов в комментариях к ис­ход­но­му тексту про­грам­мы. (См. файл mcfg.asm).

  1. Установка адреса стека, загрузка регистров SS и SP.
  2. Установка видеорежима 3 (текст 80x25 символов), очистка экрана.
  3. Проверка типа процессора. Выход с ошибкой, если процессор ниже 80386. Проверка требуется для того, чтобы при попытке запуска на старых компьютерах, программа выходила с сообщением об ошибке, а не зависала.
  4. Проверка режима работы процессора. Выход с ошибкой, если процессор ра­бо­та­ет в Protected Mode. Так как программа использует прямое вза­и­мо­дей­ствие с аппаратными ресурсами, для ее работы требуется чистый DOS.
  5. Разрешение адресной линии A20. Вначале проверяется и сохраняется для последующего восстановления исходное состояние A20. Если линия A20 исходно раз­ре­ше­на, пропускаем вызов процедуры управления. Если при управлении ли­ни­ей A20 возникли ошибки, выполняется выход с сообщением об ошибке. Под­роб­нос­ти в [17].
  6. Разрешение режима Big Real Mode для адресации диапазона памяти 0-4GB. Для этого, подпрограмма Enable_Big_Real_Mode временно переключает процессор в Protected Mode и загружает лимиты сегментов значением FFFFFFFFh. Пос­ле возврата в Real Mode значения лимитов не изменяются, что дает воз­мож­ность использовать 32-битные адреса в Real Mode. Под­роб­нос­ти в [16].
  7. Проверка поддержки интерфейса ACPI. Подпрограмма Scan_ACPI_RSDP сканирует диапазон адресов BIOS Runtime (E0000h-FFFFFh, 128KB) на предмет об­на­ру­же­ния структуры Root System Description Pointer (RSDP). Данная структура со­дер­жит указатель на корневую таблицу Root System Description Table (RSDT). Все таблицы ACPI обычно находятся в верхнем мегабайте Extended памяти. От­сут­ствие структуры RSDP означает, что платформа не поддерживает ACPI. В этом слу­чае программа завершается с сообщением об ошибке. Подробности в [4].
  8. Поиск ACPI-таблицы с сигнатурой MCFG. Эта таблица описывает па­ра­мет­ры механизма плоского доступа к конфигурационному пространству. Она со­дер­жит базовый адрес и размер окна в пространстве памяти. Подпрограмма Get­_ACPI­_Table последовательно использует два метода обнаружения искомой та­б­ли­цы – путем поиска в каталоге таблиц, находящемся в RSDT и путем прямого ска­ни­рования памяти от начала RSDT до конца текущего 64KB блока. Это свя­за­но с тем, что в некоторых реализациях BIOS, каталог содержит ссылки не на все име­ю­щиеся таблицы. Отсутствие таблицы MCFG означает, что платформа не под­дер­жи­ва­ет механизм плоского доступа. В этом случае программа за­вер­ша­ет­ся с сообщением об ошибке. Подробности в [4].
  9. Используя базовый адрес таблицы MCFG, полученный на предыдущем ша­ге, считываем из нее параметры для механизма плоского доступа к кон­фи­гу­ра­ци­он­но­му пространству – базовый адрес и размер окна в про­стран­стве памяти.

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

  1. Вывод на экран базового адреса и размера диапазона MCFG.
  2. Проверка корректности базового адреса диапазона MCFG. Если адрес ну­ле­вой или не кратен 4KB, программа завершается с сообщением об ошибке.

Примечание. На платформах, поддерживающих 64-битную адресацию, диапазон MCFG мо­жет находиться вы­ше 4GB. Данная версия программы не поддерживает такой ва­ри­ант размещения диапазона MCFG.

  1. Считывание 4К-байтного блока конфигурационных регистров из устройства с координатами Bus=0, Device=0, Function=0. Физически, данный блок рас­по­ло­жен по адресам X…X+0FFFh, где X=базовый адрес диапазона MCFG.
  2. Вывод сообщения перед началом вывода дампа регистров. Ожидание на­жа­тия клавиши пользователем.
  3. Вывод дампа регистров. Дамп 4 килобайт не помещается на экран, по­э­то­му после заполнения экрана ожидается нажатие клавиши. При нажатии [Enter] вывод дампа продолжается, [Esc] прерывает операцию.
  4. Подготовка к завершению программы. Выключаем режим Big Real Mode (устанавливаем лимиты сегментов 0000FFFFh для 16-битной адресации) и вос­ста­нав­ли­ва­ем исходное состояние адресной линии A20. Подробности в [16-17].
  5. Вывод сообщения об успешном завершении программы, ожидание на­жа­тия клавиши и выход в ОС с кодом завершения 00h.
  6. Если при запуске программы возникли ошибки на этапах, расположенных пос­ле разрешения линии A20 и включения Big Real Mode, перед завершением про­грам­мы требуется восстановить состояние линии A20 и выключить Big Real Mode. Эти действия и выполняются на данном этапе.
  7. Завершение программы, используемое при ошибках. Вывод сообщения об ошибке, ожидание нажатия клавиши и выход в ОС с кодом завершения 01h. При пе­ре­хо­де к этому пункту, регистр AX должен содержать указатель на строку со­об­ще­ния об ошибке.

Заключение

Ну не может PCI SIG запретить детям раз­би­рать игрушки и смотреть, как они уст­ро­е­ны внутри. Да­же ес­ли иг­руш­ки 64-бит­ные, а детям за 40 лет.

Разумеется, несмотря на офи­ци­аль­ную за­кры­тость спе­ци­фи­ка­ции PCI Ex­press, дан­ное ис­сле­до­ва­ние не пре­тен­ду­ет на рас­кры­тие каких-либо страш­ных тайн, так как вся при­ве­ден­ная ин­фор­ма­ция яв­ля­ет­ся ре­зуль­та­том из­у­че­ния от­кры­тых ис­точ­ни­ков (спи­сок ко­то­рых при­ла­га­ет­ся) в со­че­та­нии с ми­ни­маль­ным уме­ни­ем чи­тать меж­ду строк.

Источники информации

Электронные документы, доступные на сайте PCI SIG

  1. PCI BIOS Specification. Revision 2.1.
  2. PCI Local Bus Specification. Revision 3.0.
  3. PCI-to-PCI Bridge Architecture Specification. Revision 1.1.

Электронные документы, доступные на сайте ACPI

  1. Advanced Configuration and Power Interface Specification. Revision 3.0.

Электронные документы, доступные на сайте AMD

  1. BIOS and Kernel Developer's Guide for AMD Athlon 64 and AMD Opteron Processors. Publication #26094.
  2. BIOS and Kernel Developer's Guide for AMD NPT Family 0Fh Processors. Publication #32559.
  3. BIOS and Kernel Developer's Guide (BKDG) For AMD Family 10h Processors. Publication #31116.
  4. BIOS and Kernel Developer's Guide (BKDG) For AMD Family 11h Processors. Publication #41256.
  5. AMD-8131 HyperTransport PCI-X Tunnel Data Sheet. Publication #24637.
  6. AMD-8151 HyperTransport AGP3.0 Graphics Tunnel Data Sheet. Publication #24888.
  7. AMD-8111 HyperTransport I/O Hub Data Sheet. Publication #24674.

Электронные документы, доступные на сайте Intel Corp.

  1. Intel Core i7 Processor Extreme Edition and Intel Core i7 Processor. Datasheet, Volume 1. Document #320834-001.
  2. Intel Core i7 Processor Extreme Edition and Intel Core i7 Processor. Datasheet, Volume 2. Document #320835-002.
  3. Intel 915G/915P Express Chipset Datasheet. Document #301467-001.
  4. Intel I/O Controller Hub 6 Family Datasheet. Document #301473-001.

Книги

  1. В.Л. Григорьев. Микропроцессор i486. Архитектура и программирование. — М., 1993: «Гранал»
  2. В.А. Вегнер, А.Ю. Крутяков, В.В. Серегин, В.А. Сидоров, А.В. Спесивцев. Аппаратура персональных компьютеров и ее программирование. IBM PC/XT/AT и PS/2. — М., 1995: «Радио и связь»

Загрузить ZIP-архив 
с примером программирования
на ассемблере
можно здесь.