IA-PC HPET (hohe Präzisions-Ereignis-Timer) ist eine Spezifikation, die gemeinsam durch Intel und Microsoft in der früheren Phase dieser Dekade. entwickelt wurde. Die späteste Version ist vom Oktober 2004. Sie hat angegeben, dass Zweck zu ist
ergänzen Sie zuerst und ersetzen Sie schließlich den Vermächtnis 8254 programmierbaren Intervallzeitgeber und die Echtzeituhr-periodischen Unterbrechungserzeugungsfunktionen, die z.Z. als die `De-facto' Timer-Hardware für IA-PC verwendet werden.
Die HPET Architektur definiert einen Satz Timer, die durch das Betriebssystem benutzt werden können. Ein Zeitgliedblock ist eine Kombination eines einzelnen Kostenzählers und bis 32 Komparatoren und Gleichregister. Der Komparator vergleicht den Inhalt des Gleichregisters gegen den Wert eines freien laufenden monotonen Obenkostenzählers. Wenn der Ausgang des Obenkostenzählers dem Wert im Gleichregister entspricht, wird eine Unterbrechung erzeugt. Jeder der Komparatoren kann eine Unterbrechung ausgeben. Ein Maximum von 8 Zeitgliedblöcken werden für insgesamt 256 Timer gestützt. Jeder Zeitgliedblock kann verschiedene abstoppende Attribute haben. Spezifische Implementierungen können nur eine Teilmenge dieser Timer umfassen. Ein Minimum von drei Timern wird angefordert.
Die Spezifikation enthält das folgende Santendiagramm der HPET Architektur.

Einige der Timer können ermöglicht werden, eine periodische Unterbrechung zu erzeugen. Wenn ein Timer eingestellt wird, um periodisch zu sein, sein Zeitraum wird hinzugefügt dem Gleichregister, jedes Mal wenn ein Gleiches auftritt und so nächstes Mal rechnet, damit dieser Timer eine Unterbrechung. erzeugt. Ein Obenkostenzähler ist normalerweise 64 Bits weit, aber 32-Bitimplementierungen werden durch die Spezifikation die Erlaubnis gehabt und 64-bitc$obenkostenzähler können in 32-Bitmodus auch gefahren werden. Oben-Kostenzähler laufen an einem Minimum von 10 MHZ. welches viel schneller als ist, kann das ältere RTC (Echtzeituhr) und periodische Unterbrechungen an einem viel feiner gegliederten folglich produzieren. Die Register, die mit diesen Timern verbunden sind, werden zum Gedächtnisraum abgebildet.
Die Funktionalität des BIOS- Gebrauches ACPI (vorgerückte Konfigurations-und Energien-Schnittstelle), zum das Betriebssystem über die Position des HPET Gedächtnis-abgebildeten Registerraumes zu informieren. Ist hier ein Beispiel einer auseinandergebauten ACPI HPET Tabelle von einem Motherboard 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 ........ $
Sehen Sie Seite 30 der HPET v1.0a Spezifikation für eine ausführliche Aufschlüsselung der einzelnen Spitzen, im Falle Zeit Blockes festzusetzen (genannt Hardware Block durch das AML disassember). Merken Sie, dass nur ein Ereignis-Zeitgliedblock in der HPET Tabelle beschrieben werden muss, um ein Betriebssystem das Urprogramm zu laden. Dieses ist der Fall hier. Für Nichtvermächtnis Plattformen ist der Ereignis-Zeitgliedblock, der im HPET beschrieben wird, der, der Funktionalität liefert, um die periodische Logik der Unterbrechungs-zu ersetzen 8254/RTC.
Andere Ereignis-Zeit-Blöcke werden im ACPI namespace beschrieben. Ist hier der relevante Abschnitt von der auseinandergebauten ACPI DSDT Tabelle.
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)
}
}
}
Merken Sie das zugewiesene PNPID (PNP0103) für das HPET. Weil kein _UID spezifiziert wird, bedeutet es, dass es keine anderen HPET Zeitgliedblöcke gibt.
Ist hier eine Liste der HPET-in Verbindung stehenden outputted Mitteilungen, wenn dieses bestimmte Motherboard oben unter Fedora 11. aufgeladen wird.
$ 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 $
Die erste Linie outputted, wenn die ACPI HPET Tabelle gelesen wird. Die zweite Linie outputted, wenn die ACPI HPET Tabelle in Gedächtnis durch… /arch/x86/kernel/acpi/boot.c. abgebildet wird. Die folgende Linie outputted, wenn die HPET Vermächtnisunterbrechungen begonnen werden und HPET als der globale Taktgeber geregistriert wird. Die folgende Linie outputted, wenn der Kern überprüft, um zu garantieren, dass mindestens ein Timer ist reserviert für userspace (/dev/hpet.) Die folgenden zwei Linien des Ausganges kommt von der HPET Gerätebetreibung (… /drivers/char/hpet.c.), das es zeigt, dass 2 Timer Unterbrechungen zugeteilt haben und zwei nicht. tun.
Ist hier das relevante Teil des Ausganges von /proc/time_list, während es auf HPET bezieht:
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
Ist hier der Ausgang von /proc/sys/dev/hpet und von /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
Der HPET Fahrer (/dev/hpet) hat eine ähnliche API zum Echtzeituhrfahrer. Es ist eine Buchstabenvorrichtung, die jede mögliche Zahl der HPET Vorrichtungen stützen kann. Der Kern API hat drei Schnittstellen, die vom Fahrer exportiert werden:
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 )
Die userspace Schnittstelle zu HPET wird in der Überschrift /usr/include/linux/hpet.h definiert. Der gegenwärtige Satz der gestützten Betriebe ist:
#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 */
Das folgende Beispiel zeigt, wie man die erschienene Schnittstelle benutzt, um auf ein HPET zurückzugreifen und ein einfaches periodisches Signalzufuhr hpet_alarm zwischen 2 und 99mal ein Sekunde zu benennen.
#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;
}
Ist hier der Ausgang von diesem Beispiel, wenn er mit einer Frequenz von 32 hervorgerufen wird und von einem Wiederholungzählimpuls von 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 $
Gut denke ich, dass ich Sie mit genügenden Informationen versehen habe, damit Sie jetzt in der Lage sein sollten, wegzugehen und Experiment mit der HPET Schnittstelle sich.
Übrigens nicht alle VMware Produktunterstützung HPET. Z.Z. stellt ESX ein virtuelles HPET nicht zu den GastBetriebssystemen zur Verfügung und in einigen Fällen kann es notwendig sein, HPET wegen des Timer-Antriebs in den virtuellen Maschinen zusammen zu sperren. Sehen Sie VMware TimeKeeping zu mehr Information.
P/in prüfte das oben genannte Beispiel auf einem Motherboard Intel-DX48BT2, das 2.6.29.5 - Kern 191 laufen lässt.

























