Page 1 of 1
[FIXED] APIC Interrupts are not accepted
Posted: Sun Apr 22, 2012 7:11 pm
by ATXcs1372
Whenever I have a recurring interrupt (read: not using an inline 'int' call) bochs give the following message:
Code: Select all
00035450815d[APIC0] trigger interrupt vector=0x21
00035450815d[APIC0] triggered vector 0x21
00035450815d[APIC0] triggered vector 0x21 not accepted
The first time the interrupt is called the code does not run, thus the EOI is never written.
Bochs' debugger confirms the APIC LVT Vector as well as the IDT Vector are set correctly and to the correct address for the ISR.
I'm at a complete loss.
When I do call the interrupt using
even in a while loop it will run correctly. For some reason it is only when the interrupt is fired by the APIC Timer that it does this.
My APIC code looks like this:
Code: Select all
uint64_t apic = *((uint64_t *)0x5000); // 0x5000 contains address of the APIC from bootloader code
*((uint32_t *)(apic + APIC_SPUR)) |= 0x0100 | 0xFF; // software enable and 0xFF as spurious vector
*((uint32_t *)(apic + APIC_LDR)) = 0xFF000000;
*((uint32_t *)(apic + APIC_DFR)) = 0xF0000000;
*((uint32_t *)(apic + APIC_TPR)) = 0x00000000;
*((uint32_t *)(apic + APIC_TDCR)) = 0x00000003; // divisor of 16
*((uint32_t *)(apic + APIC_TMRLVTR)) = 0x00020000 | vector; // set to 0x21 in this case
*((uint32_t *)(apic + APIC_TICR)) = 0x00006400;
Do you see anything wrong? Have you had this problem?
Re: APIC Interrupts are not accepted
Posted: Sun Apr 22, 2012 7:26 pm
by Rudster816
You need to initialize the IOAPIC(s). Normally, the BIOS will set up all IOAPIC's to mask all interrupts, leaving it up to the OS to unmask them or use the PIC.
Re: APIC Interrupts are not accepted
Posted: Sun Apr 22, 2012 8:09 pm
by ATXcs1372
Rudster816 wrote:You need to initialize the IOAPIC(s). Normally, the BIOS will set up all IOAPIC's to mask all interrupts, leaving it up to the OS to unmask them or use the PIC.
The interrupt isn't being issued by the IOAPIC though...
Re: APIC Interrupts are not accepted
Posted: Sun Apr 22, 2012 8:40 pm
by gerryg400
Try doing an EOI at the end of the init sequence. That might kick it off.
[EDIT]: IMHO, setting the spurious interrupt vector to FF is commonly done but I think it's better to select a lower priority vector.
Re: APIC Interrupts are not accepted
Posted: Sun Apr 22, 2012 9:01 pm
by ATXcs1372
gerryg400 wrote:[EDIT]: IMHO, setting the spurious interrupt vector to FF is commonly done but I think it's better to select a lower priority vector.
I have done that as well, but to no avail.
Re: APIC Interrupts are not accepted
Posted: Sun Apr 22, 2012 9:20 pm
by gerryg400
So you tried EOI and you do sti ? Try clearing apic errors before you start.
Re: APIC Interrupts are not accepted
Posted: Sun Apr 22, 2012 9:31 pm
by ATXcs1372
gerryg400 wrote:So you tried EOI and you do sti ? Try clearing apic errors before you start.
I write 0x00000000 to the EOI register immediately before the iretq (using iretq because it is a 64-bit interrupt).
I don't think this is the immediate issue though, the actual code that makes up the ISR is never run. This leads to the EOI problem, however.
There are no APIC errors detected by Bochs but I'll look into it.
Can you elaborate on the sti part?
Re: APIC Interrupts are not accepted
Posted: Sun Apr 22, 2012 9:36 pm
by gerryg400
I'm suggesting to do an EOI during apic timer initialisation Just in case an int has already occurred.
STI refers to __asm__ ("sti"); some people forget to do it.
Re: APIC Interrupts are not accepted
Posted: Mon Apr 23, 2012 1:17 am
by xenos
I guess we already had this discussion
here...
To check whether the APIC actually gets the EOI, you could try the following: Immediately after starting bochs (before your kernel starts), hit the "configure" button in bochs' window. This will allow you to set log options for individual devices. Set the log level for the "APIC0" device's "debug" event to "report" and continue the simulation. Now you should see an entry in bochs' log file whenever an EOI is received by the APIC.
This is what it looks like in my kernel:
Code: Select all
...
d03350520844:c01061a9[APIC0] trigger interrupt vector=0x40
d03350520844:c01061a9[APIC0] triggered vector 0x40
d03350520844:c01061a9[APIC0] service_local_apic(): setting INTR=1 for vector 0x40
d03350520844:c01061a9[APIC0] local apic timer(periodic) triggered int, reset counter to 0x00010000
d03350520851:c01061a9[APIC0] acknowledge_int() returning vector 0x40
d03350520965:c0107640[APIC0] LAPIC write 0x00000000 to register 0x00b0
d03350520965:c0107640[APIC0] Wrote 0x0 to EOI
d03350520965:c0107640[APIC0] local apic received EOI, hopefully for vector 0x40
...
Re: APIC Interrupts are not accepted
Posted: Mon Apr 23, 2012 2:51 am
by gerryg400
I modified your code slightly to use my APIC defines and tried it in VMWare and on a real Intel Core 2 machine. I just put this code in the kmain function of my kernel and it got a single interrupt on both. I tried without your code and no interrupt occurred. So your code is okay (unless your #defines are incorrect).
Code: Select all
uint64_t apic = (LAPIC_VADDR); // 0x5000 contains address of the APIC from bootloader code
*((uint32_t *)(apic + LAPIC_SIV)) |= 0x0100 | 0xFF; // software enable and 0xFF as spurious vector
*((uint32_t *)(apic + LAPIC_LDR)) = 0xFF000000;
*((uint32_t *)(apic + LAPIC_DFR)) = 0xF0000000;
*((uint32_t *)(apic + LAPIC_TPR)) = 0x00000000;
*((uint32_t *)(apic + LAPIC_TDCR)) = 0x00000003; // divisor of 16
*((uint32_t *)(apic + LAPIC_TLVT)) = 0x00020000 | 0x40; // set to 0x21 in this case
*((uint32_t *)(apic + LAPIC_TICR)) = 0x00006400;
__sti();
Note that I did this prior to executing any other code that touched the APICS. I also modified the ISR vector number.
Re: APIC Interrupts are not accepted
Posted: Wed Apr 25, 2012 8:35 am
by ATXcs1372
Sorry for the delay, but I figured out the issue and was able to go on a coding storm as this was a huge roadblock.
As Gerry said I did need an "sti" call because although I issued it once, later APIC initialization code required a "cli" which I hadn't paired with an "sti".... silly me at 4 AM I'd presume.
Thank you for all the suggestions