FABRIC.md: scope 4.3.5-4.3.5e -- interrupt-driven keyboard input, per-ISA split
Next after the 4.3.4 checkpoint. amd64 needs an I/O APIC (none exists; legacy PIC is permanently masked), riscv64 needs a PLIC (external interrupts were never enabled in Phase 0), aarch64 needs GIC SPI routing (0.6 scoped PPI-only). Documentation only, no code. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
7024e413f1
commit
8fffd69347
@@ -3843,6 +3843,73 @@ document and committing that amendment as its own item.*
|
||||
> **This is the checkpoint** — 4.3.x groundwork stops here for review per this item's own
|
||||
> acceptance criterion, before scoping whatever comes next.
|
||||
|
||||
- [ ] **4.3.5 — amd64: I/O APIC bring-up + i8042 keyboard, interrupt-driven.** No I/O APIC
|
||||
driver exists in this tree today (checked: `apic.c` is Local-APIC-only, and the timer
|
||||
needs no routing because it self-interrupts) and `pic_disable()` masks the legacy 8259
|
||||
permanently — so no legacy IRQ, IRQ1 included, currently has any path to the CPU. This
|
||||
item stands up a minimal I/O APIC driver (MMIO base, redirection table entry for IRQ1
|
||||
targeting a chosen vector and the boot CPU's LAPIC ID), programs the i8042 controller for
|
||||
interrupt mode, and installs an ISR that reads the scancode from port `0x60` and issues
|
||||
`apic_eoi()`. **No polling of the i8042 status port (`0x64`) anywhere in this path** —
|
||||
that is the whole point of doing this before the REPL keyboard work, not after.
|
||||
*Done when:* a keypress in QEMU on amd64 produces a captured scancode via the interrupt
|
||||
path with no polling loop in the code, three-arch QEMU boot unaffected, log committed.
|
||||
*Refs:* §27.5.
|
||||
|
||||
- [ ] **4.3.5a — riscv64: PLIC bring-up (external interrupt controller).** Does not exist
|
||||
anywhere in this tree — Phase 0 (0.2/0.3) only ever enabled the S-mode *timer* interrupt
|
||||
(`sie.STIE`); external interrupts (`sie.SEIE`, bit 9) were never touched, and
|
||||
`interrupts.c`'s own comment ("the PLIC replaces both") describes the architecture, not
|
||||
anything implemented. This item enables `sie.SEIE`, programs the PLIC's per-source
|
||||
priority, the hart context's threshold and enable bits, and wires the trap handler's
|
||||
external-interrupt case to `PLIC claim` → dispatch → `PLIC complete`. Prerequisite for
|
||||
4.3.5b; no keyboard code in this item.
|
||||
*Done when:* a synthetic/known external interrupt source claims and completes correctly
|
||||
through the PLIC on riscv64, three-arch QEMU boot unaffected, log committed.
|
||||
*Refs:* §27.5.
|
||||
|
||||
- [ ] **4.3.5b — riscv64: virtio-keyboard-device, interrupt-driven.** Add
|
||||
`virtio-keyboard-device` (MMIO virtio, matching the existing MMIO virtio-blk pattern on
|
||||
this board) to the riscv64 `qemu`/`qemu-esp` targets in `Makefile.starkernel`. New driver
|
||||
under `src/starkernel/virtio/` for the virtio-input device class — decode `EV_KEY` events
|
||||
off the input event virtqueue. Unlike `virtio_blk.c`'s synchronous poll-the-used-ring
|
||||
pattern, this device must be interrupt-driven end to end: the used-ring notification
|
||||
arrives via the PLIC path from 4.3.5a, not a poll loop. Built on 4.3.5a.
|
||||
*Done when:* a keypress in QEMU on riscv64 produces a captured `EV_KEY` event via the
|
||||
interrupt path with no polling loop, three-arch QEMU boot unaffected, log committed.
|
||||
*Refs:* §27.5.
|
||||
|
||||
- [ ] **4.3.5c — aarch64: GIC SPI wiring for virtio-input.** Item 0.6 scoped the GIC to
|
||||
"one interrupt" (the timer PPI) on purpose and explicitly called a general GIC driver
|
||||
out of scope. A PCI-attached `virtio-keyboard-pci` device signals via legacy INTx, which
|
||||
is an SPI, not a PPI — a different GIC distributor path (SPI target-CPU and priority
|
||||
registers) that today's minimal init never touches. This item extends the GIC init from
|
||||
0.6 just far enough to enable and route one SPI, still not a general driver — scope stays
|
||||
as narrow as 0.6's did.
|
||||
*Done when:* aarch64 can take and acknowledge (`IAR`/`EOIR`) an SPI from the virtio-input
|
||||
PCI device, three-arch QEMU boot unaffected, log committed.
|
||||
*Refs:* §27.5.
|
||||
|
||||
- [ ] **4.3.5d — aarch64: virtio-keyboard-pci, interrupt-driven.** Add `virtio-keyboard-pci`
|
||||
to the aarch64 `qemu`/`qemu-esp` targets — the existing `virtio-blk-pci` device proves the
|
||||
PCI bus is already enumerated (`pci.c`) on this board, so this rides the same bus, a new
|
||||
device class. Same virtio-input driver shape as 4.3.5b (shared code where the transport
|
||||
allows — MMIO vs. PCI config-space discovery differs, the event-queue/`EV_KEY` decode
|
||||
should not). Built on 4.3.5c.
|
||||
*Done when:* a keypress in QEMU on aarch64 produces a captured `EV_KEY` event via the
|
||||
interrupt path with no polling loop, three-arch QEMU boot unaffected, log committed.
|
||||
*Refs:* §27.5.
|
||||
|
||||
- [ ] **4.3.5e — Checkpoint: one keyboard abstraction, three architectures, no polling.**
|
||||
Converge 4.3.5/4.3.5b/4.3.5d behind a single scancode/keycode interface so the REPL
|
||||
keyboard-input work (M8, outside Stadium) has one thing to call, not three. Stop and
|
||||
review here — same posture as 4.3.4 — before scoping REPL wiring.
|
||||
*Done when:* a keypress on all three architectures produces the same shape of event at
|
||||
the shared interface, confirmed with a live keypress test per architecture (not a
|
||||
synthetic/injected one — this is the first item in this slice where a real key matters),
|
||||
three-arch QEMU boot, logs committed.
|
||||
*Refs:* §27.5.
|
||||
|
||||
⋯ *(4.3.x is open-ended — more items get appended here as Console work is scoped item by*
|
||||
*item, developed on the fly per §25.0. 4.4 below is unaffected by anything added above*
|
||||
*this marker.)*
|
||||
@@ -4215,3 +4282,47 @@ projection machinery — the first real exercise of that math, expected to take
|
||||
not a quick add. Stop and review here before scoping the next 4.3.x item. Out-of-scope list
|
||||
for 4.3.1–4.3.4 is recorded once, at the 4.3 punch-list entry itself (§25.5), not repeated
|
||||
per sub-item.
|
||||
|
||||
### 27.5 Keyboard input, interrupt-driven (4.3.5–4.3.5e)
|
||||
|
||||
Scoped 2026-08-07, next after the 4.3.4 checkpoint. Purpose: get a real keypress into the
|
||||
kernel with no polling anywhere in the path, so the REPL keyboard-input work (M8, tracked
|
||||
outside Stadium — see `.claude/CLAUDE.md`'s roadmap section) has something to call. This
|
||||
section is groundwork only, same as 27.1–27.4 was for the framebuffer — it stops at "a
|
||||
keypress produces an event at a shared interface," not REPL line-editing, not a scancode-
|
||||
to-ASCII layout, not repeat/modifier-key semantics. Those are later items, scoped once
|
||||
4.3.5e is reviewed.
|
||||
|
||||
**Why this split is bigger than 4.3.3's three-way split.** 4.3.3/4.3.3a/4.3.3b all built on
|
||||
interrupt/timer substrate Phase 0 already finished. Keyboard input does not have that
|
||||
luxury on two of three architectures:
|
||||
|
||||
- **amd64** has a Local APIC (for the self-interrupting timer) but no I/O APIC driver at
|
||||
all, and `pic_disable()` (`interrupts.c:228`) permanently masks the legacy 8259 — so today
|
||||
there is no path for *any* legacy IRQ, keyboard's IRQ1 included, to reach the CPU. 4.3.5
|
||||
stands up the minimum I/O APIC needed for one redirection entry.
|
||||
- **riscv64** has never enabled external interrupts at all — Phase 0 (0.2/0.3) scoped
|
||||
strictly to the S-mode timer interrupt (`sie.STIE`). The PLIC (`sie.SEIE`, bit 9) is
|
||||
unimplemented; `interrupts.c`'s existing comment naming the PLIC describes the
|
||||
architecture, not working code. 4.3.5a is that bring-up, split out as its own item because
|
||||
it is substrate, not keyboard-specific — same shape as Phase 0's per-ISA items.
|
||||
- **aarch64**'s GIC (item 0.6) was deliberately scoped to one PPI (the timer) and explicitly
|
||||
ruled a general GIC driver out of scope. A PCI `virtio-keyboard-pci` device signals via an
|
||||
SPI, a distinct GIC path 0.6 never touched. 4.3.5c is the minimal SPI extension, held to
|
||||
the same narrow-scope discipline 0.6 used.
|
||||
|
||||
**Hardware path differs by architecture, same as the framebuffer did.** amd64's `q35`
|
||||
machine has a real i8042 PS/2 controller (QEMU default, IRQ1) — 4.3.5. Neither `virt` board
|
||||
(aarch64, riscv64) has PS/2 hardware; both get a `virtio-keyboard` device added to their
|
||||
QEMU command lines and a new virtio-input driver (this tree has none — `virtio_blk.c` is
|
||||
the only existing virtio driver, and it is fully synchronous/polled, so it is a transport
|
||||
reference only, not an interrupt-handling one) — 4.3.5b (riscv64, MMIO transport) and 4.3.5d
|
||||
(aarch64, PCI transport, riding the bus `pci.c` already enumerates for `virtio-blk-pci`).
|
||||
|
||||
**No polling, anywhere, in any of 4.3.5/4.3.5b/4.3.5d.** This is the one hard constraint
|
||||
carried through every sub-item — restated per item because it is the actual point of doing
|
||||
interrupt bring-up first rather than reading `0x64`'s status bit or spinning on a used-ring
|
||||
index, which would have been the fast/wrong way to get a key on screen quickly.
|
||||
|
||||
4.3.5e is the checkpoint, same posture as 4.3.4: converge the three architecture-specific
|
||||
paths behind one interface before anything scopes REPL line input on top of it.
|
||||
|
||||
Reference in New Issue
Block a user