Skip to content

Ctrl+Alt+D and the blocked-task dump are removed, and the hard-lockup row holds the NMI frame's rip to the lock's spin - #824

Merged
Japabu merged 9 commits into
mainfrom
wt/toyos-nohotkey
Oct 10, 2026
Merged

Japabu merged 9 commits into
mainfrom
wt/toyos-nohotkey

Conversation

@Japabu

@Japabu Japabu commented Oct 10, 2026 •

Copy link
Copy Markdown
Collaborator

The owner, told Ctrl+Alt+D was kept on purpose as the last-resort diagnostic for a wedged machine, ruled: "i dont want it. i want it removed." This branch removes the hotkey and everything only it reached.

Net against main at aade01db2: 60 files, +181 −1895. Production code (kernel/src, kernel/pure, src): +55 −1241. Tests (tests, kernel/loom, kernel/sim): +16 −309. Records (issues, README.md, kernel/CLAUDE.md): +110 −342. origin/main at a1eb2c0b9 is merged in (#816, #817, #821, #805 and what came between).

What changed, per decision

  • The hotkey. kernel/src/keyboard.rs no longer recognises Ctrl+Alt+D, so every key transition is queued.

  • The dump. kernel/src/sched/dump.rs and sched/dump_request.rs are deleted: the request word, the per-CPU report, the NMI probe of a silent CPU, the process-table census and the summary. Their loom model kernel/loom/tests/dump_request.rs goes, and so do the dump-report-relaxed negative control in both manifests and its row in src/ci.rs. drain_irqs no longer takes an Entered or serves a report.

  • Readers that only the dump called, each with no other caller (all searched with git grep across the tree):

    • The driver's ready_len, for_each_stopped, for_each_dying, running_id, ParkedInfo and for_each_parked.
    • The pure core's CpuSched::ready_len and ParkedView::{class, since, ext}, and behind them Task::since, the linear states' since and WaitClass::name: each pub in a library crate, so dead_code never saw them go uncalled.
    • process::try_for_each_thread, ThreadCensus and ThreadEntry::name_str.
    • log::console::stats() with its RECORDS/LOST/PARKS counters, and log::read::Published::lost.
  • The NMI vector now does only crate::hardlockup's sample: the note_nmi store is gone. irqchip::send_nmi (both arches) compiles only into a test kernel, because its only callers left are the nmi-nested actuator and the hard-lockup probe. Without the cfg the shipping kernel fails dead_code.

  • The panel's held report is deleted: paint_report, hold_report, the REPORT cell, its hold timers, and the probe pixels that told a repaint apart from the report (Watch, PROBE_*, sample_probes, panel_carries_report, get_pixel, glyph_ink).

  • Tests and actuators that drove the dump:

    • The dump-deaf-cpu actuator is deleted, along with the T14 row dump_nmi_probe, its testcases-deaf boot, its entry in src/metal.rs's flashable arms, its three measured prices in tests/metal/, and its judge in tests/common/faults.rs.
    • lan_hold is deleted: it was the job that only held that boot open.
  • What stays, and why:

    • irq_census::census: crate::census prints it where the machine stops.
    • kthread::is_kernel_task: quiesce uses it.
    • irqchip::kick_cpu: the xHCI driver and the SMI path use it.
    • The NMI vector and its nested-NMI guard: crate::hardlockup needs them.
    • The panel's fatal-path latch and its outwait (seize, OUTWAIT).
  • screen_fatal_behind_a_painter is rewritten, not deleted.

    • Its behaviour is still shipping code: a fatal path takes the panel from a painter that will never let go (seize). No cheaper tier holds it.
    • The only non-fatal painter left is a boot checkpoint's. So panel-painter-stalls now takes the latch from the boot thread right after boot_phase!("complete") and goes fatal holding it.
    • The test presses nothing, waits on the painter's own line (ready_marker: HELD) instead of ===READY===, and asserts as before: the fatal fill, the line on the panel, and the reset at the bound.
    • It needs QEMU because the subject is the scanout read back by screendump plus a machine reset, and the T14's glass cannot be read by the metal loop.
  • Records.

    • kernel/CLAUDE.md drops the caveat about pressing the hotkey.
    • The README.md row no longer claims a dump on the panel.
    • Comments that cited the deleted test or module are reworded or deleted (hardlockup/mod.rs, clock.rs, irq_census.rs, src/sourcegate.rs, src/qemu.rs, kernel/sim/tests/deadline_claim_race.rs, tests/common/irqcensus.rs).
  • Issues closed. Five are about the removed feature alone:

    • blocked-dump-cannot-fire-on-a-total-freeze. Its residual line ("ps and stats have no cross-CPU view of what the handles do not publish") is the larger half that issues/blocked-time-is-invisible-while-the-park-lasts.md already records.
    • nothing-can-freeze-this-machine-from-outside, a track to fire the dump at a frozen machine.
    • the-deaf-cpu-actuator-arms-on-three-seconds-of-guest-clock.
    • lan-hold-holds-a-boot-open-for-a-flat-twenty-seconds.
    • which-pass-drain-irqs-is-entered-from-is-gated-only-by-a-nightly-guest. Entered no longer exists.

    Every citation of their slugs is moved: the-host-cannot-reach-the-t14-while-it-runs-toyos.md no longer points at lan_hold.

  • hard_lockup_chain asserts the NMI frame's rip. The deleted dump_nmi_probe row was the one test that held that rip to where the CPU stood, and the rip still ships as the lockup record's pc=. The judge now reads the record's pc= line (bootlog::LOCKUP_PC, after LOCKED_UP) and requires it to resolve into sync::Lock::lock (bootlog::LOCK_SPIN: <kernel::sync::Lock< and >>::lock+), as deadline_wedge_chain holds SEAL_PC to WEDGE_SPIN.

    • Measured on the boot-actuators kernel this row boots: probe::go_deaf calls <kernel::sync::Lock<()>>::lock, which the linker folds with other Lock<T>::locks at one address, so the name the symbol table returns is any of them; hence the two halves. Its spin calls out only to Shootdown::serve_if_owed for an owed shootdown or SMI.
    • bootlog's source check pins the kernel's " pc={}", At(pc) and Lock::lock's signature.
    • Under the review's + 8 mutation the pc is cs, 0x8, which resolves to no symbol. The mutation is posted (Ctrl+Alt+D and the blocked-task dump are removed, and the hard-lockup row holds the NMI frame's rip to the lock's spin #824 (comment)). The T14 read both arms at 427dce4b0 (see Metal).
  • The merge of USB HID reports are decoded by toyos-usbhid, which believes a rollover report's modifiers and not its slots #821.

    • kernel/src/keyboard.rs merged without conflict. It keeps main's apply over toyos_usbhid transitions and this branch's handle_key with no hotkey.
    • tests/common/qemu.rs keeps QmpInput. This branch had deleted it because its one caller pressed the hotkey, but USB HID reports are decoded by toyos-usbhid, which believes a rollover report's modifiers and not its slots #821's usb_keyboard_rollover now calls it. The file is identical to main's.
    • Step 10 of the small-kernel track keeps main's MSI-X facts (QEMU's table in the register BAR, none on the T14's capability walk) and decoders, without the hotkey.
  • Small-kernel track (issues/the-kernel-is-small-interrupts-post-and-threads-wait.md):

    • Step 10 no longer keeps a hotkey on the i8042 or declares a USB-only machine without one. Its exit drops "Ctrl+Alt+D files the dump with usbd killed".
    • Step 6.5 no longer moves the dump into pass, and drops the 2026-09-30 ruling about the dump's panel.
    • Step 7.2 no longer keeps Ctrl+Alt+D where it is.
    • Stage 4's ruling no longer names the kernel's hotkeys; it states the owner's ruling as he gave it: Ctrl+Alt+D removed (2026-10-10, "i dont want it. i want it removed.").
  • Issues that advised pressing the hotkey now name what exists instead:

    • desktop-window-child-freeze.md: its exit named the dump's NMI probe. It now names the trace diary (kernel/src/trace.rs), which every CPU writes from its timer and its scheduler, printed by /system/bin/trace: a CPU whose newest record stands behind the others' stopped passing, and an IdleEnter there says it went to halt. It also says what limits that read: 8192 records a CPU, and a program has to be spawned after the freeze to take it. It has never been taken on a reproduction.
    • spawned-process-never-starts.md: QMP info registers -a in a guest, and on metal crate::hardlockup's sealed record, which reaches one of the three causes the dump's probe told apart. Its header excludes a halted CPU and a CPU with IF set, and the issue says so.
    • null-sink-applies-one-connect.md: /system/bin/trace says whether soundd's mix thread parked and was never woken; no record carries the deadline it parked with.
    • pulling-the-boot-stick-freezes-the-t14.md: the acceptance test the owner set was a stick pulled with Ctrl+Alt+D still answering; the hotkey is gone, so what the pull must leave answering is his to name again. The branch does not choose it.
  • Owed by this change: a-fatal-path-entered-outside-a-panic-holds-the-panel-with-interrupts-open.md now says its IF reading was taken with the actuator in a scheduler pass and has not been taken since the move to the boot thread.

Gates, at head aade01db2

aade01db2 merges origin/main at a1eb2c0b9 (#805, the stop takes the console wire). How each of its three conflicts was resolved is in the merge commit and in a comment on this PR. Logs are in the orchestrator's scratchpad, under orch/ctrlaltd/merge/.

  • Host: cargo run -- --ci host > ci-host.log 2>&1 gave EXIT=0 ("Host: 77 step(s), all green", 09:56:56 UTC).
  • Builds: cargo run -- --build-only gave EXIT=0, then cargo run -- --build-only --arch aarch64 gave EXIT=0.
  • Guest suite: cargo test > guest-suite.log 2>&1 gave EXIT=0: toyos-build 50 of 50 ("50 passed, 50 total"), and the harness's host-side tests 347 passed with 15 ignored. Ceilings were at 1.00x. uptime gave load 28.10 29.04 37.39 before and 21.98 27.12 35.61 after.
  • Earlier rounds:
    • At a9b68f92b, before this merge, every gate gave EXIT=0, and the guest suite passed 45 of 45 at load 90 to 98.
    • In round 2, at 22b7bb464, the suite gave EXIT=1 and passed 41 of 44: virt_smp, virt_mask_windows and virt_off_names_the_cpus_left_on went silent together at load 54 to 72. That run is recorded in issues/a-counters-read-under-host-load-can-go-silent-for-15-s.md, together with the evidence against this branch's drain_irqs change as the cause:
      • 2375834a6 already carries the change, and its guest kernel is the same. Its whole suite passed 43 of 43, those three included.
      • The read is answered from the kick vector, not from a pass.
  • Mutation of seize: posted as a comment on this PR.
  • Metal: these readings were taken at 427dce4b0. The stop takes the console wire from klogd for good and holds it to the machine's end; flush_final goes #805's kernel changes, which this merge brings in, have not been run on the T14 at aade01db2.
    • git diff 427dce4b0 a9b68f92b -- kernel is hunk for hunk git diff 46632bf25 5a3b74345 -- kernel; only blob ids and line offsets differ. So kernel/src/keyboard.rs changed only by main's own lines, and the T14 readings at 427dce4b0 carry.
    • At 427dce4b0, run by the orchestrator: boot:testcases boot:windowscase hard_lockup_ends_a_deaf_cpu, 251 passed, 0 failed, 4 boot(s), with PASS hard_lockup_ends_a_deaf_cpu (pc=…<kernel::sync::Lock<()>>::lock+0x125).
    • The red arm, the + 8 mutation on hardware: FAIL hard_lockup_ends_a_deaf_cpu … "pc=0x0000000000000008", JUDGE_EXIT=1, REVERT_EXIT=0. Both arms are posted.

What I am unsure of

  • issues/clippy-stage-two-is-lints-one-at-a-time.md and issues/idle-stack-guard-price-nearly-doubled-since-its-return.md still name dump.rs, deaf_window and dump_nmi_probe. These are measurements recorded at a past commit and still true of that commit, so I left them as they are.
  • On a frozen guest, the trace diary is the one reader of whether each CPU kept passing, and it needs a program spawned after the freeze. On metal, a CPU halted with its kick lost has no reader.
  • The pc assertion's two halves are read off this build's symbol table. A Lock::lock that the compiler inlines into its caller would name the caller and red the row, and that would be a correct red: the record would then no longer name the spin.

🤖 Generated with Claude Code

https://claude.ai/code/session_017cSFvbD35xJ2kGANVdm23C

Japabu and others added 2 commits October 10, 2026 09:18
… are removed

The owner, told the hotkey was kept on purpose as the last-resort diagnostic
for a wedged machine, ruled: "i dont want it. i want it removed."

kernel/src/keyboard.rs no longer recognises Ctrl+Alt+D; every transition is
queued. Everything only the hotkey reached goes with it:

- kernel/src/sched/dump.rs (the request, the per-CPU report, the NMI probe of
  a silent CPU, the process-table census and the summary) and
  sched/dump_request.rs, with its loom model kernel/loom/tests/dump_request.rs,
  the `dump-report-relaxed` negative control in both manifests and its row in
  src/ci.rs. `drain_irqs` takes no `Entered` and serves no report.
- The driver's dump-only readers: `ready_len`, `for_each_stopped`,
  `for_each_dying`, `running_id`, `ParkedInfo`, `for_each_parked`; the pure
  core's `CpuSched::ready_len` and `ParkedView::{class, since, ext}`;
  `process::try_for_each_thread`, `ThreadCensus` and `ThreadEntry::name_str`;
  the console drain's `stats()` and its three counters, and
  `log::read::Published::lost`.
- The NMI handler's `note_nmi` store; the handler is crate::hardlockup's
  sample alone, and `send_nmi` compiles only into a test kernel, the only
  caller left (the `nmi-nested` actuator and the hard-lockup probe).
- The panel's held report: `paint_report`, `hold_report`, the `REPORT` cell,
  its hold timers, and the probe pixels that told a repaint from the report
  (`Watch`, `PROBE_*`, `sample_probes`, `panel_carries_report`, `get_pixel`,
  `glyph_ink`).
- The `dump-deaf-cpu` actuator and the T14 row `dump_nmi_probe` that judged
  it, its `testcases-deaf` boot, its flashable-arm entry in src/metal.rs, its
  measured prices, its judge in tests/common/faults.rs, and `lan_hold`, the
  job that only held that boot open. tests/common/qemu.rs's `QmpInput`, whose
  one caller pressed the hotkey, goes too.

What stays, and why: `irq_census::census` (crate::census prints it where the
machine stops), `kthread::is_kernel_task` (quiesce), `irqchip::kick_cpu`, the
NMI vector and its nested-NMI guard (crate::hardlockup), and the panel's
fatal-path latch with its outwait.

`screen_fatal_behind_a_painter` is rewritten rather than deleted: the latch a
fatal path must take from a painter that will never let go is still the
panel's, and only a boot checkpoint's painter is left to stage it. The
`panel-painter-stalls` actuator now takes the latch from the boot thread after
the last boot phase and goes fatal holding it, and the test no longer presses
anything.

Records: kernel/CLAUDE.md drops the caveat about pressing the hotkey; the
README's row no longer claims a dump on the panel. Five issues close, each
about the removed feature alone:
blocked-dump-cannot-fire-on-a-total-freeze (its residual line, that `ps` and
`stats` have no cross-CPU view of what the handles do not publish, is the
larger half issues/blocked-time-is-invisible-while-the-park-lasts.md already
records), nothing-can-freeze-this-machine-from-outside (a track to fire the
dump at a frozen machine), the-deaf-cpu-actuator-arms-on-three-seconds-of-
guest-clock, lan-hold-holds-a-boot-open-for-a-flat-twenty-seconds and
which-pass-drain-irqs-is-entered-from-is-gated-only-by-a-nightly-guest. The
small-kernel track's step 10 no longer keeps a hotkey on the i8042 or
declares a USB-only machine without one, and steps 6.5 and 7.2 no longer
carry the dump. Each issue that advised pressing it to read a wedge names
what exists instead: QMP `info registers -a` taken before any input, and on
metal crate::hardlockup's sealed black-box record; where nothing in the tree
meets an exit any more, the issue says so.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017cSFvbD35xJ2kGANVdm23C
… a userland it never reaches

The painter now goes fatal from the boot thread after the last boot phase, so
the boot ends before `===READY===`; the test waits for the line the painter
says as it goes fatal instead.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017cSFvbD35xJ2kGANVdm23C
@Japabu

Japabu commented Oct 10, 2026

Copy link
Copy Markdown
Collaborator Author

Mutation for screen_fatal_behind_a_painter at head 2375834a6: seize gives up rather than painting over a painter that will never let go. Applied with git apply --check, kernel rebuilt, cargo test --test toyos-build -- screen_fatal_behind_a_painter → EXIT=1 (RED: "left it at fill [0, 0, 0] without "panel: a painter holding the panel went fatal": the report never took the screen"), reversed in the same script; tree clean.

--- a/kernel/src/drivers/panic_console/mod.rs
+++ b/kernel/src/drivers/panic_console/mod.rs
@@ -624,6 +624,5 @@ fn seize() -> bool {
             core::hint::spin_loop();
         }
     }
-    PAINTING.store(true, Ordering::SeqCst);
-    true
+    false
 }

@Japabu

Japabu commented Oct 10, 2026

Copy link
Copy Markdown
Collaborator Author

Review of 2375834a6 against origin/main (merge base 9b691ddce). Net: 57 files, +125 −1911. Production (kernel/src, kernel/pure, src, manifests): +43 −1233. Tests: +9 −337. Records: +73 −341.

BLOCKER

  • PR body, "Host" — cargo run -- --ci host was not measured at this head. ci-host.log ends at 07:18:38 UTC, which is before c8bb2c96d was committed (09:18:43 +0200) and before 2375834a6 (09:24:04 +0200). The head commit changes tests/toyos.rs, and the host suite's cargo clippy --workspace $GUESTS --all-targets lints that file (ci-host.log:5590, 5845). So the head's version of it has never been through the host gate. Rerun at 2375834a6 and post the command, exit code and log.
  • PR body, "Metal" — there is no T14 reading. The change reaches code that runs on every T14 boot: the keyboard path (kernel/src/keyboard.rs handle_key) and the NMI vector (kernel/src/arch/x86_64/idt/nmi.rs note), which the hard-lockup sampler enters every second. Three images are staged and none has been booted. This stays open until the testcases, testcases-watchdog and windowscase readbacks at this head are posted green.
  • tests/common/power.rs:431 — the deleted dump_nmi_probe row was the only test that asserted the NMI frame's rip lands where the CPU actually was. That rip still ships: note hands it to hardlockup::sample, and the record seals it as pc= (kernel/src/hardlockup/mod.rs:390). hard_lockup_chain checks sp, the lock and the site, and never pc. Patch kernel/src/arch/x86_64/idt/nmi.rs:45, "mov rdi, [rsp + {rip_offset}]", to "mov rdi, [rsp + {rip_offset} + 8]" so the record names cs as the pc. At this head no test goes red; at the base, dump_nmi_probe did. That is a test cut that leaves a weaker check. Fix it one of two ways:
    • Have hard_lockup_chain assert that the stuck CPU's pc= line resolves into the lock's spin, the way deadline_wedge_chain asserts SEAL_PC against WEDGE_SPIN. Then show it red under that patch on the T14.
    • Or record the gap, with an owner and an exit, in issues/the-nmi-entry-can-hand-the-lockup-sample-cs-for-rflags-and-no-test-reds.md. That issue already covers the other two loads of the same entry.

NOTE

  • kernel/pure/sched/task.rs:840, :937, :121 — three items lost their last callers with the dump:

    • Task::since (:840): its only caller is linear_state!'s since.
    • linear_state!'s since (:937): its only caller was ParkedView::since, which this branch deletes.
    • WaitClass::name (:121): its only caller was dump.rs.

    All three are pub in a library crate, so dead_code stays silent. Delete them. The body's list of readers "each with no other caller" is incomplete without them.

  • issues/desktop-window-child-freeze.md:169 — the claim that "no instrument in the tree meets this exit today" is not established. kernel/src/trace.rs's per-CPU diary is always written from the timer and the scheduler, and SYS_TRACE_READ reads it. The branch did not rule it out for showing whether each CPU kept passing across a guest reproduction. The exit should name what can read it, or say why the diary cannot.

  • issues/spawned-process-never-starts.md:127 — the issue names crate::hardlockup as the metal instrument for why a CPU stops reaching a pass. Its own header excludes a halted CPU and a CPU with IF set. Those are two of the three causes the removed probe told apart, and the issue should say so.

  • issues/the-kernel-is-small-interrupts-post-and-threads-wait.md:76 — "The kernel recognises no hotkey (owner, 2026-10-10)" states the owner's ruling more broadly than he gave it. He ruled that Ctrl+Alt+D be removed. He did not set a rule over every hotkey.

  • issues/pulling-the-boot-stick-freezes-the-t14.md:63 — under "the metal claim is still the owner's to make", the acceptance test changes from Ctrl+Alt+D answering to "the desktop still answering typing". That is an acceptance chosen by the branch and put in the owner's place.

