Skip to content

Design: the i8042 leaves the kernel for /system/bin/ps2server (stage 7.2, step 6.3) - #899

Draft
Japabu wants to merge 1 commit into
mainfrom
wt/toyos-ps2server
Draft

Japabu wants to merge 1 commit into
mainfrom
wt/toyos-ps2server

Conversation

@Japabu

@Japabu Japabu commented Oct 12, 2026

Copy link
Copy Markdown
Collaborator

Design round 1. Nothing is built. This is the design and roast for stage 7.2 of issues/the-kernel-is-small-interrupts-post-and-threads-wait.md, which is also step 6.3: the i8042 leaves the kernel, and /system/bin/ps2server drives it over the isa claim #592 built. The branch is one empty commit on main at 1acaa362f, which the build drops.

What this was read from: main at 1acaa362f; the track and issues/every-driver-is-still-in-the-kernel.md; kernel/src/arch/x86_64/i8042/ (1,364 lines), kernel/src/isa.rs, kernel/src/arch/x86_64/pio.rs, irq_ring, keyboard.rs, mouse.rs, device.rs, object/ops.rs, the supervisor's start and restart paths, kernel/ps2/, every i8042 issue; #877's design and its round-3 review; #885's and #890's rulings; and IBM's Personal System/2 Hardware Interface Technical Reference, October 1990, read page by page:

  • "Keyboard/Auxiliary Device Controller" (scan), cited below as C with the book's page;
  • "Keyboards (101- and 102-Key)" (scan), cited as K.

The owner's rulings this design follows:

The split

