diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c index 5201fd5cbd..b4e6ec4949 100644 --- a/accel/tcg/cpu-exec.c +++ b/accel/tcg/cpu-exec.c @@ -1082,6 +1082,24 @@ static inline void cpu_loop_exec_tb(CPUState *cpu, TranslationBlock *tb, #endif } +static void retranslation_segv_tb(CPUState *cpu) +{ + if (option_mem_test != 1) { + return; + } + CPUX86State *env = (CPUX86State *)cpu->env_ptr; + TranslationBlock *tb = env->segv_tb; + if (!tb || (tb->bool_flags & IS_MT_TB)) { + return; + } + mmap_lock(); + tb_phys_invalidate(tb, tb->pc & TARGET_PAGE_MASK); + mem_test_retrans_insert(tb->pc); + tb_gen_code(cpu, tb->pc, 0, tb->flags, tb->cflags & ~CF_INVALID); + env->segv_tb = NULL; + mmap_unlock(); +} + /* main execution loop */ int cpu_exec(CPUState *cpu) { @@ -1180,6 +1198,10 @@ int cpu_exec(CPUState *cpu) } } + if (ret == EXCP0E_PAGE) { + retranslation_segv_tb(cpu); + } + cpu_exec_exit(cpu); rcu_read_unlock(); diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c index 44ccc3f9e2..769dddf5d4 100644 --- a/accel/tcg/translate-all.c +++ b/accel/tcg/translate-all.c @@ -139,6 +139,48 @@ void tu_reset_tb(TranslationBlock *tb); result; \ }) /* EXPAND_TO_64BIT */ +static __thread GTree *mem_test_retrans_tree; +static gint pc_cmp(gconstpointer ap, gconstpointer bp) +{ + const target_ulong *a = ap; + const target_ulong *b = bp; + if (*a > *b) { + return 1; + } else if (*a < *b) { + return -1; + } + return 0; +} + +static inline void mem_test_retrans_tree_init(void) +{ + if (mem_test_retrans_tree) return; + mem_test_retrans_tree = g_tree_new(pc_cmp); +} + +static inline void *mem_test_retrans_lookup(uint64_t pc) +{ + if ((option_mem_test != 1)|| !mem_test_retrans_tree) + return NULL; + pc &= TARGET_PAGE_MASK; + return g_tree_lookup(mem_test_retrans_tree, &pc); +} + +bool mem_test_retrans_insert(target_ulong pc) +{ + if (option_mem_test != 1) + return false; + pc &= TARGET_PAGE_MASK; + mem_test_retrans_tree_init(); + target_ulong *key = malloc(sizeof(target_ulong)); + *key = pc; + if (!mem_test_retrans_lookup(pc)) { + g_tree_insert(mem_test_retrans_tree, key, key); + return true; + } + return false; +} + #ifdef CONFIG_LATX_SMC_OPT /* @@ -465,6 +507,9 @@ static int cpu_restore_state_from_tb(CPUState *cpu, TranslationBlock *tb, return -1; found: + if ((option_mem_test == 1) && !(tb->bool_flags & IS_MT_TB)) { + env->segv_tb = tb; + } if (reset_icount && (tb_cflags(tb) & CF_USE_ICOUNT)) { assert(icount_enabled()); /* Reset the cycle counter to the start of the block @@ -2191,6 +2236,10 @@ TranslationBlock *tb_gen_code(CPUState *cpu, #endif #endif + if (mem_test_retrans_lookup(pc)) { + tb->bool_flags |= IS_MT_TB; + } + #ifndef CONFIG_LATX #ifdef CONFIG_PROFILER /* includes aborted translations because of exceptions */ diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h index f69cc2e38b..af3f4ce761 100644 --- a/include/exec/exec-all.h +++ b/include/exec/exec-all.h @@ -66,6 +66,8 @@ void restore_state_to_opc(CPUArchState *env, TranslationBlock *tb, target_ulong *data); int encode_search(TranslationBlock *tb, uint8_t *block); +bool mem_test_retrans_insert(target_ulong pc); + /** * cpu_restore_state: * @cpu: the vCPU state is to be restore to @@ -647,8 +649,9 @@ struct TranslationBlock { #define SIGNAL_RELINK0 0x200 #define SIGNAL_UNLINK1 0x400 #define SIGNAL_RELINK1 0x800 -#define IS_CODE64 0x1000 -#define IS_TU_SPLIT 0x2000 +#define IS_CODE64 0x1000 +#define IS_TU_SPLIT 0x2000 +#define IS_MT_TB 0x4000 uint16_t bool_flags; uint8_t eflag_use; #ifdef CONFIG_LATX_INSTS_PATTERN diff --git a/target/i386/cpu.h b/target/i386/cpu.h index 7a3f8aeb89..e8f1cd28b1 100644 --- a/target/i386/cpu.h +++ b/target/i386/cpu.h @@ -1662,6 +1662,7 @@ typedef struct CPUX86State { ucontext_t *puc; uintptr_t insn_save[2]; #endif + TranslationBlock *segv_tb; } CPUX86State; struct kvm_msrs; diff --git a/target/i386/latx/translator/translate.c b/target/i386/latx/translator/translate.c index 1601fe5aa5..9d4de74956 100644 --- a/target/i386/latx/translator/translate.c +++ b/target/i386/latx/translator/translate.c @@ -3898,14 +3898,21 @@ static inline void helper_restore_reg(IR2_OPND opnd) void gen_test_page_flag(IR2_OPND mem_opnd, int mem_imm, uint32_t flag) { - if (!option_mem_test) { + if (!option_mem_test || !(flag & PAGE_WRITE)) { return; } - TranslationBlock *tb __attribute__((unused)) = NULL; - if (option_aot) { - tb = (TranslationBlock *)lsenv->tr_data->curr_tb; + + TranslationBlock *tb = (TranslationBlock *)lsenv->tr_data->curr_tb; + CPUX86State *cpu = (CPUX86State *)lsenv->cpu_state; + if ((option_mem_test == 1) && + (!cpu->segv_tb || (cpu->segv_tb->pc != tb->pc))) { + if ((tb->pc & ~TARGET_PAGE_MASK) != 0x259) { + return; + } } + tb->bool_flags |= IS_MT_TB; + IR2_OPND label_exit = ra_alloc_label(); IR2_OPND label0 = ra_alloc_label(); IR2_OPND label1 = ra_alloc_label();