[SOLVED] Keyboard IRQ from IOAPIC seems to be EOIed only when IRQ number is equal to interrupt vector

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
sfiedler
Posts: 6
Joined: Wed Jul 03, 2024 9:56 am

[SOLVED] Keyboard IRQ from IOAPIC seems to be EOIed only when IRQ number is equal to interrupt vector

Post by sfiedler »

Hello there,

I am developing an operating system written in Zig. You can find the bootloader, the kernel and a simple "development environment" in an organization on codeberg: https://codeberg.org/loup-os.

In the kernel, I am currently working on paging. However, I found a solution to an old "bug" which happened to me: the interrupt vector number seems to be misaligned on the stack, so there were always some funny interrupt vector numbers.
As I fixed that bug, remapping the interrupts from the IOAPIC was worth it because now I was able to control those numbers. But now, there are some weird things happening: when I press a key in QEMU (which I use for testing), I get indeed notified "received interrupt 49", which is my offset (48) plus the keyboard IRQ (1). The keyboard handler is able to handle it and get the scan code via port I/O. Then, the handler sends first an EOI signal to the I/O APIC (if you didn't know that, take a look at the linux kernel) and then to the Local APIC. When sending it to the I/O APIC, you need, as far as I know, the IRQ number.

However, I don't get any second keyboard interrupt when sending either the IRQ number or the interrupt vector number. So I retried it using the old version where the keyboard interrupt was mapped to interrupt vector 1 (which isn't a good idea because 1 is already the debug interrupt, but to test it I could do that) and it worked.

If you want to take a look at my current implementation, you should look at the IDT and I/O APIC code. Can anyone here help me?
Last edited by sfiedler on Tue Jul 16, 2024 2:27 am, edited 1 time in total.
Octocontrabass
Member
Member
Posts: 5560
Joined: Mon Mar 25, 2013 7:01 pm

Re: Keyboard IRQ from IOAPIC seems to be EOIed only when IRQ number is equal to interrupt vector

Post by Octocontrabass »

