starkernel: item 4.3.5 -- amd64 I/O APIC + i8042 keyboard, interrupt-driven

Punch list §25 item 4.3.5 complete.

New ioapic.c/i8042.c drivers (MADT-derived I/O APIC base, no hardcoded
constants) plus a KBD-SCAN/KBD-DEBUG diagnostic word pair. Three real
bugs found and fixed en route, all blocking this item's own acceptance:
a fatal LAPIC spurious-vector crash (nothing had driven a real external
interrupt through the I/O APIC before), OVMF leaving the keyboard device
itself scanning-disabled (0xF4 fix), and isr.S's stub table only having
individually-numbered stubs through vector 32 -- everything above that,
including our IRQ1 vector 33, silently reported as vector 255 regardless
of which IDT slot actually fired. Verified live via QEMU sendkey against
KBD-SCAN: correct XT Set-1 make/break codes for two different keys.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Robert Allan James
2026-08-08 00:18:48 -04:00
co-authored by Claude Sonnet 5
parent 78ff335b97
commit 88eb73cfe8
14 changed files with 914 additions and 11 deletions
+23
View File
@@ -49,11 +49,15 @@
#include "console.h"
#include "apic.h"
#include "timer.h"
#include "starkernel/i8042.h"
/* Set by the FORTH dispatcher just before calling entry->func(vm).
* Printed on fault to identify which word was executing. */
volatile const char *g_sk_fault_word = (void *)0;
/* Count of LAPIC spurious-vector interrupts since boot (item 4.3.5). */
volatile uint32_t g_spurious_count = 0;
#define IDT_ENTRIES 256
#define INTERRUPT_GATE 0x8E
@@ -342,6 +346,25 @@ void isr_common_handler(uint64_t vector,
return;
}
/* Handle i8042 keyboard interrupt (item 4.3.5) */
if (vector == I8042_KEYBOARD_VECTOR) {
i8042_handle_irq();
apic_eoi();
return;
}
/* Spurious interrupt: normal occasional race per Intel SDM Vol.3 §10.9,
* not a fault. No EOI -- the SDM is explicit that spurious-vector
* interrupts must not be acknowledged. g_spurious_count is a cheap,
* permanent diagnostic (item 4.3.5 found a real keyboard IRQ silently
* misreported as spurious due to a missing dedicated ISR stub -- see
* isr.S -- so a way to notice "spurious firing when it shouldn't be"
* is worth keeping, not just scaffolding for that one investigation). */
if (vector == APIC_SPURIOUS_VECTOR) {
g_spurious_count++;
return;
}
/* All other vectors are exceptions - print diagnostic and halt */
console_println("\n=== INTERRUPT/EXCEPTION ===");