Page 1 of 1
IOAPIC Interrupt correctly set, but code is never run
Posted: Tue Apr 10, 2012 10:17 am
by ATXcs1372
I am running this under bochs, so let me walk you through this:
Initial Problem:
I'm trying to get the APIC Timer to fire vector 0x20 (32) of the IDT. I have correctly set the timer as bochs is giving repeated
Code: Select all
00024807285d[APIC0] local apic timer(periodic) triggered int
messages. The problem though lies in the fact the code for that vector is never run and thus the EOI message is never sent and the previous message is followed by
Code: Select all
00024832885d[APIC0] triggered vector 0x20 not accepted
but only on the second time the interrupt is triggered, making the EOI problem pretty apparent.
Double Checks:
Correct code location is placed into vector 0x20 as I can call the location as a form a pointer function and it works (until the iretq).
Code: Select all
IDT[0x20]=64-Bit Interrupt Gate target=0x0018:0000000000201040, DPL=0
Correctly installed IOAPIC INTIN0 to vector 0x20
Code: Select all
00018381615d[IOAP ] IOAPIC: now entry[0] is dest=00, masked=0, trig_mode=0, remote_irr=0, polarity=0, delivery_status=0, dest_mode=0, delivery_mode=0, vector=20
The code to be called is
Code: Select all
localAPICTimerISR:
push rax
mov al, '6'
mov [0x000B809C], al
mov al, '0'
mov [0x000B809E], al
mov rax, QWORD [0x5000] ; stored location of local APIC for BSP
add rax, 0xB0
mov DWORD [rax], 0 ; set EOI
pop rax
iretq
Final:
Initially I worried about the plain "vector=20" from the IOAPIC message, but even installing at vector #20 the code did not run.
There is nothing printed to the screen (the two 0xB8000 locations).
The ISR is installed to the IDT long before the timer is set up.
Am I missing something obvious?
Re: IOAPIC Interrupt correctly set, but code is never run
Posted: Tue Apr 10, 2012 11:38 am
by brain
Check the trigger mode and polarity of the ioapic Interrupt redirection, I had similar problems at first and my code was zeroing the ioapic register...
Re: IOAPIC Interrupt correctly set, but code is never run
Posted: Tue Apr 10, 2012 1:04 pm
by Rudster816
You need to set a color for the characters printed
Re: IOAPIC Interrupt correctly set, but code is never run
Posted: Tue Apr 10, 2012 1:04 pm
by ATXcs1372
brain wrote:Check the trigger mode and polarity of the ioapic Interrupt redirection, I had similar problems at first and my code was zeroing the ioapic register...
AFAIK it should be a fixed interrupt (dest mode = 0) with active high (polarity = 0) and edge triggered (trigger mode = 0) which matches what bochs is telling me...
Re: IOAPIC Interrupt correctly set, but code is never run
Posted: Tue Apr 10, 2012 1:07 pm
by ATXcs1372
Rudster816 wrote:You need to set a color for the characters printed
While technically yes I should write the attribute byte for those, they've already been written from previous debug info at those two locations.
Regardless, no matter what function I make the vector point to, it isn't executed.
Re: IOAPIC Interrupt correctly set, but code is never run
Posted: Tue Apr 10, 2012 11:12 pm
by xenos
I'm a bit confused. The local APIC timer interrupt is not directed through the IOAPIC, it is generated in the local APIC. If you direct IRQ0 through the IOAPIC to the same interrupt vector 0x20, you point the PIT timer interrupt to the same interrupt vector. If you wish to use only the local APIC timer, there is no need to fiddle around with the IOAPIC at all. The only thing you need to set is the local APIC's LVT.
BTW, the message generated by Bochs ("triggered vector 0x20 not accepted") indicates that the corresponding bit of the IRR is set when the interrupt arrives, and so the interrupt is discarded, which may be caused by not correctly sending an EOI. However, this still doesn't explain why your interrupt handler doesn't get called (because otherwise it would print something to the screen and send an EOI).
Could you provide the code you use to setup the local APIC timer and LVT?
Re: IOAPIC Interrupt correctly set, but code is never run
Posted: Wed Apr 11, 2012 5:59 pm
by ATXcs1372
XenOS wrote:I'm a bit confused. The local APIC timer interrupt is not directed through the IOAPIC, it is generated in the local APIC. If you direct IRQ0 through the IOAPIC to the same interrupt vector 0x20, you point the PIT timer interrupt to the same interrupt vector. If you wish to use only the local APIC timer, there is no need to fiddle around with the IOAPIC at all. The only thing you need to set is the local APIC's LVT.
Could you provide the code you use to setup the local APIC timer and LVT?
You're right, I was misunderstanding the way the timer, APIC, and LVT worked together. I also had to change it to vector 0x21 due to the PIT interrupt I forgot I set :/
However, the vector in the LVT entry for the timer should be the vector for the IVT correct?
Here's how I setup the timer:
Code: Select all
void initializeAPICTimer(uint8_t vector)
{
uint64_t apic = *((uint64_t *)0x5000); ; local APIC location stored at 0x5000 by bootloader, is verified by kernel
*((uint32_t *)(apic + APIC_SPUR)) |= 0x000001FF;
*((uint32_t *)(apic + APIC_DFR)) = 0xFFFFFFFF;
*((uint32_t *)(apic + APIC_TPR)) = 0x00000000;
*((uint32_t *)(apic + APIC_TDCR)) = 0x00000003;
*((uint32_t *)(apic + APIC_TMRLVTR)) = 0x00020000 | vector;
*((uint32_t *)(apic + APIC_TICR)) = 0x00000640;
}
Re: IOAPIC Interrupt correctly set, but code is never run
Posted: Wed Apr 11, 2012 9:03 pm
by Brendan
Hi,
ATXcs1372 wrote:However, the vector in the LVT entry for the timer should be the vector for the IVT correct?
Yes.
Also note that the vector also determines interrupt priority. I'd be tempted to use a vector with a high number so that the local APIC timer has a higher priority than normal interrupts (and giving the local APIC's "spurious interrupt" a low number).
ATXcs1372 wrote:Here's how I setup the timer:
That looks correct to me, except you probably should use "volatile" (so that the C compiler doesn't decide that because the values written aren't used anywhere else the writes can be ignored/discarded). For example, maybe "volatile void *apic = *((void **)0x5000);".
For debugging, don't forget that you can read things like the local APIC timer's current count (should be decreasing or zero afterwards) and both the IRR and ISR (to see if the local APIC tried to send any IRQs that you missed).
Cheers,
Brendan
Re: IOAPIC Interrupt correctly set, but code is never run
Posted: Thu Apr 12, 2012 1:19 am
by ATXcs1372
Brendan wrote:
That looks correct to me, except you probably should use "volatile" (so that the C compiler doesn't decide that because the values written aren't used anywhere else the writes can be ignored/discarded). For example, maybe "volatile void *apic = *((void **)0x5000);".
Raising the task priority nor the volatile attributes fixed the issue. I even moved the interrupt into a different priority block in the IVT.
At the moment there aren't any other interrupts called so priority or a long-running interrupt shouldnt be the issue.
Executing the following code does run the interrupt as expected, but while the timer is trying to call it the code just isn't running...