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 Register), имеющий координаты в кон­фи­гу­ра­ци­он­ном пространстве 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 Express, данное исследование не претендует на раскрытие каких-либо страшных тайн, так как вся приведенная информация является результатом изучения открытых источников (список которых прилагается) в сочетании с минимальным умением читать между строк.

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

Электронные документы, доступные на сайте 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: «Радио и связь»