memory: the SMP crash is SMP-only, and what the font work cost
Two notes worth keeping out of the commit log because they are about where to start next time rather than what changed. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
d58b1cda17
commit
e577791e5e
3 changed files with 78 additions and 0 deletions
|
|
@ -52,3 +52,4 @@
|
||||||
- [Sockets and evdev](schunix-sockets-and-evdev.md) — AF_UNIX with one table lock, /dev/input/eventN, and why keycodes need a table for USB but not PS/2.
|
- [Sockets and evdev](schunix-sockets-and-evdev.md) — AF_UNIX with one table lock, /dev/input/eventN, and why keycodes need a table for USB but not PS/2.
|
||||||
- [The removed acceptance test](schunix-doom-acceptance-test.md) — deleted 2026-08-08 with its trademark references; what it found and the two techniques worth keeping.
|
- [The removed acceptance test](schunix-doom-acceptance-test.md) — deleted 2026-08-08 with its trademark references; what it found and the two techniques worth keeping.
|
||||||
- [Sharing preference](nexoniarz-sharing-preference.md) — never push or publish; unfinished work stays local.
|
- [Sharing preference](nexoniarz-sharing-preference.md) — never push or publish; unfinished work stays local.
|
||||||
|
- [SMP userspace corruption](schos-smp-userspace-corruption.md) — the intermittent `rip 0x0` crash is SMP-only and still open; what is ruled out.
|
||||||
|
|
|
||||||
43
.claude/memory/schos-smp-userspace-corruption.md
Normal file
43
.claude/memory/schos-smp-userspace-corruption.md
Normal file
|
|
@ -0,0 +1,43 @@
|
||||||
|
---
|
||||||
|
name: schos-smp-userspace-corruption
|
||||||
|
description: The intermittent "zsh jumps to rip 0" crash is SMP-only and still open — what has been ruled out, and the two facts worth starting from.
|
||||||
|
metadata:
|
||||||
|
type: project
|
||||||
|
---
|
||||||
|
|
||||||
|
Open as of 2026-09-21. Roughly one to three processes per boot die with a
|
||||||
|
user-mode fault they could not have caused themselves. It has been written off
|
||||||
|
as "one zsh in ~5 boots makes a wild jump" for a while; it is more than that.
|
||||||
|
|
||||||
|
**It is SMP-only.** Three boots at `-smp 1`: zero faults. Three at `-smp 2`:
|
||||||
|
one, three, one. This is the single most useful fact about it and it was not
|
||||||
|
known before.
|
||||||
|
|
||||||
|
**It is not only zsh.** `schinitd` has taken one too, so it is not something
|
||||||
|
about the shell.
|
||||||
|
|
||||||
|
The two signatures seen, both from `kernel/arch/x86_64/trap.c`'s extended dump
|
||||||
|
(which now fires for `rip` below a page or a faulting address near zero, not
|
||||||
|
only for GP faults):
|
||||||
|
|
||||||
|
- `trap 14 err 20 rip 0x0 addr 0x0` — an instruction fetch at zero. A process
|
||||||
|
does not branch there; it was handed a zero and followed it.
|
||||||
|
- `schinitd: trap 14 err 4 rip 0x5d7b addr 0xffffffffffffffea` — `-22`, which
|
||||||
|
is `-EINVAL`. Something returned an error and the caller used it as a
|
||||||
|
pointer.
|
||||||
|
|
||||||
|
**Ruled out: kernel stack depth.** This was the leading hypothesis and it is
|
||||||
|
wrong. Raising `KSTACKSIZE` to 8192 with static per-slot stacks did not change
|
||||||
|
the rate. The search was still worth it — the high-water mark really was 3736
|
||||||
|
of 4096 bytes in netd, 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 modified on one CPU while
|
||||||
|
the process runs on another, `kalloc`'s free list under contention, and the
|
||||||
|
buffer cache. `switchuvm()` and the `p->tf` handling were both read and look
|
||||||
|
correct — `trap()` never overwrites `p->tf`, only `syscall()` does.
|
||||||
|
|
||||||
|
Reproduce: boot `-smp 2` and count `trap 1` lines in the serial log. Six tty
|
||||||
|
shells start at once at boot, which is when it almost always happens.
|
||||||
|
|
||||||
|
Related: [[schunix-smp-and-memory-bugs]], [[schunix-console-tty]].
|
||||||
|
|
@ -84,3 +84,37 @@ is on the tested path rather than bypassed by the harness.
|
||||||
béziers. Roughly the size of everything else here, and a subtly wrong
|
béziers. Roughly the size of everything else here, and a subtly wrong
|
||||||
interpreter draws plausible-looking wrong glyphs. It plugs in as a third
|
interpreter draws plausible-looking wrong glyphs. It plugs in as a third
|
||||||
`font_ops` provider, so nothing above it changes.
|
`font_ops` provider, so nothing above it changes.
|
||||||
|
|
||||||
|
|
||||||
|
## 2026-09-21: it is the console font now
|
||||||
|
|
||||||
|
Linked into the kernel image (`consfont` in the Makefile), opened at 16 px
|
||||||
|
before `vt_init()`. Three things had to be fixed first, and two of them were
|
||||||
|
the same bug twice:
|
||||||
|
|
||||||
|
- **`ttf_render` held 21 KB of locals** on a 4096-byte kernel stack. Now
|
||||||
|
`static`, safe because every caller is serialised behind `cons.lock`.
|
||||||
|
- **`load_outline` did it again, recursively**, with a 4736-byte outline per
|
||||||
|
level. Composite glyphs are exactly Ą/Ę/Ś/Ł/Ż, so the second crash arrived
|
||||||
|
the moment the first fix let Unicode reach the screen and looked like a
|
||||||
|
fresh bug. Static outline per level, depth capped at 4 (the font's real
|
||||||
|
maximum nesting is 2), and `load_simple()` split out so the leaf's 512-byte
|
||||||
|
flag array is not multiplied by depth.
|
||||||
|
- **Component transforms were being skipped.** `'` is the comma glyph scaled
|
||||||
|
by -1 — a 180° rotation — and its offset only lands right after the
|
||||||
|
rotation. Without it the mark went 12 px into a 10 px cell and was clipped
|
||||||
|
away, so the character read as *missing from the font* rather than as
|
||||||
|
misplaced. F2Dot14 2x2 is applied now.
|
||||||
|
|
||||||
|
Neither stack bug showed in `tools/ttftest`, which has an 8 MB stack. **That is
|
||||||
|
the standing hazard of this file**: one source built for host and kernel, and
|
||||||
|
the host is most forgiving about exactly the resource the kernel is strictest
|
||||||
|
about. Check frame sizes with `llvm-objdump -d` on the kernel object, not the
|
||||||
|
host build.
|
||||||
|
|
||||||
|
The harness speaks UTF-8 now. Iterating bytes meant it could only ask for
|
||||||
|
ASCII, and ASCII is entirely simple glyphs — it could not reach the path that
|
||||||
|
mattered.
|
||||||
|
|
||||||
|
Glyph cache: 95 reserved ASCII slots plus 224 shared slots keyed by codepoint,
|
||||||
|
64 KB pool, flushed whole when it fills.
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue