From 94d40dadeddfb40cd4fd237294037a562405a2c2 Mon Sep 17 00:00:00 2001 From: salmonik Date: Sun, 2 Aug 2026 01:34:58 +0200 Subject: v0.5.4: shadow backbuffer can no longer alias the framebuffer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Real-hardware scroll freeze (no exception, QEMU-clean) — the per-word push (0.5.3) did not fix it, so the wedge is upstream of the push. A QEMU slow-display simulation (new DISPLAY_STALL knob + shell 'stall' command busy-waits per display store, mimicking an uncached real-GPU framebuffer) proved the per-word push and shadow memmove are slow but finite — the shell keeps ticking, scrolls eventually complete. The freeze mechanism QEMU cannot exhibit is the shadow *landing on the framebuffer*: the heap free list spans the fb hole, so the 1.9 MB heap shadow can alias the display on machines where firmware reports the fb as ConventionalMemory — every scroll then becomes an MMIO->MMIO memcpy on an uncached framebuffer, which wedges real hardware (a stall, no fault, hence no dump). Fix: - gop::init_shadow(): allocate the shadow from the fb-aware page allocator (init_page_allocator marks fb pages used per-page), so it can never overlap the display; heap allocation kept only as a fallback with an explicit overlap rejection. Boot log now prints 'gop: shadow @ ... origin=page-alloc|heap|none'. - Scroll shadow memmove converted to per-word stores (belt and suspenders — immune to any future fb-aliased shadow). - Verified on QEMU: shadow @ 0x100000 vs fb 0x80000000..0x801d5000, overlap=false; all 5 test suites pass; scroll completes even under the stalled-display simulation. --- CONTEXT.md | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) (limited to 'CONTEXT.md') diff --git a/CONTEXT.md b/CONTEXT.md index bf1e01f..1a1470c 100644 --- a/CONTEXT.md +++ b/CONTEXT.md @@ -113,17 +113,21 @@ Workspace version is `a.b.c` (single version for all crates): Bump the workspace version in the root `Cargo.toml` when a change of that class lands — do not leave the version to drift. Current: -`0.5.3` — the GUI era landed with 0.5.0 (graphics layer + cursor +`0.5.4` — the GUI era landed with 0.5.0 (graphics layer + cursor compositor); 0.5.1 fixed the canvas at 800×600; 0.5.2 added fault diagnostics (screen + serial dumps for every CPU exception) and real-hardware hardening (framebuffer-size clamping, fb-region exclusion -from the allocators, authoritative fb geometry logging); 0.5.3 fixed -the real-hardware scroll wedge — the scroll's full-frame push is now -per-word volatile stores like the boot-time `clear()` instead of one -1.92 MB rep-movsb, which can stall forever on an uncached real-GPU -framebuffer (a stall, not an exception — hence no crash dump). A -future major GUI overhaul (graphics windows beyond the text surface) -would be the `a` bump (1.0.0). +from the allocators, authoritative fb geometry logging); 0.5.3 changed +the scroll's full-frame push to per-word volatile stores like the +boot-time `clear()` instead of one 1.92 MB rep-movsb (a REP MOVS to an +uncached real-GPU framebuffer can stall forever — a stall, not an +exception — hence no crash dump); 0.5.4 allocates the shadow +backbuffer from the fb-aware page allocator (it can no longer land on +the framebuffer — the heap free list spans the fb hole, so a 1.9 MB +shadow could alias the display and turn every scroll into an MMIO→MMIO +memcpy) and converts the scroll's shadow memmove to per-word stores as +a belt-and-suspenders measure. A future major GUI overhaul (graphics +windows beyond the text surface) would be the `a` bump (1.0.0). ## Project layout @@ -562,7 +566,13 @@ Workspace of four crates, all built for the `x86_64-unknown-uefi` target: uncached real-GPU framebuffer wedged the CPU on some hardware (a stall, not an exception — no dump fired), while the boot-time `clear()` — the same per-word pattern — always worked. QEMU's - RAM-backed framebuffer never showed it. + RAM-backed framebuffer never showed it. **The shadow itself is + allocated from the fb-aware page allocator (0.5.4)** so it can + never land on the framebuffer: the heap's free list spans the fb + hole, so a 1.9 MB heap shadow could alias the display, making + every scroll an MMIO→MMIO memcpy that wedges real hardware. The + scroll's shadow memmove is also per-word stores (0.5.4) as a + belt-and-suspenders guard against any future fb-aliased shadow. 2. deferred scroll batching (`vt::PENDING_SCROLLS`): the logical grid scrolls instantly in RAM while the framebuffer shift+push is deferred; N pending scrolls cost one push. Bursts of streaming -- cgit v1.2.3