On bochs (cvs as of Jan. 7 2006) the PIT timer is connected to pin 0 of the IO APIC, as one would expect.
That is not the case on any of my real test computers.
I read about the MP tables in the bios, and read those on my computers... but nowhere is there any indication of ISA IRQ 0 being mapped anywhere! (Actually there is something - a local interrupt (type 4) that maps ISA IRQ 0 to LINT1 as an NMI interrupt... but I don't quite believe that) The data checksums correctly, so it seems valid, but yet...
Then I see Linux - [link]http://lxr.linux.no/source/arch/i386/kernel/io_apic.c#L2129[/link]!
Am I just overlooking something stupid here? Should I be using the APIC timer instead? If any of you have used the IO APIC in your OSes please let me know how you dealt with this.
Thanks,
Mike
IOAPIC and IRQ 0
- kataklinger
- Member
- Posts: 381
- Joined: Fri Nov 04, 2005 12:00 am
- Location: Serbia
Re:IOAPIC and IRQ 0
Have you read Intel Multiprocessor specification (version 1.4). LINT0 & LINT1 are interrupt inputs of local APIC not IO APIC. LINT0 is for ExtINT (interrupts from PIC) and LINT1 is for NMI.
IO APIC inputs (default configuration):
INTIN0 - input from pic (or not connected for configuration 7)
INTIN1 - irq 1, keyboard
INTIN2 - irq 0, pit (or not connected for configuration 2)
INTIN3 - irq 3
INTIN4 - irq 4
.....
INTIN15 - irq 15
IO APIC inputs (default configuration):
INTIN0 - input from pic (or not connected for configuration 7)
INTIN1 - irq 1, keyboard
INTIN2 - irq 0, pit (or not connected for configuration 2)
INTIN3 - irq 3
INTIN4 - irq 4
.....
INTIN15 - irq 15
Re:IOAPIC and IRQ 0
If you're using the local APIC timer, then you will get a local interrupt from the CPU itself and its APIC timer. The interrupt that it calls is set up in the memory mapped APIC registers. It doesn't come from an external source and that means it doesn't need to come through the IO APIC.
There's no need to go out of your way to configure the IO APIC and you don't need to configure the PIT to do it's own timer interrupt if you just want to use the local APIC. Of course, you can use the PIT timer if you want to ...
I'm using the local APIC timer and I don't have IRQ 0 enabled for PIT interrupts. The APIC calls the interrupt directly without any problems.
I don't know if that helps in anyway ...
There's no need to go out of your way to configure the IO APIC and you don't need to configure the PIT to do it's own timer interrupt if you just want to use the local APIC. Of course, you can use the PIT timer if you want to ...
I'm using the local APIC timer and I don't have IRQ 0 enabled for PIT interrupts. The APIC calls the interrupt directly without any problems.
I don't know if that helps in anyway ...
Re:IOAPIC and IRQ 0
Hi,
It's actually a little more complex than many people realize. Each PIC chip has an "I need to interrupt" output signal called "INTR". The slave PIC's INTR is connected to the master PICs IRQ 2 input, which is how they are "cascaded". The CPU itself also has an "INTR" pin, which is used to tell the CPU that an interrupt occured.
For computers without local APICs or I/O APICs, the master PIC's INTR is connected directly to the CPUs INTR. For computers with a local APIC this doesn't work because the CPUs INTR line needs to be connected to the local APIC and the master PIC. To get around this different motherboards do different things - some have an electronic switch as part of the chipset (called the "IMCR"), some connect the PIC's INTR output to one of the local APICs inputs (normally "LINTIN0"), some connect it to one of the I/O APICs inputs (often "INTIN0"), and some connect it to both (e.g. "LINTIN0" and "INTIN0").
Anyway, when the master PIC's INTR is connected to the I/O APICs "INTIN0", IRQ0 is usually connected to the I/O APICs "INTIN2" because there is no "IRQ2" (it's used for cascading the slave PIC chip, and isn't connected to the I/O APIC). Alternatively, IRQ0 may not be connected to the I/O APIC at all (but this is very rare - 80486 only AFAIK).
Regardless of what the motherboard does, the MP specification has entries that describe it ("I/O APIC Interrupt Assignment Entries", "Local APIC Interrupt Assignment Entries" and a flag in the floating MP pointer structure that says if an IMCR is present).
For Bochs, the master PIC's INTR line isn't emulated and the MP specification tables are broken - there's no details of where the master PIC's INTR line is connected, there are no "Local APIC Interrupt Assignment Entries" at all, there's no "I/O APIC Interrupt Assignment Entries" for PCI IRQs and there is an "I/O APIC Interrupt Assignment Entry" for IRQ2 that shouldn't be there. For Qemu, they just copied Bochs rather than doing some work of their own, so their MP specification tables are just as broken with identical problems.
The Bochs developers have been doing a lot of work on the APICs lately, so hopefully these issues will be resolved soon...
Cheers,
Brendan
This is the case on at least 3 of my computers (I only tested 3 of them), but it does depend on the motherboard. In general, whatever the motherboard does is described by the MP specification tables (and ACPI tables), so that the OS can parse these tables to figure out what goes where. This means the motherboard could do some completely unusual things (like randomly connecting any IRQ to any I/O APIC input) without the OS caring, as long as the MP specification tables (and ACPI tables) are correct.Mike wrote:On bochs (cvs as of Jan. 7 2006) the PIT timer is connected to pin 0 of the IO APIC, as one would expect.
That is not the case on any of my real test computers.
It's actually a little more complex than many people realize. Each PIC chip has an "I need to interrupt" output signal called "INTR". The slave PIC's INTR is connected to the master PICs IRQ 2 input, which is how they are "cascaded". The CPU itself also has an "INTR" pin, which is used to tell the CPU that an interrupt occured.
For computers without local APICs or I/O APICs, the master PIC's INTR is connected directly to the CPUs INTR. For computers with a local APIC this doesn't work because the CPUs INTR line needs to be connected to the local APIC and the master PIC. To get around this different motherboards do different things - some have an electronic switch as part of the chipset (called the "IMCR"), some connect the PIC's INTR output to one of the local APICs inputs (normally "LINTIN0"), some connect it to one of the I/O APICs inputs (often "INTIN0"), and some connect it to both (e.g. "LINTIN0" and "INTIN0").
Anyway, when the master PIC's INTR is connected to the I/O APICs "INTIN0", IRQ0 is usually connected to the I/O APICs "INTIN2" because there is no "IRQ2" (it's used for cascading the slave PIC chip, and isn't connected to the I/O APIC). Alternatively, IRQ0 may not be connected to the I/O APIC at all (but this is very rare - 80486 only AFAIK).
Regardless of what the motherboard does, the MP specification has entries that describe it ("I/O APIC Interrupt Assignment Entries", "Local APIC Interrupt Assignment Entries" and a flag in the floating MP pointer structure that says if an IMCR is present).
For Bochs, the master PIC's INTR line isn't emulated and the MP specification tables are broken - there's no details of where the master PIC's INTR line is connected, there are no "Local APIC Interrupt Assignment Entries" at all, there's no "I/O APIC Interrupt Assignment Entries" for PCI IRQs and there is an "I/O APIC Interrupt Assignment Entry" for IRQ2 that shouldn't be there. For Qemu, they just copied Bochs rather than doing some work of their own, so their MP specification tables are just as broken with identical problems.
The Bochs developers have been doing a lot of work on the APICs lately, so hopefully these issues will be resolved soon...
For entries with the type "NMI", "SMI" and "extINT", the source bus and source IRQ is ignored - these interrupt sources aren't connected to normal devices. You'll probably also see that the "local APIC ID" for the NMI is 0xFF (which means "all local APICs", not a local APIC with 0xFF for it's APIC ID).Mike wrote:I read about the MP tables in the bios, and read those on my computers... but nowhere is there any indication of ISA IRQ 0 being mapped anywhere! (Actually there is something - a local interrupt (type 4) that maps ISA IRQ 0 to LINT1 as an NMI interrupt... but I don't quite believe that) The data checksums correctly, so it seems valid, but yet...
Some of this code is designed to make up for problems with old dodgy motherboards or old dodgy APICs. If you don't support external local APICs (the 82489DX chips used for 80486 and very early Pentiums), and don't support EISA or MCA you could make this easier. That's what I'm doing at least...Mike wrote:Then I see Linux - [link]http://lxr.linux.no/source/arch/i386/kernel/io_apic.c#L2129[/link]!
I use the local APIC timer instead, even on single CPU computers (unless there's no choice).Mike wrote:Should I be using the APIC timer instead? If any of you have used the IO APIC in your OSes please let me know how you dealt with this.
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.
Re:IOAPIC and IRQ 0
I don't have an IMCR... and there is definitely no entry for IRQ0... or IRQ2 for that matter. I was able to get a periodic interrupt by connecting to INTIN2 on the IOAPIC so it would seem to be the timer interrupt - but nowhere does it specify anything about it!
Here are the contents of my MP tables, all values in hex
I read the MP spec and the diagrams of the default configurations - my system does not seem to be any of them!
I'm either really confused or just too tired to understand...
Thanks,
Mike
Here are the contents of my MP tables, all values in hex
Code: Select all
000F9BF0: 5F 4D 50 5F F0 C8 0E 00 01 04 DA 00 00 00 00 00 _MP_............
PCMP BaseLength=01B8 SpecRev=04 Checksum=FB OemId="COMPAQ " ProdId=" "
OEMTable=0 OemTableSize=0 EntryCount=0030 LApicAddr=FEE00000 ExtLength=0 ExtChecksum=0 Reserved=0
CPU LApicId=0 LApicVersion=10h fEnabled=1 fBsp=1 fRsvd=0 Signature=00000F12 FeatureFlags=3FEBFBFF Reserved=0 0
BUS id=0 PCI
id=1 PCI
id=2 PCI
id=9 ISA
IOAPIC Id=8 Version=11h fEnabled=1 fRsvd=0 Addr=FEC00000
INT type=0 pol=3 trig=3 srcbus=0 srcirq=7C destid=8 destirq=10
type=0 pol=3 trig=3 srcbus=0 srcirq=7D destid=8 destirq=11
type=0 pol=3 trig=3 srcbus=0 srcirq=7E destid=8 destirq=17
type=0 pol=3 trig=3 srcbus=0 srcirq=7F destid=8 destirq=13
type=0 pol=3 trig=3 srcbus=0 srcirq=04 destid=8 destirq=12
type=0 pol=3 trig=3 srcbus=0 srcirq=05 destid=8 destirq=13
type=0 pol=3 trig=3 srcbus=2 srcirq=18 destid=8 destirq=14
type=0 pol=3 trig=3 srcbus=2 srcirq=10 destid=8 destirq=10
type=0 pol=3 trig=3 srcbus=2 srcirq=11 destid=8 destirq=12
type=0 pol=3 trig=3 srcbus=2 srcirq=12 destid=8 destirq=15
type=0 pol=3 trig=3 srcbus=2 srcirq=13 destid=8 destirq=16
type=0 pol=3 trig=3 srcbus=2 srcirq=20 destid=8 destirq=14
type=0 pol=3 trig=3 srcbus=2 srcirq=24 destid=8 destirq=12
type=0 pol=3 trig=3 srcbus=2 srcirq=25 destid=8 destirq=15
type=0 pol=3 trig=3 srcbus=2 srcirq=26 destid=8 destirq=16
type=0 pol=3 trig=3 srcbus=2 srcirq=27 destid=8 destirq=10
type=0 pol=3 trig=3 srcbus=2 srcirq=28 destid=8 destirq=15
type=0 pol=3 trig=3 srcbus=2 srcirq=29 destid=8 destirq=16
type=0 pol=3 trig=3 srcbus=2 srcirq=2A destid=8 destirq=10
type=0 pol=3 trig=3 srcbus=2 srcirq=2B destid=8 destirq=12
type=0 pol=3 trig=3 srcbus=2 srcirq=2C destid=8 destirq=16
type=0 pol=3 trig=3 srcbus=2 srcirq=2D destid=8 destirq=10
type=0 pol=3 trig=3 srcbus=2 srcirq=2E destid=8 destirq=12
type=0 pol=3 trig=3 srcbus=2 srcirq=2F destid=8 destirq=15
type=0 pol=3 trig=3 srcbus=2 srcirq=34 destid=8 destirq=12
type=0 pol=3 trig=3 srcbus=2 srcirq=35 destid=8 destirq=15
type=0 pol=3 trig=3 srcbus=2 srcirq=36 destid=8 destirq=16
type=0 pol=3 trig=3 srcbus=2 srcirq=37 destid=8 destirq=10
type=0 pol=0 trig=0 srcbus=9 srcirq=01 destid=8 destirq=01
type=0 pol=0 trig=0 srcbus=9 srcirq=03 destid=8 destirq=03
type=0 pol=0 trig=0 srcbus=9 srcirq=04 destid=8 destirq=04
type=0 pol=0 trig=0 srcbus=9 srcirq=06 destid=8 destirq=06
type=0 pol=0 trig=0 srcbus=9 srcirq=07 destid=8 destirq=07
type=0 pol=0 trig=0 srcbus=9 srcirq=08 destid=8 destirq=08
type=0 pol=0 trig=0 srcbus=9 srcirq=09 destid=8 destirq=09
type=0 pol=0 trig=0 srcbus=9 srcirq=0A destid=8 destirq=0A
type=0 pol=0 trig=0 srcbus=9 srcirq=0B destid=8 destirq=0B
type=0 pol=0 trig=0 srcbus=9 srcirq=0C destid=8 destirq=0C
type=0 pol=0 trig=0 srcbus=9 srcirq=0D destid=8 destirq=0D
type=0 pol=0 trig=0 srcbus=9 srcirq=0E destid=8 destirq=0E
type=0 pol=0 trig=0 srcbus=9 srcirq=0F destid=8 destirq=0F
LINT type=1 pol=0 trig=0 srcbus=9 srcirq=0 destid=FF destlint=01
type=1 pol=0 trig=0 srcbus=9 srcirq=0 destid=FF destlint=01
I'm either really confused or just too tired to understand...
Thanks,
Mike
Re:IOAPIC and IRQ 0
Hi,
The last 2 lines don't make much sense:
Both of these lines are identical (but both are what I'd expect for the local APICs LINTIN1 input, which is usually an NMI).
There is nothing marked as "extINT" (or interrupt type 0x03), which is very unusual AFAIK. Given that the PIT is connected to INTIN2, I'd expect that the master PIC's INTR is connected to INTIN0, but then there should be an I/O APIC interrupt assignment saying:
And possibly a local APIC interrupt assignment entry (for all local APICs LINTIN0 inputs) saying:
Also, it's reporting a total of 28 PCI interrupt sources - usually you'd get one per PCI device. A computer with 28 PCI devices is possible, but it does seem unusual to me - does your computer have a lot of devices?
Then the "FeatureFlags=3FEBFBFF" seems wrong too, as reserved bits should be clear (and most of these bits are reserved).
I've got my own utility to parse and display the MP specification tables. It's written for pure DOS (i.e. it'll crash in a DOS box under windows), so you'd need a DOS boot disk. Would you mind giving it a try and posting the results? To start it I normally use "mpdump > results.txt" to create a file of the output, rather than just displaying it on the screen.
I've also got the results from this utility for 4 seperate computers (every computer I have that creates MP tables). It might be interesting to see how different some of them are..
An older single CPU Pentium 4 machine
A newer single CPU Pentium 4 machine
A dual CPU Pentium III machine
A dual CPU Pentium II machine
Of these, the Pentium III is interesting because it has 2 seperate I/O APICs with 16 inputs each.
The Pentium II is a Compaq Proliant, and most closely resembles your machine. The APIC ID's, APIC versions and PCI/ISA bus numbers are all identical (except you have an additional PCI bus). The interesting thing here is that there's a group of I/O APIC interrupt assignment entries, then a group of local APIC interrupt assignment entries, followed by one more I/O APIC interrupt assignment entry - i.e. all of the I/O APIC entries aren't in one group.
The last I/O APIC entry, which isn't part of the main group, is the one with type=3 (extINT), but there's also a local APIC interrupt assignment entry for type=3 (extINT). This shows the master PIC's INTR line connected to the I/O APICs INTIN0 input and the local APICs LINTIN0 input.
Also there is an I/O APIC interrupt assignment entry showing the ISA IRQ0 being connected to the I/O APICs INTIN2, but there are no entries for PCI IRQs for this machine (which is unusual).
Anyway, it'd be good to compare the results you've posted with the results my utility shows for your machine, just to make sure they are both reporting correct information....
[EDIT]
Ignore what I said about "FeatureFlags=3FEBFBFF" - I got the CPUs feature flags mixed up with the MP floating point structure's feature flags!
[/EDIT]
Cheers,
Brendan
This may be correct - there's no requirement for the PIT IRQ to be connected to the I/O APIC, so I guess the MP tables could ignore IRQ0 regardless of whether it's connected to the I/O APIC or not.Mike wrote:I don't have an IMCR... and there is definitely no entry for IRQ0... or IRQ2 for that matter. I was able to get a periodic interrupt by connecting to INTIN2 on the IOAPIC so it would seem to be the timer interrupt - but nowhere does it specify anything about it!
A few things here seems odd to me. For example, all I/O APIC interrupt assignments have "interrupt type = 0" and all local APIC interrupt assignments have "interrupt type = 1". I'm wondering if this is the table type and not the interrupt type.Mike wrote:Here are the contents of my MP tables, all values in hex
The last 2 lines don't make much sense:
Code: Select all
LINT type=1 pol=0 trig=0 srcbus=9 srcirq=0 destid=FF destlint=01
type=1 pol=0 trig=0 srcbus=9 srcirq=0 destid=FF destlint=01
There is nothing marked as "extINT" (or interrupt type 0x03), which is very unusual AFAIK. Given that the PIT is connected to INTIN2, I'd expect that the master PIC's INTR is connected to INTIN0, but then there should be an I/O APIC interrupt assignment saying:
Code: Select all
type=3 pol=0 trig=0 srcbus=9 srcirq=00 destid=8 destirq=0
Code: Select all
type=3 pol=0 trig=0 srcbus=9 srcirq=00 destid=FF destirq=0
Then the "FeatureFlags=3FEBFBFF" seems wrong too, as reserved bits should be clear (and most of these bits are reserved).
I've got my own utility to parse and display the MP specification tables. It's written for pure DOS (i.e. it'll crash in a DOS box under windows), so you'd need a DOS boot disk. Would you mind giving it a try and posting the results? To start it I normally use "mpdump > results.txt" to create a file of the output, rather than just displaying it on the screen.
I've also got the results from this utility for 4 seperate computers (every computer I have that creates MP tables). It might be interesting to see how different some of them are..
An older single CPU Pentium 4 machine
A newer single CPU Pentium 4 machine
A dual CPU Pentium III machine
A dual CPU Pentium II machine
Of these, the Pentium III is interesting because it has 2 seperate I/O APICs with 16 inputs each.
The Pentium II is a Compaq Proliant, and most closely resembles your machine. The APIC ID's, APIC versions and PCI/ISA bus numbers are all identical (except you have an additional PCI bus). The interesting thing here is that there's a group of I/O APIC interrupt assignment entries, then a group of local APIC interrupt assignment entries, followed by one more I/O APIC interrupt assignment entry - i.e. all of the I/O APIC entries aren't in one group.
The last I/O APIC entry, which isn't part of the main group, is the one with type=3 (extINT), but there's also a local APIC interrupt assignment entry for type=3 (extINT). This shows the master PIC's INTR line connected to the I/O APICs INTIN0 input and the local APICs LINTIN0 input.
Also there is an I/O APIC interrupt assignment entry showing the ISA IRQ0 being connected to the I/O APICs INTIN2, but there are no entries for PCI IRQs for this machine (which is unusual).
Anyway, it'd be good to compare the results you've posted with the results my utility shows for your machine, just to make sure they are both reporting correct information....
[EDIT]
Ignore what I said about "FeatureFlags=3FEBFBFF" - I got the CPUs feature flags mixed up with the MP floating point structure's feature flags!
[/EDIT]
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.
Re:IOAPIC and IRQ 0
That "type" field is definitely the interrupt type and not the table type.
I ran your program on a dos boot disk and it just hung. It printed garbage - it found an MP config table at 0xE8C10FE6 when mine, according to the "floating pointer structure" (at 0x00F9BF0) is at 0x000EC8F0. After that it didn't print anything else, and didn't return control to DOS until I pressed ctrl+alt+del to reboot, and then if I tried to write the output to a file, DOS cached it and did not write it to the disk. I let it run for about five minutes thinking it might be scanning somehow, but nothing ever happened.
The data I put in my post below is what I manually read from the BIOS through Windows. It also happens to agree with what my OS prints (which cannot yet write to any disks!)
My computer has about six PCI slots - still _way_ less than the 28 PCI interrupts...
[edit]
I tried the program again and it worked!... but I didn't redirect the output to a file. So I tried it again and it failed. It seems to work intermittently.
[/edit]
Thanks for the info,
Mike
I ran your program on a dos boot disk and it just hung. It printed garbage - it found an MP config table at 0xE8C10FE6 when mine, according to the "floating pointer structure" (at 0x00F9BF0) is at 0x000EC8F0. After that it didn't print anything else, and didn't return control to DOS until I pressed ctrl+alt+del to reboot, and then if I tried to write the output to a file, DOS cached it and did not write it to the disk. I let it run for about five minutes thinking it might be scanning somehow, but nothing ever happened.
The data I put in my post below is what I manually read from the BIOS through Windows. It also happens to agree with what my OS prints (which cannot yet write to any disks!)
My computer has about six PCI slots - still _way_ less than the 28 PCI interrupts...
[edit]
I tried the program again and it worked!... but I didn't redirect the output to a file. So I tried it again and it failed. It seems to work intermittently.
[/edit]
Thanks for the info,
Mike
- kataklinger
- Member
- Posts: 381
- Joined: Fri Nov 04, 2005 12:00 am
- Location: Serbia
Re:IOAPIC and IRQ 0
Maybe MP table is broken, even if checksum is OK. Can you send your binaries so we could test on other machine?