IA-PC HPET (отметчик времени случая высокой точности) спецификация которая совместно была начата Intel и Майкрософт в начале этой декады. Самая последняя версия dated октябрь 2004. Она заявляла что цель к
первоначально дополните и окончательно замените отметчик времени интервала наследия 8254 Programmable и функции поколения Interrupt реальнего маштаба времени периодические которое в настоящее время использованы как оборудование de-facto' отметчика времени `для IA-ПК.
Зодчество HPET определяет комплект отметчиков времени которые могут быть использованы операционной системой. Блок отметчика времени сочетание из одиночный счетчик и до 32 компараторы и регистра спички. Компаратор сравнивает содержание регистра спички против значения вверх-счетчика работающий вхолостую монотонно. Когда выход вверх-счетчика приравнивает значение в регистре спички interrupt произведен. Каждый из компараторов может вывести наружу interrupt. Максимум 8 блоков отметчика времени поддержан для итога 256 отметчиков времени. Каждый блок отметчика времени может иметь различные хронометрируя атрибуты. Специфические вставкы могут включить только подсовокупность этих отметчиков времени. Минимум 3 отметчика времени необходимы.
Спецификация содержит следующую блок-схему зодчества HPET.

Некоторые из отметчиков времени могут быть позволены произвести периодический interrupt. Если отметчик времени установлен для того чтобы быть периодическ, то свой период добавлен к регистру спички каждый раз спичка происходит, таким образом вычисляя the next time для этого отметчика времени для того чтобы произвести interrupt. Вверх-счетчик обычно 64 бита широко но трицатидвухразрядные вставкы позволены спецификацией и 64ыми-разрядн вверх-счетчиками можно также управлять в трицатидвухразрядном режиме. Вверх-счетчики бегут на минимуме 10 MHz. что гораздо быстре чем более старое RTC (реальний маштаб времени) и может таким образом произвести периодические interrupts на гораздо высокее разрешении. Регистры связали с этими отметчиками времени составлены карту к области памяти.
Функциональность польз ACPI BIOS (предварительный интерфейс конфигурации и силы) для того чтобы сообщить операционная система положения HPET памят-составила карту космос регистра. Здесь пример демонтированной таблицы ACPI HPET от материнской платы Intel DX48BT2 (AKA BoneTrail).
$ cat /sys/firmware/acpi/tables/HPET > /var/tmp/hpet.out $ iasl -d /var/tmp/hpet.out $ cat /var/tmp/hpet.dsl /* * Intel ACPI Component Architecture * AML Disassembler version 20090123 * * Disassembly of /var/tmp/hpet.out, Sun Jul 5 19:34:47 2009 * * ACPI Data Table [HPET] * * Format: [HexOffset DecimalOffset ByteLength] FieldName : FieldValue */ [000h 000 4] Signature : "HPET" /* High Precision Event Timer table */ [004h 004 4] Table Length : 00000038 [008h 008 1] Revision : 01 [009h 009 1] Checksum : CE [00Ah 010 6] Oem ID : "INTEL " [010h 016 8] Oem Table ID : "DX48BT2 " [018h 024 4] Oem Revision : 0000076E [01Ch 028 4] Asl Compiler ID : "MSFT" [020h 032 4] Asl Compiler Revision : 01000013 [024h 036 4] Hardware Block ID : 8086A301 [028h 040 12] Timer Block Register :[028h 040 1] Space ID : 00 (SystemMemory) [029h 041 1] Bit Width : 00 [02Ah 042 1] Bit Offset : 00 [02Bh 043 1] Access Width : 00 [02Ch 044 8] Address : 00000000FED00000 [034h 052 1] Sequence Number : 00 [035h 053 2] Minimum Clock Ticks : 0001 [037h 055 1] Flags (decoded below) : 00 Page Protect : 0 4K Page Protect : 0 64K Page Protect : 0 Raw Table Data 0000: 48 50 45 54 38 00 00 00 01 CE 49 4E 54 45 4C 20 HPET8.....INTEL 0010: 44 58 34 38 42 54 32 20 6E 07 00 00 4D 53 46 54 DX48BT2 n...MSFT 0020: 13 00 00 01 01 A3 86 80 00 00 00 00 00 00 D0 FE ................ 0030: 00 00 00 00 00 01 00 00 ........ $
См., что страница 30 спецификации HPET v1.0a для детального нервного расстройства индивидуальных битов в случае приурочивает блок (вызванный Оборудованием Преграждать disassember AML). Заметьте что только одному блоку отметчика времени случая нужно быть описанным в таблице HPET для того чтобы bootstrap операционная система. Это случай здесь. Для платформ non-наследия, блок отметчика времени случая описанный в HPET одно которое обеспечивает функциональность для того чтобы заменить периодическую логику Interrupt 8254/RTC.
Другие блоки времени случая описаны в namespace ACPI. Здесь уместный раздел от демонтированной таблицы ACPI DSDT.
Device (HPET)
{
Name (_HID, EisaId ("PNP0103"))
Name (_CRS, ResourceTemplate ()
{
Memory32Fixed (ReadOnly,
0xFED00000, // Address Base
0x00004000, // Address Length
)
})
Method (_STA, 0, NotSerialized)
{
If (HPEE)
{
Return (0x0F)
}
Else
{
Return (Zero)
}
}
}
Заметьте заданное PNPID (PNP0103) для HPET. Потому что никакое _UID не определено оно значит что никакие другие блоки отметчика времени HPET.
Здесь список HPET-родственных outputted сообщений когда эта определенная материнская плата booted вверх под Fedora 11.
$ dmesg | grep -i HPET ACPI: HPET CFBF2000, 0038 (r1 INTEL DX48BT2 76E MSFT 1000013) ACPI: HPET id: 0x8086a301 base: 0xfed00000 hpet clockevent registered HPET: 4 timers in total, 0 timers will be used for per-cpu timer hpet0: at MMIO 0xfed00000, IRQs 2, 8, 0, 0 hpet0: 4 comparators, 64-bit 14.318180 MHz counter rtc0: alarms up to one month, 114 bytes nvram, hpet irqs $
Первая линия outputted когда таблица ACPI HPET прочитана. Вторая линия outputted когда таблица ACPI HPET составлена карту в память… /arch/x86/kernel/acpi/boot.c. Следующая линия outputted когда interrupts наследия HPET начаты и HPET зарегистрировано как глобальные часы. Следующая линия outputted когда стержень проверяет для того чтобы обеспечить что хотя бы один отметчик времени сдержанно для userspace (/dev/hpet.) Следующие 2 линии выхода приходят от водителя прибора HPET (… /drivers/char/hpet.c.) оно показывает что 2 отметчика времени размещали interrupts и 2 не делают.
Здесь уместная часть выхода от /proc/time_list по мере того как она относит к HPET:
Tick Device: mode: 1 Broadcast device Clock Event Device: hpet max_delta_ns: 149983005959 min_delta_ns: 5000 mult: 61496114 shift: 32 mode: 3 next_event: 9223372036854775807 nsecs set_next_event: hpet_legacy_next_event set_mode: hpet_legacy_set_mode event_handler: tick_handle_oneshot_broadcast tick_broadcast_mask: 00000000 tick_broadcast_oneshot_mask: 00000000
Здесь выход от /proc/sys/dev/hpet и /proc/driver/rtc:
$ cat /proc/sys/dev/hpet/max-user-freq 64 $ cat /proc/driver/rtc rtc_time : 06:34:31 rtc_date : 2009-07-06 alrm_time : **:24:40 alrm_date : ****-**-** alarm_IRQ : no alrm_pending : no 24hr : yes periodic_IRQ : no update_IRQ : no HPET_emulated : yes DST_enable : no periodic_freq : 1024 batt_status : okay
Водитель HPET (/dev/hpet) имеет подобный API к в реальном масштабе времени формирователю тактовых импульсов. Прибор характера который может поддержать любой число приборов HPET. Стержень API имеет 3 интерфейса ехпортированного от водителя:
hpet_register( struct hpet_task *tp, int periodic ) hpet_unregister( struct hpet_task *tp ) hpet_control( struct hpet_task *tp, unsigned int cmd, unsigned long arg )
Интерфейс userspace к HPET определен в коллекторе /usr/include/linux/hpet.h. Настоящий комплект поддержанных деятельностей является следующим:
#define HPET_IE_ON _IO('h', 0x01) /* interrupt on */
#define HPET_IE_OFF _IO('h', 0x02) /* interrupt off */
#define HPET_INFO _IOR('h', 0x03, struct hpet_info) /* get information */
#define HPET_EPI _IO('h', 0x04) /* enable periodic */
#define HPET_DPI _IO('h', 0x05) /* disable periodic */
#define HPET_IRQFREQ _IOW('h', 0x6, unsigned long) /* set frequency */
Следующий пример показывает как использовать опубликованный интерфейс для того чтобы достигнуть HPET и вызвать просто периодического hpet_alarm укротителя сигнала между 2 и 99 временами секунда.
#include <stdio.h>
#include <stdlib.h;>
#include <fcntl.h>
#include <time.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>
#include <fcntl.h>
#include <sys/time.h>
#include <linux/hpet.h>
#include <stdint.h>
#include <sys/ioctl.h>
#include <signal.h>
static uint16_t hpet_sigio_count;
static uint64_t secs;
static void
hpet_alarm(int val)
{
struct timespec t;
clock_gettime(CLOCK_REALTIME, &t);
if (!secs) secs = t.tv_sec;
fprintf(stderr, "hpet_alarm called. iteration: %2d secs: %ld nsecs: %ld \n",
hpet_sigio_count, (t.tv_sec - secs) , t.tv_sec * 100000 + t.tv_nsec );
hpet_sigio_count++;
}
int
main(int argc, const char **argv)
{
struct sigaction old, new;
struct hpet_info info;
int frequency;
int iterations;
int retval = 0;
int fd;
int r, i, value;
if (argc != 3) {
fprintf(stderr, "Usage: %s frequency(1-64) iterations(10-99)\n", argv[0]);
return -1;
}
frequency = atoi(argv[1]);
iterations = atoi(argv[2]);
if (frequency > 64 || frequency < 1 ) {
fprintf(stderr, "ERROR: Invalid value for frequency\n");
return -1;
}
if (iterations < 10 || iterations > 99 ) {
fprintf(stderr, "ERROR: Invalid value for iterations\n");
return -1;
}
hpet_sigio_count = 0;
sigemptyset(&new.sa_mask);
new.sa_flags = 0;
new.sa_handler = hpet_alarm;
sigaction(SIGIO, NULL, &old);
sigaction(SIGIO, &new, NULL);
fd = open("/dev/hpet", O_RDONLY);
if (fd < 0) {
fprintf(stderr, "ERROR: Failed to open /dev/hpet\n");
return -1;
}
if ((fcntl(fd, F_SETOWN, getpid()) == 1) ||
((value = fcntl(fd, F_GETFL)) == 1) ||
(fcntl(fd, F_SETFL, value | O_ASYNC) == 1)) {
fprintf(stderr, "ERROR: fcntl failed\n");
retval = 1;
goto fail;
}
if (ioctl(fd, HPET_IRQFREQ, frequency) < 0) {
fprintf(stderr, "ERROR: Could not set /dev/hpet to have a %2dHz timer\n", frequency);
retval = 2;
goto fail;
}
if (ioctl(fd, HPET_INFO, &info) < 0) {
fprintf(stderr, "ERROR: failed to get info\n");
retval = 3;
goto fail;
}
fprintf(stdout, "\nhi_ireqfreq: 0x%lx hi_flags: %0x%lx hi_hpet: 0x%x hi_timer: 0x%x\n\n",
info.hi_ireqfreq, info.hi_flags, info.hi_hpet, info.hi_timer);
r = ioctl(fd, HPET_EPI, 0);
if (info.hi_flags && (r < 0)) {
fprintf(stderr, "ERROR: HPET_EPI failed\n");
retval = 4;
goto fail;
}
if (ioctl(fd, HPET_IE_ON, 0) < 0) {
fprintf(stderr, "ERROR: HPET_IE_ON failed\n");
retval = 5;
goto fail;
}
/* wait for specified number of signal interrupts */
for (i = 0; i < iterations; i++) {
(void) pause();
}
if (ioctl(fd, HPET_IE_OFF, 0) < 0) {
fprintf(stderr, "ERROR: HPET_IE_OFF failed\n");
retval = 6;
}
fail:
sigaction(SIGIO, &old, NULL);
if (fd > 0)
close(fd);
return retval;
}
Здесь выход от этого примера когда он призван с частотой 32 и отсчета итерирования 64.
$ sudo ./hpet_example 32 64 hi_ireqfreq: 0x20 hi_flags: 00 hi_hpet: 0x2 hi_timer: 0x4a1cb9c8 hpet_alarm called. iteration: 0 secs: 0 nsecs: 124683205055050 hpet_alarm called. iteration: 1 secs: 0 nsecs: 124683236313149 hpet_alarm called. iteration: 2 secs: 0 nsecs: 124683267566342 hpet_alarm called. iteration: 3 secs: 0 nsecs: 124683298821905 hpet_alarm called. iteration: 4 secs: 0 nsecs: 124683330077493 hpet_alarm called. iteration: 5 secs: 0 nsecs: 124683361341893 hpet_alarm called. iteration: 6 secs: 0 nsecs: 124683392590764 hpet_alarm called. iteration: 7 secs: 0 nsecs: 124683423849157 hpet_alarm called. iteration: 8 secs: 0 nsecs: 124683455101917 hpet_alarm called. iteration: 9 secs: 0 nsecs: 124683486357683 hpet_alarm called. iteration: 10 secs: 0 nsecs: 124683517617931 hpet_alarm called. iteration: 11 secs: 0 nsecs: 124683548872198 hpet_alarm called. iteration: 12 secs: 1 nsecs: 124682580229541 hpet_alarm called. iteration: 13 secs: 1 nsecs: 124682611481235 hpet_alarm called. iteration: 14 secs: 1 nsecs: 124682642740016 hpet_alarm called. iteration: 15 secs: 1 nsecs: 124682673992697 hpet_alarm called. iteration: 16 secs: 1 nsecs: 124682705247479 hpet_alarm called. iteration: 17 secs: 1 nsecs: 124682736504664 hpet_alarm called. iteration: 18 secs: 1 nsecs: 124682767758840 hpet_alarm called. iteration: 19 secs: 1 nsecs: 124682799014280 hpet_alarm called. iteration: 20 secs: 1 nsecs: 124682830270129 hpet_alarm called. iteration: 21 secs: 1 nsecs: 124682861530334 hpet_alarm called. iteration: 22 secs: 1 nsecs: 124682892784577 hpet_alarm called. iteration: 23 secs: 1 nsecs: 124682924038220 hpet_alarm called. iteration: 24 secs: 1 nsecs: 124682955294110 hpet_alarm called. iteration: 25 secs: 1 nsecs: 124682986550572 hpet_alarm called. iteration: 26 secs: 1 nsecs: 124683017805756 hpet_alarm called. iteration: 27 secs: 1 nsecs: 124683049061117 hpet_alarm called. iteration: 28 secs: 1 nsecs: 124683080318331 hpet_alarm called. iteration: 29 secs: 1 nsecs: 124683111576954 hpet_alarm called. iteration: 30 secs: 1 nsecs: 124683142828988 hpet_alarm called. iteration: 31 secs: 1 nsecs: 124683174083954 hpet_alarm called. iteration: 32 secs: 1 nsecs: 124683205337967 hpet_alarm called. iteration: 33 secs: 1 nsecs: 124683236593144 hpet_alarm called. iteration: 34 secs: 1 nsecs: 124683267851530 hpet_alarm called. iteration: 35 secs: 1 nsecs: 124683299104054 hpet_alarm called. iteration: 36 secs: 1 nsecs: 124683330358748 hpet_alarm called. iteration: 37 secs: 1 nsecs: 124683361617445 hpet_alarm called. iteration: 38 secs: 1 nsecs: 124683392870249 hpet_alarm called. iteration: 39 secs: 1 nsecs: 124683424124489 hpet_alarm called. iteration: 40 secs: 1 nsecs: 124683455379717 hpet_alarm called. iteration: 41 secs: 1 nsecs: 124683486634424 hpet_alarm called. iteration: 42 secs: 1 nsecs: 124683517889149 hpet_alarm called. iteration: 43 secs: 1 nsecs: 124683549144315 hpet_alarm called. iteration: 44 secs: 2 nsecs: 124682580500695 hpet_alarm called. iteration: 45 secs: 2 nsecs: 124682611761325 hpet_alarm called. iteration: 46 secs: 2 nsecs: 124682643011863 hpet_alarm called. iteration: 47 secs: 2 nsecs: 124682674265864 hpet_alarm called. iteration: 48 secs: 2 nsecs: 124682705521034 hpet_alarm called. iteration: 49 secs: 2 nsecs: 124682736776049 hpet_alarm called. iteration: 50 secs: 2 nsecs: 124682768030654 hpet_alarm called. iteration: 51 secs: 2 nsecs: 124682799285398 hpet_alarm called. iteration: 52 secs: 2 nsecs: 124682830544701 hpet_alarm called. iteration: 53 secs: 2 nsecs: 124682861797319 hpet_alarm called. iteration: 54 secs: 2 nsecs: 124682893051578 hpet_alarm called. iteration: 55 secs: 2 nsecs: 124682924306748 hpet_alarm called. iteration: 56 secs: 2 nsecs: 124682955562132 hpet_alarm called. iteration: 57 secs: 2 nsecs: 124682986823545 hpet_alarm called. iteration: 58 secs: 2 nsecs: 124683018073636 hpet_alarm called. iteration: 59 secs: 2 nsecs: 124683049327560 hpet_alarm called. iteration: 60 secs: 2 nsecs: 124683080586707 hpet_alarm called. iteration: 61 secs: 2 nsecs: 124683111841132 hpet_alarm called. iteration: 62 secs: 2 nsecs: 124683143095147 hpet_alarm called. iteration: 63 secs: 2 nsecs: 124683174349985 hpet_alarm called. iteration: 64 secs: 2 nsecs: 124683205607103 $
Наилучшим образом, я думаю что я обеспечивал вас с достаточной информацией так, что вы себя будете должны теперь мочь пойти прочь и эксперимент с интерфейсом HPET.
Кстати, не вся поддержка продуктов HPET VMware. В настоящее время ESX не снабубежит фактически HPET операционные системы гостя и в некоторые случаи может быть необходимо вывести HPET из строя вполне из-за смещения отметчика времени в виртуальные машины. См. TimeKeeping VMware для больше информации.
P.S. Я испытал вышеуказанный пример на материнской плате Intel DX48BT2 2.6.29.5 - стержень 191.


