SEND BACK

@Japabu

Japabu commented Oct 10, 2026

Copy link
Copy Markdown
Collaborator Author

T14 at 2375834a6, run by the orchestrator: three boots (testcases-watchdog 2896b2b5…8212cde, testcases d288e526…44507d7, windowscase 93a3509e…372c2df8d), each image's sha256 checked against request.txt, each toyos-metal --fat32-check exit 0; judge cargo test --test toyos-build -- --metal --metal-readback <dir> boot:testcases boot:windowscase: EXIT=0, [metal] 250 passed, 0 failed, 3 boot(s). Superseded by the fix round if it changes shipped kernel bytes.

Japabu and others added 4 commits October 10, 2026 09:43
…ss::name, which only the dump read

Each is `pub` in a library crate, so `dead_code` never saw them go uncalled
when the blocked-task dump, their last reader, was deleted.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017cSFvbD35xJ2kGANVdm23C
…our records say what the dump's removal left

The deleted `dump_nmi_probe` row was the one test that asserted the NMI
frame's `rip` lands where the CPU stood, and that `rip` still ships as the
lockup record's `pc=`. `hard_lockup_chain` now reads the record's own `pc`
line and requires it to resolve into `sync::Lock::lock`, whichever `Lock<T>`
the linker folded it under, the way `deadline_wedge_chain` holds `SEAL_PC` to
`WEDGE_SPIN`. On the boot-actuators kernel the probe's `PROBE_LOCK.lock()` is
a call into that function, whose spin calls out only to serve an owed
shootdown or SMI. `bootlog`'s source check pins the record's `  pc={}` and
`Lock::lock`'s signature.

