<feed xmlns='http://www.w3.org/2005/Atom'>
<title>rs-dos/rsnix/src/memory.rs, 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-01T15:33:05Z</updated>
<entry>
<title>usb: real-hardware rework — hubs, both EHCI controllers, keyboard, xHCI hardening</title>
<updated>2026-11-01T15:33:05Z</updated>
<author>
<name>salmonik</name>
<email>salmonik@tuta.io</email>
</author>
<published>2026-11-01T15:33:05Z</published>
<link rel='alternate' type='text/html' href='https://git.2137697.xyz/rs-dos/commit/?id=50b4d2f0ab05901a847d8e1318152308265e579b'/>
<id>urn:sha1:50b4d2f0ab05901a847d8e1318152308265e579b</id>
<content type='text'>
EHCI (OptiPlex 7010 / Q77 and similar Intel PCH):
- enumerate *both* EHCI controllers (00:1a.0 + 00:1d.0), not just the first
- hub support: read the hub class descriptor, power/reset each port via hub
  class requests, read the child speed, then drive the child with split
  transactions carrying the hub's address and port (TT).  On 7-series PCH the
  root port presents the integrated Rate Matching Hub (8087:0024, class 9)
  and the mouse/keyboard sit behind it; without this the driver stopped at
  "no HID mouse/keyboard endpoint in config".
- HID mouse *and* keyboard, boot protocol + idle, per-device periodic QH
  chained into the frame list, per-device report buffers and counters
- periodic re-arm follows the standard shape (qTD re-activated, Next-qTD
  re-linked); the HC owns the status/toggle overlay
- DMA from the page allocator inside [16 MiB, 4 GiB): EHCI programs 32-bit
  addresses and the page bitmap spans all RAM
- 2 ms recovery after SET_ADDRESS

xHCI:
- scratchpad buffers (HCSPARAMS2) and MaxSlotsEn &gt; 1, with per-slot EP0 and
  interrupt rings plus per-slot device contexts
- DMA from the page allocator instead of the heap allocator
- boot protocol + idle, mouse + keyboard, first-report diagnostics
- transfer events are routed to every device before matching a waiter, so a
  second device's enumeration cannot swallow an armed device's report

shared:
- rsnix/src/hid.rs: HID usage -&gt; scancode-set-1 tables, one scancode FIFO
  feeding ps2::feed_scancode, per-device boot-keyboard report differ
- WM input pump polls PS/2 -&gt; UHCI -&gt; EHCI -&gt; xHCI
- memory::alloc_pages_range(count, min, max) for bounded DMA allocations

QEMU coverage: make test-usb (EHCI + xHCI, mouse + keyboard).  QEMU's EHCI
split path delivers only the first report for FS devices, so repeated-report
delivery and the RMH path remain hardware-test items.
</content>
</entry>
<entry>
<title>USB2/1.1 (EHCI/UHCI) drivers + real-hardware bring-up hardening</title>
<updated>2026-08-17T12:53:52Z</updated>
<author>
<name>salmonik</name>
<email>salmonik@tuta.io</email>
</author>
<published>2026-08-17T12:53:52Z</published>
<link rel='alternate' type='text/html' href='https://git.2137697.xyz/rs-dos/commit/?id=be868a43185826b02bf6d091019bb779678525bb'/>
<id>urn:sha1:be868a43185826b02bf6d091019bb779678525bb</id>
<content type='text'>
- Add polled EHCI (USB2) and UHCI (USB1.1) host-controller drivers with
  HID boot mouse support, wired into cursor polling and the 'usb' shell cmd
- Add USB Legacy ownership handoff (claim_usb_legacy) plus config_write_byte
- Harden boot: verify the PIT/timer ticks before shell entry, EOI stray
  interrupts in the LAPIC to stop interrupt storms, bound PS/2 controller
  waits, and INTx-disable AHCI (polled driver)
- Add boot stage markers, klog screen echo, and QR lock; scheduler
  mark_shell_running; NO_USB stopgap to keep BIOS USB-Legacy input alive
