tcg/wasm32: trace compiled-store TLB corruption under ramrace
This commit is contained in:
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
+51
-3
@@ -32,6 +32,7 @@
|
||||
#include <emscripten/threading.h>
|
||||
#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). */
|
||||
|
||||
Reference in New Issue
Block a user