From e4a6de07c63b20116af697f4ac6ba678c9208626 Mon Sep 17 00:00:00 2001 From: Evan Reichard Date: Thu, 23 Jul 2026 10:37:23 -0400 Subject: [PATCH] tcg/wasm32: add tlbguard and store-PC window probes --- tcg/tcg.c | 6 +++++ tcg/wasm32.c | 50 +++++++++++++++++++++++++++++++++++++ tcg/wasm32.h | 12 +++++++++ tcg/wasm32/tcg-target.c.inc | 21 ++++++++++++++++ 4 files changed, 89 insertions(+) diff --git a/tcg/tcg.c b/tcg/tcg.c index 7a2be94fe1..423ba72451 100644 --- a/tcg/tcg.c +++ b/tcg/tcg.c @@ -6610,6 +6610,12 @@ int tcg_gen_code(TCGContext *s, TranslationBlock *tb, uint64_t pc_start) 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; diff --git a/tcg/wasm32.c b/tcg/wasm32.c index c7ba52c7fd..3e78b3b05e 100644 --- a/tcg/wasm32.c +++ b/tcg/wasm32.c @@ -33,7 +33,9 @@ #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; @@ -200,6 +202,39 @@ 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) { @@ -1329,10 +1364,13 @@ static __thread uint8_t *diff_fulltlb_c[NB_MMU_MODES]; int wasm_diff_mode; int wasm_stateflush_enabled; +int wasm_tlb_guard_enabled; int wasm_store_tci_disabled; int wasm_store_tci_hash; 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; @@ -1367,6 +1405,12 @@ EMSCRIPTEN_KEEPALIVE void wasm_set_store_bisect(int width, uint32_t mask, uint32 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; @@ -1384,6 +1428,11 @@ EMSCRIPTEN_KEEPALIVE void wasm_stateflush_enable(void) wasm_stateflush_enabled = 1; } +EMSCRIPTEN_KEEPALIVE void wasm_tlb_guard_enable(void) +{ + wasm_tlb_guard_enabled = 1; +} + int wasm_diff_on(void) { return wasm_diff_enabled; @@ -1627,6 +1676,7 @@ uintptr_t QEMU_DISABLE_CFI tcg_qemu_tb_exec(CPUArchState *env, 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) { diff --git a/tcg/wasm32.h b/tcg/wasm32.h index 8d23edffaa..c09765c1ef 100644 --- a/tcg/wasm32.h +++ b/tcg/wasm32.h @@ -18,6 +18,12 @@ 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 @@ -28,6 +34,9 @@ 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(); @@ -51,11 +60,14 @@ extern int wasm_store_tci_disabled; extern int wasm_store_tci_hash; 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 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_bisect(int width, uint32_t mask, uint32_t val); +void wasm_set_store_pc_window(uint32_t lo, uint32_t hi); void wasm_diff_enable(void); void wasm_diff_enable2(void); int wasm_diff_on(void); diff --git a/tcg/wasm32/tcg-target.c.inc b/tcg/wasm32/tcg-target.c.inc index c15e2ad845..1edfdaf382 100644 --- a/tcg/wasm32/tcg-target.c.inc +++ b/tcg/wasm32/tcg-target.c.inc @@ -386,6 +386,8 @@ static void tcg_wasm_out_op_end(TCGContext *s) static void tcg_wasm_out_op_i32_eqz(TCGContext *s){ tcg_wasm_out8(s, 0x45); } static void tcg_wasm_out_op_i32_eq(TCGContext *s){ tcg_wasm_out8(s, 0x46); } +static void tcg_wasm_out_op_i32_lt_u(TCGContext *s){ tcg_wasm_out8(s, 0x49); } +static void tcg_wasm_out_op_i32_ge_u(TCGContext *s){ tcg_wasm_out8(s, 0x4f); } static void tcg_wasm_out_op_i32_and(TCGContext *s){ tcg_wasm_out8(s, 0x71); } static void tcg_wasm_out_op_i32_or(TCGContext *s){ tcg_wasm_out8(s, 0x72); } //static void tcg_wasm_out_op_i32_xor(TCGContext *s){ tcg_wasm_out8(s, 0x73); } @@ -2232,6 +2234,25 @@ static uint8_t tcg_wasm_out_tlb_load(TCGContext *s, TCGReg addr, MemOpIdx oi, bo tcg_wasm_out_op_global_get_r(s, addr); 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);