Специалистам по аппаратному обеспечению и системным программистам, работающим
с платформой PC, хорошо знаком "джентльменский набор" микросхем системной
поддержки: контроллер прямого доступа к памяти (DMA) Intel 8237 (К1810ВТ37),
контроллер прерываний Intel 8259A (К1810ВН59А), системный таймер Intel 8254
(К1810ВИ54). Несмотря на то, что на современной материнской плате уже давно
нельзя увидеть перечисленные компоненты в виде отдельных микросхем (они
реализованы в составе "южного моста" чипсета) на уровне программной модели они,
как и древняя шина ISA, по-прежнему существуют.

Но время идет, и требования к материнским платам существенно возрастают.
Поэтому, инженеры пошли по пути добавления новых устройств системной поддержки,
с сохранением старых, для обеспечения совместимости. Рассмотрим подробнее,
почему современных разработчиков уже не устраивают эти "старые знакомые", и
какие устройства пришли им на смену.

"Старый" контроллер DMA, основанный на двух каскадно-включенных
микросхемах Intel 8237, обеспечивает четыре 8-разрядных и три 16-разрядных
канала. Он использует 24-битный адрес при обращении к памяти, следовательно,
может работать только с младшими 16MB. Разрядность пересылаемых данных 8 и 16
бит. Хотя были разработаны реализации 8237-подобных контроллеров, позволяющие
обойти данные ограничения, кардинальным решением это не стало. Поэтому сегодня,
для пересылки данных между периферийным устройством и памятью без участия
процессора, используется технология Bus Mastering, при которой контроллер
периферийного устройства (например, IDE или SATA) сам работает как инициатор
шинных циклов, то есть имеет свой собственный контроллер DMA. При этом
пропускная способность шин памяти и ввода-вывода используется значительно
эффективнее, так как трафик не ограничен возможностями контроллера 8237. Многие
Bus Mastering устройства также имеют аппаратную поддержку для пересылки
фрагментированных блоков, состоящих из 4KB страниц, которые могут быть
расположены не последовательно. То есть при работе с фрагментированным буфером
не потребуется вмешательство процессора после пересылки каждой страницы, даже
если следующая страница не примыкает к текущей. Технология Bus Mastering
использует децентрализацию (свой контроллер DMA в каждом устройстве), вместо
одного центрального контроллера DMA. Вместе с тем, централизованный подход в
последнее время получил возрождение в ряде серверных чипсетов Intel, но это тема
для отдельной статьи.

Примером устройства, до сих пор использующего "старый" контроллер DMA,
является контроллер гибких дисков, его не перевели на новую технологию, так как
скорость передачи данных здесь существенно ограничена возможностями самого
дисковода.

"Старый" контроллер прерываний, основанный на двух каскадно-включенных
микросхемах Intel 8259A, имеет 15 линий запросов на прерывание. Для современной
платформы, это, конечно же, мало, но применение технологии IRQ Sharing,
позволяющей нескольким устройствам совместно использовать одну линию IRQ,
оттеснило данную проблему на второй план. На первом же плане, при принятии
решения о переходе к новой реализации подсистемы прерываний, стояла поддержка
мультипроцессорных систем (включая
Multi-Core и
Hyper-Threading системы). В таких системах межпроцессорное взаимодействие
базируется на прерываниях IPI (Inter-Processor Interrupt), передаваемых
от одного процессора к другому. Также усложнился алгоритм арбитража: теперь
нужно не только выбирать наиболее приоритетный запрос IRQ из нескольких
одновременно активных, но и выбирать наименее приоритетный процессор, на который
будет направлен данный запрос, так как логичнее прервать выполнение наименее
важной процедуры. Приоритеты процессоров изменяются динамически в соответствии с
приоритетами выполняемых ими процедур. Для решения данных задач была разработана
архитектура APIC (Advanced Programmable Interrupt Controller), пришедшая
на смену контроллерам Intel 8259. Также получила развитие технология MSI
(Message Signaled Interrupts)
, основанная на передаче запросов на прерывание
не выделенными сигнальными линиями, а циклами записи в память (сообщениями).
Разумеется, используется запись не в оперативную память, а в регистры APIC,
расположенные в пространстве памяти.

"Старый" таймер, основанный на микросхеме Intel 8254 (в первых IBM
PC/XT использовался таймер Intel 8253), имеет три 16-битных счетчика (каналы
0,1,2), тактируемых частотой около 1.193 MHz. Канал 0 используется для генерации
периодических прерываний IRQ0. BIOS устанавливает для него максимальный
коэффициент деления, равный 65536 (2 в степени 16). Поэтому частота прерываний
приближенно равна 1.193 MHz / 65536 = 18.204 Hz. Прерывания от
таймера используются для подсчета времени DOS Time, выключения двигателя флоппи
дисковода при отсутствии обращений в течение заданного интервала времени и
других функций. Канал 1 в "древних" системах IBM PC/XT/AT использовался для
периодического формирования запросов на регенерацию динамического ОЗУ. Но еще во
времена процессоров 80386/80486, начали разрабатывать интеллектуальные
контроллеры ОЗУ, которые выбирают момент для выполнения регенерации так, чтобы
минимизировать простои процессора. Такие контроллеры обычно имеют внутренний
таймер и не используют канал 1 системного таймера. Для совместимости, набор
программно-доступных регистров канала 1 сохранен и большинство BIOS его
инициализируют на коэффициент деления, равный 18. Канал 2 используется для
генерации звука на PC Speaker. Частота звука зависит от запрограммированного
коэффициента деления частоты. Дополнительный порт с адресом 0061h используется
для управления работой канала 2 и прохождением сигнала на PC Speaker.

Разрядность "старого" таймера (16 бит) и разрешающая способность (1/1.193 MHz
= 838 наносекунд) не устраивают современные приложения. Также существует
потребность в более гибком управлении генерацией прерываний. Поэтому был
разработан таймер HPET (High Precision Event Timer), детально
рассмотренный в данной статье.

Примечание. Термин HPET имеет устаревший синоним — MMT или
Multimedia Timer
.

 

О предметной области

HPET или High Precision Event Timer физически расположен в
составе "южного моста" чипсета. В модельном ряду чипсетов Intel, таймер HPET
впервые появился в микросхеме ICH5, используемой в качестве "южного моста"
чипсетов Intel 865, 875, 848. В модельном ряду чипсетов AMD, таймер HPET впервые
появился в микросхеме 8111 (Hyper-Transport I/O Hub), которая входит в состав
чипсета AMD8000 (хронологически первый чипсет для платформы AMD64).

Для того, чтобы таймер HPET был доступен в адресном пространстве и распознан
операционной системой, BIOS, при старте платформы, должен выполнить
подготовительную работу, состоящую из двух основных операций. Во-первых,
необходимо запрограммировать конфигурационные регистры "южного моста",
управляющие разрешением доступа к HPET и выбором адресного диапазона для него,
это обеспечит физическую доступность регистров HPET. Во-вторых, необходимо
декларировать наличие HPET в таблицах ACPI, которые генерируются при старте
платформы в верхних адресах оперативной памяти для передачи конфигурационной
информации от BIOS к ОС, это обеспечит распознавание HPET операционной системой.
Отметим, что существует много платформ, использующих чипсеты с поддержкой HPET,
но не поддерживающих HPET, из-за того, что BIOS его не включает. Прошивка новой
версии BIOS с сайта производителя платы решит эту проблему, если конечно
разработчик BIOS добавил поддержку HPET. Иногда, в BIOS Setup есть опция для
разрешения HPET, при этом, бывает, что по умолчанию HPET выключен, поэтому нужно
проконтролировать и это.

Таймер HPET является главным предметом рассмотрения в статье. Вместе с
тем, понимая, что данная тема слишком узкая для целой статьи, автор на примере
HPET стремился осветить ряд вопросов, связанных с функционированием современных
платформ: memory-mapped I/O, взаимодействие BIOS и ОС посредством интерфейса
ACPI, программирование конфигурационных регистров чипсета. Также рассмотрен
пример на ассемблере – измерение тактовой частоты процессора с использованием
"старого" таймера и таймера HPET.

 

Memory-mapped I/O (MMIO)

Известно, что процессоры семейства x86 поддерживают два адресных пространства
– память и ввод-вывод. В "древних" системах IBM PC/XT/AT использование этих
пространств полностью соответствовало их названию: в пространстве памяти
находилось ОЗУ, ПЗУ BIOS, видео память, а в пространстве ввода-вывода регистры
управления и статуса различных системных и периферийных устройств (контроллеры
DMA, прерываний, таймер, порты COM, LPT и т. п.). По мере развития платформы PC,
производительность и функциональность схем системной поддержки и периферийных
устройств возрастала, и пространство ввода-вывода перестало устраивать
разработчиков по двум причинам: ограниченный объем (64 Кбайт) и ограниченная
поддержка в системе команд процессора. Рассмотрим вторую причину более детально:
для чтения данных из порта и записи данных в порт предусмотрены инструкции IN и
OUT соответственно. Каждая из них имеет две формы: с прямой адресацией (адрес
порта находится во втором байте инструкции) и косвенной (адрес порта находится в
регистре DX). При этом форма с прямой адресацией использует 8-битный адрес порта
и позволяет работать с 256 портами 0000h-00FFh. Для доступа к 64KB портов можно
использовать только косвенную форму. Для работы с ячейками памяти используется
значительно более мощная система адресации. Адрес может находиться в 16, 32,
64-битном регистре, может быть представлен 16, 32, 64-битной константой, а также
суммой нескольких регистров и константы. Ячейку памяти можно не только читать и
писать, но и выполнять одной инструкцией сохранение в стеке, восстановление из
стека, операции типа считывание-модификация-запись, то есть инвертировать,
инкрементировать, прибавлять константу и т. п.

Поясним сказанное на примере. Допустим, нам необходимо в регистре управления
некоторого устройства установить в "1" бит 7, оставив остальные биты без
изменений. Если регистр расположен в пространстве ввода-вывода, необходимо три
инструкции:

IN AL, <адрес порта>
OR AL,10000000b
OUT <адрес порта>, AL

Если регистр расположен в пространстве памяти, достаточно одной инструкции:

OR BYTE PTR <адрес ячейки>, 10000000b

Процессор автоматически выполнит считывание ячейки, модификацию прочитанных
данных во внутреннем буфере (логическое ИЛИ с константой 10000000b) и запись
обратно в ячейку.

Таким образом, по рассмотренным выше причинам, большинство современных
устройств, например контроллеры RAID, USB OHCI, USB EHCI, APIC, рассматриваемый
здесь таймер HPET и многие другие, используют технологию memory-mapped I/O, то
есть их регистры адресуются как ячейки памяти.

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

Но что произойдет, если эту технологию применить при чтении регистра статуса
некоторого устройства? Допустим, наша программа ожидает в цикле установки бита
готовности в регистре статуса:

Label: TEST BYTE PTR <адрес ячейки>, 000000001b ; бит 0 = Ready flag
JZ Label

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

Для решения данной проблемы, а также ряда подобных проблем, связанных с
кэшированием, опережающим чтением и отложенной записью в современных процессорах
x86 используются регистры MTRR (Memory Type Range Registers), позволяющие
разбить адресное пространство памяти на регионы и присвоить каждому региону свой
статус, в зависимости от характера использования данного региона. Предусмотрены
следующие статусы для регионов памяти:

WB (Write-Back) – разрешены все действия для оптимизации
производительности: кэширование, опережающее чтение и отложенная запись. Обычно
этот статус назначается регионам, в которых находится ОЗУ (RAM).

WT (Write-Through) – разрешены все действия для оптимизации
производительности, кроме отложенной записи. При работе с данным регионом, в
случае записи в память, процессор должен сразу обновить данные в кэш и
оперативной памяти. Этим данный статус отличается от статуса Write-Back, при
котором данные обновляются в кэш, а запись в ОЗУ происходит "при удобном
случае": когда свободна шина, когда строка вытесняется из кэш новыми данными или
при принудительной очистке кэш.

WC (Write-Combining) – кэширование не используется, но разрешены
следующие операции, оптимизирующие использование шины. Группировка нескольких
последовательных шинных циклов записи малой разрядности в один цикл, разрядность
которого равна физической разрядности шины. При чтении данных малой разрядности,
выполняется чтение, разрядность которого равна разрядности шины. По статистике,
программы часто обращаются по смежным адресам, поэтому такая замена нескольких
циклов обращения малой разрядности одним циклом большой разрядности увеличивает
производительность. Данные, прочитанные "за одно", с высокой вероятностью будут
востребованы. Обычно этот статус назначается регионам, в которых находится видео
память.

WP (Write-Protected) – память кэшируется на чтение, но защищена от
записи. Отметим, что физической блокировки циклов записи на шине процессор не
выполняет, это обязанность внешних схем (чипсета), а смысл данного статуса в
том, чтобы запретить запись в кэш-память внутри процессора. Если этого не
сделать, кэшируемое ПЗУ в адресном пространстве может "видится" как ОЗУ, то есть
содержимое ячеек изменяется после записи в них. Это связано с тем, что в
кэш-памяти будет перезаписано содержимое ячейки, несмотря на то, что по данному
адресу находится ПЗУ, содержимое которого не изменилось при попытке выполнения
записи. Обычно этот статус назначается регионам, в которых находится ПЗУ (ROM)
или Shadow RAM (ОЗУ в режиме эмуляции ПЗУ).

