<feed xmlns='http://www.w3.org/2005/Atom'>
<title>rs-dos/CONTEXT.md, branch qemu</title>
<subtitle>Simple, kernel-only, 64bit OS, early stage.
</subtitle>
<id>https://git.2137697.xyz/rs-dos/atom?h=qemu</id>
<link rel='self' href='https://git.2137697.xyz/rs-dos/atom?h=qemu'/>
<link rel='alternate' type='text/html' href='https://git.2137697.xyz/rs-dos/'/>
<updated>2026-11-01T14:53:29Z</updated>
<entry>
<title>scripts: rebuild the dev loop around build.sh/run.sh</title>
<updated>2026-11-01T14:53:29Z</updated>
<author>
<name>salmonik</name>
<email>salmonik@tuta.io</email>
</author>
<published>2026-11-01T14:53:29Z</published>
<link rel='alternate' type='text/html' href='https://git.2137697.xyz/rs-dos/commit/?id=7958276c9f0d230053520ba20f2a00f5ecda18e4'/>
<id>urn:sha1:7958276c9f0d230053520ba20f2a00f5ecda18e4</id>
<content type='text'>
`make` did not parse at all (missing separator at line 139), so every
make target was dead.  The folder also carried three overlapping
launchers (boot.sh, qemu.sh, boot-image.sh) plus a fourth partial one
in the Makefile, `cargo build --package rsdos` copy-pasted eight times,
the QEMU invocation copy-pasted per script, and the test helpers
(fail/wait_log/wait_qemu_exit/qemu_hmp) duplicated in five tests.

New layout:
- scripts/lib.sh: single config (image, OVMF, mem/smp), the one cargo
  invocation (build_all), the one QEMU shape (qemu_args), and the test
  harness (test_boot, wait_log, wait_qemu_exit, qemu_hmp, sendkeys)
- scripts/build.sh: kernel + every bins/* in one pass
- scripts/mksystem.sh: freshness-aware image build that now stages
  every bins/*.efi into /bin/cli|gui (they were never copied before)
- scripts/run.sh: build + stage + boot in one command; --headless,
  --debug (GDB stub), --monitor (HMP socket), --fresh, --mem/--smp/
  --bios/--image; on Wayland it auto-selects XWayland plus
  grab-on-hover so the mouse can be captured (Ctrl+Alt+G toggles)
- scripts/tests/: the five automated tests on the shared harness
- deleted: boot.sh, qemu.sh, boot-image.sh, lib-boot-args.sh,
  build-image-release.sh, build-bootloader.sh (rsboot chain dropped)

The Makefile is now a thin wrapper: make run, make test, make system,
make inspect, make help.  Two-command flow: ./scripts/build.sh then
./scripts/run.sh (run.sh alone also works).

Stale test assumptions fixed so the suite is green again: test-gfx
waited for "gfx: check" while the shell prints "gfx check: PASS";
test-mouse/test-msg hardcoded msgrecv = task 3 (wm-input took slot 3 —
ids are parsed from the log now); the queue-full probe targeted task 0,
whose exec pump drains its own queue as completion codes (moved to the
cursor task, which never recvs).

Verified in QEMU: make test -&gt; test-disk, test-gfx, test-mouse,
test-msg, test-fault all PASS.
</content>
</entry>
<entry>
<title>docs: ADR 0006 (executable binaries) + implementation plan + glossary terms</title>
<updated>2026-08-21T15:18:09Z</updated>
<author>
<name>salmonik</name>
<email>salmonik@tuta.io</email>
</author>
<published>2026-08-21T15:18:09Z</published>
<link rel='alternate' type='text/html' href='https://git.2137697.xyz/rs-dos/commit/?id=fc4c563ca14ddec3de3aeef5a861f9707eaae389'/>
<id>urn:sha1:fc4c563ca14ddec3de3aeef5a861f9707eaae389</id>
<content type='text'>
ADR 0006: PE32+ loader in rsnix, versioned exports-table ABI constructed
per invocation, task-per-binary, single dd-able system image with
/bin/cli and /bin/gui, shell-owned grammar with injected line streams,
per-terminal input discipline as prerequisite phase, frozen built-in
core, 0.6.0 at first exec.

Plan: five phases (image → input discipline → loader/exec → streams +
migration → GUI binaries), each with a QEMU verification gate.

Glossary: Binary, Loader, Exports table, System image; kind = launch
surface.
</content>
</entry>
<entry>
<title>Terminal-app design (ADR 0005) + disk-write controller</title>
<updated>2026-08-17T17:56:24Z</updated>
<author>
<name>salmonik</name>
<email>salmonik@tuta.io</email>
</author>
<published>2026-08-17T17:56:24Z</published>
<link rel='alternate' type='text/html' href='https://git.2137697.xyz/rs-dos/commit/?id=126d5b2e55dca93e024f5654fed6fae37a012369'/>
<id>urn:sha1:126d5b2e55dca93e024f5654fed6fae37a012369</id>
<content type='text'>
- ADR 0005: persistent home terminal (full-screen, chrome-less,
  bottom-pinned), F1 terminal windows, per-instance vt/tty/shell,
  queue-based input for all terminals, and the disk controller
- Glossary: add the Terminal term; update Task/App for the new model
- Add a re-entrant disk lock (DiskGuard over the preemption-depth
  counter) and wrap all fs/fat mutating operations per-call
</content>
</entry>
<entry>
<title>Windowed GUI: wm module, input routing, and the paint app</title>
<updated>2026-08-17T16:56:04Z</updated>
<author>
<name>salmonik</name>
<email>salmonik@tuta.io</email>
</author>
<published>2026-08-17T16:56:04Z</published>
<link rel='alternate' type='text/html' href='https://git.2137697.xyz/rs-dos/commit/?id=5558e3509d020a0e021a77f0617044497b2f2aee'/>
<id>urn:sha1:5558e3509d020a0e021a77f0617044497b2f2aee</id>
<content type='text'>
- Add the wm window-manager facility per ADR 0004: overlapping
  pixel-surface windows, damage-rectangle compositing, WM-drawn title
  bar, focus/minimize/close, and F1-F4 keybindings
- Add gop shadow compositing primitives and vt::repaint_region so the
  console stays layer 0 beneath windows
- Route mouse (absolute coords, press/release edges) and keyboard
  (focus-aware input pump) to the focused window
- Add the rspaint drawing-program crate (pen, 8 colors, clear) and shell
  draw/windows/restore commands
- Extend TaskMsg with AppMouse/Focus/Close and document the design in
  CONTEXT.md + ADR 0004
</content>
</entry>
<entry>
<title>docs: CONTEXT.md versioning — 0.5.6 backtrace dumps + 0.5.7 allocator guard</title>
<updated>2026-08-02T19:47:58Z</updated>
<author>
<name>salmonik</name>
<email>salmonik@tuta.io</email>
</author>
<published>2026-08-02T19:47:58Z</published>
<link rel='alternate' type='text/html' href='https://git.2137697.xyz/rs-dos/commit/?id=fa5b879688a4f04e0ed8966e4c1a2ce82cfacd93'/>
<id>urn:sha1:fa5b879688a4f04e0ed8966e4c1a2ce82cfacd93</id>
<content type='text'>
</content>
</entry>
<entry>
<title>v0.5.5: visible boot progress + panic-on-screen for real hardware</title>
<updated>2026-08-01T23:52:10Z</updated>
<author>
<name>salmonik</name>
<email>salmonik@tuta.io</email>
</author>
<published>2026-08-01T23:52:10Z</published>
<link rel='alternate' type='text/html' href='https://git.2137697.xyz/rs-dos/commit/?id=045c9ddf71b62dff538cd3ae1963166ab5c145a0'/>
<id>urn:sha1:045c9ddf71b62dff538cd3ae1963166ab5c145a0</id>
<content type='text'>
Real hardware has no serial console: a pre-shell panic was a silent
blank screen (the panic handler only wrote to serial, then cli;hlt).
v0.5.4's shadow change made this window reachable — if the fb-aware
page allocation or the heap fallback failed on hardware, the kernel
halted before the shell banner with zero screen output.

- gop::boot_marker(): every boot stage now draws straight to the
  framebuffer (row 0, white-on-black).  The last marker visible before
  a hang identifies where the kernel died.
- Panic handler: pre-shell panics now draw a white-on-red
  '*** PANIC *** &lt;msg&gt; at file:line' band via gop::dump_lines.
- init_shadow(): heap fallback is panic-proof (try_reserve_exact +
  resize instead of vec![0; words] which aborts on OOM); page-alloc
  result defensively re-checked against the fb region; any failure
  degrades to no-shadow mode with a visible warning band.
- Verified: full chain (rsboot -&gt; kernel) boots with markers, shell
  banner renders, all 5 test suites pass.
</content>
</entry>
<entry>
<title>v0.5.4: shadow backbuffer can no longer alias the framebuffer</title>
<updated>2026-08-01T23:35:37Z</updated>
<author>
<name>salmonik</name>
<email>salmonik@tuta.io</email>
</author>
<published>2026-08-01T23:34:58Z</published>
<link rel='alternate' type='text/html' href='https://git.2137697.xyz/rs-dos/commit/?id=94d40dadeddfb40cd4fd237294037a562405a2c2'/>
<id>urn:sha1:94d40dadeddfb40cd4fd237294037a562405a2c2</id>
<content type='text'>
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-&gt;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 @ &lt;addr&gt; ... 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.
</content>
</entry>
<entry>
<title>rsnix v0.5.3: fix real-hardware scroll wedge — per-word display push</title>
<updated>2026-08-01T21:44:41Z</updated>
<author>
<name>salmonik</name>
<email>salmonik@tuta.io</email>
</author>
<published>2026-08-01T21:44:41Z</published>
<link rel='alternate' type='text/html' href='https://git.2137697.xyz/rs-dos/commit/?id=fffec0f04dfcc63bef39eb0441cfad7b584da484'/>
<id>urn:sha1:fffec0f04dfcc63bef39eb0441cfad7b584da484</id>
<content type='text'>
The real-hardware crash (2 lines of white + freeze, no CPU exception
even with the 0.5.2 fault dumps) pointed away from a fault and at a
stall: the scroll's full-frame push used one 1.92 MB rep-movsb to the
framebuffer.  On QEMU the framebuffer is RAM, so it flies; on a real
GPU the framebuffer is uncached MMIO and the CPU's fast-string burst
path can stall forever — the shell wedges mid-instruction, the cursor
task's own writes wedge too, no exception fires (MMIO writes don't
fault), and the screen shows the torn partial push (the white bands).

The boot-time clear() always worked on the same hardware and uses
per-word volatile stores, so the scroll push now uses the identical
pattern: shadow reads (cached RAM, cheap) + individually-posted
display stores.  Interruptible between stores, never a bulk burst,
and functionally identical on QEMU (all 5 suites re-pass).

Also converts the no-shadow fallback shift to the same per-word
pattern.  CONTEXT.md updated (scroll-cost note + versioning).
</content>
</entry>
<entry>
<title>rsnix v0.5.2: fault diagnostics + real-hardware scroll-crash hardening</title>
<updated>2026-08-01T20:28:34Z</updated>
<author>
<name>salmonik</name>
<email>salmonik@tuta.io</email>
</author>
<published>2026-08-01T20:28:34Z</published>
<link rel='alternate' type='text/html' href='https://git.2137697.xyz/rs-dos/commit/?id=ab7d87bcde31c1681ea09c30534dde840a58d6fa'/>
<id>urn:sha1:ab7d87bcde31c1681ea09c30534dde840a58d6fa</id>
<content type='text'>
The real-hardware scroll crash (white bands + instant freeze, QEMU-clean)
was invisible because the only trace was a single serial line on machines
with no serial console.  This makes every crash self-identifying and
hardens the real-hardware failure surfaces:

- Every CPU exception vector 0-31 now has an IDT entry (macro-generated
  stubs; 8/14 keep their IST stacks).  A fault in the shell prints a
  white-on-red band to the framebuffer via gop::dump_lines (raw fb
  writes bypassing the vt, fully clamped) plus a parseable serial line:
  '!!! &lt;kind&gt; vec=N err=… rip=… cr2=… rsp=… rflags=… task=N "name"',
  then halts — instead of converging to a cryptic double fault.
  Background-task faults abort the task as before.
- Boot log now reports the authoritative post-SetMode geometry:
  'gop: fb base=… size=… pitch=… WxH bpp=… bgr=…', so the next real
  machine's report identifies whether pitch*height exceeds the mapping.
- Framebuffer writes (clear, push_rect, shift_up_n bulk push, cursor
  overlay) are clamped to the firmware's framebuffer_size: a pitch-
  padded mode degrades to a truncated view instead of faulting past
  the mapping.
- The GOP framebuffer region is excluded from the page allocator (and
  subtracted from the heap's conventional-region pick) even when the
  firmware lists it as ConventionalMemory — kernel allocations can
  never overwrite the display again.  The GOP protocol is located and
  peeked before the memory map is captured so the exclusion is known
  at heap-init time.
- Shell gains a hidden 'fault' command (deliberate unmapped write) and
  'make test-fault' verifies the dump: vec=14, cr2=0x400000000000,
  task=0, halt — no triple fault.  All other suites re-pass.
- CONTEXT.md: fault-dump format documented for real-hardware reports.
</content>
</entry>
<entry>
<title>rsnix v0.5.1: force the GUI canvas to 800x600 via GOP SetMode</title>
<updated>2026-08-01T19:30:48Z</updated>
<author>
<name>salmonik</name>
<email>salmonik@tuta.io</email>
</author>
<published>2026-08-01T19:30:48Z</published>
<link rel='alternate' type='text/html' href='https://git.2137697.xyz/rs-dos/commit/?id=d9c47d52039be7a61d3e9d3652f73322fb6f47ba'/>
<id>urn:sha1:d9c47d52039be7a61d3e9d3652f73322fb6f47ba</id>
<content type='text'>
The kernel used to inherit whatever GOP mode the firmware picked
(QEMU/OVMF gave 1280x800). Now every surface derives from a fixed
800x600 canvas:

- uefi: typed EfiGopQueryMode/SetMode/GetMode fn pointers in
  GraphicsOutputProtocol (were raw *mut c_void, never called).
- gop::select_gop_mode: scan the mode list for an exact 800x600
  (32-bit BGR/RGB only, the driver assumes 4 Bpp), SetMode it; fall
  back to the smallest mode that fits the canvas, then to the
  firmware's choice. SetMode may move both the mode info pointer and
  the framebuffer base, so both are re-read after the switch. Boot
  log: 'gop: mode 3 selected — 800x600 (was 1280x800)'.
- tests: relative assertions are resolution-agnostic; test-gfx and
  test-mouse had a boot-log race (shell line prints before the cursor
  task line) — now wait for the cursor line instead of grepping once.
  All four suites pass at 800x600. 0 build warnings.
</content>
</entry>
</feed>