Records:
- the small-kernel track states the owner's ruling as he gave it:
  Ctrl+Alt+D removed, not every hotkey;
- the boot-stick issue keeps his acceptance test as he set it and leaves its
  replacement to him;
- the window-child freeze's exit names the trace diary and `/system/bin/trace`
  as what can read whether each CPU kept passing, and what limits that read;
- `spawned-process-never-starts` says the hard-lockup record reaches one of
  the three causes the dump's probe told apart;
- `null-sink-applies-one-connect` no longer says no shipped program reads the
  diary.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017cSFvbD35xJ2kGANVdm23C
… run under load

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017cSFvbD35xJ2kGANVdm23C
@Japabu

Japabu commented Oct 10, 2026

Copy link
Copy Markdown
Collaborator Author

Mutation for hard_lockup_ends_a_deaf_cpu's new pc= assertion, at head 427dce4b0: the NMI entry loads the frame's cs as the sample's pc (the review's + 8). Applied with git apply --check then git apply, the row's image staged with cargo test --test toyos-build -- --metal --metal-readback <dir>/red/ hard_lockup_ends_a_deaf_cpu (exit 2 by design: the machine was not touched), and reversed in the same script (REVERT_EXIT=0, tree clean). The built kernel's nmi_entry reads mov 0x58(%rsp),%rdi under it, against 0x50 at the head. Image sha256 4f0bf5bf3b6d3629462108eed3098d5d0188593bfb7d72587090a243f8eff0f1. Not yet booted: red or green is the T14's to say, judged with the patch applied.

