wasm-emu: isolate compiled-store corruption to uzlib fault-path TB (E32-E34)

This commit is contained in:
2026-07-23 10:37:23 -04:00
parent fe6bbe4d3d
commit 28ea986875
4 changed files with 62 additions and 1 deletions
+52
View File
@@ -742,3 +742,55 @@ remaining causes: stale/corrupted TLB addend for the store's page, wasm32
address truncation/sign-extension around addends, or an in-TB ordering bug in the
compiled store TLB lookup. The next focused probe is to trace the store fast-path
host address for the `0x4201e198` TB before the `i64.store32` executes.
## E32-E34: fault-path TB isolation
Tried a narrow compiled-store guard (`?tlbguard=open`) that forces a store fast
path to the C helper if the computed host address lands inside the vCPU TLB
arrays. It did **not** suppress the crash, even though the guard range included
`fulltlb[56]`:
```text
TLBGUARD range lo=0x13e8000 hi=0x353c000
```
So the corrupting write is not caught as a normal compiled `qemu_st` fast-path
whose final host pointer falls directly inside that TLB-array range. The
corruption still appears between the TLB fill and the following byte load.
Added `?stpc=LO-HI`, an opt-in PC-window override that interprets only
store-containing TBs whose start PC lands in the window, while `?nostoretci`
keeps every other store TB compiled.
Results:
- plain `?nostoretci`: still crashes at the original signature.
- `?nostoretci&stpc=0x4201e180-0x4201e220`: **3/3 pass**
(`open example.txt` about 46-52s).
- wider/narrowed windows around `uzlib_uncompress` also pass as long as they
include the fault-path TB start.
This pins the corruption to compiled execution of the `uzlib_uncompress` TB that
contains the copy-loop sequence around:
```text
4201e18c: lw a3,56(s0)
4201e18e: lw a5,24(s0)
4201e190: lw a4,52(s0)
4201e194: addi a2,a5,1
4201e198: sw a2,24(s0)
4201e19a: add a3,a3,a4
4201e19c: lbu a4,0(a3)
4201e1a0: sb a4,0(a5)
```
The PC-window override is firmware-specific and **not** a production fix, but it
is now the smallest positive isolation: one compiled store-containing TB in the
inflate copy loop is sufficient to corrupt the vCPU TLB entry; interpreting that
TB avoids the crash while preserving compiled stores elsewhere.
Next useful step: dump or instrument the generated WASM for this exact TB and
inspect the `sw a2,24(s0)` / following `lbu` fast-path sequence. The current
node dump helper only captures early boot TBs, so late-reader TB dumping needs a
browser/open-window trigger or a PC-filtered `wasm_dump_module` path.
+2
View File
@@ -171,6 +171,8 @@ try:
driver.execute_script('window.xteinkEnableRamrace && window.xteinkEnableRamrace()')
if 'stateflush=open' in url:
driver.execute_script('window.xteinkEnableStateflush && window.xteinkEnableStateflush()')
if 'tlbguard=open' in url:
driver.execute_script('window.xteinkEnableTlbguard && window.xteinkEnableTlbguard()')
open_start = time.monotonic()
press(confirm, 'opening example.txt')
open_seconds = time.monotonic() - open_start
+7
View File
@@ -501,8 +501,15 @@ async function boot(file, variant, setStatus) {
if (params.get('stateflush') === 'open') {
window.xteinkEnableStateflush = () => options._wasm_stateflush_enable();
} else if (params.has('stateflush')) options._wasm_stateflush_enable();
if (params.get('tlbguard') === 'open') {
window.xteinkEnableTlbguard = () => options._wasm_tlb_guard_enable();
} else if (params.has('tlbguard')) options._wasm_tlb_guard_enable();
if (params.has('sthash')) options._wasm_set_store_tci_hash(Number(params.get('sthash')) || 1);
if (params.has('stcmask')) options._wasm_set_store_bisect(Number(params.get('stcw')) || 0, Number(params.get('stcmask')) >>> 0, (Number(params.get('stcval')) || 0) >>> 0);
if (params.has('stpc')) {
const [lo, hi] = params.get('stpc').split('-').map(v => Number(v));
options._wasm_set_store_pc_window(lo >>> 0, hi >>> 0);
}
options.FS.mkdirTree('/bios');
options.FS.mkdirTree('/var/tmp');
options.FS.writeFile('/bios/esp32c3-rom.bin', rom);