How to use HPET instead of PIT?

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
limp
Member
Member
Posts: 90
Joined: Fri Jun 12, 2009 7:18 am

How to use HPET instead of PIT?

Post by limp »

Hi all,

As both PIT and HPET timers are sharing the same IRQ line on PIC, what should I do to assign only one of them in the IRQ line and disconnect the other?

Thank you all.
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re: How to use HPET instead of PIT?

Post by Brendan »

Hi,
limp wrote:As both PIT and HPET timers are sharing the same IRQ line on PIC, what should I do to assign only one of them in the IRQ line and disconnect the other?
There's 3 different "interrupt mapping options":
  • Legacy replacement option: This is where HPET uses IRQ0 and IRQ8 and the PIT and RTC can't. In this case, the PIT and RTC may not even exist (e.g. they could be emulated by the firmware using SMM and HPET).
  • Standard option: For this option, each HPET interrupt has it's own interrupt routing control and a capability field that says which interrupts are valid; and you can set any of these interrupts to any IO APIC input that the capability field says is valid. In this case HPET is entirely separate from PIT and RTC and (in theory) you could use both at the same time.
  • "FSB option": If you're familiar with PCI interrupt routing, then you should be familiar with the idea of MSI (Message Signalled Interrupts), where the interrupt is delivered to the CPU by the bus and doesn't use a PIC or IO APIC input. The "FSB option" is MSI. In this case, the HPET may still be used to emulate PIT and RTC (and configured to generate IRQ0 and IRQ8), so if the "LegacyReplacement" bit is set you can't assume the PIT and RTC are actually present/usable.
Basically, HPET may not be using the same IRQ as PIT; and if HPET is using the same IRQ as PIT then you can't assume a PIT chip exists.

In general if you're using HPET then there's no good reason to use the PIT at all. Even when it is theoretically possible, the PIT is slow to access (because it uses slow/legacy IO ports) and has worse precision, and has no features that HPET doesn't have anyway. If the "LegacyReplacement" bit is set then you can ignore the PIT and don't have to worry about it (which makes things easier). Otherwise, if the PIT exists and is using IRQ0 then you'd have to make sure HPET is using a different interrupt (and then mask the PIT's IRQ in the PIC and/or IO APIC), and this is worse because it's a little more hassle and you end up with an IRQ line that's wasted by the slow/obsolete/deprecated PIT.


Cheers,

Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
limp
Member
Member
Posts: 90
Joined: Fri Jun 12, 2009 7:18 am

Re: How to use HPET instead of PIT?

Post by limp »

Thanks a lot Brendan for the reply,

I know that my Southbridge (ICH7) has both PIT and HPET timers and that PIT and HPET0 are using the same IRQ line (IRQ0 on PIC / INTI2 on I/O APIC). You said that:
Brendan wrote: Otherwise, if the PIT exists and is using IRQ0 then you'd have to make sure HPET is using a different interrupt (and then mask the PIT's IRQ in the PIC and/or IO APIC), and this is worse because it's a little more hassle and you end up with an IRQ line that's wasted by the slow/obsolete/deprecated PIT.
What do you mean by that? How can I use a different interrupt for HPET (as it is hardwired on PIC's IRQ0)?

You also said that:
Brendan wrote: If the "LegacyReplacement" bit is set then you can ignore the PIT and don't have to worry about it (which makes things easier). Otherwise, if the PIT exists....
Does this mean that I can set the "LegacyReplacement" bit only if PIT doesn't exist? Doesn't make much sense.

One other thing is that I want to exclusively use PIC and Local APIC but not I/O APIC.
In this case, if I setup PIC and LAPIC controllers and don't even consider I/O APIC, would I have a problem?
That is, if I mask PIT's IRQ on the PIC, is there any case that a PIT interrupt would be triggered by the I/O APIC?

The HPET's FSB routing capability sounds quite interesting to me.
Do you happen to know if I would get faster interrupts in this case? Do you consider it as a method with lower latency / greater level of determinism compared to standard routing?
What about the acknowledgement of the IRQ? Is it needed? In PIC, we're sending an EOI instruction, what about in FSB IRQs?

Sorry for the length of the post :)

Best wishes
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re: How to use HPET instead of PIT?

Post by Brendan »

