riscv64: virtio-keyboard-pci, interrupt-driven keyboard input (item 4.3.5c)

Punch list §25 item 4.3.5c complete.

Amended from a nonexistent MMIO transport to PCI (matching the board's
actual virtio-blk-pci precedent). New virtio-input driver: eventq with
pre-posted buffers, PLIC source computed at runtime from PCI slot/pin
(derived live from this host's QEMU riscv64 DTB), mandatory ISR-status
read, PCI interrupt-disable-bit check. New VKBD-EVENT/VKBD-DEBUG FORTH
words. Verified with a real QEMU sendkey keypress: exact KEY_A/press
match, two real interrupts serviced, zero exceptions. Three-arch
acceptance boot clean.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Robert Allan James
2026-08-08 11:51:07 -04:00
co-authored by Claude Sonnet 5
parent 5f4df673c1
commit 8251aebcf8
21 changed files with 73408 additions and 226 deletions
+17 -8
View File
@@ -24,6 +24,14 @@ extern void riscv64_install_vectors(void);
* convention as riscv64_install_vectors above. */
extern void riscv64_timer_rearm(void);
/* Defined in virtio_input.c (item 4.3.5c). g_virtio_input_plic_source is 0
* (plic_claim()'s own "nothing pending" sentinel) until
* virtio_input_find_keyboard() finds a real device and computes its
* routed source -- so this branch is inert on any boot where the device
* isn't present, same as the generic dispatch was inert before 4.3.5c. */
extern uint32_t g_virtio_input_plic_source;
extern void virtio_input_isr(void);
/* scause cause codes for supervisor-mode interrupts (RISC-V Privileged Spec
* §4.1.9, Table "Supervisor cause register values"). */
#define SCAUSE_INTERRUPT_BIT (1ULL << 63)
@@ -51,14 +59,12 @@ volatile uint32_t g_plic_claim_count = 0;
* permanently and silently. Ordering it ahead of @c heartbeat_tick() means a
* fault in the bookkeeping cannot also cost the next tick.
*
* Supervisor external (cause 9, item 4.3.5b): claim/dispatch/complete
* through the PLIC. No source is enabled by default (see plic.c), so this
* branch is normally never reached; a future consumer enabling its own
* source is what makes it fire. Dispatch here is deliberately generic --
* this item is pure PLIC substrate, not a device driver -- a future
* consumer (4.3.5c) is expected to extend this with real per-source
* handling, the same way i8042's keyboard branch sits in amd64's
* isr_common_handler().
* Supervisor external (cause 9): claim/dispatch/complete through the PLIC
* (substrate, item 4.3.5b). Source 10 (UART) stays unclaimed by anything
* here -- 4.3.5b's own synthetic-interrupt self-test that used it was run
* once and reverted, not a standing consumer. virtio-input (item 4.3.5c)
* is the first real per-source dispatch, the same shape as i8042's
* keyboard branch in amd64's isr_common_handler().
*
* Any other cause is ignored rather than fatal: an unexpected-but-harmless
* asynchronous interrupt should not take the kernel down.
@@ -76,6 +82,9 @@ void riscv64_interrupt_handler(uint64_t scause)
uint32_t irq = plic_claim();
if (irq != 0) {
g_plic_claim_count++;
if (irq == g_virtio_input_plic_source) {
virtio_input_isr();
}
plic_complete(irq);
}
}