Page 1 of 1

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

Posted: Wed Jul 03, 2024 10:24 am
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?

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

Posted: Wed Jul 03, 2024 8:56 pm
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.

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

Posted: Thu Jul 04, 2024 2:36 am
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.

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

Posted: Thu Jul 04, 2024 5:09 pm
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.

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

Posted: Fri Jul 05, 2024 3:10 am
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.

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

Posted: Fri Jul 05, 2024 2:36 pm
by Octocontrabass
The IOAPIC status looks reasonable, but what about the local APIC?

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

Posted: Sat Jul 06, 2024 1:49 am
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

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

Posted: Sat Jul 06, 2024 4:02 pm
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.

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

Posted: Sun Jul 07, 2024 11:56 am
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…

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

Posted: Tue Jul 16, 2024 2:26 am
by sfiedler
And now I gave my OS just some time without doing anything in my OS, and it just works!