--- a/kernel/src/arch/x86_64/idt/nmi.rs
+++ b/kernel/src/arch/x86_64/idt/nmi.rs
@@ -42,7 +42,7 @@
         "push r10",
         "push r11",
         "push rbp",
-        "mov rdi, [rsp + {rip_offset}]",
+        "mov rdi, [rsp + {rip_offset} + 8]",
         "mov rsi, [rsp + {rsp_offset}]",
         "mov rdx, [rsp + {rflags_offset}]",
         "mov rbp, rsp",

@Japabu Japabu changed the title The kernel recognises no hotkey: Ctrl+Alt+D and the blocked-task dump are removed Ctrl+Alt+D and the blocked-task dump are removed, and the hard-lockup row holds the NMI frame's rip to the lock's spin Oct 10, 2026
@Japabu

Japabu commented Oct 10, 2026

Copy link
Copy Markdown
Collaborator Author

T14 at 427dce4b0, run by the orchestrator. Green arm: four boots (hardlockup f7f610f6…5032860d, testcases-watchdog 8b4950f6…14b475, testcases 6f98deec…8d7fea, windowscase 86fb149e…825fc2), each image's sha256 checked against request.txt, each toyos-metal --fat32-check exit 0; judge cargo test --test toyos-build -- --metal --metal-readback <dir> boot:testcases boot:windowscase hard_lockup_ends_a_deaf_cpu: EXIT=0, [metal] 251 passed, 0 failed, 4 boot(s). Red arm (the review's + 8 patch, staged by red/stage.sh, image sha256 4f0bf5bf…f8eff0f1 checked): boot exit 0; red/judge.sh applied the patch, judged, reverted: FAIL hard_lockup_ends_a_deaf_cpu: the record puts the stuck cpu outside the lock's spin […]: "| pc=0x0000000000000008", JUDGE_EXIT=1, REVERT_EXIT=0, worktree status empty. The new pc= assertion reds the mutation on hardware.

@Japabu

Japabu commented Oct 10, 2026

Copy link
Copy Markdown
Collaborator Author

Round 2 review of 427dce4b0 against origin/main, merge base 46632bf25. Net: 61 files, +173 −1933. Production (kernel/src, kernel/pure, src): +55 −1241. Tests: +16 −347. Records: +102 −342.

First-round BLOCKERs

  • Host not measured at head: CLOSED. r2/logs/ci-host-final.head reads 427dce4b0, ci-host-final.exit reads EXIT=0, and the log ends Host: 77 step(s), all green at 08:25:42.
  • No T14 reading: CLOSED. metal-r2/request.txt names head 427dce4b0. judge.log ends [metal] 251 passed, 0 failed, 4 boot(s), with PASS hard_lockup_ends_a_deaf_cpu.
  • rip assertion lost with dump_nmi_probe: CLOSED. tests/common/power.rs:451 holds pc= to LOCK_SPIN.
    • Green arm: metal-r2/hardlockup/loader.log:55 reads pc=0xffff8000604dc225 <kernel::sync::Lock<()>>::lock+0x125.
    • Red arm, the + 8 patch on hardware: red/judge-run.log gives FAIL hard_lockup_ends_a_deaf_cpu … "pc=0x0000000000000008", JUDGE_EXIT=1, REVERT_EXIT=0.

First-round NOTEs