sfiedler wrote: Wed Jul 03, 2024 10:24 amThen, the handler sends first an EOI signal to the I/O APIC (if you didn't know that, take a look at the linux kernel) and then to the Local APIC.
Sending an EOI to the IOAPIC is only necessary if you've set the EOI broadcast suppression bit (bit 12) in the Spurious-Interrupt Vector Register in the local APIC. Maybe I've overlooked something, but I don't see any code to access that register.

Local APIC EOI broadcast suppression and the IOAPIC EOI register are optional features. You need to make sure both exist before you can use them.
sfiedler
Posts: 6
Joined: Wed Jul 03, 2024 9:56 am

Re: Keyboard IRQ from IOAPIC seems to be EOIed only when IRQ number is equal to interrupt vector

Post by sfiedler »

I didn't know that sending the I/O APIC EOI is only needed in special cases, thanks for that!
I took a look (again) at the OSDev Wiki Article about the (local) APIC and set that spurious interrupt vector register to 0xff, as recommended. I also removed the line of code which sends the EOI to the I/O APIC. The issue persists.

EDIT: Just for the sake of knowing it, I set the interrupt vector number to the IRQ number again (so keyboard => interrupt 1) and "deactivated" the debug interrupt (by not handling it). Like magic, it worked! But this isn't a solution.
Octocontrabass
Member
Member
Posts: 5560
Joined: Mon Mar 25, 2013 7:01 pm

Re: Keyboard IRQ from IOAPIC seems to be EOIed only when IRQ number is equal to interrupt vector

Post by Octocontrabass »

Is the IOAPIC configured for edge or level trigger? If it's edge trigger, you need to send the EOI before you read the byte from the PS/2 controller. If it's level trigger, you need to send the EOI after you read the byte.

What state are the interrupt controllers in when it gets stuck? Use "info pic" in the QEMU monitor to check.
sfiedler
Posts: 6
Joined: Wed Jul 03, 2024 9:56 am

Re: Keyboard IRQ from IOAPIC seems to be EOIed only when IRQ number is equal to interrupt vector

Post by sfiedler »

Octocontrabass wrote: Thu Jul 04, 2024 5:09 pm Is the IOAPIC configured for edge or level trigger? If it's edge trigger, you need to send the EOI before you read the byte from the PS/2 controller. If it's level trigger, you need to send the EOI after you read the byte.
Thanks for that! I knew there was something about those trigger modes but I didn't find much documentation about that in the OSDev wiki.
Octocontrabass wrote: Thu Jul 04, 2024 5:09 pm What state are the interrupt controllers in when it gets stuck? Use "info pic" in the QEMU monitor to check.

Code: Select all

ioapic0: ver=0x20 id=0x00 sel=0x3f (redir[23])
  pin 0  0x0000000000010030 dest=0 vec=48  active-hi edge  masked fixed  physical
  pin 1  0x0000000000000031 dest=0 vec=49  active-hi edge         fixed  physical
  pin 2  0x0000000000010032 dest=0 vec=50  active-hi edge  masked fixed  physical
  pin 3  0x0000000000010033 dest=0 vec=51  active-hi edge  masked fixed  physical
  pin 4  0x0000000000010034 dest=0 vec=52  active-hi edge  masked fixed  physical
  pin 5  0x0000000000010035 dest=0 vec=53  active-hi edge  masked fixed  physical
  pin 6  0x0000000000010036 dest=0 vec=54  active-hi edge  masked fixed  physical
  pin 7  0x0000000000010037 dest=0 vec=55  active-hi edge  masked fixed  physical
  pin 8  0x0000000000010038 dest=0 vec=56  active-hi edge  masked fixed  physical
  pin 9  0x0000000000010039 dest=0 vec=57  active-hi edge  masked fixed  physical
  pin 10 0x000000000001003a dest=0 vec=58  active-hi edge  masked fixed  physical
  pin 11 0x000000000001003b dest=0 vec=59  active-hi edge  masked fixed  physical
  pin 12 0x000000000001003c dest=0 vec=60  active-hi edge  masked fixed  physical
  pin 13 0x000000000001003d dest=0 vec=61  active-hi edge  masked fixed  physical
  pin 14 0x000000000001003e dest=0 vec=62  active-hi edge  masked fixed  physical
  pin 15 0x000000000001003f dest=0 vec=63  active-hi edge  masked fixed  physical
  pin 16 0x0000000000010040 dest=0 vec=64  active-hi edge  masked fixed  physical
  pin 17 0x0000000000010041 dest=0 vec=65  active-hi edge  masked fixed  physical
  pin 18 0x0000000000010042 dest=0 vec=66  active-hi edge  masked fixed  physical
  pin 19 0x0000000000010043 dest=0 vec=67  active-hi edge  masked fixed  physical
  pin 20 0x0000000000010044 dest=0 vec=68  active-hi edge  masked fixed  physical
  pin 21 0x0000000000010045 dest=0 vec=69  active-hi edge  masked fixed  physical
  pin 22 0x0000000000010046 dest=0 vec=70  active-hi edge  masked fixed  physical
  pin 23 0x0000000000010047 dest=0 vec=71  active-hi edge  masked fixed  physical
  IRR      (none)
  Remote IRR (none)
  
So fixed, active-high and not masked.
Octocontrabass
Member
Member
Posts: 5560
Joined: Mon Mar 25, 2013 7:01 pm

Re: Keyboard IRQ from IOAPIC seems to be EOIed only when IRQ number is equal to interrupt vector

Post by Octocontrabass »

The IOAPIC status looks reasonable, but what about the local APIC?
sfiedler
Posts: 6
Joined: Wed Jul 03, 2024 9:56 am

Re: Keyboard IRQ from IOAPIC seems to be EOIed only when IRQ number is equal to interrupt vector

Post by sfiedler »

Octocontrabass wrote: Fri Jul 05, 2024 2:36 pm The IOAPIC status looks reasonable, but what about the local APIC?
"info lapic" puts out:

Code: Select all

dumping local APIC state for CPU 0 

LVT0	0x00000700 active-hi edge                              ExtINT (vec 0)
LVT1	0x00000400 active-hi edge                              NMI   
LVTPC	0x00010000 active-hi edge  masked                      Fixed  (vec 0)
LVTERR	0x00010000 active-hi edge  masked                      Fixed  (vec 0)
LVTTHMR	0x00010000 active-hi edge  masked                      Fixed  (vec 0)
LVTT	0x00030020 active-hi edge  masked         periodic     Fixed  (vec 32)
Timer	DCR=0xb (divide by 1) initial_count = 10000000 current_count = 2125649
SPIV	0x0000010f APIC enabled, focus=off, spurious vec 15
ICR	0x00000000 physical edge de-assert no-shorthand
ICR2	0x00000000 cpu 0 (APIC ID)
ESR	0x00000000
ISR	49 
IRR	49 

APR 0x00 TPR 0x00 DFR 0x0f LDR 0x00 PPR 0x30
Octocontrabass
Member
Member
Posts: 5560
Joined: Mon Mar 25, 2013 7:01 pm

Re: Keyboard IRQ from IOAPIC seems to be EOIed only when IRQ number is equal to interrupt vector

Post by Octocontrabass »

sfiedler wrote: Sat Jul 06, 2024 1:49 am

Code: Select all

ISR	49 
IRR	49 
The local APIC hasn't received your EOI.

The local APIC accepts only aligned 32-bit reads and writes. Anything else is undefined behavior.
sfiedler
Posts: 6
Joined: Wed Jul 03, 2024 9:56 am

Re: Keyboard IRQ from IOAPIC seems to be EOIed only when IRQ number is equal to interrupt vector

Post by sfiedler »

When I simply change the types to "u32", everything stops working. But in my paging code (which I enabled locally), physFromVirt returns null for the Local APIC base. Mapping any page creates a page fault. Now, at least I have something I can work on :D .

EDIT: physFromVirt returning null was a wrong "else" in my program (I had a double if and the else should have been in the first branch, but I had it in the second), now it's fixed and it returns 0xfdc0000000. Only thing is: I don't know what I should do with that…
sfiedler
Posts: 6
Joined: Wed Jul 03, 2024 9:56 am

Re: Keyboard IRQ from IOAPIC seems to be EOIed only when IRQ number is equal to interrupt vector

Post by sfiedler »

And now I gave my OS just some time without doing anything in my OS, and it just works!
Post Reply