High Precision timer & IOAPIC connection

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
Anon5710
Posts: 21
Joined: Thu Nov 08, 2012 1:44 pm

High Precision timer & IOAPIC connection

Post by Anon5710 »

Hi,

I recently implemented IOAPIC support, I have tested my system and everything seems to work, usb, lan, etc...
Now i did this so i could enable the HPET timer and have a sub millisecond timer.

My chipset ICH7 supports 3 timers the first 2 can map interrupts onto IRQ 20-23 the third can map his interrupts onto IRQ11 and IRQ20-23.
I have got the hpet working on IRQ 11, but now trying to set the IRQ to 21 i've run into problems.

From the "software-developers-hpet-spec-1-0a"
The interrupts are all active high.
If the interrupts are mapped to the I/O APIC and set for level-triggered mode, they can be shared with PCI
interrupts.
From my ICH7 chipset:
When programming the polarity of internal interrupt sources on the APIC, interrupts 0
through 15 receive active-high internal interrupt sources, while interrupts 16 through 23
receive active-low internal interrupt sources.
So what does this mean ?
I'm having a hard time believing that a hardware manufacturer would implement incompatible devices on the same chipset. :?:
Especially since today's new chipset (NM10) has the same text in it's datasheet.

I must be missing something, anyone with an idea ?
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re: High Precision timer & IOAPIC connection

Post by Brendan »

Hi,
Anon5710 wrote:
When programming the polarity of internal interrupt sources on the APIC, interrupts 0
through 15 receive active-high internal interrupt sources, while interrupts 16 through 23
receive active-low internal interrupt sources.
So what does this mean ?
It probably means that if you configure HPET to use IRQ 11 it should be "active high, edge triggered" the same as all other legacy ISA devices (and the interrupt can't be shared in this case); and if you configure HPET to use IRQs 20 to 23 it should be "active low, level triggered" the same as all other PCI devices (and the interrupt can be shared in this case).

Note that configuring the HPET to use IRQs 20 to 23 would include disabling the legacy replacement routing (the "LEG_RT_CNF" bit the "GEN_CONF" field), setting the "TIMERn_INT_ROUT_CNF" field to a value from 20 to 23, and also setting the "TIMERn_INT_TYPE_CNF" field to 1 (level triggered).


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.
Anon5710
Posts: 21
Joined: Thu Nov 08, 2012 1:44 pm

Re: High Precision timer & IOAPIC connection

Post by Anon5710 »

Brendan wrote:Hi,
It probably means that if you configure HPET to use IRQ 11 it should be "active high, edge triggered" the same as all other legacy ISA devices (and the interrupt can't be shared in this case); and if you configure HPET to use IRQs 20 to 23 it should be "active low, level triggered" the same as all other PCI devices (and the interrupt can be shared in this case).

Note that configuring the HPET to use IRQs 20 to 23 would include disabling the legacy replacement routing (the "LEG_RT_CNF" bit the "GEN_CONF" field), setting the "TIMERn_INT_ROUT_CNF" field to a value from 20 to 23, and also setting the "TIMERn_INT_TYPE_CNF" field to 1 (level triggered).
I'm well aware of the above, the point is the hpet interrupts are all active high, while the IOAPIC IRQ from 16 to 23 are active low.
kinda ridiculous to put these devices in the same chipset while they can't work together.
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re: High Precision timer & IOAPIC connection

Post by Brendan »

Hi,
Anon5710 wrote:I'm well aware of the above, the point is the hpet interrupts are all active high, while the IOAPIC IRQ from 16 to 23 are active low.
kinda ridiculous to put these devices in the same chipset while they can't work together.
Sorry - I was only looking at the ICH7 datasheet.

The HPET specification is probably wrong and/or misleading. For example; the part of the specification you quoted might only be saying that the interrupt signal/s from the HPET chip itself are active high before it gets mangled by the chipset's IRQ routing logic, and may not mean that the interrupt signal is still active high after it's been mangled by the chipset's IRQ routing logic.

To put it another way; for ICH7 I'd assume that there is no inverter between the HPET's interrupt output and IO APIC input #11, but there is an inverter between the HPET's interrupt output and IO APIC inputs #20 to #23 (such that the HPET chip's output is active high when it goes into the inverter but is active low by the time it gets to the IO APIC input).


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.
rdos
Member
Member
Posts: 3306
Joined: Wed Oct 01, 2008 1:55 pm

Re: High Precision timer & IOAPIC connection

Post by rdos »

IMO, the HPET seems to be reliable only if it supports MSI delivery. In other cases, it is often severely broken. Therefore, I think you need to test if it works, and which interrupts it can generate, as this is frequently not correct.
User avatar
Owen
Member
Member
Posts: 1700
Joined: Fri Jun 13, 2008 3:21 pm
Location: Cambridge, United Kingdom
Contact:

Re: High Precision timer & IOAPIC connection

Post by Owen »

rdos wrote:IMO, the HPET seems to be reliable only if it supports MSI delivery. In other cases, it is often severely broken. Therefore, I think you need to test if it works, and which interrupts it can generate, as this is frequently not correct.
Are you getting your info from ACPI? If not, theres problem #1 (but I suspect this isn't the case, because I know you have ACPI support)

If you are, are you claiming to be pretty much every version of Windows ever released? Most BIOSes will do a query along the lines of _OSI("Windows 2005") to see if the OS claims to be Windows >= Vista, and if not hide the HPET (because otherwise it shows up as an "unknown device" in Windows device manager), and don't have any code path for non-Windows OSes, because the only non-Windows OS big enough for them to even consider supporting is Linux... and the Linux guys now completely and utterly claim to be Windows vLATEST, because the path of least bugs for everyone is for them to follow the ACPI specified behaviour and Windows behaviour except in cases where the latter conflicts with their needs.

TL;DR: Everyone pretends to be _OS("Windows NT") and reports support for the latest Windows ACPI interface
Anon5710
Posts: 21
Joined: Thu Nov 08, 2012 1:44 pm

Re: High Precision timer & IOAPIC connection

Post by Anon5710 »

well, i tried to get it working but no success.
By single stepping i could see my interrupt handler being called before my code should get there. Exactly what i would expect with an inverted signal.

So i gave up, used IRQ11 (edge triggerd, active high) and voila it worked ! :)
Can't use the other timers tough. :( (no connection to IOAPIC)

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

Re: High Precision timer & IOAPIC connection

Post by Brendan »

Hi,
Anon5710 wrote:well, i tried to get it working but no success.
By single stepping i could see my interrupt handler being called before my code should get there. Exactly what i would expect with an inverted signal.

So i gave up, used IRQ11 (edge triggerd, active high) and voila it worked ! :)
Can't use the other timers tough. :( (no connection to IOAPIC)
Now I'm confused. Here's some code from Linux' HPET driver ("usr/src/linux-3.5.7-gentoo/drivers/char/hpet.c"):