All five are answered at this head:

  • Task::since, linear_state!'s since and WaitClass::name are deleted. The since field is still read by accounting (task.rs:848, :1159).
  • desktop-window-child-freeze.md now names the trace diary and its limits. Both check out against the tree: SLOTS = 8192 at kernel/src/trace.rs:27, and userland/trace exists.
  • spawned-process-never-starts.md states hardlockup's two exclusions.
  • The stage 4 ruling is narrowed to Ctrl+Alt+D, with the owner's words.
  • pulling-the-boot-stick gives the acceptance back to the owner.

The guest-suite red (41 of 44 at 22b7bb464). I judge it not this branch's, on measurements already in hand:

  • Same kernel, whole suite green. The drain_irqs change is in c8bb2c96d. At 2375834a6, the suite was EXIT=0, 43 of 43, with virt_mask_windows, virt_smp and virt_off_names_the_cpus_left_on passing at 07:25:59–07:26:04 at load 28.66 → 61.52 (logs/guest-suite.log:877–886, guest-suite.uptime-*.txt). git diff 2375834a6 427dce4b0 touches no kernel source except kernel/pure/sched/task.rs, which deletes three pub methods with no caller. Those emit no code, so the guest kernel is the same one in the green run and the red run. The rest of the diff is main's merge (userland, harness, licences), the new pc= assertion and issues.
  • The answer path does not run through drain_irqs. The counters read is answered from the kick vector: counters::serve_here at kernel/src/arch/aarch64/trap.rs:209, which publishes and posts ANSWERED (kernel/src/counters.rs:137-157). The issue's one register capture puts the slow CPUs in that waiter list's ticket spin and at the kick EOI, not in a pass. What the branch takes out of drain_irqs is three unarmed checks that each load an atomic and return (serve_request, serve_if_owed, hold_report). On a machine that never pressed the key, removing them only shortens a pass.
  • The shape points at the host. All three guests were built and launched together, at 08:16:07–08:16:09, right after a 23 s artifact-lock wait (r2/logs/guest-suite.log:885–909). They fell silent within the same 4 s of host clock, 08:16:17–08:16:21. Not one of them recovered inside 15 s, while 24 vCPUs ran on 14 cores at load 54 → 72. Three independent QEMU processes do not go quiet together from one guest-kernel defect unless the host stops them. The issue already records the same profile on four other branches whose diffs reach nothing these guests run.
  • What would not settle it: the same three under the same load at the base. The issue puts the rate at about 1 in 5 to 1 in 30 guests under load, so one green base run proves nothing and one red base run adds a fifth sighting. Neither moves this branch. What settles the cause is the issue's own exit, a QMP register capture of a silent guest, and that is the issue owner's work, not this branch's.
  • The record rule is met. Root CLAUDE.md says a red seen only under load is recorded with the host's load. 427dce4b0 adds the run to issues/a-counters-read-under-host-load-can-go-silent-for-15-s.md with load, ceiling factor, worker times and the last guest lines.

BLOCKER

(none open)

NOTE

  • issues/a-counters-read-under-host-load-can-go-silent-for-15-s.md — the new paragraph names the branch's drain_irqs change as a suspect but omits the evidence against it. The same kernel was green in the whole suite at 2375834a6, at load up to 61.52, and the read is answered from the kick vector, not from a pass. The record is not false, but it is incomplete; prose only.

LAND

Japabu and others added 2 commits October 10, 2026 11:00
The stage 5 usbd step keeps main's MSI-X and decoder facts (#821) and
this branch's removal of Ctrl+Alt+D; keyboard.rs takes main's
toyos-usbhid `apply` and this branch's hotkey removal from handle_key.

