IA-PC HPET的IA -電腦 HPET (High Precision Event Timer) is a specification which was jointly developed by Intel and Microsoft in the early part of this decade.. (高精度事件定時器)是一種規範,共同開發的英特爾和微軟在這個十年初.. The latest version is dated October 2004.最新版本的日期是2004年10月。 It's stated purpose is to它的既定目的,是
initially supplement and eventually replace the legacy 8254 Programmable Interval Timer and the Real Time Clock Periodic Interrupt generation functions that are currently used as the 'de-facto' timer hardware for IA-PCs.最初補充並最終取代舊的8254可編程間隔定時器和實時時鐘週期產生中斷的功能是目前使用的'事實上的'計時器硬件的IA - PC機。
The該 HPET HPET architecture defines a set of timers that can be used by the operating system.架構定義一組定時器,可使用的操作系統。 A timer block is a combination of a single counter and up to 32 comparators and match registers.計時器塊是一個單一的組合櫃和32比較和匹配寄存器。 The comparator compares the contents of the match register against the value of a free running monotonic up-counter.比較的內容,比較匹配寄存器的值對單調了一個自由運行計數器。 When the output of the up-counter equals the value in the match register an interrupt is generated.當輸出的向上計數器等於價值的匹配寄存器產生中斷。 Each of the comparators can output an interrupt.每個比較器可以輸出一個中斷。 A maximum of 8 timer blocks are supported for a total of 256 timers.阿最大的8塊支持定時器共256定時器。 Each timer block can have different clocking attributes.每個定時器塊可以有不同的時鐘屬性。 Specific implementations may include only a subset of these timers.具體的實現可能只包含一個子集,這些計時器。 A minimum of three timers is required.阿最低3定時器是必要的。
The specification contains the following block diagram of the HPET architecture.該規範包含以下框圖 HPET架構。

