diff --git a/docs/wasm-inflate-panic.md b/docs/wasm-inflate-panic.md index a2302f4..a708378 100644 --- a/docs/wasm-inflate-panic.md +++ b/docs/wasm-inflate-panic.md @@ -537,3 +537,36 @@ device/timer callbacks are properly serialized against vCPU stores (BQL/memory barriers), or run device memory access on the vCPU thread. Opt-in repro/debug controls now available: `?nostoretci`, `?sthash`, `?stcw/stcmask/stcval`, `?yieldtrace`. Production default remains blanket store-TCI. + +## E18: not dynamic function-table churn either + +Confirmed the threading model: the build uses `-pthread -sPROXY_TO_PTHREAD=1 +-sASYNCIFY=1`, and `qemu_thread_create` runs the vCPU in its own pthread, +concurrent with the main/IO-loop thread over shared memory. So a genuine +guest-RAM data race is possible. + +Tested the most tractable non-thread hypothesis first: each compiled TB adds a +WASM table function and batch-`removeFunction`s once >500 removals are pending; +more compiled stores (both widths) means more churn, which is timing-dependent. +Added opt-in `?noremove` (`wasm_set_disable_tb_removal`) to leak functions +instead of recycling table indices. + +Result: `?nostoretci&noremove` crashed 4/4 (Load access faults). Recycling of +WASM table indices is **not** the corruption source. + +### Ruled out so far +- specific store-TB identity (E15) +- store `DONE_FLAG` block-replay/redispatch (E17) +- WASM function-table index reuse (E18) + +### Standing conclusion +The corruption is a nondeterministic concurrency issue between the vCPU pthread +(compiled `i64.storeN`) and the concurrent main/IO thread (timer/device +callbacks, AIO/block completions) over shared guest memory or QEMU softmmu +metadata — the class of bug upstream qemu-wasm avoids with blanket store-TCI. +Confirming the exact racing access needs thread-aware instrumentation (e.g., +logging IO-thread guest-RAM writes and TLB mutations during reader open) rather +than more store-gating experiments. Production stays on blanket store-TCI. + +Opt-in debug knobs now available: `?nostoretci`, `?sthash`, +`?stcw/stcmask/stcval`, `?yieldtrace`, `?noremove`. diff --git a/third_party/qemu b/third_party/qemu index 9e91849..b6d67a8 160000 --- a/third_party/qemu +++ b/third_party/qemu @@ -1 +1 @@ -Subproject commit 9e9184949d44669a52307e28641c8a6af3c7cbe5 +Subproject commit b6d67a89bb626d23ca5102103c1f927cd90ca384 diff --git a/web/app.js b/web/app.js index fb42ab9..e6ea3fa 100644 --- a/web/app.js +++ b/web/app.js @@ -494,6 +494,7 @@ async function boot(file, variant, setStatus) { else if (params.has('tcgdiff')) options._wasm_diff_enable(); if (params.has('nostoretci')) options._wasm_disable_store_tci(); if (params.has('yieldtrace')) options._wasm_enable_yield_trace(); + if (params.has('noremove')) options._wasm_set_disable_tb_removal(); 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); options.FS.mkdirTree('/bios');