I have SMP support in my kernel now, and it boots up to 16 CPUs perfectly fine.
But I have an issue trying to enable IRQs. I set up 24 IRQs in the I/O APIC registers 0x10 - 0x3F, and I'm perfectly sure I'm doing that correctly. I put the interrupt number in the lowest 8 bits and set bits 56-63 to the CPU number I want to receive the interrupt.
Then, I set up the PIT and install its IRQ handler. In Bochs and QEMU, the IRQ is received once. However, in QEMU if I emulate more than 2 CPUs it doesn't get called at all. On my laptop (4 CPUs), it is also never received.
Can someone point out what I'm doing wrong? Do I need to do something with the local APIC? Do I need to enable the I/O APIC somehow?
P.S.: Is there an alternative for EOI on the I/O APIC?
Can't enable IRQs with I/O APIC
- BrightLight
- Member
- Posts: 901
- Joined: Sat Dec 27, 2014 9:11 am
- Location: Maadi, Cairo, Egypt
- Contact:
Can't enable IRQs with I/O APIC
You know your OS is advanced when you stop using the Intel programming guide as a reference.
Re: Can't enable IRQs with I/O APIC
Hi,
Finally; when an interrupt does occur (excluding any of the spurious IRQs) you have to send an EOI to the local APIC's "EOI Register" (and not to any PIC chip).
Cheers,
Brendan
You'd need to (in order):omarrx024 wrote:I have SMP support in my kernel now, and it boots up to 16 CPUs perfectly fine.
But I have an issue trying to enable IRQs. I set up 24 IRQs in the I/O APIC registers 0x10 - 0x3F, and I'm perfectly sure I'm doing that correctly. I put the interrupt number in the lowest 8 bits and set bits 56-63 to the CPU number I want to receive the interrupt.
Then, I set up the PIT and install its IRQ handler. In Bochs and QEMU, the IRQ is received once. However, in QEMU if I emulate more than 2 CPUs it doesn't get called at all. On my laptop (4 CPUs), it is also never received.
Can someone point out what I'm doing wrong? Do I need to do something with the local APIC? Do I need to enable the I/O APIC somehow?
P.S.: Is there an alternative for EOI on the I/O APIC?
- Parse ACPI 's "MADT/APIC" table to figure out how legacy ISA IRQs are connected to IO APIC inputs (and fall back to Intel's "MultiProcessor Specification" tables if there is no ACPI).
- Mask all IRQs (not the "cascade" line) in the PIC chips
- Mask everything in all IO APICs. You can "pre-setup" each IO APIC input while doing this. Note: there can be more than one IO APIC - e.g. a pair of IO APICs with 16 inputs each, or a set of four IO APICs, or....
- Create (or make sure you already have) an IDT with interrupt vectors for the local APIC's spurious IRQ, the master PIC's spurious IRQ and the slave PIC's spurious IRQ.
- For each CPU (in any order):
- Set the local APIC's "Task Priority Register" to zero
- Setup the local APIC's "Spurious Interrupt Vector Register" (give it a vector for the spurious IRQ, and enable the local APIC)
- (Optional maybe) setup the local APIC's "Destination Format Register" for flat mode
- (Optional maybe) setup the local APIC's "Logical Destination Register"
- Do whatever ACPI and/or MP spec tables told you to do (if anything) with the local APIC's "LINT0" and "LINT1" interrupts
- If ACPI and/or MP spec tables told you there's an IMCR, diddle the IMCR to switch from "PIC mode" to "IO APIC mode" (see MP spec for details)
Finally; when an interrupt does occur (excluding any of the spurious IRQs) you have to send an EOI to the local APIC's "EOI Register" (and not to any PIC chip).
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.
- BrightLight
- Member
- Posts: 901
- Joined: Sat Dec 27, 2014 9:11 am
- Location: Maadi, Cairo, Egypt
- Contact:
Re: Can't enable IRQs with I/O APIC
Does this mean I use APIC table entry type 2 (interrupt source override)?Brendan wrote:Parse ACPI 's "MADT/APIC" table to figure out how legacy ISA IRQs are connected to IO APIC inputs (and fall back to Intel's "MultiProcessor Specification" tables if there is no ACPI).
What is the register offset?Brendan wrote:Set the local APIC's "Task Priority Register" to zero
Thanks in advance!
P.S.: How do I send EOI?
Last edited by BrightLight on Thu Jan 07, 2016 5:14 am, edited 1 time in total.
You know your OS is advanced when you stop using the Intel programming guide as a reference.
Re: Can't enable IRQs with I/O APIC
Hi,
For ACPI, the general idea is that you start by assuming there's a 1:1 mapping between ISA IRQs and IO APIC inputs (e.g. "IO APIC input #0 = ISA IRQ0; IO APIC input #1 = ISA IRQ1; ...; IO APIC input #15 = ISA IRQ15", but skipping "ISA IRQ 2" because it doesn't exist).
Then the "interrupt source override" structures (in ACPI's MADT/APIC table) tells you how that assumed/original 1:1 mapping needs to be changed. Typically you'll have one for ACPI's SCI and one for "ISA IRQ0", but different computers are different.
Cheers,
Brendan
Yes.omarrx024 wrote:Does this mean I use APIC table entry type 2 (interrupt source override)?Brendan wrote:Parse ACPI 's "MADT/APIC" table to figure out how legacy ISA IRQs are connected to IO APIC inputs (and fall back to Intel's "MultiProcessor Specification" tables if there is no ACPI).
For ACPI, the general idea is that you start by assuming there's a 1:1 mapping between ISA IRQs and IO APIC inputs (e.g. "IO APIC input #0 = ISA IRQ0; IO APIC input #1 = ISA IRQ1; ...; IO APIC input #15 = ISA IRQ15", but skipping "ISA IRQ 2" because it doesn't exist).
Then the "interrupt source override" structures (in ACPI's MADT/APIC table) tells you how that assumed/original 1:1 mapping needs to be changed. Typically you'll have one for ACPI's SCI and one for "ISA IRQ0", but different computers are different.
I don't remember these details (I just look them up in Intel's manual when I need to); but if you want me to guess, "offset 0x340" sounds like it might be close to me..omarrx024 wrote:What is the register offset?Brendan wrote:Set the local APIC's "Task Priority Register" to zero
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.
- BrightLight
- Member
- Posts: 901
- Joined: Sat Dec 27, 2014 9:11 am
- Location: Maadi, Cairo, Egypt
- Contact:
Re: Can't enable IRQs with I/O APIC
Thanks a lot! I've got the IRQs working on Bochs, QEMU and real hardware.
But I still have one problem: the IRQ is only received once. When I try to send an EOI to the local APIC register 0xA0, Bochs console log says:
How do I send EOI?
EDIT: I've figured how to send EOI from the Intel manuals and inter-processor IRQs are working like a charm. Thanks again!
But I still have one problem: the IRQ is only received once. When I try to send an EOI to the local APIC register 0xA0, Bochs console log says:
Code: Select all
00028654781i[APIC0 ] warning: write to read-only APIC register 0xa0
EDIT: I've figured how to send EOI from the Intel manuals and inter-processor IRQs are working like a charm. Thanks again!
You know your OS is advanced when you stop using the Intel programming guide as a reference.
Re: Can't enable IRQs with I/O APIC
to send EOI
ApicWrite(0xB0, 0);
ApicWrite(0xB0, 0);
- BrightLight
- Member
- Posts: 901
- Joined: Sat Dec 27, 2014 9:11 am
- Location: Maadi, Cairo, Egypt
- Contact:
Re: Can't enable IRQs with I/O APIC
Thanks, but I've already figured this out from Intel's manual.digo_rp wrote:to send EOI
ApicWrite(0xB0, 0);
You know your OS is advanced when you stop using the Intel programming guide as a reference.