From 598b5e66fd3a6a38d9bf809a4b9620e21cb8b2d2 Mon Sep 17 00:00:00 2001 From: Evan Reichard Date: Fri, 24 Jul 2026 10:37:12 -0400 Subject: [PATCH] tcg/wasm32: remove compiled-store investigation probes --- accel/tcg/cpu-exec.c | 24 -- accel/tcg/cputlb.c | 94 ------ system/memory.c | 15 - system/physmem.c | 89 ------ tcg/tcg.c | 17 - tcg/wasm32.c | 604 +----------------------------------- tcg/wasm32.h | 42 --- tcg/wasm32/tcg-target.c.inc | 61 ---- 8 files changed, 1 insertion(+), 945 deletions(-) diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c index 5fdc8d5347..8163295f34 100644 --- a/accel/tcg/cpu-exec.c +++ b/accel/tcg/cpu-exec.c @@ -41,9 +41,6 @@ #include "tb-context.h" #include "internal-common.h" #include "internal-target.h" -#if defined(EMSCRIPTEN) && !defined(CONFIG_TCG_INTERPRETER) -#include "../../tcg/wasm32.h" -#endif /* -icount align implementation. */ @@ -176,14 +173,6 @@ uint32_t curr_cflags(CPUState *cpu) cflags |= CF_NO_GOTO_TB; } -#if defined(EMSCRIPTEN) && !defined(CONFIG_TCG_INTERPRETER) - /* E10 needs one TB per dispatch so wasm_cur_tb_pc stays exact; E11 keeps - * chaining live to avoid watchdog-only slowdowns before the armed window. */ - if (wasm_diff_needs_nochain()) { - cflags |= CF_NO_GOTO_TB | CF_NO_GOTO_PTR; - } -#endif - return cflags; } @@ -428,11 +417,6 @@ const void *HELPER(lookup_tb_ptr)(CPUArchState *env) cpu_get_tb_cpu_state(env, &pc, &cs_base, &flags); cflags = curr_cflags(cpu); -#if defined(EMSCRIPTEN) && !defined(CONFIG_TCG_INTERPRETER) - if (wasm_diff_needs_nochain_at(pc)) { - cflags |= CF_NO_GOTO_TB | CF_NO_GOTO_PTR; - } -#endif if (check_for_breakpoints(cpu, pc, &cflags)) { cpu_loop_exit(cpu); } @@ -471,9 +455,6 @@ cpu_tb_exec(CPUState *cpu, TranslationBlock *itb, int *tb_exit) } qemu_thread_jit_execute(); -#if defined(EMSCRIPTEN) && !defined(CONFIG_TCG_INTERPRETER) - wasm_cur_tb_pc = itb->pc; -#endif ret = tcg_qemu_tb_exec(cpu_env(cpu), tb_ptr); cpu->neg.can_do_io = true; qemu_plugin_disable_mem_helpers(cpu); @@ -995,11 +976,6 @@ cpu_exec_loop(CPUState *cpu, SyncClocks *sc) cflags = cpu->cflags_next_tb; if (cflags == -1) { cflags = curr_cflags(cpu); -#if defined(EMSCRIPTEN) && !defined(CONFIG_TCG_INTERPRETER) - if (wasm_diff_needs_nochain_at(pc)) { - cflags |= CF_NO_GOTO_TB | CF_NO_GOTO_PTR; - } -#endif } else { cpu->cflags_next_tb = -1; } diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c index f1d23d6ab9..a673eb2eb7 100644 --- a/accel/tcg/cputlb.c +++ b/accel/tcg/cputlb.c @@ -73,28 +73,6 @@ } \ } while (0) -#if defined(EMSCRIPTEN) && !defined(CONFIG_TCG_INTERPRETER) -extern int wasm_ramrace_trace; -static uint32_t wasm_ramrace_tlb_logs; - -static void wasm_ramrace_log_tlb(const char *kind, CPUState *cpu, vaddr addr) -{ - if (!wasm_ramrace_trace || current_cpu) { - return; - } - - wasm_ramrace_tlb_logs++; - if (wasm_ramrace_tlb_logs <= 200 || (wasm_ramrace_tlb_logs % 10000) == 0) { - printf("RAMRACE tlb-%s off-vcpu #%u tid=%lu cpu=%p addr=0x%llx\n", - kind, wasm_ramrace_tlb_logs, (unsigned long)pthread_self(), - cpu, (unsigned long long)addr); - fflush(stdout); - } -} -#else -#define wasm_ramrace_log_tlb(kind, cpu, addr) ((void)0) -#endif - #define assert_cpu_is_self(cpu) do { \ if (DEBUG_TLB_GATE) { \ g_assert(!(cpu)->created || qemu_cpu_is_self(cpu)); \ @@ -439,7 +417,6 @@ static void tlb_flush_by_mmuidx_async_work(CPUState *cpu, run_on_cpu_data data) void tlb_flush_by_mmuidx(CPUState *cpu, uint16_t idxmap) { tlb_debug("mmu_idx: 0x%" PRIx16 "\n", idxmap); - wasm_ramrace_log_tlb("full", cpu, 0); assert_cpu_is_self(cpu); @@ -456,7 +433,6 @@ void tlb_flush_by_mmuidx_all_cpus_synced(CPUState *src_cpu, uint16_t idxmap) const run_on_cpu_func fn = tlb_flush_by_mmuidx_async_work; tlb_debug("mmu_idx: 0x%"PRIx16"\n", idxmap); - wasm_ramrace_log_tlb("full-all", src_cpu, 0); flush_all_helper(src_cpu, fn, RUN_ON_CPU_HOST_INT(idxmap)); async_safe_run_on_cpu(src_cpu, fn, RUN_ON_CPU_HOST_INT(idxmap)); @@ -632,7 +608,6 @@ static void tlb_flush_page_by_mmuidx_async_2(CPUState *cpu, void tlb_flush_page_by_mmuidx(CPUState *cpu, vaddr addr, uint16_t idxmap) { tlb_debug("addr: %016" VADDR_PRIx " mmu_idx:%" PRIx16 "\n", addr, idxmap); - wasm_ramrace_log_tlb("page", cpu, addr); assert_cpu_is_self(cpu); @@ -652,7 +627,6 @@ void tlb_flush_page_by_mmuidx_all_cpus_synced(CPUState *src_cpu, uint16_t idxmap) { tlb_debug("addr: %016" VADDR_PRIx " mmu_idx:%"PRIx16"\n", addr, idxmap); - wasm_ramrace_log_tlb("page-all", src_cpu, addr); /* This should already be page aligned */ addr &= TARGET_PAGE_MASK; @@ -803,7 +777,6 @@ void tlb_flush_range_by_mmuidx(CPUState *cpu, vaddr addr, { TLBFlushRangeData d; - wasm_ramrace_log_tlb("range", cpu, addr); assert_cpu_is_self(cpu); /* @@ -844,8 +817,6 @@ void tlb_flush_range_by_mmuidx_all_cpus_synced(CPUState *src_cpu, TLBFlushRangeData d, *p; CPUState *dst_cpu; - wasm_ramrace_log_tlb("range-all", src_cpu, addr); - /* * If all bits are significant, and len is small, * this devolves to tlb_flush_page. @@ -986,27 +957,9 @@ void tlb_reset_dirty(CPUState *cpu, ram_addr_t start1, ram_addr_t length) static inline void tlb_set_dirty1_locked(CPUTLBEntry *tlb_entry, vaddr addr) { -#if defined(EMSCRIPTEN) && !defined(CONFIG_TCG_INTERPRETER) - if (wasm_ramrace_trace && (addr & TARGET_PAGE_MASK) == 0x3fcb8000u) { - printf("FAULTTRACE tlb_set_dirty1 entry=%p before_read=0x%llx before_write=0x%llx before_addend=0x%llx addr=0x%llx\n", - tlb_entry, (unsigned long long)tlb_entry->addr_read, - (unsigned long long)tlb_entry->addr_write, - (unsigned long long)tlb_entry->addend, (unsigned long long)addr); - fflush(stdout); - } -#endif if (tlb_entry->addr_write == (addr | TLB_NOTDIRTY)) { tlb_entry->addr_write = addr; } -#if defined(EMSCRIPTEN) && !defined(CONFIG_TCG_INTERPRETER) - if (wasm_ramrace_trace && (addr & TARGET_PAGE_MASK) == 0x3fcb8000u) { - printf("FAULTTRACE tlb_set_dirty1 after entry=%p read=0x%llx write=0x%llx addend=0x%llx\n", - tlb_entry, (unsigned long long)tlb_entry->addr_read, - (unsigned long long)tlb_entry->addr_write, - (unsigned long long)tlb_entry->addend); - fflush(stdout); - } -#endif } /* update the TLB corresponding to virtual page vaddr @@ -1125,16 +1078,6 @@ void tlb_set_page_full(CPUState *cpu, int mmu_idx, is_ram = memory_region_is_ram(section->mr); is_romd = memory_region_is_romd(section->mr); -#if defined(EMSCRIPTEN) && !defined(CONFIG_TCG_INTERPRETER) - if (wasm_ramrace_trace && paddr_page == 0x3fcb8000u) { - printf("FAULTTRACE tlb_fill vaddr=0x%llx paddr=0x%llx asidx=%d prot=0x%x mr=%p name=%s ram=%d romd=%d readonly=%d xlat=0x%llx sz=0x%llx\n", - (unsigned long long)addr_page, (unsigned long long)paddr_page, - asidx, prot, section->mr, memory_region_name(section->mr) ?: "(null)", - is_ram, is_romd, section->readonly, - (unsigned long long)xlat, (unsigned long long)sz); - fflush(stdout); - } -#endif if (is_ram || is_romd) { /* RAM and ROMD both have associated host memory. */ @@ -1227,15 +1170,6 @@ void tlb_set_page_full(CPUState *cpu, int mmu_idx, full = &desc->fulltlb[index]; full->xlat_section = iotlb - addr_page; full->phys_addr = paddr_page; -#if defined(EMSCRIPTEN) && !defined(CONFIG_TCG_INTERPRETER) - if (wasm_ramrace_trace && paddr_page == 0x3fcb8000u) { - printf("FAULTTRACE tlb_store index=%u iotlb=0x%llx addr_page=0x%llx stored_xlat=0x%llx phys=0x%llx\n", - index, (unsigned long long)iotlb, (unsigned long long)addr_page, - (unsigned long long)full->xlat_section, - (unsigned long long)full->phys_addr); - fflush(stdout); - } -#endif /* Now calculate the new entry */ tn.addend = addend - addr_page; @@ -1455,15 +1389,6 @@ static int probe_access_internal(CPUState *cpu, vaddr addr, *pfull = full = &cpu->neg.tlb.d[mmu_idx].fulltlb[index]; flags |= full->slow_flags[access_type]; -#if defined(EMSCRIPTEN) && !defined(CONFIG_TCG_INTERPRETER) - if (wasm_ramrace_trace && ((addr & TARGET_PAGE_MASK) == 0x3fcb8000u)) { - printf("FAULTTRACE probe addr=0x%llx index=%lu access=%d tlb_addr=0x%llx flags=0x%x slow=0x%x addend=0x%llx full_xlat=0x%llx\n", - (unsigned long long)addr, (unsigned long)index, access_type, - (unsigned long long)tlb_addr, flags, full->slow_flags[access_type], - (unsigned long long)entry->addend, (unsigned long long)full->xlat_section); - fflush(stdout); - } -#endif /* Fold all "mmio-like" bits into TLB_MMIO. This is not RAM. */ if (unlikely(flags & ~(TLB_WATCHPOINT | TLB_NOTDIRTY | TLB_CHECK_ALIGNED)) @@ -1754,16 +1679,6 @@ static bool mmu_lookup1(CPUState *cpu, MMULookupPageData *data, MemOp memop, data->full = full; data->flags = flags; -#if defined(EMSCRIPTEN) && !defined(CONFIG_TCG_INTERPRETER) - if (wasm_ramrace_trace && ((addr & TARGET_PAGE_MASK) == 0x3fcb8000u)) { - printf("FAULTTRACE mmu_lookup1 addr=0x%llx mmu=%d index=%lu maybe_resized=%d tlb_addr=0x%llx flags=0x%x entry=%p full=%p full_xlat=0x%llx addend=0x%llx\n", - (unsigned long long)addr, mmu_idx, (unsigned long)index, maybe_resized, - (unsigned long long)tlb_addr, flags, entry, full, - (unsigned long long)full->xlat_section, - (unsigned long long)entry->addend); - fflush(stdout); - } -#endif /* Compute haddr speculatively; depending on flags it might be invalid. */ data->haddr = (void *)((uintptr_t)addr + entry->addend); @@ -2063,15 +1978,6 @@ static uint64_t do_ld_mmio_beN(CPUState *cpu, CPUTLBEntryFull *full, attrs = full->attrs; section = io_prepare(&mr_offset, cpu, full->xlat_section, attrs, addr, ra); mr = section->mr; -#if defined(EMSCRIPTEN) && !defined(CONFIG_TCG_INTERPRETER) - if (wasm_ramrace_trace && ((addr & TARGET_PAGE_MASK) == 0x3fcb8000u)) { - printf("FAULTTRACE mmio_read addr=0x%llx xlat_section=0x%llx mr_offset=0x%llx mr=%p name=%s ram=%d romd=%d readonly=%d\n", - (unsigned long long)addr, (unsigned long long)full->xlat_section, - (unsigned long long)mr_offset, mr, memory_region_name(mr) ?: "(null)", - memory_region_is_ram(mr), memory_region_is_romd(mr), section->readonly); - fflush(stdout); - } -#endif BQL_LOCK_GUARD(); return int_ld_mmio_beN(cpu, full, ret_be, addr, size, mmu_idx, diff --git a/system/memory.c b/system/memory.c index 0e0a8a95ee..3958314765 100644 --- a/system/memory.c +++ b/system/memory.c @@ -32,7 +32,6 @@ #include "sysemu/tcg.h" #include "qemu/accel.h" #include "hw/boards.h" -#include "hw/core/cpu.h" #include "migration/vmstate.h" #include "exec/address-spaces.h" @@ -1405,10 +1404,6 @@ static const MemoryRegionOps ram_device_mem_ops = { }, }; -#if defined(EMSCRIPTEN) && !defined(CONFIG_TCG_INTERPRETER) -extern int wasm_ramrace_trace; -#endif - bool memory_region_access_valid(MemoryRegion *mr, hwaddr addr, unsigned size, @@ -1421,16 +1416,6 @@ bool memory_region_access_valid(MemoryRegion *mr, ", size %u, region '%s', reason: rejected\n", is_write ? "write" : "read", addr, size, memory_region_name(mr)); -#if defined(EMSCRIPTEN) && !defined(CONFIG_TCG_INTERPRETER) - if (wasm_ramrace_trace) { - printf("FAULTTRACE rejected %s addr=0x%llx size=%u mr=%p name=%s ops=%p opaque=%p ram=%d rom=%d readonly=%d current_cpu=%p\n", - is_write ? "write" : "read", (unsigned long long)addr, - size, mr, memory_region_name(mr) ?: "(null)", mr->ops, - mr->opaque, memory_region_is_ram(mr), memory_region_is_rom(mr), - mr->readonly, current_cpu); - fflush(stdout); - } -#endif return false; } diff --git a/system/physmem.c b/system/physmem.c index fa963be27b..addd5d0c4b 100644 --- a/system/physmem.c +++ b/system/physmem.c @@ -78,10 +78,6 @@ #include "monitor/monitor.h" -#ifdef EMSCRIPTEN -#include -#endif - #ifdef CONFIG_LIBDAXCTL #include #endif @@ -93,47 +89,6 @@ */ RAMList ram_list = { .blocks = QLIST_HEAD_INITIALIZER(ram_list.blocks) }; -#if defined(EMSCRIPTEN) && !defined(CONFIG_TCG_INTERPRETER) -int wasm_ramrace_trace; -static uint32_t wasm_ramrace_read_logs; -static uint32_t wasm_ramrace_cached_read_logs; -static uint32_t wasm_ramrace_write_logs; -static uint32_t wasm_ramrace_cached_write_logs; -static uint32_t wasm_ramrace_map_logs; -static uint32_t wasm_ramrace_unmap_logs; - -EMSCRIPTEN_KEEPALIVE void wasm_enable_ramrace_trace(void) -{ - wasm_ramrace_trace = 1; -} - -static bool wasm_ramrace_overlaps_dram(hwaddr addr, hwaddr len) -{ - const hwaddr dram_lo = 0x3fc80000u; - const hwaddr dram_hi = 0x3fce0000u; - - return len > 0 && addr < dram_hi && addr + len > dram_lo; -} - -static void wasm_ramrace_log_access(const char *kind, hwaddr addr, hwaddr len, - uint32_t *counter) -{ - if (!wasm_ramrace_trace || current_cpu || !wasm_ramrace_overlaps_dram(addr, len)) { - return; - } - - (*counter)++; - if (*counter <= 200 || (*counter % 10000) == 0) { - printf("RAMRACE %s off-vcpu #%u tid=%lu addr=0x%llx len=0x%llx\n", - kind, *counter, (unsigned long)pthread_self(), - (unsigned long long)addr, (unsigned long long)len); - fflush(stdout); - } -} -#else -#define wasm_ramrace_log_access(kind, addr, len, counter) ((void)0) -#endif - static MemoryRegion *system_memory; static MemoryRegion *system_io; @@ -2979,15 +2934,6 @@ static MemTxResult flatview_read(FlatView *fv, hwaddr addr, l = len; mr = flatview_translate(fv, addr, &mr_addr, &l, false, attrs); -#if defined(EMSCRIPTEN) && !defined(CONFIG_TCG_INTERPRETER) - if (wasm_ramrace_trace && current_cpu && mr->ops == &unassigned_mem_ops) { - printf("FAULTTRACE flatview_read addr=0x%llx len=0x%llx mr_addr=0x%llx translated_len=0x%llx fv=%p root=%p root_name=%s nr=%u\n", - (unsigned long long)addr, (unsigned long long)len, - (unsigned long long)mr_addr, (unsigned long long)l, - fv, fv->root, memory_region_name(fv->root) ?: "(null)", fv->nr); - fflush(stdout); - } -#endif if (!flatview_access_allowed(mr, attrs, addr, len)) { return MEMTX_ACCESS_ERROR; } @@ -3002,9 +2948,6 @@ MemTxResult address_space_read_full(AddressSpace *as, hwaddr addr, FlatView *fv; if (len > 0) { -#if defined(EMSCRIPTEN) && !defined(CONFIG_TCG_INTERPRETER) - wasm_ramrace_log_access("address_space_read", addr, len, &wasm_ramrace_read_logs); -#endif RCU_READ_LOCK_GUARD(); fv = address_space_to_flatview(as); result = flatview_read(fv, addr, attrs, buf, len); @@ -3021,9 +2964,6 @@ MemTxResult address_space_write(AddressSpace *as, hwaddr addr, FlatView *fv; if (len > 0) { -#if defined(EMSCRIPTEN) && !defined(CONFIG_TCG_INTERPRETER) - wasm_ramrace_log_access("address_space_write", addr, len, &wasm_ramrace_write_logs); -#endif RCU_READ_LOCK_GUARD(); fv = address_space_to_flatview(as); result = flatview_write(fv, addr, attrs, buf, len); @@ -3299,15 +3239,6 @@ void *address_space_map(AddressSpace *as, FlatView *fv; trace_address_space_map(as, addr, len, is_write, *(uint32_t *) &attrs); -#if defined(EMSCRIPTEN) && !defined(CONFIG_TCG_INTERPRETER) - if (is_write) { - wasm_ramrace_log_access("address_space_map_write", addr, len, - &wasm_ramrace_map_logs); - } else { - wasm_ramrace_log_access("address_space_map_read", addr, len, - &wasm_ramrace_map_logs); - } -#endif if (len == 0) { return NULL; @@ -3373,18 +3304,6 @@ void address_space_unmap(AddressSpace *as, void *buffer, hwaddr len, mr = memory_region_from_host(buffer, &addr1); if (mr != NULL) { if (is_write) { -#if defined(EMSCRIPTEN) && !defined(CONFIG_TCG_INTERPRETER) - if (wasm_ramrace_trace && !current_cpu && access_len > 0) { - wasm_ramrace_unmap_logs++; - if (wasm_ramrace_unmap_logs <= 200 || - (wasm_ramrace_unmap_logs % 10000) == 0) { - printf("RAMRACE address_space_unmap_write off-vcpu #%u tid=%lu host-ram=0x%llx len=0x%llx\n", - wasm_ramrace_unmap_logs, (unsigned long)pthread_self(), - (unsigned long long)addr1, (unsigned long long)access_len); - fflush(stdout); - } - } -#endif invalidate_and_set_dirty(mr, addr1, access_len); } if (xen_enabled()) { @@ -3600,10 +3519,6 @@ address_space_read_cached_slow(MemoryRegionCache *cache, hwaddr addr, hwaddr mr_addr, l; MemoryRegion *mr; -#if defined(EMSCRIPTEN) && !defined(CONFIG_TCG_INTERPRETER) - wasm_ramrace_log_access("address_space_read_cached", addr, len, - &wasm_ramrace_cached_read_logs); -#endif l = len; mr = address_space_translate_cached(cache, addr, &mr_addr, &l, false, MEMTXATTRS_UNSPECIFIED); @@ -3621,10 +3536,6 @@ address_space_write_cached_slow(MemoryRegionCache *cache, hwaddr addr, hwaddr mr_addr, l; MemoryRegion *mr; -#if defined(EMSCRIPTEN) && !defined(CONFIG_TCG_INTERPRETER) - wasm_ramrace_log_access("address_space_write_cached", addr, len, - &wasm_ramrace_cached_write_logs); -#endif l = len; mr = address_space_translate_cached(cache, addr, &mr_addr, &l, true, MEMTXATTRS_UNSPECIFIED); diff --git a/tcg/tcg.c b/tcg/tcg.c index 665b4ed0b7..fe774afa25 100644 --- a/tcg/tcg.c +++ b/tcg/tcg.c @@ -6607,15 +6607,6 @@ int tcg_gen_code(TCGContext *s, TranslationBlock *tb, uint64_t pc_start) #endif #if defined(EMSCRIPTEN) && !defined(CONFIG_TCG_INTERPRETER) - wasm_diff_register_tb(tb->tc.ptr, tcg_splitwx_to_rx(tb->tc.ptr), pc_start, - wasm_tb_had_store, - wasm_tb_had_store && !wasm_tb_had_helper); - if (wasm_tb_had_store && wasm_store_pc_hi && pc_start >= wasm_store_pc_lo && - pc_start < wasm_store_pc_hi) { - wasm_tci_only_tb = true; - printf("STPC TCI pc=0x%llx\n", (unsigned long long)pc_start); - fflush(stdout); - } if (wasm_tci_only_tb) { for (int i = 0; i < get_core_nums(); i++) { export_vec_base[i] = WASM_TCI_ONLY_ENTRY; @@ -6684,14 +6675,6 @@ int tcg_gen_code(TCGContext *s, TranslationBlock *tb, uint64_t pc_start) } *(uint32_t *)wasm_blob_ptr_base = s->code_ptr - wasm_blob_ptr_base - 4; - if (wasm_dump_pc_hi && pc_start >= wasm_dump_pc_lo && pc_start < wasm_dump_pc_hi) { - uint32_t mod_len = *(uint32_t *)wasm_blob_ptr_base; - const uint8_t *mod = wasm_blob_ptr_base + 4; - char dump_name[32]; - snprintf(dump_name, sizeof(dump_name), "pc-%08llx", (unsigned long long)pc_start); - wasm_dump_module(mod, mod_len, dump_name); - } - size_base = (uint32_t*)s->code_ptr; s->code_ptr += 4; memcpy(s->code_ptr, target_helper_funcs, num_helper_funcs * 4); diff --git a/tcg/wasm32.c b/tcg/wasm32.c index 4a7c9ea773..ae920d7606 100644 --- a/tcg/wasm32.c +++ b/tcg/wasm32.c @@ -32,10 +32,7 @@ #include #include "wasm32.h" -extern int wasm_ramrace_trace; -extern int wasm_tlb_guard_enabled; __thread uintptr_t tci_tb_ptr; -static __thread int tlbtrace_guard_announced; __thread bool wasm_tci_only_tb; static int instantiated_wasm_count; @@ -44,28 +41,6 @@ EMSCRIPTEN_KEEPALIVE int wasm_instantiated_tb_count(void) return qatomic_read(&instantiated_wasm_count); } -EM_JS(void, wasm_dump_module_js, (int ptr, int len, int name), { - const bytes = Uint8Array.from(HEAP8.subarray(ptr, ptr + len)); - const dumpName = UTF8ToString(name); - try { - const fs = require('fs'); - const fname = '/tmp/tbdump-' + dumpName + '.wasm'; - fs.writeFileSync(fname, bytes); - out('WASM_DUMP wrote ' + fname + ' (' + len + ' bytes)'); - } catch (e) { - let hex = ''; - for (let i = 0; i < bytes.length; i++) hex += bytes[i].toString(16).padStart(2, '0'); - out('WASM_DUMP_HEX_BEGIN ' + dumpName + ' ' + len); - for (let i = 0; i < hex.length; i += 2048) out('WASM_DUMP_HEX ' + dumpName + ' ' + hex.slice(i, i + 2048)); - out('WASM_DUMP_HEX_END ' + dumpName); - } -}); - -void wasm_dump_module(const uint8_t *p, int len, const char *name) -{ - wasm_dump_module_js((int)p, len, (int)name); -} - /* Disassemble TCI bytecode. */ int print_insn_tci(bfd_vma addr, disassemble_info *info) { @@ -207,39 +182,6 @@ EM_JS(void, init_wasm32_js, (int tb_ptr_ptr, int cur_core_num, int to_remove_ins }; }); -static void wasm_update_tlb_guard(CPUArchState *env) -{ - uintptr_t lo = UINTPTR_MAX; - uintptr_t hi = 0; - CPUState *cpu = env_cpu(env); - - ctx.tlb_guard_on = wasm_tlb_guard_enabled; - if (!ctx.tlb_guard_on) { - return; - } - - for (int i = 0; i < NB_MMU_MODES; i++) { - CPUTLBDescFast *fast = &cpu->neg.tlb.f[i]; - CPUTLBDesc *desc = &cpu->neg.tlb.d[i]; - size_t n = fast->table ? ((fast->mask >> CPU_TLB_ENTRY_BITS) + 1) : 0; - if (n) { - lo = MIN(lo, (uintptr_t)fast->table); - hi = MAX(hi, (uintptr_t)(fast->table + n)); - } - if (desc->fulltlb && n) { - lo = MIN(lo, (uintptr_t)desc->fulltlb); - hi = MAX(hi, (uintptr_t)(desc->fulltlb + n)); - } - } - ctx.tlb_guard_lo = (uint32_t)lo; - ctx.tlb_guard_hi = (uint32_t)hi; - if (wasm_ramrace_trace && !tlbtrace_guard_announced) { - printf("TLBGUARD range lo=0x%x hi=0x%x\n", ctx.tlb_guard_lo, ctx.tlb_guard_hi); - fflush(stdout); - tlbtrace_guard_announced = 1; - } -} - void init_wasm32() { if (!initdone) { @@ -1313,544 +1255,17 @@ static inline uintptr_t tcg_qemu_tb_exec_tci(CPUArchState *env) } } -/* - * Compiled-vs-TCI differential (debug). - * - * TCI stays the live/authoritative path (never crashes). For a TB whose guest PC - * is in the inflate window we additionally run the compiled blob as a shadow - * against a DRAM + register snapshot, then compare the resulting registers and - * DRAM against the authoritative TCI run. The first mismatch pinpoints the TB - * (and the first divergent guest register / DRAM word) whose compiled codegen is - * wrong — the corruption only manifests through a store, so a divergent DRAM word - * is the miscompiled write. Opt-in via wasm_diff_enable(); no effect otherwise. - */ -#define DIFF_DRAM_BASE 0x3fc80000u -#define DIFF_DRAM_SIZE 0x60000u -#define DIFF_PC_LO 0x42000000ull -#define DIFF_PC_HI 0x42200000ull - -__thread uint64_t wasm_cur_tb_pc; -static int wasm_diff_enabled; -static GHashTable *diff_store_tbs; -static GHashTable *diff_safe_tbs; -static __thread int diff_reported; -static __thread int diff_announced; -static __thread int diff_started; -static __thread int diff_skipped_slow; -static __thread uint32_t diff_compared; -static __thread uint8_t *diff_dram_pre, *diff_dram_c, *diff_dram_t; -static __thread uint8_t diff_env_pre[sizeof(CPUArchState)]; -static __thread uint8_t diff_env_c[sizeof(CPUArchState)]; -static __thread uint8_t diff_env_t[sizeof(CPUArchState)]; - -/* - * TB Entry Reads CPUNegativeOffsetState - The exit/interrupt check at TB start - * loads env-8 (icount_decr/exit flag), which lives before CPUArchState. The - * shadow must see the same pre-state here or it wrongly takes the early-exit - * path, so snapshot a window immediately below env too. - */ -#define DIFF_NEG sizeof(CPUNegativeOffsetState) -static __thread uint8_t diff_neg_pre[DIFF_NEG]; -static __thread uint8_t diff_neg_t[DIFF_NEG]; -static __thread uint8_t *diff_tlb_pre[NB_MMU_MODES]; -static __thread uint8_t *diff_fulltlb_pre[NB_MMU_MODES]; -static __thread size_t diff_tlb_size[NB_MMU_MODES]; -static __thread size_t diff_fulltlb_size[NB_MMU_MODES]; -static __thread uint32_t diff_compiled_ret; -static __thread int diff_tci_iters; -static __thread uint32_t diff2_eligible, diff2_incomplete, diff2_race; -static __thread uint64_t tlbtrace_last_read, tlbtrace_last_write, tlbtrace_last_addend, tlbtrace_last_xlat; - -/* Mode 2 (E11): compiled runs LIVE, so its post-state must be re-applied after - * the TCI shadow. These hold the full compiled-post machine state. */ -static __thread uint8_t diff_neg_c[DIFF_NEG]; -static __thread uint8_t *diff_tlb_c[NB_MMU_MODES]; -static __thread uint8_t *diff_fulltlb_c[NB_MMU_MODES]; - -int wasm_diff_mode; -int wasm_stateflush_enabled; -int wasm_tlb_guard_enabled; -uint64_t wasm_dump_pc_lo; -uint64_t wasm_dump_pc_hi; -int wasm_store_tci_disabled; -int wasm_store_tci_hash; -int wasm_store_helper_tci; -int wasm_store_bisect_on; -int wasm_store_bisect_width; -uint64_t wasm_store_pc_lo; -uint64_t wasm_store_pc_hi; -int wasm_yield_trace; -uint32_t wasm_yield_reentries; - -EMSCRIPTEN_KEEPALIVE void wasm_enable_yield_trace(void) -{ - wasm_yield_trace = 1; -} -uint32_t wasm_store_bisect_mask; -uint32_t wasm_store_bisect_val; - -EMSCRIPTEN_KEEPALIVE void wasm_disable_store_tci(void) -{ - wasm_store_tci_disabled = 1; -} - -/* E15 isolation: 1 = interpret even-hash store TBs, 2 = odd-hash. Both widths - * stay in the compiled half, so it separates a width-semantic bug from a - * compiled-store-population threshold. */ -EMSCRIPTEN_KEEPALIVE void wasm_set_store_tci_hash(int mode) -{ - wasm_store_tci_hash = mode; -} - -EMSCRIPTEN_KEEPALIVE void wasm_set_store_helper_tci(void) -{ - wasm_store_helper_tci = 1; -} - -/* E15 bisection: compile a store TB only when (hash(pc) & mask) == val, else - * TCI. Runtime-settable so the culprit set can be binary-searched with no - * rebuild. */ -EMSCRIPTEN_KEEPALIVE void wasm_set_store_bisect(int width, uint32_t mask, uint32_t val) -{ - wasm_store_bisect_on = 1; - wasm_store_bisect_width = width; - wasm_store_bisect_mask = mask; - wasm_store_bisect_val = val; -} - -EMSCRIPTEN_KEEPALIVE void wasm_set_store_pc_window(uint32_t lo, uint32_t hi) -{ - wasm_store_pc_lo = lo; - wasm_store_pc_hi = hi; -} - -EMSCRIPTEN_KEEPALIVE void wasm_diff_enable(void) -{ - wasm_diff_enabled = 1; - wasm_diff_mode = 1; -} - -EMSCRIPTEN_KEEPALIVE void wasm_diff_enable2(void) -{ - wasm_diff_enabled = 1; - wasm_diff_mode = 2; -} - -EMSCRIPTEN_KEEPALIVE void wasm_stateflush_enable(void) -{ - wasm_stateflush_enabled = 1; -} - -EMSCRIPTEN_KEEPALIVE void wasm_tlb_guard_enable(void) -{ - wasm_tlb_guard_enabled = 1; -} - -EMSCRIPTEN_KEEPALIVE void wasm_set_dump_pc_window(uint32_t lo, uint32_t hi) -{ - wasm_dump_pc_lo = lo; - wasm_dump_pc_hi = hi; -} - -int wasm_diff_on(void) -{ - return wasm_diff_enabled; -} - -int wasm_diff_needs_nochain(void) -{ - return wasm_diff_mode == 1; -} - -int wasm_diff_needs_nochain_at(uint64_t pc) -{ - return (wasm_stateflush_enabled || wasm_diff_mode == 2) && - pc >= DIFF_PC_LO && pc < DIFF_PC_HI; -} - -static void wasm_trace_dram_tlb(CPUArchState *env, uint64_t pc) -{ - CPUState *cpu; - const vaddr page = 0x3fcb8000u; - - if (!wasm_ramrace_trace || pc < DIFF_PC_LO || pc >= DIFF_PC_HI) { - return; - } - - cpu = env_cpu(env); - for (int mmu = 0; mmu < NB_MMU_MODES; mmu++) { - CPUTLBDescFast *fast = &cpu->neg.tlb.f[mmu]; - CPUTLBDesc *desc = &cpu->neg.tlb.d[mmu]; - if (!fast->table || !desc->fulltlb) { - continue; - } - size_t n = (fast->mask >> CPU_TLB_ENTRY_BITS) + 1; - for (size_t i = 0; i < n; i++) { - CPUTLBEntry *e = &fast->table[i]; - if (((e->addr_read & TARGET_PAGE_MASK) == page) || - ((e->addr_write & TARGET_PAGE_MASK) == page)) { - CPUTLBEntryFull *f = &desc->fulltlb[i]; - if (e->addr_read != tlbtrace_last_read || - e->addr_write != tlbtrace_last_write || - e->addend != tlbtrace_last_addend || - f->xlat_section != tlbtrace_last_xlat) { - printf("TLBTRACE pc=0x%llx mmu=%d index=%zu entry=%p full=%p read=0x%llx write=0x%llx addend=0x%llx full_xlat=0x%llx\n", - (unsigned long long)pc, mmu, i, e, f, - (unsigned long long)e->addr_read, - (unsigned long long)e->addr_write, - (unsigned long long)e->addend, - (unsigned long long)f->xlat_section); - fflush(stdout); - tlbtrace_last_read = e->addr_read; - tlbtrace_last_write = e->addr_write; - tlbtrace_last_addend = e->addend; - tlbtrace_last_xlat = f->xlat_section; - } - return; - } - } - } -} - -void wasm_diff_register_tb(const void *rw_ptr, const void *rx_ptr, uint64_t pc, - bool has_store, bool safe_shadow) -{ - if (!diff_store_tbs) { - diff_store_tbs = g_hash_table_new(g_direct_hash, g_direct_equal); - diff_safe_tbs = g_hash_table_new(g_direct_hash, g_direct_equal); - } - g_hash_table_remove(diff_store_tbs, rw_ptr); - g_hash_table_remove(diff_store_tbs, rx_ptr); - g_hash_table_remove(diff_safe_tbs, rw_ptr); - g_hash_table_remove(diff_safe_tbs, rx_ptr); - if (!has_store) { - return; - } - gpointer value = GUINT_TO_POINTER((uint32_t)pc); - g_hash_table_insert(diff_store_tbs, (void *)rw_ptr, value); - g_hash_table_insert(diff_store_tbs, (void *)rx_ptr, value); - if (safe_shadow) { - g_hash_table_insert(diff_safe_tbs, (void *)rw_ptr, GINT_TO_POINTER(1)); - g_hash_table_insert(diff_safe_tbs, (void *)rx_ptr, GINT_TO_POINTER(1)); - } -} - -bool wasm_diff_lookup_store_tb(const void *tb_ptr, uint64_t *pc) -{ - gpointer value = diff_store_tbs ? g_hash_table_lookup(diff_store_tbs, tb_ptr) : NULL; - if (!value) { - return false; - } - if (pc) { - *pc = GPOINTER_TO_UINT(value); - } - return true; -} - -bool wasm_diff_lookup_safe_tb(const void *tb_ptr) -{ - return diff_safe_tbs && g_hash_table_contains(diff_safe_tbs, tb_ptr); -} - -static void diff_report(uint64_t pc) -{ - uint32_t pre_ra, pre_sp, stack_m4 = 0, stack_0 = 0, stack_4 = 0; - memcpy(&pre_ra, diff_env_pre + 4, 4); - memcpy(&pre_sp, diff_env_pre + 8, 4); - if (pre_sp >= DIFF_DRAM_BASE + 4 && pre_sp + 8 <= DIFF_DRAM_BASE + DIFF_DRAM_SIZE) { - uint32_t off = pre_sp - DIFF_DRAM_BASE; - memcpy(&stack_m4, diff_dram_pre + off - 4, 4); - memcpy(&stack_0, diff_dram_pre + off, 4); - memcpy(&stack_4, diff_dram_pre + off + 4, 4); - } - /* Compare guest integer registers (env offset 0..127 = gpr[0..31]). */ - for (int i = 0; i < 32; i++) { - uint32_t c, t; - memcpy(&c, diff_env_c + i * 4, 4); - memcpy(&t, diff_env_t + i * 4, 4); - if (c != t) { - uint32_t neg8_pre, neg8_t; - memcpy(&neg8_pre, diff_neg_pre + DIFF_NEG - 8, 4); - memcpy(&neg8_t, diff_neg_t + DIFF_NEG - 8, 4); - printf("TCGDIFF pc=0x%llx gpr[%d] compiled=0x%08x tci=0x%08x " - "pre-ra=0x%08x pre-sp=0x%08x cret=0x%08x neg8_pre=0x%08x neg8_t=0x%08x tci_iters=%d\n", - (unsigned long long)pc, i, c, t, pre_ra, pre_sp, - diff_compiled_ret, neg8_pre, neg8_t, diff_tci_iters); - fflush(stdout); - diff_reported = 1; - return; - } - } - /* Compare DRAM word-by-word; first divergent word is the miscompiled store. */ - for (uint32_t off = 0; off < DIFF_DRAM_SIZE; off += 4) { - uint32_t c, t; - memcpy(&c, diff_dram_c + off, 4); - memcpy(&t, diff_dram_t + off, 4); - if (c != t) { - printf("TCGDIFF pc=0x%llx dram[0x%08x] compiled=0x%08x tci=0x%08x\n", - (unsigned long long)pc, DIFF_DRAM_BASE + off, c, t); - fflush(stdout); - diff_reported = 1; - return; - } - } -} - -static void diff_snapshot_pre(void) -{ - if (!diff_dram_pre) { - diff_dram_pre = malloc(DIFF_DRAM_SIZE); - diff_dram_c = malloc(DIFF_DRAM_SIZE); - diff_dram_t = malloc(DIFF_DRAM_SIZE); - } - CPUNegativeOffsetState *neg = (void *)((uint8_t *)ctx.env - DIFF_NEG); - memcpy(diff_env_pre, ctx.env, sizeof(CPUArchState)); - memcpy(diff_neg_pre, neg, DIFF_NEG); - for (int i = 0; i < NB_MMU_MODES; i++) { - size_t tlb_size = neg->tlb.f[i].mask + (1 << CPU_TLB_ENTRY_BITS); - size_t n = (neg->tlb.f[i].mask >> CPU_TLB_ENTRY_BITS) + 1; - size_t fulltlb_size = n * sizeof(CPUTLBEntryFull); - diff_tlb_pre[i] = g_realloc(diff_tlb_pre[i], tlb_size); - diff_fulltlb_pre[i] = g_realloc(diff_fulltlb_pre[i], fulltlb_size); - diff_tlb_size[i] = tlb_size; - diff_fulltlb_size[i] = fulltlb_size; - memcpy(diff_tlb_pre[i], neg->tlb.f[i].table, tlb_size); - memcpy(diff_fulltlb_pre[i], neg->tlb.d[i].fulltlb, fulltlb_size); - } - cpu_physical_memory_read(DIFF_DRAM_BASE, diff_dram_pre, DIFF_DRAM_SIZE); -} - -static bool diff_restore_pre(CPUArchState *env) -{ - CPUNegativeOffsetState *neg = (void *)((uint8_t *)env - DIFF_NEG); - CPUNegativeOffsetState *pre = (void *)diff_neg_pre; - for (int i = 0; i < NB_MMU_MODES; i++) { - if (neg->tlb.f[i].table != pre->tlb.f[i].table || - neg->tlb.d[i].fulltlb != pre->tlb.d[i].fulltlb) { - return false; - } - } - cpu_physical_memory_write(DIFF_DRAM_BASE, diff_dram_pre, DIFF_DRAM_SIZE); - memcpy(env, diff_env_pre, sizeof(CPUArchState)); - memcpy(neg, diff_neg_pre, DIFF_NEG); - for (int i = 0; i < NB_MMU_MODES; i++) { - memcpy(neg->tlb.f[i].table, diff_tlb_pre[i], diff_tlb_size[i]); - memcpy(neg->tlb.d[i].fulltlb, diff_fulltlb_pre[i], diff_fulltlb_size[i]); - } - return true; -} - -static void diff_ensure_compiled(const void *tb_ptr) -{ - ctx.tb_ptr = (uint32_t *)tb_ptr; - int slot_off = (uint32_t)ctx.tb_ptr + export_vec_off; - if (*(int32_t *)slot_off <= 0) { - instantiate_wasm(); - } -} - -/* Capture/restore full compiled-post machine state (mode 2 live trajectory). */ -static void diff_capture_compiled_post(CPUArchState *env) -{ - CPUNegativeOffsetState *neg = (void *)((uint8_t *)env - DIFF_NEG); - memcpy(diff_neg_c, neg, DIFF_NEG); - for (int i = 0; i < NB_MMU_MODES; i++) { - diff_tlb_c[i] = g_realloc(diff_tlb_c[i], diff_tlb_size[i]); - diff_fulltlb_c[i] = g_realloc(diff_fulltlb_c[i], diff_fulltlb_size[i]); - memcpy(diff_tlb_c[i], neg->tlb.f[i].table, diff_tlb_size[i]); - memcpy(diff_fulltlb_c[i], neg->tlb.d[i].fulltlb, diff_fulltlb_size[i]); - } -} - -static void diff_restore_compiled_post(CPUArchState *env) -{ - CPUNegativeOffsetState *neg = (void *)((uint8_t *)env - DIFF_NEG); - cpu_physical_memory_write(DIFF_DRAM_BASE, diff_dram_c, DIFF_DRAM_SIZE); - memcpy(env, diff_env_c, sizeof(CPUArchState)); - memcpy(neg, diff_neg_c, DIFF_NEG); - for (int i = 0; i < NB_MMU_MODES; i++) { - memcpy(neg->tlb.f[i].table, diff_tlb_c[i], diff_tlb_size[i]); - memcpy(neg->tlb.d[i].fulltlb, diff_fulltlb_c[i], diff_fulltlb_size[i]); - } -} - -static bool diff_run_compiled(const void *tb_ptr) -{ - ctx.tb_ptr = (uint32_t *)tb_ptr; - ctx.do_init = 1; - ctx.done_flag = 2; - int slot_off = (uint32_t)ctx.tb_ptr + export_vec_off; - g_assert(*(int32_t *)slot_off > 0); - diff_compiled_ret = ((wasm_func_ptr)(*(uint32_t *)slot_off))(&ctx); - memcpy(diff_env_c, ctx.env, sizeof(CPUArchState)); - cpu_physical_memory_read(DIFF_DRAM_BASE, diff_dram_c, DIFF_DRAM_SIZE); - /* done_flag 2 = pure inline (no slow path); 1 = completed store slow-path - * helper. Both finished this TB (tb_ptr==0); 0 = genuine unwind, skip. */ - return ctx.done_flag != 0 && (uint32_t)ctx.tb_ptr == 0; -} - uintptr_t QEMU_DISABLE_CFI tcg_qemu_tb_exec(CPUArchState *env, const void *v_tb_ptr) { ctx.env = env; ctx.tb_ptr = (uint32_t*)v_tb_ptr; ctx.do_init = 1; - wasm_update_tlb_guard(env); - - if (wasm_diff_mode == 2) { - if (!diff_started) { - printf("TCGDIFF2 enabled first-pc=0x%llx\n", - (unsigned long long)wasm_cur_tb_pc); - fflush(stdout); - diff_started = 1; - } - uint64_t pc = 0; - int slot = *(int32_t *)((uint32_t)ctx.tb_ptr + export_vec_off); - bool eligible = !diff_reported && slot > 0 && - wasm_diff_lookup_store_tb(v_tb_ptr, &pc) && - wasm_diff_lookup_safe_tb(v_tb_ptr) && - pc >= DIFF_PC_LO && pc < DIFF_PC_HI; - if (eligible) { - if (!diff_announced) { - printf("TCGDIFF2 active first-store-pc=0x%llx\n", - (unsigned long long)pc); - fflush(stdout); - diff_announced = 1; - } - diff_snapshot_pre(); - struct wasmContext pre_ctx = ctx; - - /* Run compiled LIVE (authoritative buggy path); accumulate its state. */ - bool compiled_complete = diff_run_compiled(v_tb_ptr); - uint32_t res = diff_compiled_ret; - diff_capture_compiled_post(env); - struct wasmContext c_ctx = ctx; - - diff2_eligible++; - if (!compiled_complete) { - diff2_incomplete++; - } - if ((diff2_eligible % 20000) == 0) { - printf("TCGDIFF2 progress eligible=%u incomplete=%u race=%u compared=%u pc=0x%llx\n", - diff2_eligible, diff2_incomplete, diff2_race, diff_compared, - (unsigned long long)pc); - fflush(stdout); - } - - /* Rewind, run the known-good TCI shadow, compare. */ - if (compiled_complete && diff_restore_pre(env)) { - ctx = pre_ctx; - do { - tcg_qemu_tb_exec_tci(env); - } while ((uint32_t)ctx.tb_ptr != 0); - memcpy(diff_env_t, env, sizeof(CPUArchState)); - memcpy(diff_neg_t, (uint8_t *)env - DIFF_NEG, DIFF_NEG); - cpu_physical_memory_read(DIFF_DRAM_BASE, diff_dram_t, DIFF_DRAM_SIZE); - uint32_t neg8_t_flag; - memcpy(&neg8_t_flag, diff_neg_t + DIFF_NEG - 8, 4); - if (neg8_t_flag & 0xffff0000) { - diff2_race++; - } else { - diff_compared++; - if (diff_compared == 1 || diff_compared % 10000 == 0) { - printf("TCGDIFF2 compared=%u pc=0x%llx\n", diff_compared, - (unsigned long long)pc); - fflush(stdout); - } - diff_report(pc); - } - } - - /* Restore the live compiled trajectory and continue. */ - diff_restore_compiled_post(env); - ctx = c_ctx; - return res; - } - /* Non-eligible: fall through to normal dispatch (compiled runs live). */ - } else if (wasm_diff_mode == 1) { - if (!diff_started) { - printf("TCGDIFF enabled first-pc=0x%llx tb-meta=0x%08x\n", - (unsigned long long)wasm_cur_tb_pc, *(uint32_t *)ctx.tb_ptr); - fflush(stdout); - diff_started = 1; - } - uint64_t pc = 0; - bool is_store_tb = wasm_diff_lookup_store_tb(v_tb_ptr, &pc); - int eligible = !diff_reported && is_store_tb && - wasm_diff_lookup_safe_tb(v_tb_ptr) && - pc >= DIFF_PC_LO && pc < DIFF_PC_HI; - if (eligible) { - if (!diff_announced) { - printf("TCGDIFF active first-store-pc=0x%llx\n", (unsigned long long)pc); - fflush(stdout); - diff_announced = 1; - } - - diff_ensure_compiled(v_tb_ptr); - struct wasmContext pre_ctx = ctx; - diff_snapshot_pre(); - - /* Run and retain the authoritative TCI result first. */ - uint32_t res; - int tci_iters = 0; - do { - res = tcg_qemu_tb_exec_tci(env); - tci_iters++; - } while ((uint32_t)ctx.tb_ptr != 0); - diff_tci_iters = tci_iters; - struct wasmContext tci_ctx = ctx; - memcpy(diff_env_t, env, sizeof(CPUArchState)); - memcpy(diff_neg_t, (uint8_t *)env - DIFF_NEG, DIFF_NEG); - cpu_physical_memory_read(DIFF_DRAM_BASE, diff_dram_t, DIFF_DRAM_SIZE); - - /* Rewind guest state, run compiled as a shadow, then restore TCI. */ - bool restored = diff_restore_pre(env); - ctx = pre_ctx; - bool compiled_complete = restored && diff_run_compiled(v_tb_ptr); - cpu_physical_memory_write(DIFF_DRAM_BASE, diff_dram_t, DIFF_DRAM_SIZE); - memcpy(env, diff_env_t, sizeof(CPUArchState)); - memcpy((uint8_t *)env - DIFF_NEG, diff_neg_t, DIFF_NEG); - ctx = tci_ctx; - - /* Skip Async-Exit Races - If the IO thread forced a CPU exit - * (icount_decr.high == -1) around the TCI run, TCI took the TB-entry - * interrupt exit while the restored compiled shadow saw a cleared - * flag and ran fully. That divergence is a harness race, not codegen. */ - uint32_t neg8_t_flag; - memcpy(&neg8_t_flag, diff_neg_t + DIFF_NEG - 8, 4); - if (neg8_t_flag & 0xffff0000) { - compiled_complete = false; - } - - if (compiled_complete && !diff_reported) { - diff_compared++; - if (diff_compared == 1 || diff_compared % 10000 == 0) { - printf("TCGDIFF compared=%u pc=0x%llx\n", diff_compared, - (unsigned long long)pc); - fflush(stdout); - } - diff_report(pc); - } else if (!diff_skipped_slow) { - printf("TCGDIFF skip-slow-path pc=0x%llx\n", (unsigned long long)pc); - fflush(stdout); - diff_skipped_slow = 1; - } - return res; - } - } - while (true) { int tb_entry_ptr = (uint32_t)ctx.tb_ptr + export_vec_off; uint32_t res; - uint32_t prev_tb = (uint32_t)ctx.tb_ptr; - bool was_compiled = false; - bool diff_store_tci = wasm_diff_mode == 1 && - wasm_diff_lookup_store_tb(ctx.tb_ptr, NULL); - if (diff_store_tci) { - res = tcg_qemu_tb_exec_tci(env); - } else if (*(int32_t*)tb_entry_ptr > 0) { + if (*(int32_t*)tb_entry_ptr > 0) { res = ((wasm_func_ptr)(*(uint32_t*)tb_entry_ptr))(&ctx); - was_compiled = true; } else if (*(int32_t *)tb_entry_ptr == WASM_TCI_ONLY_ENTRY) { res = tcg_qemu_tb_exec_tci(env); } else if (*(int32_t*)tb_entry_ptr > (-1 * INSTANTIATE_NUM)) { @@ -1860,23 +1275,6 @@ uintptr_t QEMU_DISABLE_CFI tcg_qemu_tb_exec(CPUArchState *env, instantiate_wasm(); qatomic_inc(&instantiated_wasm_count); res = ((wasm_func_ptr)(*(uint32_t*)tb_entry_ptr))(&ctx); - was_compiled = true; - } - if (was_compiled) { - uint64_t pc = 0; - wasm_diff_lookup_store_tb((void *)prev_tb, &pc); - wasm_trace_dram_tlb(env, pc); - } - /* E17: a compiled TB that returns non-zero with the same tb_ptr and - * do_init still clear is a mid-TB yield/resume (rewind path), not a - * chain (chains set do_init=1) and not completion (tb_ptr==0). */ - if (wasm_yield_trace && was_compiled && (uint32_t)ctx.tb_ptr == prev_tb && - (uint32_t)ctx.tb_ptr != 0 && ctx.do_init == 0) { - wasm_yield_reentries++; - if (wasm_yield_reentries <= 20 || (wasm_yield_reentries % 5000) == 0) { - printf("YIELD reentry #%u tb=0x%x\n", wasm_yield_reentries, prev_tb); - fflush(stdout); - } } if ((uint32_t)ctx.tb_ptr == 0) { return res; diff --git a/tcg/wasm32.h b/tcg/wasm32.h index 0739de937a..a8b525abe3 100644 --- a/tcg/wasm32.h +++ b/tcg/wasm32.h @@ -18,12 +18,6 @@ struct wasmContext { uint64_t *stack128; // 28 uint32_t unwinding; - // 32 - uint32_t tlb_guard_lo; - // 36 - uint32_t tlb_guard_hi; - // 40 - uint32_t tlb_guard_on; }; #define ENV_OFF 0 @@ -34,9 +28,6 @@ struct wasmContext { #define DONE_FLAG_OFF 20 #define STACK128_OFF 24 #define UNWINDING_OFF 28 -#define TLB_GUARD_LO_OFF 32 -#define TLB_GUARD_HI_OFF 36 -#define TLB_GUARD_ON_OFF 40 void set_done_flag(); @@ -50,39 +41,6 @@ void flush_tb_instances(void); void init_wasm32(); -void wasm_dump_module(const uint8_t *p, int len, const char *name); - -/* TCG compiled-vs-TCI differential (debug, opt-in via wasm_diff_enable()). - * wasm_cur_tb_pc is the guest PC of the TB about to run, set by cpu_tb_exec. */ -extern __thread uint64_t wasm_cur_tb_pc; -extern int wasm_diff_mode; -extern int wasm_store_tci_disabled; -extern int wasm_store_tci_hash; -extern int wasm_store_helper_tci; -extern int wasm_store_bisect_on; -extern int wasm_store_bisect_width; -extern uint64_t wasm_store_pc_lo; -extern uint64_t wasm_store_pc_hi; -extern uint64_t wasm_dump_pc_lo; -extern uint64_t wasm_dump_pc_hi; -extern uint32_t wasm_store_bisect_mask; -extern uint32_t wasm_store_bisect_val; -void wasm_disable_store_tci(void); -void wasm_set_store_tci_hash(int mode); -void wasm_set_store_helper_tci(void); -void wasm_set_store_bisect(int width, uint32_t mask, uint32_t val); -void wasm_set_store_pc_window(uint32_t lo, uint32_t hi); -void wasm_set_dump_pc_window(uint32_t lo, uint32_t hi); -void wasm_diff_enable(void); -void wasm_diff_enable2(void); -int wasm_diff_on(void); -int wasm_diff_needs_nochain(void); -int wasm_diff_needs_nochain_at(uint64_t pc); -void wasm_diff_register_tb(const void *rw_ptr, const void *rx_ptr, uint64_t pc, - bool has_store, bool safe_shadow); -bool wasm_diff_lookup_store_tb(const void *tb_ptr, uint64_t *pc); -bool wasm_diff_lookup_safe_tb(const void *tb_ptr); - extern __thread bool wasm_tci_only_tb; #define INSTANTIATE_NUM 1500 diff --git a/tcg/wasm32/tcg-target.c.inc b/tcg/wasm32/tcg-target.c.inc index 98de221ac4..85f7038e9d 100644 --- a/tcg/wasm32/tcg-target.c.inc +++ b/tcg/wasm32/tcg-target.c.inc @@ -2235,25 +2235,6 @@ static uint8_t tcg_wasm_out_tlb_load(TCGContext *s, TCGReg addr, MemOpIdx oi, bo tcg_wasm_out_op_i64_add(s); tcg_wasm_out_op_local_set(s, TMP64_0_IDX); - if (!is_ld) { - tcg_wasm_out_ctx_i32_load(s, TLB_GUARD_ON_OFF); - tcg_wasm_out_op_if_noret(s); - tcg_wasm_out_op_local_get(s, TMP64_0_IDX); - tcg_wasm_out_op_i32_wrap_i64(s); - tcg_wasm_out_ctx_i32_load(s, TLB_GUARD_LO_OFF); - tcg_wasm_out_op_i32_ge_u(s); - tcg_wasm_out_op_local_get(s, TMP64_0_IDX); - tcg_wasm_out_op_i32_wrap_i64(s); - tcg_wasm_out_ctx_i32_load(s, TLB_GUARD_HI_OFF); - tcg_wasm_out_op_i32_lt_u(s); - tcg_wasm_out_op_i32_and(s); - tcg_wasm_out_op_if_noret(s); - tcg_wasm_out_op_i64_const(s, 0); - tcg_wasm_out_op_local_set(s, TMP64_0_IDX); - tcg_wasm_out_op_end(s); - tcg_wasm_out_op_end(s); - } - tcg_wasm_out_op_end(s); @@ -3383,14 +3364,8 @@ static uint8_t tcg_tci_out_qemu_ldst(TCGContext *s, TCGOpcode opc, const TCGArg insn = deposit32(insn, 0, 8, opc); tcg_tci_out32(s, insn); } -/* Dump tags: instrumentation-only, set during codegen so tcg.c can dump one store-TB / load-TB - * module for static analysis. No effect on emitted code. */ -__thread bool wasm_tb_had_store; -__thread bool wasm_tb_had_load; -__thread bool wasm_tb_had_helper; static void tcg_out_qemu_ld(TCGContext *s, TCGOpcode opc, const TCGArg *args, bool is_64) { - wasm_tb_had_load = true; tcg_tci_out_qemu_ldst(s, opc, args); // Aliased qemu_ld - The wasm32 wrapper corrupts vCPU TLB state when the load destination also holds the address. if (args[0] == args[1]) { @@ -3400,40 +3375,8 @@ static void tcg_out_qemu_ld(TCGContext *s, TCGOpcode opc, const TCGArg *args, bo } static void tcg_out_qemu_st(TCGContext *s, TCGOpcode opc, const TCGArg *args, bool is_64) { - wasm_tb_had_store = true; tcg_tci_out_qemu_ldst(s, opc, args); tcg_wasm_out_qemu_st(s, args, is_64); - bool store_tci = false; - if (s->gen_tb && (wasm_store_tci_hash || wasm_store_bisect_on)) { - uint64_t pc = s->gen_tb->pc; - uint32_t h = (uint32_t)((pc * 0x9e3779b97f4a7c15ull) >> 33); - if (wasm_store_bisect_on) { - /* Bisect one width: other widths stay compiled so their culprit is - * always present; the bisected width compiles only its hash bucket. - * This makes finding each culprit a single-target binary search. */ - int w = 1 << (opc & MO_SIZE); - bool compiled; - if (wasm_store_bisect_width && w != wasm_store_bisect_width) { - compiled = true; - } else { - compiled = (h & wasm_store_bisect_mask) == wasm_store_bisect_val; - if (compiled) { - printf("STBISECT compile pc=0x%llx h=0x%x w=%d\n", - (unsigned long long)pc, h, w); - fflush(stdout); - } - } - store_tci = !compiled; - } else { - store_tci = ((h & 1) == (uint32_t)(wasm_store_tci_hash - 1)); - } - } - if (wasm_store_helper_tci && (wasm_tb_had_helper || wasm_tb_had_load)) { - store_tci = true; - } - if (wasm_diff_mode != 2 && store_tci) { - wasm_tci_only_tb = true; - } } static void tcg_out_deposit_i32(TCGContext *s, TCGOpcode opc, TCGReg dest, TCGReg arg1, TCGReg arg2, int pos, int len) { @@ -3557,7 +3500,6 @@ static bool tcg_out_sti(TCGContext *s, TCGType type, TCGArg val, static void tcg_out_call(TCGContext *s, const tcg_insn_unit *target, const TCGHelperInfo *info) { - wasm_tb_had_helper = true; tcg_tci_out_call(s, target, info); tcg_wasm_out_call(s, target, info); } @@ -3837,9 +3779,6 @@ void tcg_out_init() { current_label_pos = 0; env_cached = false; wasm_tci_only_tb = false; - wasm_tb_had_store = false; - wasm_tb_had_load = false; - wasm_tb_had_helper = false; } /* Test if a constant matches the constraint. */