From 231d33b65fbd5080dec1f1391c0f9f5b12f412c2 Mon Sep 17 00:00:00 2001 From: japabu Date: Wed, 11 Nov 2026 02:34:46 +0200 Subject: [PATCH 1/3] issues: what the kernel still holds, by responsibility, at 9349705ce The small-kernel track gains an inventory of kernel/src (215 files, 55,378 lines) by area, what the manual assigns to userland and is still in the kernel with its size and dependents, a proposed ranking of the next removals with their ordering against #1200, and dead or stale code found on the way. No code changes. Co-Authored-By: Claude Fable 5.2 --- ...-small-interrupts-post-and-threads-wait.md | 109 ++++++++++++++++++ 1 file changed, 109 insertions(+) diff --git a/issues/the-kernel-is-small-interrupts-post-and-threads-wait.md b/issues/the-kernel-is-small-interrupts-post-and-threads-wait.md index 3404660c79c..01ec8753821 100644 --- a/issues/the-kernel-is-small-interrupts-post-and-threads-wait.md +++ b/issues/the-kernel-is-small-interrupts-post-and-threads-wait.md @@ -327,6 +327,115 @@ Beside that order, each waiting on something outside it: `a_stream_truncated_at_any_offset_resyncs_within_two_packets`. **Done** (#899). +## What the kernel still holds + +An inventory at `9349705ce` (main, 2026-11-10): `git ls-files +'kernel/src/*.rs'` is 215 files and 55,378 lines by `wc -l`. Each file is +counted once, in the area of its main responsibility. "Kept" is the manual's +kernel page read against the code; the notes say where that reading is an +inference. Nothing here is ruled, and the ranking is a proposal. + +| Area | Files | Lines | Kept by the design | +|---|---|---|---| +| Memory: page tables, address spaces, frames, heap, TLB, user copies, shared memory | 27 | 7,975 | yes | +| CPU bring-up, per-CPU state, control registers, microcode, FPU state, the boot handoff | 24 | 6,304 | yes | +| IOMMU: VT-d, AMD-Vi, SMMUv3, domains, faults | 19 | 6,126 | yes | +| Objects, handles and IPC: pipes, messages, ports, namespaces, events, inboxes, the watch | 22 | 5,751 | yes, but the TTY mark and the file-shaped `SYS_FSTAT` (below) | +| Device claims: PCI enumeration, config space, MSI, BARs, hot-plug, `isa` rows, the framebuffer | 18 | 5,585 | yes, but the OpRegion window (below) | +| Interrupt controllers, vectors, traps | 10 | 3,970 | yes | +| Log ring, console UART, panic console, panic capture, own symbols | 17 | 3,517 | yes | +| Scheduling: the core's driver, context switch, idle states, jobs, preemption | 20 | 3,160 | yes | +| Firmware tables, ACPI mode, reset and power-off, the machine's stop, what the loader named | 12 | 3,099 | yes for the tables, the `acpi` row and power; the rest below | +| Processes, threads, spawn | 8 | 2,736 | yes, less the userland text a spawn carries (below) | +| Clocks: TSC and generic timer, the wall clock, typed durations | 7 | 1,847 | the clock yes; the manual names no CMOS driver | +| Counters, the diary, IRQ census, mask windows, boot deadline, hard lockup, chipset watchdog | 14 | 1,844 | counters and diary yes; the three bounds are unnamed there and inferred to be the kernel's, since they bound the kernel | +| Paged objects and their pager calls | 2 | 1,325 | yes | +| Syscall entry and argument decode | 3 | 806 | yes | +| Test-only: actuators, `SYS_DEBUG`, the IOMMU test device, the log storm | 6 | 668 | behind `boot-actuators` or `test-actuators` | +| Locks, seqlock, hasher, random | 6 | 665 | yes | + +The kernel also links the crates beside it, whose lines carry their host +tests: `kernel/pure` (49 files, 26,108, the scheduler core 15,570 of it), +`kernel/proclife` (3,550), `kernel/pci` (2,211), `kernel/smmu` (1,463), +`kernel/its` (985), `kernel/amdvi` (902) and four under 200. `kernel/sim` +(10,242) and `kernel/loom` (6,088) are harnesses no kernel links. + +Observed: no filesystem, storage, input, network, audio or USB driver, no +ELF or AML parser and no virtio is left in `kernel/src`. What it parses is +firmware's static tables (`toyos-acpi`), the build's own table +(`toyos-kimage`), the vendor's microcode container, and, below, a UEFI +device path. + +### Userland's, by the manual, and still here + +Sizes are of `kernel/src` and read off the functions, so estimates but for +the first. + +| What | Size | Dependents | Owner in the design, and what blocks it | +|---|---|---|---| +| A child's arguments and environment | about 140, by #1200's count | std, libc, `toyos::startup` | the parent's startup block: #1200 | +| Endowment labels: a blob per process for its life, answered by `SYS_ENDOWMENTS`, of which the kernel reads three (`JOB_LABEL`, `SELF_LABEL`, `QUIT_LABEL`) | ~130 | `toyos::endow`, the supervisor's table | the startup block (inferred, and #1200's record says so); needs the child's handle numbers known to its parent and the three kernel-read labels as typed spawn fields; after #1200 | +| The path a program was read from, up to 64 KiB of text per process, which a crash's frames and the spawn's log lines name | ~40 | `symbolize`, `lib/symbols` | userland, once a frame is named by build-id and something maps a build-id to a file; unbuilt | +| The TTY mark on a pipe end (`SYS_MARK_TTY`, `FileType::Tty`) | ~40 | std's spawn, libc's `isatty` and stdio, std's stdio | a fact about a stream that only libc and std read; a label or the block could carry it (inferred); after the labels | +| The main thread's stack: 8 MiB and a guard the kernel chooses and reserves | ~30 | `SYS_STACK_INFO`, which only a guest test calls | the parent's layout, as a thread's stack already is its process's (inferred); after #1200, when a child's stack starts empty | +| What the loader named: partition GUIDs by role, in the inventory, and the boot sources `SYS_BOOT_SOURCES` answers, whose device paths `loaded.rs` parses (`toyos-devicepath`) only to refuse the loader's own bytes | ~95, and the kernel's link to a 324-line parser | the supervisor, `toyos::syscap`, the manifest's inventory reader | the supervisor's, handed as a read-only boot image as ROOT is (inferred); the manual says a partition GUID is never the kernel's; blocked on nothing | +| The IGD OpRegion window: `SYS_DEVICE_FIRMWARE_WINDOW` reads Intel graphics' `ASLS` and maps what it names | ~90 and ~30 of `pcidev` | tgl-display, the supervisor, the manifest | device-specific knowledge in the kernel; a window of firmware memory the ACPI service names for a claim would be generic (inferred); needs a design | +| The supervisor's last words, userland text written into the kernel's ring (`SYS_LOG_LAST_WORDS`) | ~20 | the supervisor | the manual says userland output never enters the kernel ring; this is its one exception, and the manual does not name it | + +Kept by the manual's text, where a second reading is the owner's: +namespaces are kernel objects (~215 lines with their three calls) while the +overview keeps service lookup out of the kernel; the stop's quiesce +(`quiesce.rs`, the stop half of `syscall/machine.rs`, `toyos-quiesce`, ~330 +and 294) stops every userland thread in the kernel while the supervisor owns +the orderly stop; and x86-64 drives the CMOS clock and its IRQ8 (285) while +the loader hands firmware's `GetTime` on both architectures and only AArch64 +reads it. The CMOS is also the TSC's reference (`clocksource.rs`); whether +that needs it is not investigated. + +### The next removals, ranked (a proposal) + +By mechanisms eliminated: + +1. #1200: `SYS_GET_ENV`, the environment kept per process, the kernel's + write onto a child's stack. +2. Endowment labels, after #1200: `SYS_ENDOWMENTS`, the per-process blob + and its charge, and label text the kernel compares. +3. The path, after #1200 gives the process a name of its own: the last + 64 KiB string a spawn copies, and with it the 132 KiB a thread is charged + for two such strings (below). +4. What the loader named, independent of the others: `SYS_BOOT_SOURCES`, + the inventory's partition records, the device-path parser. +5. The TTY mark, with or after 2: `SYS_MARK_TTY`. It meets + `issues/a-received-handle-has-no-knowable-type.md`, which wants + `SYS_FSTAT` to answer more, so the two are designed together. +6. The main thread's stack, after #1200: `SYS_STACK_INFO` and the kernel's + two stack constants. + +By lines: none of these is large. Together they are about 590 of 55,378; +what the manual assigns to userland is nearly out. The larger numbers are +the three second readings above (about 830 together) and need the owner +before any is work, and the OpRegion window needs a design first. + +### Dead or nearly so, recorded and not deleted + +- `SYS_STACK_INFO` is called by `tests/guest/rust-tests/src/bin/std_threads.rs` + alone, and `SYS_VM_DECOMMIT` by two guest tests alone (`mmap_stress`, + `starveling`). +- `KernelArgs::boot_partition_start_lba` and `boot_partition_blocks` are + read by one log line (`kernel/src/main.rs`), and `wall_clock_*` by no + x86-64 code. +- `KernelStack::heap` (`kernel/src/loader/start.rs`) charges every thread + two strings at 64 KiB and a page, "as a rename's paths"; no call takes + two strings since the file calls went, and after #1200 the spawn's path + is the one string of that bound. +- `FileType::File`, `Directory` and `Symlink` are answered by no kernel path + and named by nothing in `sdk`, `system`, `lib` or `apps`; the kernel's + `Stat` answers `mtime`, `volume` and `node` as zero for every object. +- Stale text: `kernel/Cargo.toml`'s description says "filesystem"; + `kernel/CLAUDE.md`'s first caveat is about a filesystem on the idle path; + `quiesce.rs`'s header speaks of the block layer and a USB stop, neither + of which the kernel has. + ## Standing No device wait, spin or poll happens while holding a spinlock or inside a From f9186fb747238806b527a9b95de6310bc3313c32 Mon Sep 17 00:00:00 2001 From: japabu Date: Wed, 11 Nov 2026 02:55:45 +0200 Subject: [PATCH 2/3] issues: the inventory says which labels the kernel compares and which two strings a spawn copies today Co-Authored-By: Claude Fable 5.2 --- ...he-kernel-is-small-interrupts-post-and-threads-wait.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/issues/the-kernel-is-small-interrupts-post-and-threads-wait.md b/issues/the-kernel-is-small-interrupts-post-and-threads-wait.md index 01ec8753821..c6633d69a90 100644 --- a/issues/the-kernel-is-small-interrupts-post-and-threads-wait.md +++ b/issues/the-kernel-is-small-interrupts-post-and-threads-wait.md @@ -374,7 +374,7 @@ the first. | What | Size | Dependents | Owner in the design, and what blocks it | |---|---|---|---| | A child's arguments and environment | about 140, by #1200's count | std, libc, `toyos::startup` | the parent's startup block: #1200 | -| Endowment labels: a blob per process for its life, answered by `SYS_ENDOWMENTS`, of which the kernel reads three (`JOB_LABEL`, `SELF_LABEL`, `QUIT_LABEL`) | ~130 | `toyos::endow`, the supervisor's table | the startup block (inferred, and #1200's record says so); needs the child's handle numbers known to its parent and the three kernel-read labels as typed spawn fields; after #1200 | +| Endowment labels: a blob per process for its life, answered by `SYS_ENDOWMENTS`, of which the kernel compares three (`JOB_LABEL`, `SELF_LABEL`, `QUIT_LABEL`) and writes three more for the supervisor | ~130 | `toyos::endow`, the supervisor's table | the startup block (inferred, and #1200's record says so); needs the child's handle numbers known to its parent and the three kernel-read labels as typed spawn fields; after #1200 | | The path a program was read from, up to 64 KiB of text per process, which a crash's frames and the spawn's log lines name | ~40 | `symbolize`, `lib/symbols` | userland, once a frame is named by build-id and something maps a build-id to a file; unbuilt | | The TTY mark on a pipe end (`SYS_MARK_TTY`, `FileType::Tty`) | ~40 | std's spawn, libc's `isatty` and stdio, std's stdio | a fact about a stream that only libc and std read; a label or the block could carry it (inferred); after the labels | | The main thread's stack: 8 MiB and a guard the kernel chooses and reserves | ~30 | `SYS_STACK_INFO`, which only a guest test calls | the parent's layout, as a thread's stack already is its process's (inferred); after #1200, when a child's stack starts empty | @@ -425,9 +425,9 @@ before any is work, and the OpRegion window needs a design first. read by one log line (`kernel/src/main.rs`), and `wall_clock_*` by no x86-64 code. - `KernelStack::heap` (`kernel/src/loader/start.rs`) charges every thread - two strings at 64 KiB and a page, "as a rename's paths"; no call takes - two strings since the file calls went, and after #1200 the spawn's path - is the one string of that bound. + two strings at 64 KiB and a page, "as a rename's paths". No rename is + left; a spawn's path and arguments are the two strings today, and after + #1200 its path is the one string of that bound. - `FileType::File`, `Directory` and `Symlink` are answered by no kernel path and named by nothing in `sdk`, `system`, `lib` or `apps`; the kernel's `Stat` answers `mtime`, `volume` and `node` as zero for every object. From 89ead046ad8fe93082159df8a3f7b7e61828e643 Mon Sep 17 00:00:00 2001 From: japabu Date: Wed, 11 Nov 2026 03:17:55 +0200 Subject: [PATCH 3/3] Review r1 of #1208: the inventory says "the design", and four readings leave it for records of their own The section cites the design and never the manual. The program's path moves out of the userland-by-design table into a set of design changes, labelled inferred, and out of the ranked order. The CMOS driver points at its existing defect, which gains the clock's use of the RTC's edges as a TSC reference. Namespaces, the stop's sweep and the quit's walk are each a finding the orchestrator resolves. FileType's three file kinds are reused by the file protocol's clients, not dead; one 64 KiB string stays charged while SYS_NAMESPACE_OPEN's name is unbounded; kernel/copies is a harness; the line sums say which rows they add; two more stale texts are listed. Co-Authored-By: Claude Fable 5.2 --- ...ervice-lookup-is-kept-out-of-the-kernel.md | 30 ++++++ ...-who-is-asked-to-quit-and-who-is-killed.md | 26 +++++ ...-small-interrupts-post-and-threads-wait.md | 94 +++++++++++-------- ...-thread-at-a-stop-the-supervisor-orders.md | 31 ++++++ ...-wall-clock-the-loader-already-hands-it.md | 7 ++ 5 files changed, 147 insertions(+), 41 deletions(-) create mode 100644 issues/a-namespace-is-a-kernel-object-and-service-lookup-is-kept-out-of-the-kernel.md create mode 100644 issues/the-kernel-decides-who-is-asked-to-quit-and-who-is-killed.md create mode 100644 issues/the-kernel-stops-every-userland-thread-at-a-stop-the-supervisor-orders.md diff --git a/issues/a-namespace-is-a-kernel-object-and-service-lookup-is-kept-out-of-the-kernel.md b/issues/a-namespace-is-a-kernel-object-and-service-lookup-is-kept-out-of-the-kernel.md new file mode 100644 index 00000000000..c82c3e4441b --- /dev/null +++ b/issues/a-namespace-is-a-kernel-object-and-service-lookup-is-kept-out-of-the-kernel.md @@ -0,0 +1,30 @@ +--- +status: open +kind: finding +opened: 2026-11-11 +--- + +# A namespace is a kernel object, and service lookup is kept out of the kernel + +An open design question, the orchestrator's to resolve. Found by the +inventory in +`issues/the-kernel-is-small-interrupts-post-and-threads-wait.md`. + +The kernel holds a table of service names to connectors per namespace +(`kernel/src/object/namespace.rs`) and three calls over it, +`SYS_NAMESPACE_BUILD`, `SYS_NAMESPACE_OPEN` and `SYS_NAMESPACE_NAMES` +(`kernel/src/syscall/ipc.rs`), about 215 lines: it copies name text of up +to 64 KiB (`SYS_NAMESPACE_OPEN`, through `user_str`), compares it and lists +it. The design keeps a namespace as an immutable kernel object and, in its +statement of what stays out of the kernel, names service lookup. Both +cannot be the whole truth of this code. + +The two readings: the object is the mechanism and "lookup" means a global +registry, which the kernel has none of, so nothing moves; or name text is +userland's, a process is endowed connectors and its parent's library maps +names to them, and the kernel's table and three calls go. The second is an +inference, not a design anyone wrote. + +**Exit**: one reading is chosen and the design says it in one place; under +the first this file is deleted, under the second it becomes a stage of the +track. diff --git a/issues/the-kernel-decides-who-is-asked-to-quit-and-who-is-killed.md b/issues/the-kernel-decides-who-is-asked-to-quit-and-who-is-killed.md new file mode 100644 index 00000000000..2a002a7e8ca --- /dev/null +++ b/issues/the-kernel-decides-who-is-asked-to-quit-and-who-is-killed.md @@ -0,0 +1,26 @@ +--- +status: open +kind: finding +opened: 2026-11-11 +--- + +# The kernel decides who is asked to quit and who is killed + +An open design question, the orchestrator's to resolve, and an inference: +raised by the review of #1208, of the inventory in +`issues/the-kernel-is-small-interrupts-post-and-threads-wait.md`. + +`SYS_PROCESS_QUIT` walks the subtree in the kernel, puts the reason in the +notice of each process that listens and kills each that does not +(`kernel/proclife/src/quit.rs`, 216 lines; `quit_process` in +`kernel/src/process.rs`; `kernel/src/object/notice.rs`, 61). The design +reads both ways: quitting gracefully is the parent's job, and interrupt, +hang-up and terminate requests are native events a program receives. Under +the first a parent would ask its children over its own protocol and the +kernel would keep only the kill; under the second the kernel's walk is the +mechanism those events need. +`issues/a-childs-end-is-an-event-and-a-parent-takes-its-children-down.md` +built it as its stage 6. + +**Exit**: the design says which reading holds; this file is deleted, or the +walk's removal becomes a stage of the track. diff --git a/issues/the-kernel-is-small-interrupts-post-and-threads-wait.md b/issues/the-kernel-is-small-interrupts-post-and-threads-wait.md index c6633d69a90..bdc61b600ec 100644 --- a/issues/the-kernel-is-small-interrupts-post-and-threads-wait.md +++ b/issues/the-kernel-is-small-interrupts-post-and-threads-wait.md @@ -331,24 +331,24 @@ Beside that order, each waiting on something outside it: An inventory at `9349705ce` (main, 2026-11-10): `git ls-files 'kernel/src/*.rs'` is 215 files and 55,378 lines by `wc -l`. Each file is -counted once, in the area of its main responsibility. "Kept" is the manual's -kernel page read against the code; the notes say where that reading is an -inference. Nothing here is ruled, and the ranking is a proposal. +counted once, in the area of its main responsibility. "Kept" is the design +read against the code; "inferred" marks a reading the design does not +state. Nothing here is ruled, and the ranking is a proposal. | Area | Files | Lines | Kept by the design | |---|---|---|---| | Memory: page tables, address spaces, frames, heap, TLB, user copies, shared memory | 27 | 7,975 | yes | | CPU bring-up, per-CPU state, control registers, microcode, FPU state, the boot handoff | 24 | 6,304 | yes | | IOMMU: VT-d, AMD-Vi, SMMUv3, domains, faults | 19 | 6,126 | yes | -| Objects, handles and IPC: pipes, messages, ports, namespaces, events, inboxes, the watch | 22 | 5,751 | yes, but the TTY mark and the file-shaped `SYS_FSTAT` (below) | -| Device claims: PCI enumeration, config space, MSI, BARs, hot-plug, `isa` rows, the framebuffer | 18 | 5,585 | yes, but the OpRegion window (below) | +| Objects, handles and IPC: pipes, messages, ports, namespaces, events, inboxes, the watch | 22 | 5,751 | yes, but the TTY mark (below) | +| Device claims: PCI enumeration, config space, MSI, BARs, hot-plug, `isa` rows, the framebuffer | 18 | 5,585 | yes, but the OpRegion's lookup (below) | | Interrupt controllers, vectors, traps | 10 | 3,970 | yes | | Log ring, console UART, panic console, panic capture, own symbols | 17 | 3,517 | yes | | Scheduling: the core's driver, context switch, idle states, jobs, preemption | 20 | 3,160 | yes | | Firmware tables, ACPI mode, reset and power-off, the machine's stop, what the loader named | 12 | 3,099 | yes for the tables, the `acpi` row and power; the rest below | | Processes, threads, spawn | 8 | 2,736 | yes, less the userland text a spawn carries (below) | -| Clocks: TSC and generic timer, the wall clock, typed durations | 7 | 1,847 | the clock yes; the manual names no CMOS driver | -| Counters, the diary, IRQ census, mask windows, boot deadline, hard lockup, chipset watchdog | 14 | 1,844 | counters and diary yes; the three bounds are unnamed there and inferred to be the kernel's, since they bound the kernel | +| Clocks: TSC and generic timer, the wall clock, typed durations | 7 | 1,847 | the clock yes; the CMOS driver is a recorded defect (below) | +| Counters, the diary, IRQ census, mask windows, boot deadline, hard lockup, chipset watchdog | 14 | 1,844 | counters and diary yes; the three bounds are unnamed and inferred to be the kernel's, since they bound the kernel | | Paged objects and their pager calls | 2 | 1,325 | yes | | Syscall entry and argument decode | 3 | 806 | yes | | Test-only: actuators, `SYS_DEBUG`, the IOMMU test device, the log storm | 6 | 668 | behind `boot-actuators` or `test-actuators` | @@ -357,8 +357,9 @@ inference. Nothing here is ruled, and the ranking is a proposal. The kernel also links the crates beside it, whose lines carry their host tests: `kernel/pure` (49 files, 26,108, the scheduler core 15,570 of it), `kernel/proclife` (3,550), `kernel/pci` (2,211), `kernel/smmu` (1,463), -`kernel/its` (985), `kernel/amdvi` (902) and four under 200. `kernel/sim` -(10,242) and `kernel/loom` (6,088) are harnesses no kernel links. +`kernel/its` (985), `kernel/amdvi` (902) and three under 200. `kernel/sim` +(10,242), `kernel/loom` (6,088) and `kernel/copies` (73) are harnesses no +kernel links. Observed: no filesystem, storage, input, network, audio or USB driver, no ELF or AML parser and no virtio is left in `kernel/src`. What it parses is @@ -366,7 +367,7 @@ firmware's static tables (`toyos-acpi`), the build's own table (`toyos-kimage`), the vendor's microcode container, and, below, a UEFI device path. -### Userland's, by the manual, and still here +### Userland's, by the design, and still here Sizes are of `kernel/src` and read off the functions, so estimates but for the first. @@ -374,23 +375,29 @@ the first. | What | Size | Dependents | Owner in the design, and what blocks it | |---|---|---|---| | A child's arguments and environment | about 140, by #1200's count | std, libc, `toyos::startup` | the parent's startup block: #1200 | -| Endowment labels: a blob per process for its life, answered by `SYS_ENDOWMENTS`, of which the kernel compares three (`JOB_LABEL`, `SELF_LABEL`, `QUIT_LABEL`) and writes three more for the supervisor | ~130 | `toyos::endow`, the supervisor's table | the startup block (inferred, and #1200's record says so); needs the child's handle numbers known to its parent and the three kernel-read labels as typed spawn fields; after #1200 | -| The path a program was read from, up to 64 KiB of text per process, which a crash's frames and the spawn's log lines name | ~40 | `symbolize`, `lib/symbols` | userland, once a frame is named by build-id and something maps a build-id to a file; unbuilt | +| Endowment labels: a blob per process for its life, answered by `SYS_ENDOWMENTS`, of which the kernel compares three (`JOB_LABEL`, `SELF_LABEL`, `QUIT_LABEL`) and writes three more for the supervisor | ~130 | `toyos::endow`, the supervisor's table | the startup block (inferred); needs the child's handle numbers known to its parent and the three compared labels as typed spawn fields; after #1200 | | The TTY mark on a pipe end (`SYS_MARK_TTY`, `FileType::Tty`) | ~40 | std's spawn, libc's `isatty` and stdio, std's stdio | a fact about a stream that only libc and std read; a label or the block could carry it (inferred); after the labels | -| The main thread's stack: 8 MiB and a guard the kernel chooses and reserves | ~30 | `SYS_STACK_INFO`, which only a guest test calls | the parent's layout, as a thread's stack already is its process's (inferred); after #1200, when a child's stack starts empty | -| What the loader named: partition GUIDs by role, in the inventory, and the boot sources `SYS_BOOT_SOURCES` answers, whose device paths `loaded.rs` parses (`toyos-devicepath`) only to refuse the loader's own bytes | ~95, and the kernel's link to a 324-line parser | the supervisor, `toyos::syscap`, the manifest's inventory reader | the supervisor's, handed as a read-only boot image as ROOT is (inferred); the manual says a partition GUID is never the kernel's; blocked on nothing | -| The IGD OpRegion window: `SYS_DEVICE_FIRMWARE_WINDOW` reads Intel graphics' `ASLS` and maps what it names | ~90 and ~30 of `pcidev` | tgl-display, the supervisor, the manifest | device-specific knowledge in the kernel; a window of firmware memory the ACPI service names for a claim would be generic (inferred); needs a design | -| The supervisor's last words, userland text written into the kernel's ring (`SYS_LOG_LAST_WORDS`) | ~20 | the supervisor | the manual says userland output never enters the kernel ring; this is its one exception, and the manual does not name it | +| The main thread's stack: 8 MiB and a guard the kernel chooses and reserves | ~30 | `SYS_STACK_INFO`, which only a guest test calls | its creator's, since the design gives a thread's stack a caller-chosen size; after #1200, when a child's stack starts empty | +| What the loader named: partition GUIDs by role, in the inventory, and the boot sources `SYS_BOOT_SOURCES` answers, whose device paths `loaded.rs` parses (`toyos-devicepath`) only to refuse the loader's own bytes | ~95, and the kernel's link to a 324-line parser | the supervisor, `toyos::syscap`, the manifest's inventory reader | the design gives the kernel a typed description of what was loaded and keeps a partition GUID out of it; passing the description on unread, as a read-only boot image as ROOT is, fits both (inferred) and waits on no other change | +| The IGD OpRegion's lookup: a firmware window is a granted privilege the design keeps, but `SYS_DEVICE_FIRMWARE_WINDOW` finds it by reading Intel graphics' `ASLS` | ~90 and ~30 of `pcidev` | tgl-display, the supervisor, the manifest | the lookup is device knowledge; a window the ACPI service names for a claim would be generic (inferred); needs a design | +| The supervisor's last words, userland text written into the kernel's ring (`SYS_LOG_LAST_WORDS`) | ~20 | the supervisor | the design keeps userland output out of the kernel's ring and names no exception; this is one | -Kept by the manual's text, where a second reading is the owner's: -namespaces are kernel objects (~215 lines with their three calls) while the -overview keeps service lookup out of the kernel; the stop's quiesce -(`quiesce.rs`, the stop half of `syscall/machine.rs`, `toyos-quiesce`, ~330 -and 294) stops every userland thread in the kernel while the supervisor owns -the orderly stop; and x86-64 drives the CMOS clock and its IRQ8 (285) while -the loader hands firmware's `GetTime` on both architectures and only AArch64 -reads it. The CMOS is also the TSC's reference (`clocksource.rs`); whether -that needs it is not investigated. +Changes of the design, each inferred and none of them work until resolved: + +- **The program's path**, up to 64 KiB of text per process (~40 lines), + which the kernel writes into a killed program's report as its file. The + design reports a killed program by file, offset and build-id, so removing + the path changes that. It needs a frame named by build-id alone and + something in userland that maps a build-id to a file; neither is built. +- **Namespaces**: + `issues/a-namespace-is-a-kernel-object-and-service-lookup-is-kept-out-of-the-kernel.md`. +- **The stop's sweep of userland threads**: + `issues/the-kernel-stops-every-userland-thread-at-a-stop-the-supervisor-orders.md`. +- **The quit's walk**: + `issues/the-kernel-decides-who-is-asked-to-quit-and-who-is-killed.md`. + +Already a defect with its exit: the x86-64 CMOS driver and its IRQ8 (285 +lines), `issues/x86-64-reads-the-cmos-for-a-wall-clock-the-loader-already-hands-it.md`. ### The next removals, ranked (a proposal) @@ -400,21 +407,18 @@ By mechanisms eliminated: write onto a child's stack. 2. Endowment labels, after #1200: `SYS_ENDOWMENTS`, the per-process blob and its charge, and label text the kernel compares. -3. The path, after #1200 gives the process a name of its own: the last - 64 KiB string a spawn copies, and with it the 132 KiB a thread is charged - for two such strings (below). -4. What the loader named, independent of the others: `SYS_BOOT_SOURCES`, +3. What the loader named, independent of the others: `SYS_BOOT_SOURCES`, the inventory's partition records, the device-path parser. -5. The TTY mark, with or after 2: `SYS_MARK_TTY`. It meets +4. The TTY mark, with or after 2: `SYS_MARK_TTY`. It meets `issues/a-received-handle-has-no-knowable-type.md`, which wants `SYS_FSTAT` to answer more, so the two are designed together. -6. The main thread's stack, after #1200: `SYS_STACK_INFO` and the kernel's +5. The main thread's stack, after #1200: `SYS_STACK_INFO` and the kernel's two stack constants. -By lines: none of these is large. Together they are about 590 of 55,378; -what the manual assigns to userland is nearly out. The larger numbers are -the three second readings above (about 830 together) and need the owner -before any is work, and the OpRegion window needs a design first. +By lines: none is large. The five ranked are about 435 of 55,378; with the +OpRegion's lookup (~120, which needs a design) and the last words (~20), +the table's rows are about 575. What the design gives userland is nearly +out, and a larger number needs one of the design changes above. ### Dead or nearly so, recorded and not deleted @@ -426,15 +430,23 @@ before any is work, and the OpRegion window needs a design first. x86-64 code. - `KernelStack::heap` (`kernel/src/loader/start.rs`) charges every thread two strings at 64 KiB and a page, "as a rename's paths". No rename is - left; a spawn's path and arguments are the two strings today, and after - #1200 its path is the one string of that bound. -- `FileType::File`, `Directory` and `Symlink` are answered by no kernel path - and named by nothing in `sdk`, `system`, `lib` or `apps`; the kernel's - `Stat` answers `mtime`, `volume` and `node` as zero for every object. + left: a spawn's path and arguments are the two strings today. After #1200 + no call copies two, and one string of that bound remains for as long as + a spawn's path or `SYS_NAMESPACE_OPEN`'s name, which nothing bounds below + 64 KiB, is copied; the page is the namespace names'. +- `FileType::File`, `Directory` and `Symlink` are answered by no kernel + path: the file protocol's clients (`sdk/toyos/src/files/owner.rs`, + `sdk/libc/src/posix_io.rs`, `sdk/std/sys/fs.rs`) reuse the kernel ABI's + enum for answers the kernel never gives. The kernel's `Stat` answers + `mtime`, `volume` and `node` as zero for every object + (`issues/fstats-answer-is-declared-twice.md` owns its two declarations). - Stale text: `kernel/Cargo.toml`'s description says "filesystem"; `kernel/CLAUDE.md`'s first caveat is about a filesystem on the idle path; `quiesce.rs`'s header speaks of the block layer and a USB stop, neither - of which the kernel has. + of which the kernel has; `UserImage`'s doc comment + (`kernel/src/process.rs`) says "the file the kernel opened", and the + kernel opens none; `loaded.rs`'s header says it "interprets no path" + above a function that parses one. ## Standing diff --git a/issues/the-kernel-stops-every-userland-thread-at-a-stop-the-supervisor-orders.md b/issues/the-kernel-stops-every-userland-thread-at-a-stop-the-supervisor-orders.md new file mode 100644 index 00000000000..efdd46ec1c6 --- /dev/null +++ b/issues/the-kernel-stops-every-userland-thread-at-a-stop-the-supervisor-orders.md @@ -0,0 +1,31 @@ +--- +status: open +kind: finding +opened: 2026-11-11 +--- + +# The kernel stops every userland thread at a stop the supervisor orders + +An open design question, the orchestrator's to resolve. Found by the +inventory in +`issues/the-kernel-is-small-interrupts-post-and-threads-wait.md`. + +`SYS_SHUTDOWN` and `SYS_REBOOT` first stop every userland thread at its +next return to Ring 3 and wait for them inside a budget +(`kernel/src/quiesce.rs`, 216 lines, deciding by `toyos-quiesce`, 294, and +about 110 of `kernel/src/syscall/machine.rs`), then log the census and end +the machine. The supervisor owns the orderly stop and has already ended or +flushed what it started before it asks +(`issues/the-supervisor-is-host-tested-and-owns-the-stop.md`). The design +names the power-off as the kernel's and does not name this stop of +threads. + +What is not established is what the kernel's stop holds that the +supervisor's does not: the census is of a machine that has stopped, and the +console wire is taken from its holder. Whether a supervisor that ends its +subtree before the call makes the kernel's sweep redundant is an inference +nobody has checked against the stop's tests. + +**Exit**: what the kernel's sweep establishes that the supervisor's stop +cannot is written at `kernel/src/quiesce.rs`'s header and this file +deleted, or the sweep is removed as a stage of the track. diff --git a/issues/x86-64-reads-the-cmos-for-a-wall-clock-the-loader-already-hands-it.md b/issues/x86-64-reads-the-cmos-for-a-wall-clock-the-loader-already-hands-it.md index ecc6bae2a83..1f4cc83e719 100644 --- a/issues/x86-64-reads-the-cmos-for-a-wall-clock-the-loader-already-hands-it.md +++ b/issues/x86-64-reads-the-cmos-for-a-wall-clock-the-loader-already-hands-it.md @@ -16,6 +16,13 @@ two readers of one clock, and on x86-64 the field is written and never read. Whether the T14's firmware answers `GetTime` from the same CMOS is not measured. +The wall clock is not the CMOS driver's only reader: x86-64's clock takes +the RTC's update-ended edges, on IRQ8, as the third reference that tells a +TSC step from a stall of the chipset's counters +(`kernel/src/arch/x86_64/clocksource.rs`, `rtc::last_edge`). So the exit +below deletes the wall-clock read and the century register, and +`arch/x86_64/rtc.rs` whole only if that reference goes or moves with it. + Exit condition: x86-64 anchors on the loader's reading, and `arch/x86_64/rtc.rs`, `acpi::rtc_century_register` and their callers are deleted with it, against a metal row reading the T14's wall clock; or a