UC (Uncacheable) – запрещено кэширование и все действия, направленные
на увеличение производительности. Для регионов памяти, имеющих такой статус,
процессор выполняет только те операции, которые явно указаны в программе.
Запрещена любая "инициатива" со стороны процессора по изменению разрядности
шинных циклов и порядка их выполнения. Этот статус назначается регионам, в
которых находятся регистры управления и состояния различных устройств (MMIO,
Memory-mapped I/O), он позволяет сохранить протокол взаимодействия с устройством
на уровне шинных циклов в том виде, в каком его написал программист.

Подробности в [5], [10], [14], [15], [16].

Рассматриваемый в данной статье таймер HPET использует MMIO, его регистры
расположены в пространстве памяти, это одно из его отличий от "старого" таймера
Intel 8254, использующего порты 0040h-0043h. Как было показано выше, регион
памяти, содержащий MMIO должен иметь статус Uncacheable. Присвоение этого
статуса (то есть программирование MTRR) выполняет BIOS при старте платформы.

 

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

Электронные документы, доступные на сайте
developer.intel.com.

1) IA-PC HPET (High Precision Event Timers) Specification. Revision 1.0a.
2) Intel 64 and IA-32 Architectures Software Developer’s Manual. Volume 1: Basic
Architecture. Order Number 253665-023US.
3) Intel 64 and IA-32 Architectures Software Developer’s Manual. Volume 2A:
Instruction Set Reference, A-M. Order Number 253666-023US.
4) Intel 64 and IA-32 Architectures Software Developer’s Manual. Volume 2B:
Instruction Set Reference, N-Z. Order Number 253667-023US.
5) Intel 64 and IA-32 Architectures Software Developer’s Manual. Volume 3A:
System Programming Guide, Part 1. Order Number 253668-023US.
6) Intel 64 and IA-32 Architectures Software Developer’s Manual. Volume 3B:
System Programming Guide, Part 2. Order Number 253669-023US.
7) Intel 915G/915P Express Chipset Datasheet. Document Number 301467-001.
8) Intel I/O Controller Hub 6 (ICH6) Family Datasheet. Document Number
301473-001.

Электронные документы, доступные на сайте
developer.amd.com.

9) AMD64 Architecture Programmer’s Manual. Volume 1: Application Programming.
Publication No. 24592.
10) AMD64 Architecture Programmer’s Manual. Volume 2: System Programming.
Publication No. 24593.
11) AMD64 Architecture Programmer’s Manual. Volume 3: General-Purpose and System
Instructions. Publication No. 24594.
12) AMD64 Architecture Programmer’s Manual. Volume 4: 128-Bit Media
Instructions. Publication No. 26568.
13) AMD64 Architecture Programmer’s Manual. Volume 5: 64-Bit Media and x87
Floating-Point Instructions. Publication No. 26569.
14) BIOS and Kernel Developer’s Guide for AMD Athlon 64 and AMD Opteron
Processors. Publication No. 26094.
15) BIOS and Kernel Developer’s Guide for AMD NPT Family 0Fh Processors.
Publication No. 32559.
16) BIOS and Kernel Developer’s Guide (BKDG) For AMD Family 10h Processors.
Publication No. 31116.

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

17) PCI BIOS Specification. Revision 2.1.

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

18) Advanced Configuration and Power Interface Specification. Hewlett-Packard
Corporation, Intel Corporation, Microsoft Corporation, Phoenix Technologies
Ltd., Toshiba Corporation. Revision 3.0.

 

Книги

19) В.Л. Григорьев. Микропроцессор i486. Архитектура и программирование.
Москва ТОО “ГРАНАЛ” 1993.
20) В.Г. Артюхов, А.А. Будняк. В.Ю. Лапий. С.М. Молявко, А.И. Петренко.
Проектирование микропроцессорной электронно-вычислительной аппаратуры.
Справочник. Киев “Тэхника” 1988.
21) К. Г. Самофалов, О.В. Викторов. Микропроцессоры. Библиотека инженера. Киев
“Тэхника” 1989.
22) 2B ProGroup: В.А. Вегнер, А.Ю. Крутяков, В.В. Серегин, В.А. Сидоров, А.В.
Спесивцев. Аппаратура персональных компьютеров и ее программирование. IBM
PC/XT/AT и PS/2. Москва “Радио и связь” 1995.
23) Ю.М. Казаринов, В.Н. Номоконов, Г.С. Подклетнов, Ф.В. Филиппов.
Микропроцессорный комплект К1810. Структура, программирование, применение.
Справочная книга. Москва “Высшая школа” 1990.

Оставить мнение

Check Also

Что можно сделать с iPhone, зная пасскод. Как сливают данные, уводят iCloud и блокируют остальные устройства

Последние несколько месяцев мы много писали о нововведениях в iOS 11. «Теперь-то заживем!»…