Code: Select all

static void hpet_timer_set_irq(struct hpet_dev *devp)
{
	unsigned long v;
	int irq, gsi;
	struct hpet_timer __iomem *timer;

	spin_lock_irq(&hpet_lock);
	if (devp->hd_hdwirq) {
		spin_unlock_irq(&hpet_lock);
		return;
	}

	timer = devp->hd_timer;

	/* we prefer level triggered mode */
	v = readl(&timer->hpet_config);
	if (!(v & Tn_INT_TYPE_CNF_MASK)) {
		v |= Tn_INT_TYPE_CNF_MASK;
		writel(v, &timer->hpet_config);
	}
	spin_unlock_irq(&hpet_lock);

	v = (readq(&timer->hpet_config) & Tn_INT_ROUTE_CAP_MASK) >>
				 Tn_INT_ROUTE_CAP_SHIFT;

	/*
	 * In PIC mode, skip IRQ0-4, IRQ6-9, IRQ12-15 which is always used by
	 * legacy device. In IO APIC mode, we skip all the legacy IRQS.
	 */
	if (acpi_irq_model == ACPI_IRQ_MODEL_PIC)
		v &= ~0xf3df;
	else
		v &= ~0xffff;

	for_each_set_bit(irq, &v, HPET_MAX_IRQ) {
		if (irq >= nr_irqs) {
			irq = HPET_MAX_IRQ;
			break;
		}

		gsi = acpi_register_gsi(NULL, irq, ACPI_LEVEL_SENSITIVE,
					ACPI_ACTIVE_LOW);
		if (gsi > 0)
			break;

		/* FIXME: Setup interrupt source table */
	}

	if (irq < HPET_MAX_IRQ) {
		spin_lock_irq(&hpet_lock);
		v = readl(&timer->hpet_config);
		v |= irq << Tn_INT_ROUTE_CNF_SHIFT;
		writel(v, &timer->hpet_config);
		devp->hd_hdwirq = gsi;
		spin_unlock_irq(&hpet_lock);
	}
	return;
}
From what I can tell, Linux always uses "level triggered" and programs the interrupt as "active low". This makes me wonder how you've setup the corresponding IO APIC input (e.g. if you've left it as default settings).


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.
Anon5710
Posts: 21
Joined: Thu Nov 08, 2012 1:44 pm

Re: High Precision timer & IOAPIC connection

Post by Anon5710 »

I find that code hard to read, but anways, I did not forget to setup the coresponding ioapic entry.

My hpet driver basicly has one input variable namly the wanted IRQ.

Setting IRQ20-23 for all timers and IOAPIC ACTIVE_LOW(or high) & level_trig does not work. Set its irq to 11, set hpet to edge triggerd and the same code works perfectly. (I was even able to get an interrupt each 100µs )

Maybe its fixed in newer chipsets, ICH7 is pretty old (~2007).
Post Reply