- alloc_pages_above for DMA buffers that must avoid low conventional memory
- Expand DEBUG_NOTES with EHCI/QEMU bring-up findings
</content>
</entry>
<entry>
<title>v0.5.9: fix OptiPlex heap crash — EBS retry must not rebuild the free list</title>
<updated>2026-08-03T23:44:05Z</updated>
<author>
<name>salmonik</name>
<email>salmonik@tuta.io</email>
</author>
<published>2026-08-03T23:44:05Z</published>
<link rel='alternate' type='text/html' href='https://git.2137697.xyz/rs-dos/commit/?id=3e2261d83176752f3ea21e0c97f330b4c1757437'/>
<id>urn:sha1:3e2261d83176752f3ea21e0c97f330b4c1757437</id>
<content type='text'>
Root cause: on real hardware SetMode can invalidate the pre-captured
ExitBootServices map key, so EBS fails and the retry refreshed the map
via capture_memory_map -&gt; init_heap, which REBUILT the free list from
the raw map and wiped the allocation state of every pre-EBS live object
(the display shadow and the vt grids). Their spans became free while
still live, later allocations carved inside the shadow, and the display
writes clobbered them — zeroed back-pointers (family A ptr=0x404443e0
block=0x0) and gray glyph pixels (family B 0xaaaaaa00aaaaaa = 0x00AAAAAA
= PALETTE[7] fg-7 text colour, not a firmware scrub).

Fix: refresh_and_exit now re-captures the map and returns a fresh EBS
key without rebuilding the free list (refresh_map_key); the free list is
the authoritative live-allocation state. Verified in QEMU under a forced
EBS failure (SIMULATE_EBS_FAILURE test hook): verify ok, probe NOT free,
flhead outside the shadow — identical to a clean boot, and the full
shell sequence is crash-free.

Also: removed the crash-family debug markers from the screen (boot-time
heapdbg lines, vt verify marker, shadow marker) — the vt grid self-check
stays serial-only. Version 0.5.8 -&gt; 0.5.9.
</content>
</entry>
<entry>
<title>v0.5.7: guard report else-branch initializes all mem lines (fix broken build)</title>
<updated>2026-08-02T22:22:53Z</updated>
<author>
<name>salmonik</name>
<email>salmonik@tuta.io</email>
</author>
<published>2026-08-02T22:22:53Z</published>
<link rel='alternate' type='text/html' href='https://git.2137697.xyz/rs-dos/commit/?id=ab633cef20d35b9231fbbebc1a6fff3662968c03'/>
<id>urn:sha1:ab633cef20d35b9231fbbebc1a6fff3662968c03</id>
<content type='text'>
</content>
</entry>
<entry>
<title>v0.5.7: fix unused-init warning in guard report</title>
<updated>2026-08-02T22:22:12Z</updated>
<author>
<name>salmonik</name>
<email>salmonik@tuta.io</email>
</author>
<published>2026-08-02T22:22:12Z</published>
<link rel='alternate' type='text/html' href='https://git.2137697.xyz/rs-dos/commit/?id=9170484301338d5993bb9198ad54b517a583c38a'/>
<id>urn:sha1:9170484301338d5993bb9198ad54b517a583c38a</id>
<content type='text'>
</content>
</entry>
<entry>
<title>v0.5.7: guard dumps block-header math + 16-word window; vt content verify; shadow marker</title>
<updated>2026-08-02T22:21:52Z</updated>
<author>
<name>salmonik</name>
<email>salmonik@tuta.io</email>
</author>
<published>2026-08-02T22:21:52Z</published>
<link rel='alternate' type='text/html' href='https://git.2137697.xyz/rs-dos/commit/?id=834b931d068a9a76e2c2a85267f24a22e93276cf'/>
<id>urn:sha1:834b931d068a9a76e2c2a85267f24a22e93276cf</id>
<content type='text'>
The klog -t 2 crash drops a 126-byte String (the vt verify klog line)
whose data ptr 0x40444970 points into the first-heap-block region whose
content is the firmware 0x00AAAAAA scrub — a stale pointer, not a real
allocation (back-pointer slot never written).  Upgrades so the next
real-hardware crash shows the full picture:
- guard: explicit candidate block bases (b=ptr-24 / b16=ptr-32) with
  their size/free fields, plus a 16-word window (mem..mem4) from
  ptr-0x30 instead of the old 8 words
- vt::debug_verify: content probe of the cells grid (must be all-BLANK
  at shell entry) — catches a stale in-heap cells pointer that passes
  the range checks
- gop: on-screen marker for shadow carved vs NO-SHADOW fallback
  (the scrub content at the crash ptr suggests the shadow was rejected
  and its block stayed free + firmware-scrubbed)