Hi,
limp wrote:I know that my Southbridge (ICH7) has both PIT and HPET timers and that PIT and HPET0 are using the same IRQ line (IRQ0 on PIC / INTI2 on I/O APIC). You said that:
Brendan wrote: Otherwise, if the PIT exists and is using IRQ0 then you'd have to make sure HPET is using a different interrupt (and then mask the PIT's IRQ in the PIC and/or IO APIC), and this is worse because it's a little more hassle and you end up with an IRQ line that's wasted by the slow/obsolete/deprecated PIT.
What do you mean by that? How can I use a different interrupt for HPET (as it is hardwired on PIC's IRQ0)?

You also said that:
Brendan wrote: If the "LegacyReplacement" bit is set then you can ignore the PIT and don't have to worry about it (which makes things easier). Otherwise, if the PIT exists....
Does this mean that I can set the "LegacyReplacement" bit only if PIT doesn't exist? Doesn't make much sense.
Think of it like this:

Code: Select all

if(BIOS_or_firmware_left_the_LegacyReplacement_bit_set() ) {
    /* Can't assume a PIT exists */
    just_use_HPET();
} else {
    /* PIT is mostly useless anyway */
    just_use_HPET();
}
For determining which IRQ you can use; if you're using PIC then I don't really know and you may have no choice other than to use the IRQ0 and IRQ8 (and to make sure the PIT and RTC, if they exist, don't try to use these IRQs and cause conflicts). If you're using IO APICs then you get to choose which IO APIC input to use (and can use MSI if it's supported instead); but you still have to make sure nothing else is using the IRQ/s and causing conflicts (which includes the PIT and RTC, but also includes any other "edge triggered" IRQ, as they can't be shared like "level triggered" PCI IRQs can).
limp wrote:One other thing is that I want to exclusively use PIC and Local APIC but not I/O APIC.
In this case, if I setup PIC and LAPIC controllers and don't even consider I/O APIC, would I have a problem?
That should work. The problem is that the PIC isn't very good for a variety of reasons (see below).
limp wrote:That is, if I mask PIT's IRQ on the PIC, is there any case that a PIT interrupt would be triggered by the I/O APIC?
It's possible to configure both the PIT and IO APIC to send IRQs to the CPU (and I strongly recommend against doing that). For backward compatibility, the default state of the IO APIC is "all IRQs disabled", so if you don't touch it you don't have to worry.
limp wrote:The HPET's FSB routing capability sounds quite interesting to me.
MSI (used to reduce IRQ sharing on PCI) and the HPET's "FSB routing" capability require IO APICs.
limp wrote:Do you happen to know if I would get faster interrupts in this case? Do you consider it as a method with lower latency / greater level of determinism compared to standard routing? What about the acknowledgement of the IRQ? Is it needed? In PIC, we're sending an EOI instruction, what about in FSB IRQs?
There's a lot of things here. First, all legacy/ISA devices are slow - due to original ISA bus timing, any IO port access to a legacy/ISA device costs 1 us. This includes PIC, PIT, serial ports, parallel ports, the PS2/keyboard controller, the ISA DMA chips, etc. For example, to send the EOI to the slave PIC and the master PIC, it will cost you 2 us (or about 6000 cycles on a modern CPU). When you've got modern PCI devices (e.g. a video card doing a vertical retrace IRQ 60 times per second, plus an ethernet card under load, plus USB and SATA disk controllers, etc) sending the EOIs to the PIC chip/s can add up to a performance problem. Worse, PCI IRQs are almost always routed to the slave PIC, so you have to use 2 IO port accesses for the (master and slave) EOIs. For an example, regardless of how fast the CPU is, at about 500000 IRQs per second (through the slave PIC) you'll spend 100% of CPU time doing EOIs alone.

For IO APICs, interrupts from the local APIC and MSI, you still have to send an EOI. However, in this case the EOI is sent by doing a write to the local APIC (which is built into the CPU), and an EOI probably costs about 10 cycles (instead of about 3000 cycles).

The next thing to consider is IRQ sharing. If an IRQ is shared by 4 devices, then you need to run 4 different IRQ handers each time that IRQ occurs (and you can assume that the IRQ will happen a lot more often when there's 4 IRQs connected to it too). That adds up to more overhead. For modern computers there's lots of PCI devices (for example, the computer I'm using now has 8 USB controllers, 2 SATA controllers, 2 video cards, 2 audio cards and 2 ethernet cards and some other stuff - a minimum of 16 PCI IRQs) and the PIC chips typically only have 4 inputs left over for PCI. With 16 PCI IRQs and 4 PIC chip inputs, you end up with an average of 4 devices sharing each of those IRQs (but that's only an average - you could have 3 IRQs with 2 devices sharing each of them, and 12 devices sharing one IRQ). For IO APICs there's typically 24 inputs (where about 12 of them are used for legacy/ISA) which leaves you with about 12 IRQs for 16 devices. That's a lot less IRQ sharing (and a lot less overhead caused by IRQ sharing). It's still not quite "good enough" for modern systems though, which is why PCI added support for MSI (and then made it mandatory for PCI-X devices). With MSI, devices don't use IO APIC inputs, and you could have 220 devices all using separate interrupts without any IRQ sharing (if all devices support MSI).

Finally there's IRQ balancing. In modern computers (with multiple CPUs) you can spread the IRQ handling overhead across multiple CPUs; so you don't end up with one CPU constantly being pounded. You can also use a special "send to lowest priority CPU" mode so that IRQs don't interrupt important stuff (e.g. very high priority tasks; CPUs that are in critical sections, etc). Of course you have to use IO APICs for that. With IO APICs and MSI you also get a lot more control over IRQ priorities.

How much difference each of these things make depends on a lot of things - how many devices, how many IRQs per second, how many CPUs, how well implemented the software is, etc.


Cheers,

Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
Post Reply