From fe6bbe4d3d8c817d0c94c67c94c0be9f5753d1de Mon Sep 17 00:00:00 2001 From: Evan Reichard Date: Thu, 23 Jul 2026 07:50:54 -0400 Subject: [PATCH] wasm-emu: document concrete TLB-array corruption path (E23-E31) --- docs/wasm-inflate-panic.md | 68 ++++++++++++++++++++++++++++++++++++++ third_party/qemu | 2 +- 2 files changed, 69 insertions(+), 1 deletion(-) diff --git a/docs/wasm-inflate-panic.md b/docs/wasm-inflate-panic.md index 835293a..3d8ea9a 100644 --- a/docs/wasm-inflate-panic.md +++ b/docs/wasm-inflate-panic.md @@ -674,3 +674,71 @@ across the relevant call/branch, and whether the wasm backend emits the corresponding store. The observed bug is now specifically: **compiled globals and `CPUArchState` are allowed to diverge, and the wasm backend exposes stale env to helper/exception-visible code when store TBs stay compiled.** + + +## E23-E31: concrete TLB-array corruption + +Added `FAULTTRACE`/`TLBTRACE` under `?ramrace=open` to inspect the exact failing +load path. + +Key observations from crashing `?nostoretci&ramrace=open` runs: + +1. The faulting guest address (`0x3fcb8004`/`0x3fcb80a6`) is valid ESP32-C3 DRAM. +2. TLB fill resolves the page correctly as RAM: + +```text +FAULTTRACE tlb_fill vaddr=0x3fcb8000 paddr=0x3fcb8000 asidx=0 prot=0x3 + mr=esp32c3.iram ram=1 romd=0 xlat=0x3c000 +FAULTTRACE tlb_store index=56 iotlb=0x9c000 addr_page=0x3fcb8000 + stored_xlat=0xffffffffc03e4000 phys=0x3fcb8000 +FAULTTRACE mmu_lookup1 addr=0x3fcb8000 index=56 maybe_resized=1 + tlb_addr=0x3fcb8000 flags=0x0 full_xlat=0xffffffffc03e4000 addend=0xc19d4000 +``` + +3. Before the next byte load on the same page, the compact TLB and full TLB entry + are corrupted: + +```text +FAULTTRACE mmu_lookup1 addr=0x3fcb8004 index=56 maybe_resized=0 + tlb_addr=0x3fcb8200 flags=0x200 full_xlat=0x0 addend=0xc0348000 +FAULTTRACE mmio_read addr=0x3fcb8004 xlat_section=0x0 mr=(null) ram=0 +``` + +`0x200` is `TLB_MMIO`, so the vCPU incorrectly dispatches a DRAM read through +the MMIO/unassigned path. This is why the access is rejected even though the +guest address is in DRAM. + +The corruption happens inside the active compiled TB before it returns, so the +post-TB scanner only sees the last good state. The faulting firmware sequence is +in `uzlib_uncompress`: + +```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) # faults after TLB entry was corrupted +4201e1a0: sb a4,0(a5) +``` + +The compiled store at `0x4201e198` is now the prime suspect: it likely writes +through a bad host address into the TLB arrays, changing the same page's TLB +entry from RAM to MMIO and zeroing `fulltlb[index].xlat_section`. That matches +why blanket store-TCI works: the C/TCI store path does not corrupt the TLB arrays. + +### Current root-cause statement + +The bug is no longer just "nondeterministic race". It is specifically: + +> compiled wasm store fast-path sometimes computes/uses a bad host address and +> writes into the vCPU softmmu TLB arrays (`CPUTLBEntry`/`CPUTLBEntryFull`), +> causing the immediately following load from valid DRAM to be treated as MMIO +> with `xlat_section=0`. + +Still unknown: why the store fast path obtains the bad host address. Candidate +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. diff --git a/third_party/qemu b/third_party/qemu index 346c789..cd3f083 160000 --- a/third_party/qemu +++ b/third_party/qemu @@ -1 +1 @@ -Subproject commit 346c7898514487a3ad5ecee2f9d4d04b97069af0 +Subproject commit cd3f083fb052a32bcde00f5d0f92d7cb2141a457