From 374ed800967f323af3f3dd39e02787f63e0c5600 Mon Sep 17 00:00:00 2001 From: Nexoniarz Date: Mon, 21 Sep 2026 21:53:08 +0200 Subject: [PATCH] plan: bring the 1.0 register up to date, and file the SMP corruption in Gate 0 The register steers everything and it had drifted. The text-layer row said the console still indexes font_data[256][16]; it has not for three commits. Half of that row is closed -- the console draws real TrueType through font_ops -- and the half that is not (deleting the cell grid) is now its own item rather than hiding behind the finished one. The font-from-disk row is restated rather than closed: the typeface is linked into the kernel on purpose, because a panic during boot has to be readable, so what is open is a *replaceable* font and not having one at all. And Gate 0 gains the row it most needs. User processes are corrupted on SMP -- zero faults across three boots at -smp 1, one/three/one at -smp 2, and it takes schinitd as well as shells. That is exactly the situation Gate 0 exists to prevent carrying into the compositor: a desktop built on a kernel that randomly corrupts processes fails indistinguishably from its own bugs. What has been ruled out is recorded with it, so the next attempt does not repeat the search. Co-Authored-By: Claude Opus 5 --- docs/plan/1.0.md | 42 +++++++++++++++++++++++++++++++++++------- 1 file changed, 35 insertions(+), 7 deletions(-) diff --git a/docs/plan/1.0.md b/docs/plan/1.0.md index 4cd07c7..bd28197 100644 --- a/docs/plan/1.0.md +++ b/docs/plan/1.0.md @@ -84,8 +84,8 @@ The galling ones. The work exists, is tested, and nothing uses it. | | Where it stopped | |---|---| -| **The text layer** | `kernel/dev/text.c` and `kernel/dev/ttf.c` are 850 lines that rasterise TrueType and draw at any pixel position. The console still indexes `font_data[256][16]`. The only caller is a self-test. | -| **A font from disk** | Same layer, same reason. The console's 8×16 CP437 grid is compiled in. | +| ~~**The text layer**~~ | **Half closed, and the half that closed is the one that mattered.** The console draws real TrueType through `font_ops` now: cells hold a codepoint, the cell size comes from the font's measured advance, and `kernel/dev/ttf.c` has a caller that is not a self-test. What is still unused is `text.c`'s *proportional* path — the console remains a fixed grid. See Gate 0. | +| **A font from disk** | Still true, and now deliberate rather than pending: the console typeface is linked into the kernel image, because a panic during boot has to be readable before there is a filesystem. Loading a *second* font from disk is the open part. | | **Socket activation** | `schinitd` parses `[Socket name]` and remembers the path. Nothing holds the socket. **This is the entire reason for copying launchd**, and it is the half that was not built. | | **`display_ops.wait_vblank`** | In the vtable, implemented by the VBE driver, left null by virtio-gpu. A compositor that needs it cannot rely on it. | @@ -191,19 +191,47 @@ right then. started reading the RTC; the comments outlived the condition. Two errors, not one — `uptime()` counts 10 ms ticks and they were used as seconds, so the clocks also ran 100× fast. +- [ ] **User processes are corrupted on SMP.** One to three per boot die with a + fault they could not have caused: `rip 0x0` — an instruction fetch at + zero, which a process does not branch to, it is handed and follows — or a + dereference of `0xffffffffffffffea`, which is `-EINVAL`. **Zero across + three boots at `-smp 1`; one, three and one at `-smp 2`.** It hits + `schinitd` as well as shells. + + This is now the most important row in Gate 0, and it is the row Gate 0 + was written for: a compositor built on a kernel that randomly corrupts + user processes will fail in ways indistinguishable from its own bugs. + + Ruled out: kernel stack depth. That was the leading theory and it was + wrong — raising `KSTACKSIZE` to 8192 changed nothing. The search was + still worth it (the high-water mark really was 3736 of 4096 bytes, and + the AP scheduler stack really was being handed a page it did not own), + but neither was this. Not yet examined: TLB coherence when a page table + is changed on one CPU while the process runs on another, `kalloc`'s free + list under contention, and the buffer cache. - [ ] **`getrusage` does not distinguish `RUSAGE_CHILDREN`** from `RUSAGE_SELF`. - [ ] **`/proc//exe` is a regular file, not a symlink**, so `readlink()` - fails and `ps -o comm` prints `[init]`. Needs symlink support in procfs. + fails and `ps -o comm` prints `[init]`. Symlinks themselves now work — + `open()` and `stat()` follow them, which they never did — so what is left + is procfs growing a symlink node type, not symlink support. - [ ] **OVMF memory reporting**, if the region-list fix did not fully close it. **Work already done and not connected:** These are the galling ones — the replacement exists, is tested, and is unused. -- [ ] **Port the console onto the text layer and delete the cell grid.** - `text.c` and `ttf.c` both exist and work. The console still indexes - `font_data[256][16]`. -- [ ] **Load a font from disk** and point the console at it. +- [x] ~~**Point the console at a real typeface.**~~ It draws JetBrains Mono + through `font_ops` and `ttf.c`. The blocker was not the font: `vtcell.ch` + was **one byte** holding a CP437 index, so `Ą` (U+0104) could not be + *stored*, whatever was drawing it. The cell is a `uint32` codepoint now + and the cell size comes from the font's measured advance. +- [ ] **Delete the cell grid.** The other half of the original item, and still + open. The console is a fixed grid of codepoints; `text.c`'s proportional + path has no caller. Nothing needs this before the compositor, which is + why it is separated from the row above rather than left blocking it. +- [ ] **Load a font from disk** and point the console at it. The built-in one + is linked in on purpose — an early panic has to be readable — so this is + about a *replaceable* font, not about having one. - [x] ~~**Interrupt-driven receive.**~~ The e1000's handler calls `netdev_rx_signal()`, which ends the network thread's wait early; the frame is still *pulled* by the thread, because an interrupt handler can neither