Some of the timers may be enabled to generate a periodic interrupt.一些可能被啟用計時器產生週期性的中斷。 If a timer is set to be periodic, its period is added to the match register each time a match occurs, thus computing the next time for this timer to generate an interrupt..如果定時器被設置為週期,其週期被添加到匹配寄存器,每次比賽時,從而計算下一次該定時器產生一個中斷 .. An up-counter is usually 64 bits wide but 32-bit implementations are permitted by the specification and 64-bit up-counters can also be driven in 32-bit mode.向上的計數器通常是64位元寬,但32位實現是允許的規格和64位了,櫃檯也可以驅動在32位模式。 Up-counters run at a minimum of 10 MHz.最新的櫃檯至少運行 10兆赫。 which is much faster than the older這是速度遠遠超過了舊 RTC實時時鐘 (Real Time Clock) and can thus produce periodic interrupts at a much higher resolution. (實時時鐘),所以可以產生週期性的中斷在更高的分辨率。 The registers associated with these timers are mapped to memory space.與這些相關的寄存器映射到計時器的內存空間。
The BIOS uses BIOS使用 ACPI支持ACPI ( Advanced Configuration and Power Interface) functionality to inform the operating system of the location of the HPET memory-mapped register space. (高級配置和電源接口)功能,以告知作業系統中的位置的HPET內存映射的寄存器空間。 Here is an example of a disassembled ACPI HPET table from an Intel DX48BT2 (AKA BoneTrail) motherboard.下面是一個例子,一個拆散的ACPI HPET表從一個 Intel DX48BT2(又名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 ........ $
See page 30 of the HPET v1.0a specification for a detailed breakdown of the individual bits in the Event Time Block (called Hardware Block by the AML disassember).見 30頁的HPET v1.0a規範詳細的分類,個人位的事件時塊(稱為硬件模塊的反洗錢 disassember)。 Note that only one Event Timer Block need be described in the HPET table in order to bootstrap an operating system.請注意,只有1座事件定時器需要加以說明的HPET表,以引導操作系統。 This is the case here.這是這裡的情況。 For non-legacy platforms, the Event Timer Block described in the HPET is the one that provides functionality to replace the 8254/RTC Periodic Interrupt Logic.對於非傳統平台,事件定時器模塊描述了HPET是一個提供的功能,以取代8254/RTC週期中斷邏輯。
Other Event Time Blocks are described in the ACPI namespace.其他活動的時間段中描述的ACPI命名空間。 Here is the relevant section from the disassembled ACPI DSDT table.以下是有關條文從拆解的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)
}
}
}
Note the assigned PNPID ( PNP0103 ) for the HPET.注意分配PNPID(PNP0103)的HPET。 Because no _UID is specified it means that there are no other HPET timer blocks.因為沒有 _UID指定這意味著沒有其他HPET計時器塊。
Here is a list of the HPET-related messages outputted when this particular motherboard is booted up under Fedora 11.這裡是一個名單的HPET相關的消息時,這個輸出是主板啟動的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 $
The first line is outputted when the ACPI HPET table is read.第一行是輸出時的ACPI HPET表是只讀。 The second line is outputted when the ACPI HPET table is mapped into memory by …/arch/x86/kernel/acpi/boot.c .第二行是輸出時的ACPI HPET表映射到內存... / arch/x86/kernel/acpi/boot.c。 The next line is outputted when the HPET legacy interrupts are started and HPET is registered as the global clock.下一行是輸出時遺留下來的HPET中斷開始,HPET是註冊為全局時鐘。 The following line is outputted when the kernel checks to ensure that at least one timer is reserved for userspace ( /dev/hpet .) The next two lines of output comes from the HPET device driver ( …/drivers/char/hpet.c .) It shows that 2 timers have allocated interrupts and two do not..下面的行是在內核輸出檢查,以確保至少一個計時器是留給用戶空間(/開發/ hpet。)接下來的兩行輸出來自HPET設備驅動程序(... /司機/炭/ hpet.c。 )這表明,已撥出 2定時器中斷和兩個不..
Here is the relevant part of the output from /proc/time_list as it relates to HPET:以下是有關部分的輸出從/ 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
Here is the output from /proc/sys/dev/hpet and /proc/driver/rtc :下面是輸出從/ proc / sys目錄下的/ dev / hpet和/ proc /驅動器/實時時鐘 :
$ 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
The HPET driver ( /dev/hpet ) has a similar API to the Real Time Clock driver.該HPET驅動程序(/開發/ hpet)也有類似的API來實時時鐘驅動程序。 It is a character device which can support any number of HPET devices.這是一個字符設備,可以支持任意數量的HPET設備。 The kernel API has three interfaces exported from the driver:該內核 API接口有三個出口的驅動程序:
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 )
The userspace interface to HPET is defined in the header /usr/include/linux/hpet.h .用戶空間接口HPET是定義在頭/ usr / include中/ Linux的/ hpet.h。 The current set of supported operations is:目前集支持的操作是:
#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 */
The following example shows how to use the published interface to access a HPET and call a simple periodic signal handler hpet_alarm between 2 and 99 times a second.下面的示例演示如何使用已發布的接口訪問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;
}
Here is the output from this example when it is invoked with a frequency of 32 and an iteration count of 64.下面是從這個例子的輸出時,調用了一個頻率為 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 $
Well, I think that I have provided you with enough information so that you should now be able to go away and experiment with the HPET interface yourself.嗯,我認為我只要你有足夠的信息,以便您現在應該可以回去實驗與 HPET接口自己。
By the way, not all VMware products support HPET.順便說一下,不是所有的VMware產品支持HPET。 Currently ESX does not provide a virtual HPET to guest operating systems and in some cases it may be necessary to disable HPET altogether because of timer drift in virtual machines.目前的ESX不提供一個虛擬 HPET為客人作業系統並在一些情況下,可能需要禁用HPET計時器漂移完全是因為在虛擬機。 See見 VMware TimeKeeping VMware的時鐘 for more information.獲取更多信息。
PS I tested the the above example on an Intel DX48BT2 motherboard running a 2.6.29.5-191 kernel. PS我測試了上面的例子主板上的Intel DX48BT2運行 2.6.29.5-191內核。






