</content>
</entry>
<entry>
<title>v0.5.7: guard reports the drop's size/align — identifies the clobbered struct</title>
<updated>2026-08-02T21:13:46Z</updated>
<author>
<name>salmonik</name>
<email>salmonik@tuta.io</email>
</author>
<published>2026-08-02T21:13:46Z</published>
<link rel='alternate' type='text/html' href='https://git.2137697.xyz/rs-dos/commit/?id=c10eb2333f277f815234f9fc26a5441e68ef7b40'/>
<id>urn:sha1:c10eb2333f277f815234f9fc26a5441e68ef7b40</id>
<content type='text'>
The OptiPlex crashes free garbage (0xaaaaaa, 0xaaaaaa00aaaaaa) whose
value is the firmware's 0x00AAAAAA scrub pattern left in stack/heap.
The drop size/align (the dealloc layout) now prints on the band, so the
next repro shows both the garbage ptr AND the size it was freed with —
cap×elem_size pinpoints which struct's fields were clobbered.
</content>
</entry>
<entry>
<title>v0.5.7: guard report 4-words-per-line — 16 stack words survive band hand-copy</title>
<updated>2026-08-02T20:46:59Z</updated>
<author>
<name>salmonik</name>
<email>salmonik@tuta.io</email>
</author>
<published>2026-08-02T20:46:59Z</published>
<link rel='alternate' type='text/html' href='https://git.2137697.xyz/rs-dos/commit/?id=e649a3de7d853bf82a9105a2cb3869c7b8c96108'/>
<id>urn:sha1:e649a3de7d853bf82a9105a2cb3869c7b8c96108</id>
<content type='text'>
The OptiPlex repro copies are truncated at the ~110-char band width, so
the old single-line 'stk:' (12 words, &gt;200 chars) lost the return chain
after a few words.  Split mem/stk dumps into 4-words-per-line blocks:
mem+mem2 (8 words around the corruption) and stk..stk4 (16 words) —
the drop caller chain now survives hand transcription.
</content>
</entry>
<entry>
<title>v0.5.7: allocator corruption guard + full register dump for real-hardware repro</title>
<updated>2026-08-02T19:47:18Z</updated>
<author>
<name>salmonik</name>
<email>salmonik@tuta.io</email>
</author>
<published>2026-08-02T19:47:18Z</published>
<link rel='alternate' type='text/html' href='https://git.2137697.xyz/rs-dos/commit/?id=0187b802113a10a9ee99af48b811cd332c660a13'/>
<id>urn:sha1:0187b802113a10a9ee99af48b811cd332c660a13</id>
<content type='text'>
The OptiPlex #GP (vec=13 in __rust_dealloc) frees a garbage pointer: the
back-pointer at [ptr-8] is clobbered by the time the shell drops its
Parsed struct.  A blind store to the bogus block header was an opaque
#GP — now it is a readable report:

- dealloc validates the back-pointer (in-heap block, sane size, in-use)
  before trusting it; on failure it prints ptr/block/heap range, the
  memory around the block header, and the live stack chain, writes the
  crash band + crash.log, and halts (memory.rs: heap_guard_report).
- fault dumps now carry the full register set (rax..rdi, rbx, r8..r15)
  so the next repro shows the exact freed ptr and clobbered value.
- new 'corrupt' shell hook deliberately clobbers a live block's
  back-pointer to prove the guard fires (test-fault-style halt).

Verified: test-msg/test-disk/test-fault pass; corrupt hook reports
ptr=.. block=0xdeedbeef... with mem dump instead of #GP. rs-dos.img
rebuilt with the release kernel.
</content>
</entry>
<entry>
<title>v0.5.6: fault dumps carry kernel image base + stack backtrace</title>
<updated>2026-08-02T14:06:40Z</updated>
<author>
<name>salmonik</name>
<email>salmonik@tuta.io</email>
</author>
<published>2026-08-02T14:06:40Z</published>
<link rel='alternate' type='text/html' href='https://git.2137697.xyz/rs-dos/commit/?id=a459dd3fb267bfba24c3fad1e3dc789bf50ee20b'/>
<id>urn:sha1:a459dd3fb267bfba24c3fad1e3dc789bf50ee20b</id>
<content type='text'>
- fault_dump prints img= (kernel image base) on the serial line and
  the on-screen band, so a real-hardware repro can be resolved against
  the PDB without serial
- backtrace: rbp-chain walk then a raw scan of the stack above the
  interrupted rsp; both filter to the .text range (PE-header parse via
  memory::text_range) so only code addresses are collected
- on-screen boot marker shows the kernel image range at every boot
- crash.log now records img= + bt= lines alongside rip/rsp
</content>
</entry>
</feed>
