ACPI Timer

From OSDev Wiki
Jump to navigation Jump to search

The ACPI Power Management Timer is a very simple timer which runs at 3.579545 MHz and generates an SCI when the counter has overflown. It is quite limiting (you cannot set custom rates, for example). This generally means that using other timers to generate interrupts, like APIC Timer and HPET, is usually a better idea. However, the ACPI PM Timer is still a very nice and straightforward time source, which is very easy to support and can be used to calibrate other timers (LAPIC/TSC) and/or as a general monotonic time source, without necessarily having to make use of its interrupt.

Detecting the ACPI Power Management Timer

The computer must obviously support ACPI first. Then, you need to look into the RSDP to get the RSDT or XSDT, to find the FADT table. Once you got it, you need to check if the PMTimerLength is 4. If it isn't, then you must assume the timer is not available. Then, if the ACPI revision is 2 or greater, and the X_PMTimerBlock Generic Address Structure is available (check if the address is not 0), use it. Otherwise, use PMTimerBlock as an IO port.

24-bit and 32-bit mode

The ACPI Power Management Timer supports 24 and 32 bit counters. To check if the counter is 32 bit, simply check if bit 8 of FADT Flags if set.

Reading the counter value

If using X_PMTimerBlock:

  • Check in which address space the address is:
    • If it's MMIO: map the address into virtual memory and read the counter as an unsigned 32 bit integer from it
    • If it's IO: read the counter as unsigned 32 bit integer from IO

Else if using PMTimerBlock:

  • Read the counter as an unsigned 32 bit integer from IO

Counter value

Bits Description
0:23 The 24 bits of the counter.
24:31 The upper 8 bits of the counter, if it's a 32 bit one. If the counter is 24 bit, then they're 0.

IRQs

The ACPI Power Management Timer generates a SCI when the counter has overflown. To know more about SCIs, see FADT#SCI_Interrupt.

Handling overflows

The ACPI PM timer overflows after very short time, which is about 5 seconds with a 24 bit counter, and about 20 minutes with 32 bits, which means that you must explicitly handle it if you are using it as a time source.

One of the strategies to handling overflows is recording the last time read from the timer into a variable, and having a software counter to count overflows (with atomics, if your kernel supports multiprocessing). When you detect that the ACPI timer's counter has gone back in time, you increment the overflow counter, keeping the monotonic time. To not miss the potential overflows while the timer has not been read for a long time, the kernel may set up a periodic task, which makes sure the timer is always read before that happens (for example, once a second). You may then choose to use interrupts from a different timer (for example, LAPIC one-shot or TSC deadline) to generate the event, or potentially use the timer itself.

Comparison to other x86 timers

In its current state, x86 PCs have many different timers and time sources (PIT, RTC, ACPI PM Timer, HPET, LAPIC, TSC, paravirtualization timers, etc.), all of which might or might not be present in any given PC. While the ACPI timer is simple, it is still important for mid 2000s to new hardware.

Comparing it to PIT, the ACPI PM timer in combination with some other timer is often a better choice, considering that the former has a lot of quirks (has been seen be broken in different on both old and latest generation hardware), is more difficult to discover (requires executing AML to do it properly, or probing it on its standard ports, which has its own set of problems), and is arguably more difficult to support.

Comparing PM Timer to HPET, the latter should offer better precision, and more functionality. However, there are a lot of systems that allow disabling HPET in BIOS, or just don't have it in the first place (especially laptops), which means that you can't rely on it always being present.

Finally, TSC is a good alternative to ACPI PM timer as a monotonic time source. If invariant TSC is present, it is probably more convenient to use it instead, with the ACPI PM, HPET or other timer being used as a calibration reference during boot (if the CPUID leaf 0x15 TSC frequency is not available).

This means, that in kernels targeting physical hardware made during and after late 90s, it is a good idea to support several different timers/counters. Namely, ACPI PM, HPET and APIC/TSC is a solid set of timers to support to cover most of the relevant hardware.

See Also

External Links