aarch64: virtio-keyboard-pci, interrupt-driven keyboard input (item 4.3.5e)
Punch list §25 item 4.3.5e complete. Extended virtio_input.c with a GIC-routed interrupt path alongside 4.3.5c's PLIC one -- same capability walk, feature negotiation, eventq handling (confirming §27.5.1's prediction that these items would share most of the driver). aarch64_irq_handler() dispatches to virtio_input_isr() before its EOIR write, same claim-dispatch-complete ordering riscv64 uses. Verified with a real QEMU sendkey keypress: exact KEY_A/press match, two real interrupts serviced, identical result to riscv64. Found (not fixed) an unrelated pre-existing bug: BYE's cold-reset path faults on aarch64, discovered incidentally since nobody had exercised it from a monitored session before. Three-arch acceptance boot clean. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
2a2d7c5e5e
commit
a373c9124a
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* virtio_input.c — Virtio 1.0 input device driver for StarKernel (item 4.3.5c)
|
||||
* virtio_input.c — Virtio 1.0 input device driver for StarKernel
|
||||
* (riscv64: item 4.3.5c; aarch64: item 4.3.5e)
|
||||
*
|
||||
* Modern virtio 1.0 interface only (device ID 0x1052). No legacy fallback
|
||||
* exists for virtio-input (unlike virtio-blk's 0x1001) -- input postdates
|
||||
@@ -9,20 +10,24 @@
|
||||
* buffers: unlike virtio_blk.c's synchronous request/response pattern, the
|
||||
* driver posts empty VirtioInputEvent buffers up front and the device
|
||||
* fills+posts them to the used ring asynchronously, signalled by the PLIC
|
||||
* (see virtio_input_isr(), called from arch/riscv64/interrupts.c on a
|
||||
* matching claim) -- no polling anywhere in this path.
|
||||
* (riscv64) or GIC (aarch64) -- see virtio_input_isr(), called from
|
||||
* arch/riscv64/interrupts.c or arch/aarch64/interrupts.c on a matching
|
||||
* claim -- no polling anywhere in this path.
|
||||
*
|
||||
* The PCI capability walker below is a deliberate duplicate of
|
||||
* virtio_blk.c's static walk_virtio_caps(), not a shared/promoted version
|
||||
* -- decided at this item rather than refactoring the working, tested
|
||||
* virtio_blk.c (FABRIC.md item 4.3.5c note, carries forward to 4.3.5e).
|
||||
* -- decided at item 4.3.5c rather than refactoring the working, tested
|
||||
* virtio_blk.c, carried forward here.
|
||||
*
|
||||
* Interrupt routing (PLIC source computation/enable) is riscv64-specific
|
||||
* and arch-guarded below; the capability walk, feature negotiation, and
|
||||
* queue/event handling are arch-agnostic and compiled for all three
|
||||
* targets (same idiom as pci.c itself: config-space access already
|
||||
* differs per arch internally, this file adds one more arch-guarded
|
||||
* piece on top rather than a second copy of the whole file).
|
||||
* Interrupt routing (source computation/enable) is arch-guarded below,
|
||||
* riscv64 (PLIC) and aarch64 (GIC) each with their own slot/pin-to-source
|
||||
* formula (FABRIC.md §27.5.1 aarch64, §27.5.2 riscv64, both derived live
|
||||
* from this host's own QEMU DTB, not assumed identical to each other). The
|
||||
* capability walk, feature negotiation, and queue/event handling are
|
||||
* arch-agnostic and compiled for all three targets (same idiom as pci.c
|
||||
* itself: config-space access already differs per arch internally, this
|
||||
* file adds one more arch-guarded piece on top rather than a second copy
|
||||
* of the whole file).
|
||||
*/
|
||||
|
||||
#ifndef __STARKERNEL__
|
||||
@@ -42,6 +47,12 @@
|
||||
#include "starkernel/plic.h"
|
||||
#endif
|
||||
|
||||
#if defined(ARCH_AARCH64)
|
||||
/* Defined in arch/aarch64/apic.c (item 4.3.5d). Extern-in-place, same
|
||||
* convention that file's own cross-file declarations already use. */
|
||||
extern void apic_spi_enable(uint32_t intid);
|
||||
#endif
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
* Virtio 1.0 PCI capability structures -- duplicated from virtio_blk.c
|
||||
* (see file header for why), plus VIRTIO_PCI_CAP_ISR_CFG actually used
|
||||
@@ -200,6 +211,12 @@ static int g_vinput_ready = 0;
|
||||
* real claim. Checked by arch/riscv64/interrupts.c's dispatch. */
|
||||
uint32_t g_virtio_input_plic_source = 0;
|
||||
|
||||
/* GIC INTID (aarch64) this device's INTx routes to, computed at init. 0 is
|
||||
* not a valid SPI INTID (SPIs start at 32), so it is likewise a safe
|
||||
* "invalid/not found" sentinel. Checked by arch/aarch64/interrupts.c's
|
||||
* dispatch. */
|
||||
uint32_t g_virtio_input_gic_intid = 0;
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
* Capability walker -- duplicated from virtio_blk.c, see file header.
|
||||
* ------------------------------------------------------------------------- */
|
||||
@@ -251,11 +268,15 @@ static inline void wmb(void) {
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
* Interrupt routing -- riscv64 (PLIC). aarch64 (GIC, item 4.3.5e) is not
|
||||
* yet implemented; the #else path reports rather than silently no-ops, so
|
||||
* a future arch attempting to use this file without adding its own
|
||||
* routing fails loudly instead of "working" with a permanently-pending,
|
||||
* never-enabled source.
|
||||
* Interrupt routing -- riscv64 (PLIC, item 4.3.5c) and aarch64 (GIC, item
|
||||
* 4.3.5e). Both compute their target source from the same PCI slot/pin
|
||||
* swizzle shape (§27.5.1 aarch64, §27.5.2 riscv64) but with different base
|
||||
* offsets and controller calls -- derived independently from each board's
|
||||
* own DTB, not assumed identical. The #else path (amd64, which never
|
||||
* attaches this device) reports rather than silently no-ops, so a future
|
||||
* arch attempting to use this file without adding its own routing fails
|
||||
* loudly instead of "working" with a permanently-pending, never-enabled
|
||||
* source.
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
#if defined(ARCH_RISCV64)
|
||||
@@ -275,6 +296,23 @@ static int enable_interrupt_route(const PciDevice *pci)
|
||||
g_virtio_input_plic_source = source;
|
||||
return 0;
|
||||
}
|
||||
#elif defined(ARCH_AARCH64)
|
||||
static int enable_interrupt_route(const PciDevice *pci)
|
||||
{
|
||||
uint8_t pin = pci_read8(pci, (uint16_t)PCI_CFG_INT_PIN);
|
||||
if (pin < 1u || pin > 4u) {
|
||||
console_println("virtio-input: bad/absent INT_PIN");
|
||||
return -1;
|
||||
}
|
||||
uint32_t slot = pci->device;
|
||||
uint32_t spi = 3u + ((slot + (uint32_t)pin - 1u) % 4u);
|
||||
uint32_t intid = 32u + spi;
|
||||
|
||||
apic_spi_enable(intid);
|
||||
|
||||
g_virtio_input_gic_intid = intid;
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
static int enable_interrupt_route(const PciDevice *pci)
|
||||
{
|
||||
@@ -466,7 +504,8 @@ int virtio_input_find_keyboard(void) {
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
* Interrupt path -- called from arch/riscv64/interrupts.c on a matching
|
||||
* PLIC claim (g_virtio_input_plic_source).
|
||||
* PLIC claim (g_virtio_input_plic_source) or arch/aarch64/interrupts.c on
|
||||
* a matching GIC IRQ (g_virtio_input_gic_intid).
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
void virtio_input_isr(void) {
|
||||
|
||||
Reference in New Issue
Block a user