@@ -344,6 +344,7 @@ struct CPUState {
bool unplug;
bool crash_occurred;
bool exit_request;
+ bool step_next_tb;
/* updates protected by BQL */
uint32_t interrupt_request;
int singlestep_enabled;
@@ -367,13 +367,12 @@ static inline void tb_add_jump(TranslationBlock *tb, int n,
static inline TranslationBlock *tb_find(CPUState *cpu,
TranslationBlock *last_tb,
- int tb_exit)
+ int tb_exit, uint32_t cf_mask)
{
TranslationBlock *tb;
target_ulong cs_base, pc;
uint32_t flags;
bool acquired_tb_lock = false;
- uint32_t cf_mask = curr_cflags();
tb = tb_lookup__cpu_state(cpu, &pc, &cs_base, &flags, cf_mask);
if (tb == NULL) {
@@ -501,7 +500,7 @@ static inline bool cpu_handle_exception(CPUState *cpu, int *ret)
} else if (replay_has_exception()
&& cpu->icount_decr.u16.low + cpu->icount_extra == 0) {
/* try to cause an exception pending in the log */
- cpu_exec_nocache(cpu, 1, tb_find(cpu, NULL, 0), true);
+ cpu_exec_nocache(cpu, 1, tb_find(cpu, NULL, 0, curr_cflags()), true);
*ret = -1;
return true;
#endif
@@ -697,7 +696,19 @@ int cpu_exec(CPUState *cpu)
int tb_exit = 0;
while (!cpu_handle_interrupt(cpu, &last_tb)) {
- TranslationBlock *tb = tb_find(cpu, last_tb, tb_exit);
+ uint32_t cf_mask = curr_cflags();
+ TranslationBlock *tb;
+
+ /* For precise smc, we generate a block containing just the
+ instruction modifying the memory, ensuring that it cannot
+ modify itself. We also need to single-step past a
+ stop-after-access watchpoint. */
+ if (cpu->step_next_tb) {
+ cf_mask |= 1;
+ cpu->step_next_tb = false;
+ }
+
+ tb = tb_find(cpu, last_tb, tb_exit, cf_mask);
cpu_loop_exec_tb(cpu, tb, &last_tb, &tb_exit);
/* Try to align the host and virtual clocks
if the guest is in advance */
@@ -1463,14 +1463,12 @@ void tb_invalidate_phys_page_range(tb_page_addr_t start, tb_page_addr_t end,
int is_cpu_write_access)
{
TranslationBlock *tb, *tb_next;
-#if defined(TARGET_HAS_PRECISE_SMC)
- CPUState *cpu = current_cpu;
- CPUArchState *env = NULL;
-#endif
tb_page_addr_t tb_start, tb_end;
PageDesc *p;
int n;
#ifdef TARGET_HAS_PRECISE_SMC
+ CPUState *cpu = current_cpu;
+ CPUArchState *env = NULL;
int current_tb_not_found = is_cpu_write_access;
TranslationBlock *current_tb = NULL;
int current_tb_modified = 0;
@@ -1547,11 +1545,7 @@ void tb_invalidate_phys_page_range(tb_page_addr_t start, tb_page_addr_t end,
#endif
#ifdef TARGET_HAS_PRECISE_SMC
if (current_tb_modified) {
- /* we generate a block containing just the instruction
- modifying the memory. It will ensure that it cannot modify
- itself */
- tb_gen_code(cpu, current_pc, current_cs_base, current_flags,
- 1 | curr_cflags());
+ cpu->step_next_tb = true;
cpu_loop_exit_noexc(cpu);
}
#endif
@@ -1666,11 +1660,7 @@ static bool tb_invalidate_phys_page(tb_page_addr_t addr, uintptr_t pc)
p->first_tb = NULL;
#ifdef TARGET_HAS_PRECISE_SMC
if (current_tb_modified) {
- /* we generate a block containing just the instruction
- modifying the memory. It will ensure that it cannot modify
- itself */
- tb_gen_code(cpu, current_pc, current_cs_base, current_flags,
- 1 | curr_cflags());
+ cpu->step_next_tb = true;
/* tb_lock will be reset after cpu_loop_exit_noexc longjmps
* back into the cpu_exec loop. */
return true;
@@ -2390,11 +2390,8 @@ static void check_watchpoint(int offset, int len, MemTxAttrs attrs, int flags)
{
CPUState *cpu = current_cpu;
CPUClass *cc = CPU_GET_CLASS(cpu);
- CPUArchState *env = cpu->env_ptr;
- target_ulong pc, cs_base;
target_ulong vaddr;
CPUWatchpoint *wp;
- uint32_t cpu_flags;
assert(tcg_enabled());
if (cpu->watchpoint_hit) {
@@ -2434,8 +2431,7 @@ static void check_watchpoint(int offset, int len, MemTxAttrs attrs, int flags)
cpu->exception_index = EXCP_DEBUG;
cpu_loop_exit(cpu);
} else {
- cpu_get_tb_cpu_state(env, &pc, &cs_base, &cpu_flags);
- tb_gen_code(cpu, pc, cs_base, cpu_flags, 1 | curr_cflags());
+ cpu->step_next_tb = true;
cpu_loop_exit_noexc(cpu);
}
}
We were generating code during tb_invalidate_phys_page_range and check_watchpoint, and (seemingly) discarding the TB, assuming that it would magically be picked up during the next iteration through the cpu_exec loop. Instead, set a flag in CPUState so that we set cflags to properly request a TB with a single guest insn so that there is no more magic. Signed-off-by: Richard Henderson <richard.henderson@linaro.org> --- include/qom/cpu.h | 1 + accel/tcg/cpu-exec.c | 19 +++++++++++++++---- accel/tcg/translate-all.c | 18 ++++-------------- exec.c | 6 +----- 4 files changed, 21 insertions(+), 23 deletions(-) -- 2.13.6