From ab18c430f57f4fec468b4351311b0d4d13c14585 Mon Sep 17 00:00:00 2001 From: japabu Date: Sun, 4 Oct 2026 01:43:03 +0200 Subject: [PATCH 1/4] issues: record the owner's 2026-10-03 rulings where their tracks live MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Notes only. The observability umbrella track issues/diagnostics/toyos-explains-itself.md, from strategy v2 and its roast (adopt with named changes), with the owner's rulings: shipped readers, "Keep crash records", "Only with permission", "General counters", "Always on", symbols "adopt". The pillar tracks point at it. The trace track keeps only the owner's words as his; the rest is "proposal accepted". The memory-overwrite request is declined (kind: rejected) and the parity track says so; the T14's MOR reads set under Ubuntu, so clearing it is a new defect. The latency bar is "131 µs". Linux's turbostat and perf msr readings of the T14 go into the before-the-wipe issue with their commands. The ACPI rulings (back to legacy mode, extracts only, clean-room AML) and the views rulings (restrict, adopt, /tmp per session) go into their tracks. Issue files naming toyos-sched, toyos-proclife or toyos-pcid point at kernel/pure, kernel/loom and kernel/sim (#694), save transcripts run at a named commit. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01WcU2Dsw6mDYtwYfzVHPzM8 --- ...t-ubuntu-left-set-stays-set-under-toyos.md | 39 ++++ ...-the-firmwares-memory-overwrite-request.md | 37 ++-- ...ge-takes-a-names-lowest-pid-for-the-job.md | 2 +- ...he-table-lock-again-is-gated-by-nothing.md | 2 +- ...clippy-stage-two-is-lints-one-at-a-time.md | 2 +- .../parallel-tests-red-under-other-suites.md | 4 +- ...dropped-watchs-answer-as-its-completion.md | 2 +- ...ig-the-guest-cut-deleted-is-still-cited.md | 5 +- .../design-debt/redesign-the-log-subsystem.md | 5 + .../design-debt/what-is-owed-on-file-size.md | 2 +- ...-in-the-machine-can-read-the-trace-ring.md | 22 +- .../the-kernel-keeps-nothing-it-enumerates.md | 4 + issues/diagnostics/toyos-explains-itself.md | 139 +++++++++++++ issues/filesystem/where-everything-lives.md | 6 +- ...el-lack-reads-owed-before-the-t14s-wipe.md | 192 ++++++++++++++++++ .../process-start-skew-on-a-runner.md | 2 +- ...rupts-every-cpu-every-2-2-s-under-toyos.md | 4 +- ...rogram-sees-only-the-files-it-was-given.md | 15 +- ...nds-its-wake-on-a-waiter-that-then-dies.md | 2 +- ...e-before-its-child-lands-claims-nothing.md | 2 +- ...alk-by-the-threads-it-parks-on-one-ring.md | 4 +- ...-four-billion-threads-panics-the-kernel.md | 2 +- ...-total-that-reads-zero-under-contention.md | 2 + ...ntry-under-preemption-has-no-loom-model.md | 2 +- issues/kernel/desktop-window-child-freeze.md | 2 +- ...ness-is-per-thread-so-thread-count-wins.md | 2 +- ...ranularity-bound-crossed-at-four-widths.md | 2 +- ...ing-enter-trips-the-one-queue-invariant.md | 2 +- ...ducer-and-a-kernel-that-waits-on-nobody.md | 4 + ...hing-charges-kernel-memory-to-a-process.md | 4 + ...s-without-the-timer-stop-before-cpu-off.md | 2 +- ...acement-is-blind-to-caches-and-topology.md | 2 +- ...ve-up-on-one-thread-beside-the-held-one.md | 2 +- ...-thread-disagrees-about-a-reaped-parent.md | 4 +- issues/kernel/spawned-process-never-starts.md | 6 +- .../steal-probe-node-dies-with-its-victim.md | 6 +- .../the-global-pipe-lock-spans-a-user-copy.md | 2 +- ...s-linux-on-every-machine-toyos-supports.md | 5 +- ...-small-interrupts-post-and-threads-wait.md | 2 +- ...ernel-still-parses-what-userland-writes.md | 5 +- ...heduler-explorer-never-generates-a-stop.md | 6 +- ...exits-completion-post-is-the-second-one.md | 2 +- .../toyos-beats-linuxs-latency-on-the-t14.md | 8 +- issues/kernel/toyos-runs-on-arm64.md | 12 +- ...ine-in-acpi-mode-and-interprets-its-aml.md | 15 ++ 45 files changed, 509 insertions(+), 84 deletions(-) create mode 100644 issues/boot-media/a-memory-overwrite-request-ubuntu-left-set-stays-set-under-toyos.md create mode 100644 issues/diagnostics/toyos-explains-itself.md diff --git a/issues/boot-media/a-memory-overwrite-request-ubuntu-left-set-stays-set-under-toyos.md b/issues/boot-media/a-memory-overwrite-request-ubuntu-left-set-stays-set-under-toyos.md new file mode 100644 index 00000000000..d409fa5294b --- /dev/null +++ b/issues/boot-media/a-memory-overwrite-request-ubuntu-left-set-stays-set-under-toyos.md @@ -0,0 +1,39 @@ +--- +status: open +kind: defect +opened: 2026-10-04 +--- + +# A memory-overwrite request Ubuntu left set stays set under ToyOS + +The owner's ruling "Keep crash records" (2026-10-03, +`issues/diagnostics/toyos-explains-itself.md`) has ToyOS not ask the firmware +to wipe memory at reset. On the T14 the request is already made: under its +Ubuntu (`6.8.0-142-generic`), whose EFI stub sets it on every boot +(`issues/boot-media/the-loader-never-sets-the-firmwares-memory-overwrite-request.md`), + +``` +ls /sys/firmware/efi/efivars/ | grep -i -E "MemoryOverwrite|MOR" +for f in /sys/firmware/efi/efivars/MemoryOverwriteRequestControl*; do [ -e "$f" ] && { echo "$f"; od -An -tx1 "$f"; }; done +``` + +read `07 00 00 00 01` for `MemoryOverwriteRequestControl` and `07 00 00 00 00` +for `MemoryOverwriteRequestControlLock`: efivarfs's four attribute bytes +(non-volatile, boot-service and runtime access), then the value: the request +0x01, set, and its lock 0x00, unlocked. The variable is +non-volatile, so it stays set into every ToyOS boot that follows Ubuntu, and +`bootloader/src` neither reads nor writes it. Whether this firmware honours it +on the reset paths ToyOS takes is unmeasured: a black-box record has survived +two hours of Ubuntu, which does not say what an unclean reset does. Every +UEFI call ToyOS makes is the loader's, so the write belongs with +`issues/boot-media/the-loader-does-only-what-must-precede-the-handover.md`. + +**Exit**: where the firmware defines `MemoryOverwriteRequestControl` and it +reads non-zero, the loader writes 0 before `ExitBootServices` and logs the +value it found; where the firmware defines none, it makes no `SetVariable` +call under that GUID. A guest test on a fresh OVMF variable store planted with +1 reads 0 after the loader's pass, and one planted with nothing finds no +variable under the GUID; deleting the write reds the first, and an +unconditional write reds the second. On the T14, a boot that follows Ubuntu +logs the 1 it found, and a black-box record sealed by a forced reset of that +boot is read by the next. diff --git a/issues/boot-media/the-loader-never-sets-the-firmwares-memory-overwrite-request.md b/issues/boot-media/the-loader-never-sets-the-firmwares-memory-overwrite-request.md index 8520f027d76..b7e313b5516 100644 --- a/issues/boot-media/the-loader-never-sets-the-firmwares-memory-overwrite-request.md +++ b/issues/boot-media/the-loader-never-sets-the-firmwares-memory-overwrite-request.md @@ -1,6 +1,6 @@ --- -status: open -kind: defect +status: none +kind: rejected opened: 2026-09-29 --- @@ -13,26 +13,17 @@ At `Ubuntu-6.8.0-142.142`, the x86 EFI stub runs `MemoryOverwriteRequestControl`=1 under vendor `e20939be-32d4-41be-a150-897f85d49829` (`drivers/firmware/efi/libstub/tpm.c:20-21`) so firmware wipes RAM -on the next boot after an unclean reset. That function first reads the -existing variable and returns without writing when the firmware has none -defined (`tpm.c:36-40`), and it never inspects -the status of the `set_efi_var` call it does make (`tpm.c:42-45`). -`bootloader/src` writes no variable under this GUID at all. +on the next boot after an unclean reset, where the firmware already defines +the variable (`tpm.c:36-40`). `bootloader/src` writes no variable under this +GUID. -Root `CLAUDE.md`'s firmware rule puts every UEFI call ToyOS makes in the -loader, before `ExitBootServices`: the write is a `SetVariable` there, and -belongs with -`issues/boot-media/the-loader-does-only-what-must-precede-the-handover.md`. +**Declined** (owner, 2026-10-03): **"Keep crash records"**. ToyOS does not ask +the firmware to wipe memory at reset; crash records survive a reset in RAM +(`issues/diagnostics/toyos-explains-itself.md`). So ToyOS stays below Linux on +this one line of +`issues/kernel/the-kernel-is-at-least-as-secure-as-linux-on-every-machine-toyos-supports.md`: +whoever resets a ToyOS machine into a boot medium of their own can read what +the last boot left in RAM. -**Exit**: on firmware that already defines `MemoryOverwriteRequestControl`, -the loader sets it to 1 before `ExitBootServices` and does not act on whether -the write succeeded; on firmware that does not define it, the loader performs -no `SetVariable` call under that GUID. The guest test `mor_is_set_where_defined` -has two boots, each on a fresh OVMF `VARS`. The first plants -`MemoryOverwriteRequestControl`=0 under that GUID with `vars::plant` -(`tests/common/update.rs`), boots, and asserts `vars::live` reads it as 1; -both helpers take only the anti-rollback floor's vendor today, so they gain -the vendor as an argument. The second plants nothing and asserts no variable -exists under that GUID afterward. Deleting the loader's `SetVariable` leaves -the planted 0 and reds the first boot; dropping its read of the variable -first makes the write unconditional and reds the second. +A request already set by another system is a different matter: +`issues/boot-media/a-memory-overwrite-request-ubuntu-left-set-stays-set-under-toyos.md`. diff --git a/issues/build/a-metal-judge-takes-a-names-lowest-pid-for-the-job.md b/issues/build/a-metal-judge-takes-a-names-lowest-pid-for-the-job.md index dd9cf30e3a0..261a81fe34b 100644 --- a/issues/build/a-metal-judge-takes-a-names-lowest-pid-for-the-job.md +++ b/issues/build/a-metal-judge-takes-a-names-lowest-pid-for-the-job.md @@ -13,7 +13,7 @@ job before the job spawned anything. The kernel does not issue pids in landing order. A spawn refused after its admission gives its pid back, and the next admission takes it -(`toyos_proclife::pids`). A spawn admitted before a job and refused after the +(`kernel::proclife::pids`). A spawn admitted before a job and refused after the job landed hands a pid below the job's to the next spawn, and if that is the job's child of the same name the judge reads the child's exit as the job's. diff --git a/issues/build/a-settled-thread-join-taking-the-table-lock-again-is-gated-by-nothing.md b/issues/build/a-settled-thread-join-taking-the-table-lock-again-is-gated-by-nothing.md index e61c9f7c81b..9bb8a169122 100644 --- a/issues/build/a-settled-thread-join-taking-the-table-lock-again-is-gated-by-nothing.md +++ b/issues/build/a-settled-thread-join-taking-the-table-lock-again-is-gated-by-nothing.md @@ -6,7 +6,7 @@ opened: 2026-09-28 # A settled thread join taking the table lock again is gated by nothing -`toyos_proclife::join::Join::ask` calls its `collect` only while the join is +`kernel::proclife::join::Join::ask` calls its `collect` only while the join is unsettled, and `a_settled_join_does_not_take_the_table_again` holds that. Whether `collect` is where the kernel takes `PROCESS_TABLE` is `kernel/src/process.rs`'s `ask_join`, in no crate a host test compiles. PR diff --git a/issues/build/clippy-stage-two-is-lints-one-at-a-time.md b/issues/build/clippy-stage-two-is-lints-one-at-a-time.md index cc889c0c357..806aca4bb7f 100644 --- a/issues/build/clippy-stage-two-is-lints-one-at-a-time.md +++ b/issues/build/clippy-stage-two-is-lints-one-at-a-time.md @@ -48,7 +48,7 @@ the group). | lint | count | why | |---|---:|---| | `checked_conversions` | 1 | `4a98107f^:kernel/src/arch/syscall.rs`'s device-register-write syscall bounded a `u64` against `u32::MAX` with a manual `as` comparison, then cast twice more in the body. Restructured through `u32::try_from` — one conversion, no repeated casts, at a trust-boundary site that is exactly what this bar is for. | -| `manual_midpoint` | 3 | `(a + b) / 2` can overflow near the integer's max; `T::midpoint` can't. Two in a `toyos-desktop` test, one in `toyos-sched/sim`'s binary-search shrinker — no realistic overflow today, but the fix is free and closes the class everywhere, forever. | +| `manual_midpoint` | 3 | `(a + b) / 2` can overflow near the integer's max; `T::midpoint` can't. Two in a `toyos-desktop` test, one in `kernel/sim`'s binary-search shrinker — no realistic overflow today, but the fix is free and closes the class everywhere, forever. | | `redundant_clone` | 6 | Real, not the false-positive-prone lint its `nursery` placement suggested — every instance checked was a clone of a binding never used again after (verified by hand, not by trusting the lint): `4a98107f^:kernel/src/arch/syscall.rs`, a `kernel-loom` test, `toyos-cc`'s parser (a double clone — the match scrutinee was already an owned value), and three in `tests/toyos.rs`. | | `unchecked_time_subtraction` | 1 | `tests/toyos.rs`: a bare `Duration - Duration` that panics identically today either way — `.checked_sub().expect(msg)` says why it can't underflow instead of hiding the same panic behind an operator. No behavior change; an honesty win at zero cost. | | `unnecessary_semicolon` | 2 | Two dead `;` after `if` statements in `kernel/src/process.rs` and `kernel/src/main.rs`. Nothing to weigh. | diff --git a/issues/build/parallel-tests-red-under-other-suites.md b/issues/build/parallel-tests-red-under-other-suites.md index bdb5567824f..bf4fc12c3ab 100644 --- a/issues/build/parallel-tests-red-under-other-suites.md +++ b/issues/build/parallel-tests-red-under-other-suites.md @@ -70,7 +70,7 @@ changes. - **`netd_connection_caps`** — retired 2026-09-04, green 5 of 5 beside a full fast tier. - **`metal_sim_pointer_churn`** — observed once, on a host carrying three other - suites *and* a `toyos-sched-sim` run. Not investigated. Still + suites *and* a `kernel-sim` run. Not investigated. Still `Sched::Parallel`. - **`dump_nmi_probe`** — retired 2026-09-04, green 3 of 3 beside a full fast tier. `4ad8875` made it `Sched::Serial`, @@ -163,7 +163,7 @@ changes. of its own — five sightings, each carrying the *guest's own panic text* — and that class has since been diagnosed and fixed: a CPU could hand a thief the task whose context it was still standing on, so two CPUs ran one kernel stack - (`SchedPass::answer_steal_requests`, `toyos-sched/src/cpu.rs`). This sighting + (`SchedPass::answer_steal_requests`, `kernel/pure/sched/cpu.rs`). This sighting carried no console at all — `TestResult::error` held the verdict, a failing test's guest console is not printed, and by the time the re-runs were green the capture was gone — so it can be neither confirmed as that class nor ruled diff --git a/issues/build/the-two-watch-poll-model-counts-a-dropped-watchs-answer-as-its-completion.md b/issues/build/the-two-watch-poll-model-counts-a-dropped-watchs-answer-as-its-completion.md index 899c9c18517..4e131baa43e 100644 --- a/issues/build/the-two-watch-poll-model-counts-a-dropped-watchs-answer-as-its-completion.md +++ b/issues/build/the-two-watch-poll-model-counts-a-dropped-watchs-answer-as-its-completion.md @@ -6,7 +6,7 @@ opened: 2026-09-30 # The two-watch poll model counts a dropped watch's answer as its completion -`toyos-sched/loom/tests/loom_watch.rs`'s +`kernel/loom/tests/loom_watch.rs`'s `a_poll_on_two_watches_racing_both_posts_completes_exactly_once` moves both worlds into their producer threads, so both watches drop before its assertion, and a watch's drop fires every live entry as `Fire::Gone`, which the model's diff --git a/issues/build/the-update-rig-the-guest-cut-deleted-is-still-cited.md b/issues/build/the-update-rig-the-guest-cut-deleted-is-still-cited.md index 52745ef69bb..218017c7ecc 100644 --- a/issues/build/the-update-rig-the-guest-cut-deleted-is-still-cited.md +++ b/issues/build/the-update-rig-the-guest-cut-deleted-is-still-cited.md @@ -9,7 +9,7 @@ opened: 2026-10-03 #660 (`06788146b`) deleted `tests/common/update.rs` with its `Rig`, `tests/common/fwvars.rs` and `tests/updatecase/system.toml`. `git grep -n 'fwvars\|updatecase\|common/update\.rs\|Rig::\|vars::plant\|vars::live'` finds -nine lines in three files, each planning or describing a test on them: +seven lines in two files, each planning or describing a test on them: - `issues/boot-media/the-loader-does-only-what-must-precede-the-handover.md`, six lines. Stage 3's exit takes `fwvars::live` as @@ -17,9 +17,6 @@ nine lines in three files, each planning or describing a test on them: `tests/updatecase/system.toml` grants `slots` and that two tests run `updatecase`; one of its negative controls signs with `Rig::update` and reads the floor with `fwvars::live`, which its oracles name too. -- `issues/boot-media/the-loader-never-sets-the-firmwares-memory-overwrite-request.md`, - two lines: its exit's `mor_is_set_where_defined` plants and reads the vars - store with `vars::plant` and `vars::live`. - `issues/build/the-kernel-console-split-does-not-re-arm-across-a-guest-reset.md`, one line: the reset in place it describes is `Rig::boot`'s. diff --git a/issues/design-debt/redesign-the-log-subsystem.md b/issues/design-debt/redesign-the-log-subsystem.md index c3d4a99a434..e49abb550e2 100644 --- a/issues/design-debt/redesign-the-log-subsystem.md +++ b/issues/design-debt/redesign-the-log-subsystem.md @@ -17,6 +17,11 @@ names nothing that will land. The directory re-shape is a scheduling matter exactly as priced below: one clean pass in a window with few worktrees in flight, and never interleaved with a code change. +The log is a pillar of `issues/diagnostics/toyos-explains-itself.md`, and +its ring is +`issues/kernel/logging-records-from-every-producer-and-a-kernel-that-waits-on-nobody.md`'s; +this file holds the sinks and the layout. + The target shape stands as reviewed: a log core (ring + context stamping, once) with serial, file and screen as independent sinks carrying explicit backpressure — a slow sink drops-and-counts, never blocks, does no unbounded diff --git a/issues/design-debt/what-is-owed-on-file-size.md b/issues/design-debt/what-is-owed-on-file-size.md index 306c88deed9..42fd77d9c95 100644 --- a/issues/design-debt/what-is-owed-on-file-size.md +++ b/issues/design-debt/what-is-owed-on-file-size.md @@ -44,7 +44,7 @@ what survives it is a different question. no function body changed. The split made two facts visible and filed: 58 refusal `return`s exit past the epilogue, and a refused syscall is counted but not timed. -- `process.rs` — the lifecycle state machine is `toyos-proclife/` (pure, +- `process.rs` — the lifecycle state machine is `kernel/pure/proclife/` (pure, `forbid(unsafe_code)`, every interleaving of a scripted pair of paths enumerated; #142's mechanism class now has a host reproduction). Three subjects are still decided inside the file and reachable only by a booted diff --git a/issues/diagnostics/nothing-in-the-machine-can-read-the-trace-ring.md b/issues/diagnostics/nothing-in-the-machine-can-read-the-trace-ring.md index 9522e85abcd..efa32ab5211 100644 --- a/issues/diagnostics/nothing-in-the-machine-can-read-the-trace-ring.md +++ b/issues/diagnostics/nothing-in-the-machine-can-read-the-trace-ring.md @@ -8,13 +8,17 @@ opened: 2026-07-30 `kernel/src/trace.rs` is a per-CPU ring of `RING_CAPACITY` 24-byte `repr(C)` records, enabled from `main.rs` at boot and written by the timer, the -scheduler, `irq_ring` and every `toyos_sched::hw::TraceEvent` the core emits. +scheduler, `irq_ring` and every `kernel::sched::hw::TraceEvent` the core emits. Its one reader is LLDB: `p &TRACE_RINGS` and then `memory read`, which is why the discriminants are fixed by hand and held there by const assertions. A booted machine can ask itself nothing: no syscall, no tool, no gate. -**Ruled** (owner, 2026-10-03): the ring is finished in three steps, and the -work then stops and is judged before anything more is built on it. +Part of `issues/diagnostics/toyos-explains-itself.md`, whose shared +foundations this track obeys. + +**Proposal accepted** (owner, 2026-10-03): the ring is finished in three +steps, and the work then stops and is judged before anything more is built on +it. 1. **The ring is readable**: the log's slot protocol, raw counter stamps, `SYS_TRACE_READ` in the shape of the log's read, the `trace` right it @@ -27,7 +31,10 @@ work then stops and is judged before anything more is built on it. pick events, with no tracer in the kernel. **Exit**, on the T14: the 50 ms for which `hold_once` keeps both windows open once a boot (`kernel/src/windows.rs`) reads back as at least that much lateness. -3. **Windows over a threshold, and shootdown records.** **Exit**: `SYS_DEBUG`'s +3. **Windows over a threshold, shootdown records, and slow system calls.** + A system call over the threshold is recorded with its number and its + program, in the shipped kernel: **"Always on"** (owner, 2026-10-03). + **Exit**: `SYS_DEBUG`'s shootdown-acknowledgement delay names the delayed CPU and its time in the trace. A window's record names its opener by address, which `issues/kernel/the-cpu-that-spawns-a-toybox-applet-reads-1-4-ms-of-interrupts-and-preemption-off-on-the-t14.md` @@ -39,13 +46,16 @@ Behind that judgement, and not before it: interrupt enter and exit records with a noise reader, the profiling sample, and the censuses moved onto the ring. -The lines he drew: +The proposal's other lines, accepted with it: - The ring stays always written in the shipping kernel. - Reading it needs a new `trace` right. -- The reader tool is not in the shipped image. - The LLDB reading path and its pinned numbers go. - A T14 judge may read a binary trace file, the decoder printing the lines a pull request quotes. - The profiling sample shares the ring. - 2 MiB of rings at eight CPUs is accepted. + +The reader ships with ToyOS, in the owner's words (2026-10-03): "its obvious +that we want to be able to understand kernel metrics from within toyos ... +thats an important and productive tool that should be shipped with toyos." diff --git a/issues/diagnostics/the-kernel-keeps-nothing-it-enumerates.md b/issues/diagnostics/the-kernel-keeps-nothing-it-enumerates.md index 4a34a411442..35c4b960333 100644 --- a/issues/diagnostics/the-kernel-keeps-nothing-it-enumerates.md +++ b/issues/diagnostics/the-kernel-keeps-nothing-it-enumerates.md @@ -11,6 +11,10 @@ goes for NVMe Identify strings, USB INQUIRY strings, the GPT table and mount metadata. There is no `hw` and no `disk`, because there is nothing for them to read. Retention is the bulk of this work and it is blocked on nothing. +`inspect` is a pillar of `issues/diagnostics/toyos-explains-itself.md`, which +adds a `kernel.*` root rendered from the counters and a `supervisor.*` root +from the program table. + On top of retention, in dependency order: 1. **Retention plus one query syscall and a topic decoder**, with `hw` and diff --git a/issues/diagnostics/toyos-explains-itself.md b/issues/diagnostics/toyos-explains-itself.md new file mode 100644 index 00000000000..e06f266eced --- /dev/null +++ b/issues/diagnostics/toyos-explains-itself.md @@ -0,0 +1,139 @@ +--- +status: open +kind: track +opened: 2026-10-04 +--- + +# ToyOS explains itself: log, diary, counters, accounting, inspect, sizes and post-mortem on shared foundations + +ToyOS answers what it is doing, what it did and what it is made of from +inside itself, with programs it ships. Today the answers are scattered: the +log carries numbers in prose (`irq:`, `tlb:`, `PMM:`, `sched:`, `syscalls:`), +the trace ring has LLDB as its only reader, nothing reads APERF, MPERF, +`MSR_SMI_COUNT`, RAPL or C-state residency, a process's memory is a byte sum +that reads 0 under contention, and a user symbol is resolved by the kernel. +This track is the one plan for all of it; each pillar's own track carries its +steps and its exits, and nothing here restates them. + +## The owner's rulings (2026-10-03) + +- **Shipped**: "its obvious that we want to be able to understand kernel + metrics from within toyos ... thats an important and productive tool that + should be shipped with toyos." Every reader (`trace`, `inspect kernel.*`, + `size`) is in every image, and access is by rights alone. +- **"Keep crash records"**: ToyOS does not ask the firmware to wipe memory at + reset; crash records survive a reset in RAM + (`issues/boot-media/the-loader-never-sets-the-firmwares-memory-overwrite-request.md`, + `issues/boot-media/a-memory-overwrite-request-ubuntu-left-set-stays-set-under-toyos.md`). +- **"Only with permission"**: reading counters takes a right. The revealing + ones (power, frequency, per-device interrupt counts and per-CPU wake counts) + take the strict diary (`trace`) right. Admin tools hold it; toybox does not. +- **"General counters"**: the firmware-interrupt (`MSR_SMI_COUNT`) reading of + stage 1 of + `issues/kernel/toyos-runs-the-machine-in-acpi-mode-and-interprets-its-aml.md` + is built as the first piece of the general counters, not as a one-off check. +- **"Always on"**: the shipped kernel records a system call that runs over the + threshold in the diary, with its number and its program. +- **Symbols, "adopt"**: the kernel names only itself. A killed program is + reported as file and offset, and userland names it. The kernel keeps its + own ELF reader (`toyos-elf`). + +Every answer to "where does this run" is ToyOS: the decoder, the reducers, the +symbolizer and every tool run inside ToyOS, and nothing in the build, the tests +or the reading of a record rests on another machine. Linux's readings of the +T14 are oracles recorded as data +(`issues/hardware/linuxs-readings-of-the-t14-and-the-tcg-model-lack-reads-owed-before-the-t14s-wipe.md`). + +## The architecture (proposal accepted, 2026-10-03, with the roast's changes) + +Four kinds of answer, four places, and no pillar keeps a store of its own: +words go to the **log**, events to the **diary** (the trace ring), numbers +about now to **counters**, the Process object and `inspect`, and static facts +to the ELF files. The kernel records, stamps and counts; userland reduces, +symbolizes and renders. No kernel thread writes a record: the thread or +interrupt that caused it does. + +| Pillar | Where it lives | Its track | +|---|---|---| +| Log | the kernel's ring and each program's ring, read by `logkeeper` | `issues/kernel/logging-records-from-every-producer-and-a-kernel-that-waits-on-nobody.md`; the sinks half of `issues/design-debt/redesign-the-log-subsystem.md` | +| Diary | per-CPU rings of 32-byte slots, `SYS_TRACE_READ`, the `trace` tool | `issues/diagnostics/nothing-in-the-machine-can-read-the-trace-ring.md` | +| Counters | one table declared once in `toyos-abi`, per-CPU software words and a per-CPU hardware block | this file | +| Profile | samples are diary records; the sampler is the hard-lockup detector's | behind the diary's judgement; `issues/hardware/a-frozen-toyos-waits-for-a-hand-on-the-power-button.md` arms it every boot | +| Accounting | the Process object (`SYS_PROCESS_STATS`) and the roster | `issues/kernel/nothing-charges-kernel-memory-to-a-process.md`, `issues/kernel/a-processs-memory-is-a-byte-total-that-reads-zero-under-contention.md`, `issues/diagnostics/blocked-time-is-invisible-while-the-park-lasts.md` | +| Inspect | one root per owner over its connector; `kernel.*` from counters, `supervisor.*` from the program table | `issues/diagnostics/the-kernel-keeps-nothing-it-enumerates.md` | +| Sizes | a pure crate over `toyos-elf` behind a toybox `size` applet, and the same crate in `--ci host` | this file | +| Post-mortem | one reset-surviving region holding the black box, the previous boot's log and later its diary | the log's step 1, the diary, this file | +| Symbols | userland names user addresses; the kernel names only its own | `issues/kernel/the-kernel-still-parses-what-userland-writes.md` Move 3, `issues/build/debug-true-produces-no-debug-info.md` | + +Shared foundations, which every pillar's track obeys: + +- **One clock.** Every stamp is the CPU's free-running counter (TSC, + `CNTVCT_EL0`); binary records carry raw ticks, text carries nanoseconds by + `toyos-abi/src/clock.rs`'s formula; a persisted region's header carries the + clock words. +- **One identity.** pid and tid (`issues/diagnostics/a-record-cannot-name-thread-zero.md`); + the CPU is implied by the ring; a pid is never authority. +- **One vocabulary per stream, in `toyos-abi`.** A persisted region carries the + vocabulary itself, not a digest of it. A program's events are keyed records + in its own log ring, their keys the program's own and opaque to a decoder + that does not know them. +- **Two reader shapes.** A tap (log, diary): many readers, each its own + position; a read names one stream and a `u64` position, and the kernel clamps + it and computes loss saturating, never taking a count from the caller. A + queue (a program's ring read by `logkeeper`): one reader, and a full ring + refuses and counts. +- **One right per kind of disclosure**, each right's doc listing what it + discloses: `log`, `trace` (every schedule, syscall numbers and durations, + input timing through interrupt drains, sampled addresses, and the revealing + counters), `counters`, roster, inventory, Process `READ`, and one connector + per server. `ps` stays on `SYS_SYSINFO`'s ambient header, and no toybox + applet gains a right before per-applet rows exist + (`issues/isolation/one-manifest-row-grants-every-applet-and-one-is-compared.md`). +- **One decoder crate**, pure, `no_std` with `alloc`, forbidding unsafe: the + diary, persisted bytes and counter deltas, with its reducers checked on the + host against the scheduler simulator (`kernel/sim/src/latency.rs`). The log + stays with `toyos-logstream`; `ps` and `stats` link neither. +- **One reset-surviving region**, which absorbs the black box under one + header: the writer's identity and kernel build-id, the clock words, the + vocabulary, a previous and a current half. The previous boot's bytes are + handed out raw and decoded in userland as untrusted input. +- **One sampler per CPU**: the PMU-overflow NMI the hard-lockup detector arms. + The profile and the detector share one counter, at one fixed rate (997 Hz) + held by a profile handle and reverted when it closes. The NMI writes only + per-CPU words and a staging array its own CPU moves into the diary at its + next kernel exit; it never writes a ring and never dereferences a thread. A + Ring 3 sample raises a self-IPI so its user call chain is walked from the + sample's own stack. The boot deadline's seal names each CPU's last `rip` + from the Ring 0 timer frame. +- **One cross-CPU request vector per architecture**, carrying kicks, counter + requests and the self-IPI; the timer's vector means expiry only. A + counter request is served by the requester on its own CPU, which then parks + on a Watch the last answer posts, under a bound; a CPU silent at the bound + is reported stale, never waited on without a bound and never a panic. +- **Counters are monotonic counts and alloc/free pairs only.** A maximum is + an over-threshold diary record. A hardware counter is read only where a pure + function of the CPU's vendor, family and model says it exists, and every + counter it admits is read on each CPU at bring-up, so a wrong verdict ends + the boot rather than a user's read. +- **"Now" stays "now".** `inspect` and counters answer now; the log and the + diary answer what happened. A list of processes or modules is a paged read, + and a module record is written at an executable file mapping. + +## What is to be built, in order + +Lane A, what the latency work +(`issues/kernel/toyos-beats-linuxs-latency-on-the-t14.md`) needs: the +diary's tid 0 and the NMI `rflags` defect +(`issues/kernel/the-nmi-entry-can-hand-the-lockup-sample-cs-for-rflags-and-no-test-reds.md`) +ahead of the step that reads them; then the counters with their right, the +request vector and the kick moved onto it, whose T14 exit is that in legacy +mode the SMI count rises alike on every CPU, and through which ACPI stage 1 +reads its flatness; then interrupts on in syscalls; then the diary's three +steps and their judgement. Lane B, behind the judgement: the profile, call +chains, the remaining record kinds (waker-to-woken records before usbd). Lane +C, beside them: the rest of the counters (RAPL, C-state residency, thermal), +the log's steps, the accounting fixes, the `inspect` roots, and `size`. + +**Exit**: every pillar track above is closed, and at a ToyOS shell on the T14 +`inspect kernel.*`, `trace` and `size` answer, each under the right its +manifest row names. diff --git a/issues/filesystem/where-everything-lives.md b/issues/filesystem/where-everything-lives.md index 9fa3b2de22f..01bf18711c7 100644 --- a/issues/filesystem/where-everything-lives.md +++ b/issues/filesystem/where-everything-lives.md @@ -24,7 +24,7 @@ may reach it. Every line below is the owner's ruling. /home/ Desktop Documents Downloads Music Pictures Videos Fonts Apps// /boot bootloader, kernel, kernel arguments; the updater's alone /log /media logs; foreign volumes, one /media/