tests/common/qemu.rs keeps `QmpInput`: this branch deleted it with the
hotkey test, its one caller then, and #821's usb_keyboard_rollover is a
caller now.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017cSFvbD35xJ2kGANVdm23C
…nst the drain_irqs change

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017cSFvbD35xJ2kGANVdm23C
@Japabu
Japabu marked this pull request as ready for review October 10, 2026 09:14
…nsole wire (#805), into the Ctrl+Alt+D removal

Three conflicts, each a hunk of #805's beside a hunk this branch deleted:

- kernel/src/actuator.rs: #805's three wire actuators
  (wire-held-across-the-stop, wire-kept-through-the-stop,
  wire-held-at-the-last-word) stay; dump-deaf-cpu, which #805's side kept
  only as context, stays removed.
- kernel/src/log/console.rs: #805's let_go and staged module stay; the
  RECORDS/LOST/PARKS counters and stats(), read only by the removed
  sched::dump, stay removed, as do their stores, which merged clean.
- kernel/src/sched/driver.rs: #805's for_each_ready, read by
  console::staged::say_klogd_unrun, stays; ready_len, for_each_stopped,
  for_each_dying, running_id, ParkedInfo and for_each_parked, read only by
  the removed sched::dump, stay removed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017cSFvbD35xJ2kGANVdm23C
@Japabu

Japabu commented Oct 10, 2026

Copy link
Copy Markdown
Collaborator Author

Merge of origin/main at a1eb2c0b9 (#805), head aade01db2

Three files conflicted. In each, #805 added a hunk next to one this branch deletes:

After the merge, rg finds no remaining reference to dump_deaf_cpu, sched::dump, console::stats or the removed driver functions. The one remaining "Ctrl+Alt+D" outside issues/ is toyos-usbhid's chord test from #821, which tests decoding and not the kernel shortcut. Net against a1eb2c0b9 is the same as before: 60 files, +181 −1895.

Gates at aade01db2

$ git rev-parse HEAD
aade01db2720a93df9bbb13ec6772df8c7e1da24

$ cargo run -- --ci host > ci-host.log 2>&1; echo EXIT=$?
09:56:56 [ci] Host: 77 step(s), all green
EXIT=0

$ cargo run -- --build-only > build-x86.log 2>&1; echo EXIT=$?
EXIT=0

$ cargo run -- --build-only --arch aarch64 > build-aarch64.log 2>&1; echo EXIT=$?
EXIT=0

$ cargo test > guest-suite.log 2>&1; echo EXIT=$?
test result: ok. 347 passed; 0 failed; 15 ignored; 0 measured; 0 filtered out; finished in 10.08s
10:01:18 host: fastest boot 427 ms against the reference 1424 ms — liveness ceilings paid at 1.00x
10:01:18 test result: ok. 50 passed, 50 total (93.6s; workers: 610s building, 448s testing)
test result: ok. 39 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.04s
EXIT=0
uptime before: load averages: 28.10 29.04 37.39
uptime after:  load averages: 21.98 27.12 35.61

These have not run on the T14 at aade01db2. The metal readings in the body were taken at 427dce4b0. Since this merge, origin/main has moved to d5bc4df9d (#812, #820). git merge-tree reports that it merges into this branch with no conflict.

@Japabu
Japabu enabled auto-merge October 10, 2026 10:02
@Japabu
Japabu added this pull request to the merge queue Oct 10, 2026
Merged via the queue into main with commit ea09d63 Oct 10, 2026
3 checks passed
@Japabu
Japabu deleted the wt/toyos-nohotkey branch October 10, 2026 10:45
Japabu added a commit that referenced this pull request Oct 10, 2026
…ring-up (#825) and the hotkey removal (#824), into consent

The one conflict is Profile::arch in tests/common/qemu.rs: main adds
HeadlessUsbSpare and this branch adds Desktop to the same x86-64 arm;
both stay.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017cSFvbD35xJ2kGANVdm23C
Japabu added a commit that referenced this pull request Oct 10, 2026
…uthority (#826), the SMMUv3 bring-up (#825), the hotkey removal (#824) and evidence on the pull request (#835), into virtio-sound and the shared PCI claim

Two conflicts, both resolved by keeping every hunk of both sides:

- tests/common/qemu.rs: the virtio-gpu device arm (this branch) and the
  two iommu-testdev arms (#825) are separate `if`s on separate Shape
  fields; HeadlessVirtioGpu and VirtSmmu are disjoint profiles, so no
  machine gains or reorders a device.
- tests/toyos.rs RUST_SKIP: virtio_sound_counts (this branch) and
  partition_grant, update_idle_slot (#826) all kept.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017cSFvbD35xJ2kGANVdm23C
Japabu added a commit that referenced this pull request Oct 10, 2026
… batch: the icons' and wallpaper's digests hash with toyos-sha2

Cargo.toml keeps both sides' entries: main's toyos-sha2 and usbd members
and toyos-sha2 dependency, and the batch's removal of `image`. `sha2` was
replaced by toyos-sha2 on main and left in place on the batch, whose
#813 and #814 added two tests hashing with it; as main meant every
SHA-256 the build takes to be toyos-sha2's, those two tests now hash
with toyos-sha2 and the root manifest drops `sha2`.

Cargo.lock is the batch's, re-resolved by `cargo metadata --offline`;
its delta from the batch's head is exactly main's delta from the merge
base.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017cSFvbD35xJ2kGANVdm23C
Japabu added a commit that referenced this pull request Oct 10, 2026
, #826, #835, #833, #831 and #822, into wt/toyos-netperf

No hunk conflicted. userland/netstack/src/main.rs took both sides: main's
removal of `mod device` and the branch's batched `node.receive` and its
module-doc line. The TCP window-scaling and loss-probe commits main
carries were already in the branch from #820, so their files merged to
main's text plus the branch's own delta. Both lockfiles are main's and
pass `cargo metadata --locked`. The branch's new issue still cites
`VirtioNet::poll_rx` and `toyos_i219::RX_BUDGET` as they stand on main.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017cSFvbD35xJ2kGANVdm23C
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