[FIXED] APIC Interrupts are not accepted

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
ATXcs1372
Member
Member
Posts: 30
Joined: Wed Jun 01, 2011 7:14 pm

[FIXED] APIC Interrupts are not accepted

Post 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

Code: Select all

asm volatile("int $0x21");
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?
Last edited by ATXcs1372 on Wed Apr 25, 2012 8:35 am, edited 1 time in total.
Rudster816
Member
Member
Posts: 141
Joined: Thu Jun 17, 2010 2:36 am

Re: APIC Interrupts are not accepted

Post 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.
ATXcs1372
Member
Member
Posts: 30
Joined: Wed Jun 01, 2011 7:14 pm

Re: APIC Interrupts are not accepted

Post 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...
gerryg400
Member
Member
Posts: 1801
Joined: Thu Mar 25, 2010 11:26 pm
Location: Melbourne, Australia

Re: APIC Interrupts are not accepted

Post 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.
If a trainstation is where trains stop, what is a workstation ?
ATXcs1372
Member
Member
Posts: 30
Joined: Wed Jun 01, 2011 7:14 pm

Re: APIC Interrupts are not accepted

Post 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.
gerryg400
Member
Member
Posts: 1801
Joined: Thu Mar 25, 2010 11:26 pm
Location: Melbourne, Australia

Re: APIC Interrupts are not accepted

Post by gerryg400 »

So you tried EOI and you do sti ? Try clearing apic errors before you start.
If a trainstation is where trains stop, what is a workstation ?
ATXcs1372
Member
Member
Posts: 30
Joined: Wed Jun 01, 2011 7:14 pm

Re: APIC Interrupts are not accepted

Post 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?
gerryg400
Member
Member
Posts: 1801
Joined: Thu Mar 25, 2010 11:26 pm
Location: Melbourne, Australia

Re: APIC Interrupts are not accepted

Post 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.
If a trainstation is where trains stop, what is a workstation ?
User avatar
xenos
Member
Member
Posts: 1121
Joined: Thu Aug 11, 2005 11:00 pm
Libera.chat IRC: xenos1984
Location: Tartu, Estonia
Contact:

Re: APIC Interrupts are not accepted

Post 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
...
Programmers' Hardware Database // GitHub user: xenos1984; OS project: NOS
gerryg400
Member
Member
Posts: 1801
Joined: Thu Mar 25, 2010 11:26 pm
Location: Melbourne, Australia

Re: APIC Interrupts are not accepted

Post 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.
If a trainstation is where trains stop, what is a workstation ?
ATXcs1372
Member
Member
Posts: 30
Joined: Wed Jun 01, 2011 7:14 pm

Re: APIC Interrupts are not accepted

Post 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
Post Reply