[SOLVED] Flood of PS2 keyboard IRQs (PS2 driver error)

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
User avatar
austanss
Member
Member
Posts: 377
Joined: Sun Oct 11, 2020 9:46 pm
Location: United States

[SOLVED] Flood of PS2 keyboard IRQs (PS2 driver error)

Post by austanss »

My operating system has a functioning scheduler, and (I confidently presume) I've solidly configured my interrupt handling and the IOAPIC/LAPIC/PIC/IDT shenanigans. For context, my LAPIC timer interrupt handling works fine, and delivers interrupts at the expected frequency, so I have no reason to believe that my IOAPIC, LAPIC, or IDT configuration is bugged. I am not attempting to make a kernel shell with kernel keyboard handling. Instead, I have a "pid 0" process named 'frame' which contains a rudimentary startup shell and terminal, all isolated from the kernel and running happily in a contained userspace process. My LAPIC timer is used to coordinate context switches, albeit at a relatively low frequency (and also there is no real "switch" because there is only one process).

I have properly implemented the SYSCALL instruction, and I am confident that they work properly because my lone user process is able to properly acquire framebuffer access from the kernel, as is evidenced by the functional userspace terminal.

Basically, I've all but completely isolated the issue to the actual keyboard handling code on the kernel side. I've debugged the userspace keyboard handler ad nauseam, and found that what mainly happens is the first keyboard interrupt is handled correctly, and I do hit the breakpoints in the user code that handles the interrupts. However, after that interrupt returns, I am able to see the EOI being sent to the LAPIC, but after the interrupt ends I receive a spam of interrupts 0x22 (the keyboard IRQ vector). This spam is not triggered until a key is pressed. The flood is large enough that it probably prevents the process from having enough CPU time to execute properly. However, further debugging demonstrated that the interrupts do not trample each other, and each and every IRQ I successfully handles and proceeds to send an EOI.

Yet, it's not throwing any exceptions. I'm kind of at a loss. I'll keep debugging.
Last edited by austanss on Sun Apr 07, 2024 7:43 am, edited 1 time in total.
Skylight: https://github.com/austanss/skylight

I make stupid mistakes and my vision is terrible. Not a good combination.

NOTE: Never respond to my posts with "it's too hard".
User avatar
austanss
Member
Member
Posts: 377
Joined: Sun Oct 11, 2020 9:46 pm
Location: United States

Re: Flood of PS2 keyboard IRQs (all other IRQs work fine)

Post by austanss »

I've isolated the issue to the ps2_kbd_sync_leds() call in the IRQ handler. When I sync the LEDs, I use the ps2_kbd_send_command() function, which is a very thorough function that polls the PS/2 controller and waits for ACKs, deals with resends, and detects errors. I know it is unwise to send commands in the middle of an interrupt, so I commented the line and it worked fine. I do want the keyboard lights to be synchronized with the key states, though, and I wonder how else I could do that effectively without causing this weird behavior.
Skylight: https://github.com/austanss/skylight

I make stupid mistakes and my vision is terrible. Not a good combination.

NOTE: Never respond to my posts with "it's too hard".
Octocontrabass
Member
Member
Posts: 5560
Joined: Mon Mar 25, 2013 7:01 pm

Re: Flood of PS2 keyboard IRQs (all other IRQs work fine)

Post by Octocontrabass »

If you're getting an IRQ flood from the PS/2 controller, you're not reading port 0x60 to acknowledge the IRQ. I haven't figured out why that might be happening, but I did see you're sometimes reading port 0x60 more than once per IRQ, which is also wrong. The PS/2 controller raises an IRQ every time there's a byte available for you to read from port 0x60 - scan code or otherwise.
User avatar
austanss
Member
Member
Posts: 377
Joined: Sun Oct 11, 2020 9:46 pm
Location: United States

Re: Flood of PS2 keyboard IRQs (all other IRQs work fine)

Post by austanss »

I think it's possible I've made a slight design flaw. Whenever I press and release the A key, I get three interrupts, as logged by QEMU. Whenever I press and release the RIGHT ALT key, I get five interrupts. Clearly, from referring to the scan code set 2 reference, I am not getting one interrupt on press and one on release as I originally anticipated, but rather an interrupt for every scan code byte.

(The A key sends one byte on press, 0x1C; and two bytes on release, 0xF0 and 0x1C.)
(The RIGHT ALT key sends two bytes on press: 0xE0 and 0x11. It sends three on release: 0xE0, 0xF0, and 0x11.)

My code is designed with the idea that every IRQ corresponds to a press or release, but that's not the case.
Skylight: https://github.com/austanss/skylight

I make stupid mistakes and my vision is terrible. Not a good combination.

NOTE: Never respond to my posts with "it's too hard".
User avatar
austanss
Member
Member
Posts: 377
Joined: Sun Oct 11, 2020 9:46 pm
Location: United States

Re: Flood of PS2 keyboard IRQs (all other IRQs work fine)

Post by austanss »

Sure enough, I was able to restructure my IRQ handler in a more sensible way that actually corresponds with controller behavior, and now keyboard input works perfectly. I'm not sure how I made this oversight, but I guess in all the documentation I've read about PS/2 input it was never really emphasized.
Skylight: https://github.com/austanss/skylight

I make stupid mistakes and my vision is terrible. Not a good combination.

NOTE: Never respond to my posts with "it's too hard".
User avatar
iansjack
Member
Member
Posts: 4703
Joined: Sat Mar 31, 2012 3:07 am
Location: Chichester, UK

Re: [SOLVED] Flood of PS2 keyboard IRQs (PS2 driver error)

Post by iansjack »

It all depends upon which scan code set you are using: https://wiki.osdev.org/PS/2_Keyboard

It’s probably best to consider receiving and acknowledging the codes as separate from interpreting them. The interrupt handler can just read the code, put it in a queue and acknowledge it. The driver can then read codes from the queue and interpret them.
User avatar
austanss
Member
Member
Posts: 377
Joined: Sun Oct 11, 2020 9:46 pm
Location: United States

Re: [SOLVED] Flood of PS2 keyboard IRQs (PS2 driver error)

Post by austanss »

iansjack wrote:The interrupt handler can just read the code, put it in a queue and acknowledge it.
That's basically what my code does now. The kernel driver is designed to interpret scancodes into simpler byte-sized key-codes. It then sends those codes into a buffer, a buffer which is read by the sole user process that is assigned to handle and process keycodes. The userspace manager then sends the keycodes to whatever it wants, which in my case is just the basic user shell. Then the shell processes the actual keycodes and handles presses and releases and decodes the keys into characters. Then the userspace tty writes the characters to the screen, and the shell saves the character to the command buffer.

The interrupt handler though, is what I was doing wrong. Every time I got an interrupt, I was attempting to retrieve the whole scan code. What I do instead, now, is only read one scan code byte, save it to the buffer, see if the scancode is finished (with a large switch block that handles the scancode set 2), and if it is, then I interpret the scan code and send out the keycode to the processes, and clear the buffer. If the scan code is still incomplete, then I simply save the new scancode to the buffer, increment the buffer iterator, and send the EOI.
Skylight: https://github.com/austanss/skylight

I make stupid mistakes and my vision is terrible. Not a good combination.

NOTE: Never respond to my posts with "it's too hard".
Post Reply