The kernel keeps only what userland cannot do.

  • The claim: pio::fill_i8042_row (ports 0x60 and 0x64, ISA lines 1 and 12) and crate::isa, both unchanged. After the move nothing in the kernel speaks the 8042's protocol: the row names the function's ports and lines, and nothing else.
  • The post: isa::isr records the interrupt on the claim and posts its watch. That handler already serves the isa rows (The panic console takes no input, and an isa claim grants a process exact ports #592), so the i8042's own vector 0x24 and handler go.
  • The panic path: unchanged. Since The panic console takes no input, and an isa claim grants a process exact ports #592 it reads no port of the i8042, and the panic console takes no input.
  • One new thing, the input feed (next section): how a userland driver's key transitions reach the kernel's keyboard and pointer streams. The track keeps the merge with USB HID where it is, in the kernel, so the kernel needs a way in for a userland source.

/system/bin/ps2server takes everything else.

  • the controller probe;
  • the scancode-set decision;
  • both decoders;
  • the aux device's self-reset re-enable;
  • the undecoded-byte naming and the counters;
  • the response to a wedged controller.

It is exempt.owns, since its job exists only on ToyOS: it owns the i8042 ToyOS claims for it. It is two packages, following soundserver's and netstack's shape:

  • system/ps2server/ps2 is kernel/ps2 moved by git mv, keeping the package name toyos-ps2. It is pure and host-tested: the set-1 decoder and the 3-byte packet decoder as today, plus the probe and the byte stream as state machines over a Controller trait (status, data, command, write, clock). Bytes from a device are input from outside the program's trust, so the decoders stay a crate of their own (reviewer.md, Fit).
  • system/ps2server is the program: the claim, the ports through toyos::ioport, the poller, and the feed.

The input feed: how key transitions reach the input stack

Today the driver calls keyboard::handle_key and mouse::handle_motion from the scheduler pass's drain. After the move, ps2server writes the same transitions into a claim.

The ABI.

  • A new class, DeviceType::InputFeed = 11, spelled "input-feed" in a devices row.
  • toyos_abi::input::FeedRecord, six bytes: kind: u8, code: u8, dx: i16, dy: i16. It is decoded once, in toyos-abi, into one of:
    • Key { usage, pressed }: code is a HID Keyboard-page usage. Usage 0 is refused.
    • Pointer { buttons, dx, dy }: relative motion, screen-oriented, with buttons in boot-mouse order. i16 makes the kernel's dx * scale overflow unrepresentable: 32767 × 64 + 32767 < 2³¹.
    • Lost: release everything this feed holds. It is sent on an overrun code or a dropped byte, today's KeyOutcome::Lost and the drain's lost.
    • An unknown kind, or a nonzero dx or dy on a non-pointer record, is refused.
  • A write carries 1 to 64 whole records. It is copied to the kernel stack before any lock is taken, decoded whole, and applied only if every record decodes. Anything else is InvalidArgument, and nothing is applied. The holder's records are the only thing the kernel takes from it.
  • SDK: toyos::InputFeed::send(&[FeedRecord]), and toyos::IsaDev, with describe, irq and ack, shaped as AcpiDev is.

The kernel side is Claimed::Feed(Feed) in device.rs, about 120 lines:

  • Not exclusive: any number of feeds may be minted. Each feed is one keyboard and one pointer: a 256-bit set of the usages it holds, and a PointerSource it claims at mint. When no source entry is free, the mint is Exhausted.
  • The mint declares the source: it calls keyboard::declare_source and mouse::declare_source.
  • A write:
    • Key updates the feed's set and calls handle_key.
    • Pointer calls handle_motion(source, buttons, Relative { dx, dy }, 0).
    • Lost releases the feed's usages and calls mouse::release_buttons(source).
    • The watch of whichever stream queued is posted.
  • The drop is the release. On the claim's last close, which is also process teardown, the feed queues a key-up for every usage it holds and calls mouse::unbind(source). So a dead holder never leaves a Shift or a drag stuck. This replaces the driver's machine-wide keyboard::release_all, which also released USB keyboards' keys. release_all goes, since nothing else calls it.
  • PointerSource::PS2 goes, with its permanently reserved entry 0 and unbind's assert. PS/2's pointer now claims an entry like any other.
  • The merge is unchanged: HELD, the modifier union and the 512-event queues. The keyboard and mouse claims' readers (the compositor and the console) see nothing new.

Endowment order. The track's "a keyboard claim is refused while no source exists, which init's order of endowment then decides" becomes one rule. A program whose devices names input-feed is started, and so endowed, before any program whose devices names keyboard or mouse. That is one rank in the supervisor's boot(), beside its storage-first rank. The decision moves into toyos-manifest (start_order) so a host test holds it.

Restart: a crashed ps2server comes back without the kernel noticing

  • The kernel runs only the claims' generic releases. ps2server's process ends, and its two claims drop:

    • the isa row's drop masks the lines, empties the record and answers the polls;
    • the ports go back with the process (isa::process_ends);
    • the feed's drop releases its keys and buttons.

    No kernel code knows ps2server. The only kernel lines are the row's generic isa: the i8042's ports are pid N's and … went back with pid N.

  • The supervisor restarts it: its row is restart = true, and the supervisor mints both claims again. Its existing CLAIM_RETURN retry covers the deferred release, a compromise that issues/deferred-release-outlives-its-syscall.md already records.

  • One supervisor change: a restart row is started again only when its process ended other than by a clean exit. A clean exit means the program has nothing to serve:

    • ps2server on AArch64, where no row is filled and the claim is NotFound;
    • ps2server on a legacy-free x86 machine, where port 0x64 reads 0xFF.

    On main such a program would be restarted three times and then logged as a service whose ports closed. A kill (137), a handle fault (139) or a panic is restarted. diskserver and fileserver never exit cleanly, since serve diverges.

  • The new ps2server probes from whatever state the dead one left: interrupts on, scanning on, aux reporting on, or a byte in the output buffer. The first thing it does is disable both ports and empty the output buffer. What was typed while no ps2server ran is not delivered: 0xF5 "clears its output buffer" (K 21). The aux reset runs again, about 400 ms on the T14 (issues/t14-keyboard-will-not-report-its-scancode-set.md).

The probe and the stream, following IBM's reference

The probe keeps today's sequence and decisions, and departs from them only where IBM's reference says otherwise:

  1. The scan-set query is made with translation off. IBM says to disable translate mode while asking for the set, so the controller does not translate the answer (K 23; C 8, the note on bit 6). Today the kernel asks with translation on and reads the translated byte (0x41 for set 2). ps2server reads the raw set:

  2. A polled read waits 7 µs after the status read that showed the output buffer full (C 12: "When polling the Type 1 controller for the output-buffer-full condition, wait 7 microseconds … before reading the output buffer"). Root CLAUDE.md allows a fixed delay where a hardware document mandates one, and it is cited at the site.

  3. A write is made only with IBF and OBF both clear (C 12, C 6). Today the kernel waits on IBF alone. A byte found waiting before a write is one nothing asked for: it is read and named among the undecoded bytes.

  4. Device exchanges wait on the interrupt, not a spin. Controller commands (0x20, 0x60, 0xAA, 0xAB, 0xA9, 0xAD/0xAE, 0xA7/0xA8) are polled with interrupts off in the config byte, as today: the probe writes that byte itself, and firmware may have left its bits clear. Before the device stage, the probe sets the port's interrupt bit. IBM: bit 0 raises IRQ 1 "when it places keyboard or command controller response data into its output buffer", and bit 1 raises IRQ 12 for aux data (C 9). Then every keyboard and aux answer is waited for on the claim's record, bounded by the stage's deadline:

    • the keyboard's 0xFA acks;
    • the set byte;
    • the aux device's 0xFA 0xAA id.

    No CPU spins through the T14's ~400 ms aux reset. A byte from the other port during an exchange is fed to the stream, not taken as the answer. Today's read_data takes any byte (mod.rs:802).

  5. Every bounded wait looks at its condition once more after its deadline. A preempted ps2server can lengthen a wait, but never turn a late answer into silence.

The stage budgets stay as today (250, 500, 750 and 600 ms). They are liveness ceilings, and a working machine never spends them. The one bound IBM sets that decides an outcome is the set byte's 20 ms, which A2 takes.

The steady state takes one byte per interrupt:

  1. Wait on the claim.
  2. Take the record.
  3. Read the status. If OBF is set, read one byte, with AUXB saying which port.
  4. Feed the decoder.
  5. Write the feed records.
  6. ack the claim.

The controller cannot load another byte until this one is read. It holds the clock low (C 13, step 5; K 38), and the keyboard keeps up to 16 bytes in its FIFO meanwhile (K 19). So each record announces exactly the byte read after it, and a record with nothing behind it is a harmless empty wake. Edge or level, no edge is lost: a level line is masked by isa::isr until ps2server's ack.

The mouse framer's gap becomes the device's own idle time. It is the claim record's last_nanos for this byte minus the clock at ps2server's read of the previous aux byte, both on the clock page's clock. Today the gap is between two ISR reads. In userland, a delayed read inhibits the device (C 13), so the gap between arrival times includes ps2server's own delay. A preemption longer than PACKET_GAP_NS inside a packet would then split it, which is the shape issues/i8042-mouse-ends-four-packets-short-with-a-clean-exit.md measured on the host. Measured from the host's release, a slow ps2server can delay a resync but never split a packet. MouseDecoder::feed(byte, idle_ns) replaces feed(byte, now_ns) and loses last_ns. The 5 ms threshold stands on C 14's clock figures: 60–100 µs a bit, so 10–16.7 kHz.

The aux self-reset (0xAA 0x00 mid-stream) re-enables reporting as today: keyboard port off, 0xD4 0xF4, then the ack waited on the record, keyboard port on. After 3 failures the pointer is written off by clearing the aux interrupt bit and sending 0xA7. No kernel ioapic mask is needed, so the kernel's 30 ms interrupts-off re-enable (mod.rs:931) goes.

A wedged controller: OBF still set after 16 reads in one wake. ps2server disables both ports, says so, and exits non-zero. The supervisor's restart limit, 3 in 10 s, then gives up on it. This replaces the kernel's QUARANTINE.

Diagnostics kept:

  • the probe's lines, word for word but ps2server: for i8042:;
  • the undecoded bytes named whole (Partial::blame);
  • the counters line, at most every 10 s and only when an interrupt arrived since the last one.

Not carried: the HEALTH verdict machine, with its quiet verdict, the arming-edge bookkeeping, to_screen and the idle loop's verdict_due. In userland, the armed line followed by no counters line already says the pin never asserted.

The boot console, the T14 and the AMD laptop

  • Before userland, nothing reads keys, as today. The kernel's driver queued them, and the first keyboard claim discarded them (device.rs:190). Now they wait in the keyboard and are emptied by the probe. ps2server always probes after the kernel's xHCI legacy handoff, so no SMM trap answers on 0x60/0x64.
  • images/console.toml (--console-boot, the shell on the panel) starts ps2server. The new rank mints its feed before the console's keyboard claim.
    • images/system.toml does the same for the compositor.
    • tests/images/metalcase.toml starts it, because that image is the flashed machine's shape.
    • images/diag.toml does not, since nothing there reads input. The clause in its header about the i8042: line on the panel goes, because that line no longer exists.
    • tests/images/testcases.toml does not, so the isa rows still find the row free.
  • The T14's EC-emulated keyboard answers 0xF0 with 0xEE (issues/t14-keyboard-will-not-report-its-scancode-set.md). Whether it still does with translation off is measured by M1. If it does, the Refused arm decides set 2 translated from firmware's cfg 0x77, as today. The boot in seven that firmware hands over cfg 0x00 is still disabled by name (issues/t14-hands-over-an-uninitialised-8042.md, unchanged). Its TrackPoint answers reset, id 0x00, rate and resolution, and is armed as today.
  • The AMD laptop's EC acks 0xF0 and 0x00 and sends no set byte (Design: the AMD bench's desktop — keyboard, volume keys, HDA controller choice, native rate, codec volume #877's issue, measured with translation on). With translation off, M1 shows whether it answers. If it does, ps2server reads the set and A2's arm is not reached there. If it does not, A2's Unanswered arm decides.

#877

#877's A2 and A3 are designs, not built, and both edit files this change moves.

M1: one cheap measurement before the build

One T14 boot and one AMD-bench boot of a scratch kernel that never lands. Its i8042 probe makes the 0xF0 0x00 query with config bit 6 clear, as K 23 asks, and logs the answer. That tells which arm each laptop takes under IBM's procedure, and so which line the metal row holds each bench to. The patch is about 10 lines in query_scancode_set's caller. The orchestrator runs it, since every metal bench is his.

What is deleted

Whole files, counted at 1acaa362f with wc -l:

File Lines
kernel/src/arch/x86_64/i8042/mod.rs 1,284
kernel/src/arch/x86_64/i8042/tally.rs 80
kernel/src/arch/x86_64/idt/i8042.rs 6
kernel/src/arch/aarch64/keyboard_controller.rs 13
kernel/loom/tests/i8042_tally.rs 214
tests/guest/rust-tests/src/bin/isa_claim_refused.rs (its premise, a kernel that drives the i8042, goes) 23

Hunks, about 70 lines in all, each an estimate until the build counts it:

  • idt/mod.rs: the 0x24 vector, I8042_VECTOR and mod i8042 (4);
  • x86_64/mod.rs: i8042 and the keyboard_controller seam (2);
  • aarch64/mod.rs (1) and boot.rs (1);
  • sched/driver.rs: verdict_due and service (3);
  • irq_ring's I8042 (3);
  • irq_census's i8042 source (3), with its parsers in tests/common/irqcensus.rs and tests/checks.rs;
  • the i8042-withheld actuator (4), with its uses in tests/toyos.rs, tests/metal/src/lib.rs, tests/common/power.rs and tests/common/isa.rs;
  • drivers/acpi.rs's iapc_boot_arch (5), and lib/acpi's, with its three tests (about 35), whose one caller only logged it: "Logged, never obeyed" (mod.rs:981);
  • keyboard::release_all (13), with its block in input_merge_test (7);
  • mouse.rs's PS2 entry (about 8);
  • kernel/loom/src/lib.rs's i8042_tally module (6).

kernel/ps2 (1,023 lines) leaves kernel/ for system/ps2server/ps2.

kernel/src: 63,836 lines at 1acaa362f (find kernel/src -name '*.rs' -print0 | xargs -0 cat | wc -l). The change takes out about 1,430 and adds about 120 for the feed, so it ends near 62,530, about 1,300 fewer. The build reports the measured number.

Two interrupts-off sections go with the driver:

  • the arming write and its read-back (mod.rs:1192-1242), polled against the probe's budget;
  • the aux re-enable's IrqGuard, bounded at 30 ms (mod.rs:931).

Step 6's rule has the windows measured against step 2's readings with the mask_windows row, by the orchestrator.

Issues:

  • The track's stage 7.2 and step 6.3 are marked done, with their evidence.
  • the-i8042-tallys-release-acquire-pair-has-no-negative-control.md and screen-diag-boot-leaves-no-i8042-line-on-the-panel.md are closed. Neither exit can be met once its subject, the tally and the kernel's panel line, is deleted. Whether that closes them is the orchestrator's call.
  • No other issue is edited.

Checks

Under #890, the kernel's part is tested as the kernel's integration, ps2server as units and modules, with one very cheap smoke test.

Host (cargo run -- --ci host):

  • toyos-ps2's decode.rs and fuzz.rs, moved. The mouse tests are rewritten to idle_ns, and one new test puts a host delay longer than PACKET_GAP_NS inside a packet and asserts the packet survives.

  • probe.rs, against a scripted fake controller whose machine shapes are:

    • QEMU's (answers 0x02);
    • the T14's (0xEE with cfg 0x77 → armed; with cfg 0x30 → disabled);
    • the AMD bench's (acks, never answers);
    • absent (0xFF);
    • a failed self-test;
    • a dropped config write;
    • an aux device that fails its BAT, where the keyboard is still armed;
    • a controller left by a dead holder, which arms;
    • an aux self-reset mid-stream, re-enabled, and three failures, written off.

    The fake also refuses, by panicking, each of IBM's rules above when broken:

    • a set query with bit 6 set;
    • a polled read sooner than 7 µs after its status;
    • a write with IBF or OBF set;
    • a device answer read before its interrupt.
  • stream.rs:

    • overrun → Lost;
    • undecoded runs named whole;
    • a wedged controller ends the stream.
  • toyos-abi: FeedRecord's decode refusals.

  • toyos-manifest: start_order puts a feeder before a reader.

The kernel's integration:

  • The isa rows isa_ports_are_the_binders_alone and isa_lines_reach_their_holder stay as they are, less i8042-withheld. They hold the claim and the post on the T14.

  • A new T14 row, input_feed, rides the existing testcases boot as one more job, so it costs no extra flash. A job holds two feeds and the keyboard and mouse readers. It asserts:

    • feed A's Shift and feed B's a arrive as Shift and a with MOD_SHIFT;
    • every malformed write is refused, and the reader then reads nothing;
    • a child holding a third feed presses Ctrl and a pointer button and is killed, and the reader sees both released with no write from anyone.

    Why it is a metal row and not a guest test: nothing in it needs QEMU, and a metal row is the cheaper tier. Its binary goes in RUST_SKIP.

The smoke test. console_image_boots, an existing QEMU boot of images/console.toml on Profile::Metal, additionally must say ps2server's armed lines for both ports. That needs no new boot.

Why it needs QEMU: QEMU's i8042 answers the set query, so this is the one place the read-the-set arm meets an implementation that is not ours. Neither laptop answers it today (M1 may change that).

Metal, run by the orchestrator:

  • ps2server_arms rides METALCASE, adding no flash, on the T14 and on the AMD bench (--metal-host). The judge holds each bench to its line from M1:
    • the keyboard armed, with its arm named;
    • on the T14, aux id 0x00 … reporting on as well;
    • no i8042= source in the IRQ census;
    • no kernel line naming the i8042 beyond the isa claim's own.
  • mask_windows, base against branch, by step 2's rule.
  • The track's exit, "typing resumes after ps2server is killed and restarted": under Integration between modules is tested only for the kernel, and an integration test outside it is cut #890 no row launches or kills a userland program, so the exit is met by composition:
    • the fake controller's dead-holder test;
    • input_feed's release on a holder's death;
    • the isa rows' release;
    • and one hand check on the T14 with a scratch build that never lands. Its ps2server panics once, 20 s after arming. Someone types before and after, and the log shows the supervisor's ended; started again, a second armed line, and a counters line counting keys.

Negative controls:

  • The whole change reverted onto the base: the smoke test and ps2server_arms go red, since nothing says ps2server:.
  • One mutation per IBM rule above, each turning probe.rs red.
  • Arrival-to-arrival gaps in place of idle time: the new mouse test goes red.
  • Feed::drop releasing nothing: input_feed goes red.
  • The rank removed: start_order's test goes red.

Oracles: IBM's reference, at the pages cited. QEMU's i8042 and keyboard, an implementation that is not ours. Both laptops' ECs. The HID Usage Tables, for the decoder's existing tables.

Where the moved code rested on Linux

  • kernel/src/arch/x86_64/i8042/mod.rs:892-895: the set is read and never written, citing "Linux's atkbd_select_set, EDK2's Ps2KeyboardDxe". Now it rests on ToyOS's own reading: the T14's EC answers 0xF0 0x02 with 0xEE. A read that answers needs no write, and K 22–23 documents both.
  • kernel/ps2/src/key.rs:4 and :172: set 2 behind translation is called "Linux's default configuration". Now it is C 8, the PC-compatible mode.
  • issues/t14-keyboard-will-not-report-its-scancode-set.md justifies the Refused arm as "exactly what Linux's i8042.c/atkbd do", and withholds 0xF2 by atkbd_skip_getid. Now the arm rests on C 8 and K 22 (set 2 after power-on or reset), and ps2server sends the keyboard no 0xF2. The issue file is not edited (root CLAUDE.md, Prose).
  • The moved code carries no reference to Linux, and this design adds none.

Roast

  • ps2server holds the machine's reset line in every shipped boot. 0xFE and 0xD1 reach the CPU's reset (C 10–11). The I/O bitmap cannot see a value. issues/the-i8042s-holder-holds-the-machines-reset-line.md records this, owned by the power broker's track. Until now only test jobs held the row, and from this change on, every shipped boot's ps2server does. It is still true, and still tracked.
  • The kernel keeps a merge that userland could own. The feed adds ABI and about 120 kernel lines in order to delete about 1,430. The merge stays in the kernel only because xHCI HID is there. When usbd lands (step 10), every source is a feed and the kernel's streams only merge userland's records. Whether they then leave too is the next question, and not this one.
  • A keyboard claim's evidence weakens. A minted feed is "a source", even on a machine whose controller ps2server then finds absent. The refusal now means "no feeder in this image and no xHCI bound".
  • The supervisor gains two rules: feeders are endowed before readers, and a clean exit is not restarted. The second reaches every restart row.
  • isa::ack stops refusing a row with no level line, and answers Ok. ps2server cannot know its lines' triggers: the claim's description is the port set, and the MADT decides. So it acks every wake, which costs one syscall a wake on an edge row. The alternative, trigger bits in the description, is an ABI change for one reader.
  • One more context switch on the keystroke path, and ps2server is a normal thread, not RT. Under CPU load the keyboard's 16-byte FIFO (K 19), about five translated keystrokes, absorbs the delay. Past that the keyboard's overrun becomes Lost, and the feed's keys are released. Nothing is timed on QEMU, and the T14's numbers are reported, not judged.
  • Device exchanges now wait on interrupts, which changes the probe on every machine. An EC that answers a device command without raising its line would fail the probe by name. Every EC raises it for keystrokes, so none is expected, but only the two metal rows can say.
  • Following IBM changes the exchange every machine sees: the query with translation off, the 7 µs, and writes only with OBF clear. QEMU is read in the smoke test, and the laptops are read by M1 and ps2server_arms.
  • The probe's ceilings are ToyOS's own, not IBM's. They bound liveness, and IBM gives no figure for a controller command's answer.
  • 0xAA, 0xAB and 0xA9 are not in IBM's PS/2 controller chapter, whose list (C 8–11) runs 20–3F, 60–7F, A4–A8, AD, AE, C0–C2, D0–D4, E0, F0–FF. They are kept because the kernel sends them every boot and QEMU and both laptops answer them. Their reference, the PC AT one, is not read here.
  • IBM's pointing-device chapter is not read. The aux commands (0xFF, 0xF2, 0xF3 0x64, 0xE8 0x03, 0xF4) are carried as the kernel sends them. The build cites them or says it cannot.
  • A restart loses what was typed while no ps2server ran, and runs the aux BAT again.
  • The diag image loses its panel line for the i8042. ps2server's lines are in /log only.
  • A keyboard reset (0xFF) is considered and not designed. It would put every keyboard in set 2 by IBM's own word (K 22), with no inference, and would close the T14's uninitialised-8042 boot. But it adds 300–500 ms of BAT to every start (K 20), and an EC that does not implement it would lose its keyboard. That is the owner's question on issues/t14-hands-over-an-uninitialised-8042.md, which records it as his.

What I am unsure of

  • The track's exit. I am not sure the composition plus one hand check meets "typing resumes after ps2server is killed and restarted" as the owner meant it, given Integration between modules is tested only for the kernel, and an integration test outside it is cut #890.
  • input_feed on the guest suite as well. As a metal row, it runs only when the orchestrator runs the T14.
  • IRQ 1 and 12 on the laptops. Whether they are edge or level, by their MADTs, is not read. The uniform ack makes it not matter.
  • The two issue closes. Whether the-i8042-tallys-… and screen-diag-boot-… close in this change or are left for the orchestrator.
  • The restart rule. The supervisor's restart path has no test today (rg 'started again' tests/ finds none), and this design adds none: the rule is one comparison a reader checks.

No gate is claimed: nothing is built.

🤖 Generated with Claude Code

https://claude.ai/code/session_015xhaydXCVRNscoccHYFUWy

An empty commit that opens the design round for stage 7.2 and step 6.3
of issues/the-kernel-is-small-interrupts-post-and-threads-wait.md. The
design and its roast are the pull request's body; nothing is built, and
the build drops this commit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015xhaydXCVRNscoccHYFUWy
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant