Traduisez

Translate to EnglishÜbersetzen Sie zum Deutsch/GermanΜεταφράστε στα ελληνικά/GreekПереведите к русскому/RussianOversetter til Norsk/NorwegianÖversätta till Svensk/Swedishहिनà¥à¤¦à¥€ अनà¥à¤µà¤¾à¤¦ करने के लिà¤/Hindi
Tradueix al català/CatalanTulkot uz latviešu/LatvianPreložiť do slovenčiny/SlovakVertaal aan het Nederlands/Dutchترجمة الى العربية/ArabicTraduzca al Español/SpanishTraduisez au Français/French
Traduca ad Italiano/ItalianTraduza ao Português/Portuguese日本語に翻訳しなさい /Japanese한국어에게 번역하십시오/Korean中文翻译/Chinese Simplified中文翻译/Chinese TraditionalПереклад на українську/Ukrainian

Appui du Linux HPET

IA-PC HPET (temporisateur d'événement de haute précision) est des spécifications qui ont été conjointement développées par Intel et Microsoft dans la partie précédente de cette décennie. La dernière version est datée d'octobre 2004. Elle a énoncé que le but est à

complétez au commencement et remplacez par la suite le rythmeur programmable du legs 8254 et les fonctions périodiques de génération d'interruption d'horloge temps réel qui sont actuellement employés comme matériel de temporisateur du `De-facto'pour des IA-PCs.

L'architecture de HPET définit un ensemble de temporisateurs qui peuvent être employés par le du système d'exploitation. Un bloc de temporisateur est une combinaison d'un compteur simple et jusqu'à 32 comparateurs et registres d'allumette. Le comparateur compare le contenu du registre d'allumette contre la valeur d'un vers le haut-compteur monotonique courant libre. Quand le rendement du vers le haut-compteur égale la valeur dans le registre d'allumette une interruption est produite. Chacun des comparateurs peut produire une interruption. Un maximum de 8 blocs de temporisateur sont soutenus pour un total de 256 temporisateurs. Chaque bloc de temporisateur peut avoir différents attributs de synchronisation. Les réalisations spécifiques peuvent inclure seulement un sous-ensemble de ces temporisateurs. Trois temporisateurs au minimum est prié.

Les spécifications contiennent le schéma fonctionnel suivant de l'architecture de HPET.

Schéma fonctionnel de matériel

Certains des temporisateurs peuvent être permis de produire d'une interruption périodique. Si un temporisateur est placé pour être périodique, sa période est ajoutée au registre d'allumette chaque fois que une allumette se produit, de ce fait calculant la prochaine fois pour que ce temporisateur produise d'une interruption. Un vers le haut-compteur est habituellement 64 bits au loin mais des réalisations à 32 bits sont autorisées par les spécifications et des vers le haut-compteurs 64-bit peuvent également être conduits en mode à 32 bits. les Vers le haut-compteurs fonctionnent à 10 mégahertz au minimum. ce qui est beaucoup plus rapide que le RTC plus ancien (horloge temps réel) et peut produire ainsi des interruptions périodiques à une résolution beaucoup plus élevée. Les registres liés à ces temporisateurs sont tracés à l'espace mémoire.

La fonctionnalité des utilisations ACPI de BIOS (interface avancée de configuration et de puissance) pour informer le du système d'exploitation de l'endroit du HPET mémoire-a tracé l'espace de registre. Voici un exemple d'une table démontée d'ACPI HPET d'une carte mère d'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                          ........
$


Voir la page 30 des spécifications de HPET v1.0a pour une panne détaillée du peu individuel en cas chronométrer le bloc (appelé Hardware Block par le disassember d'AML). Notez que seulement un bloc de temporisateur d'événement doit être décrit dans la table de HPET afin d'amorcer un du système d'exploitation. C'est le cas ici. Pour des plates-formes de non-legs, le bloc de temporisateur d'événement décrit dans le HPET est celui qui fournit la fonctionnalité pour remplacer la logique périodique de l'interruption 8254/RTC.

D'autres blocs de temps d'événement sont décrits dans le namespace d'ACPI. Voici la section appropriée de la table démontée d'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)
                    }
                }
            }


Notez le PNPID assigné (PNP0103) pour le HPET. Puisqu'aucun _UID n'est spécifié il signifie qu'il n'y a aucun autre bloc de temporisateur de HPET.

Voici une liste des messages HPET-connexes outputted quand cette carte mère particulière est initialisée sous 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
$


La première ligne outputted quand la table d'ACPI HPET est lue. La deuxième ligne outputted quand la table d'ACPI HPET est tracée dans la mémoire par /arch/x86/kernel/acpi/boot.c. La prochaine ligne outputted quand les interruptions de legs de HPET sont commencées et HPET est enregistré comme horloge globale. La ligne suivante outputted quand le grain vérifie pour s'assurer qu'au moins un temporisateur est réservé pour l'userspace (/dev/hpet.) Les deux prochaines lignes du rendement vient du programme pilote de périphérique de HPET ( /drivers/char/hpet.c.) qu'il prouve que 2 temporisateurs ont assigné des interruptions et deux ne font pas.

Voici la partie appropriée du rendement de /proc/time_list pendant qu'elle se rapporte à 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


Voici le rendement de /proc/sys/dev/hpet et de /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

Le conducteur de HPET (/dev/hpet) a un api semblable au conducteur d'horloge temps réel. C'est un périphérique en mode caractère qui peut soutenir tout nombre de dispositifs de HPET. Le grain api a trois interfaces exportées du conducteur :

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 )


L'interface d'userspace à HPET est définie dans l'en-tête /usr/include/linux/hpet.h. L'ensemble courant d'opérations soutenues est :

#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 */


L'exemple suivant montre comment employer l'interface éditée pour accéder à un HPET et pour appeler un hpet_alarm périodique simple de traiteur de signal entre 2 et 99 moments par seconde.

#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;
}


Voici le rendement de cet exemple quand il est appelé avec une fréquence de 32 et d'un compte d'itération de 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
$


Bien, je pense que je t'ai fourni assez d'information de sorte que vous devriez maintenant pouvoir partir et expérience avec l'interface de HPET vous-même.

D'ailleurs, non tout l'appui de produits de VMware HPET. Actuellement ESX ne fournit pas un HPET virtuel aux logiciels d'exploitation d'invité et dans certains cas il peut être nécessaire de désactiver HPET tout à fait en raison de la dérive de temporisateur dans des machines virtuelles. Voir le TimeKeeping de VMware pour plus d'information.

Livre par pouce carré a examiné le l'exemple ci-dessus sur une carte mère d'Intel DX48BT2 courant 2.6.29.5 - le grain 191.
 

Laissez une réponse