diff --git a/docs/wasm-inflate-panic.md b/docs/wasm-inflate-panic.md index 0cff6dc..e78c2cf 100644 --- a/docs/wasm-inflate-panic.md +++ b/docs/wasm-inflate-panic.md @@ -360,3 +360,50 @@ if a full-execution comparison is later required. Both `?tcgdiff` (E10) and `?tcgdiff2` (E11) are retained as opt-in tools; production store-TCI path is unchanged. + +## E12/E13: normal-speed compiled stores and file-open-armed E11 + +### `?nostoretci` probe +Added opt-in `?nostoretci` to disable the store-TCI workaround without enabling +any differential overhead. Result: the exact original corruption still +reproduces at normal speed during reader open: + +- `Load access fault` +- `MEPC 0x4201e210` +- `MTVAL 0x3fcb8004` / invalid read near the inflate/text buffer region + +So store-TCI is still required in production. + +### `?tcgdiff2=open` +Arming E11 from boot was too slow or perturbed app init. Added a browser-test +hook so `?tcgdiff2=open` arms `wasm_diff_enable2()` immediately before the test +presses Confirm to open `example.txt`. Boot and app init therefore run on the +normal production path, and compiled stores become live only over the repro +interval. + +With the all-app-flash window (`0x42000000..0x42200000`), the first observed +mode-2 divergence after arming is register state, not DRAM: + +```text +TCGDIFF pc=0x4201d6ea gpr[2] compiled=0x3fcb42f0 tci=0x3fcb42e0 +pre-ra=0x42029374 pre-sp=0x3fcb42f0 +``` + +This is `utf8NextCodepoint()`: TCI applies the stack-frame prologue (`sp -= 16`) +while the compiled-live path has stale `sp` in `CPUArchState`. The later crash +is still the known invalid read at `MEPC 0x4201e210`. + +### Current interpretation +E10 remains green because it forces no-chain and runs TCI live, then compiled as +a disposable shadow. E11 is the real compiled-live path and exposes state that is +stale across compiled execution/chaining boundaries. The remaining suspect is no +longer individual store codegen; it is **compiled TB state materialization**: +WASM register globals and `CPUArchState` can diverge across real compiled-live +entry/exit/chaining, and store-TCI masks the bad store-containing TBs by routing +them through TCI. + +A tested broad fix candidate — making store TBs return to C instead of using the +same-module `BLOCK_PTR` chain — caused an app-init interrupt-watchdog timeout, +so it is not viable as-is. A narrower fix should target state materialization +(flush/reload live guest register state at compiled TB boundaries or before +helper/exception-visible points) rather than disabling chaining wholesale. diff --git a/tests/browser_raw_sd.py b/tests/browser_raw_sd.py index b15adac..c522a09 100644 --- a/tests/browser_raw_sd.py +++ b/tests/browser_raw_sd.py @@ -165,6 +165,8 @@ try: press(confirm, 'opening Browse Files') press(confirm, 'opening Test directory') press(confirm, 'highlighting example.txt') + if 'tcgdiff2=open' in url: + driver.execute_script('window.xteinkArmTcgDiff2 && window.xteinkArmTcgDiff2()') open_start = time.monotonic() press(confirm, 'opening example.txt') open_seconds = time.monotonic() - open_start diff --git a/third_party/qemu b/third_party/qemu index 4dd5425..b3ffe97 160000 --- a/third_party/qemu +++ b/third_party/qemu @@ -1 +1 @@ -Subproject commit 4dd54253ab8376cd523b8774c6338e44011f29c5 +Subproject commit b3ffe97fb30fa2f72be4a678a9130edc90a85a27 diff --git a/web/app.js b/web/app.js index 52d5ae4..f17d332 100644 --- a/web/app.js +++ b/web/app.js @@ -490,8 +490,11 @@ async function boot(file, variant, setStatus) { stdin: () => null, }; options.preRun = [() => { - if (params.has('tcgdiff2')) options._wasm_diff_enable2(); + if (params.get('tcgdiff2') === 'open') { + window.xteinkArmTcgDiff2 = () => options._wasm_diff_enable2(); + } else if (params.has('tcgdiff2')) options._wasm_diff_enable2(); else if (params.has('tcgdiff')) options._wasm_diff_enable(); + if (params.has('nostoretci')) options._wasm_disable_store_tci(); options.FS.mkdirTree('/bios'); options.FS.mkdirTree('/var/tmp'); options.FS.writeFile('/bios/esp32c3-rom.bin', rom);