diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c index 7fc3fd0b8b..c6c5ab00ab 100644 --- a/accel/tcg/cputlb.c +++ b/accel/tcg/cputlb.c @@ -1107,6 +1107,16 @@ 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. */ @@ -1199,6 +1209,15 @@ 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; @@ -1418,6 +1437,15 @@ 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)) @@ -1708,6 +1736,16 @@ 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 index=%lu maybe_resized=%d tlb_addr=0x%llx flags=0x%x full=%p full_xlat=0x%llx addend=0x%llx\n", + (unsigned long long)addr, (unsigned long)index, maybe_resized, + (unsigned long long)tlb_addr, flags, 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); @@ -2007,6 +2045,15 @@ 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 3958314765..0e0a8a95ee 100644 --- a/system/memory.c +++ b/system/memory.c @@ -32,6 +32,7 @@ #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" @@ -1404,6 +1405,10 @@ 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, @@ -1416,6 +1421,16 @@ 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 937ac4d663..fa963be27b 100644 --- a/system/physmem.c +++ b/system/physmem.c @@ -2979,6 +2979,15 @@ 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; } diff --git a/tcg/wasm32.c b/tcg/wasm32.c index 53fd8e58c1..c7ba52c7fd 100644 --- a/tcg/wasm32.c +++ b/tcg/wasm32.c @@ -32,6 +32,7 @@ #include #include "wasm32.h" +extern int wasm_ramrace_trace; __thread uintptr_t tci_tb_ptr; __thread bool wasm_tci_only_tb; static int instantiated_wasm_count; @@ -1318,6 +1319,7 @@ 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. */ @@ -1398,12 +1400,53 @@ int wasm_diff_needs_nochain_at(uint64_t pc) 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 read=0x%llx write=0x%llx addend=0x%llx full_xlat=0x%llx\n", + (unsigned long long)pc, mmu, i, + (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 (!wasm_diff_on()) { - return; - } 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); @@ -1750,6 +1793,11 @@ uintptr_t QEMU_DISABLE_CFI tcg_qemu_tb_exec(CPUArchState *env, 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). */