accel/tcg: Fix tb_invalidate_phys_page_unwind

When called from syscall(), we are not within a TB and pc == 0.
We can skip the check for invalidating the current TB.

Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
Richard Henderson 2022-12-24 04:35:22 -08:00
parent cee44b037b
commit 1b660f42ef
1 changed files with 43 additions and 35 deletions

View File

@ -1024,43 +1024,51 @@ void tb_invalidate_phys_page(tb_page_addr_t addr)
*/ */
bool tb_invalidate_phys_page_unwind(tb_page_addr_t addr, uintptr_t pc) bool tb_invalidate_phys_page_unwind(tb_page_addr_t addr, uintptr_t pc)
{ {
assert(pc != 0); TranslationBlock *current_tb;
#ifdef TARGET_HAS_PRECISE_SMC bool current_tb_modified;
assert_memory_lock(); TranslationBlock *tb;
{ PageForEachNext n;
TranslationBlock *current_tb = tcg_tb_lookup(pc);
bool current_tb_modified = false;
TranslationBlock *tb;
PageForEachNext n;
addr &= TARGET_PAGE_MASK; /*
* Without precise smc semantics, or when outside of a TB,
PAGE_FOR_EACH_TB(addr, addr + TARGET_PAGE_SIZE, unused, tb, n) { * we can skip to invalidate.
if (current_tb == tb && */
(tb_cflags(current_tb) & CF_COUNT_MASK) != 1) { #ifndef TARGET_HAS_PRECISE_SMC
/* pc = 0;
* If we are modifying the current TB, we must stop its #endif
* execution. We could be more precise by checking that if (!pc) {
* the modification is after the current PC, but it would tb_invalidate_phys_page(addr);
* require a specialized function to partially restore return false;
* the CPU state. }
*/
current_tb_modified = true; assert_memory_lock();
cpu_restore_state_from_tb(current_cpu, current_tb, pc); current_tb = tcg_tb_lookup(pc);
}
tb_phys_invalidate__locked(tb); addr &= TARGET_PAGE_MASK;
} current_tb_modified = false;
if (current_tb_modified) { PAGE_FOR_EACH_TB(addr, addr + TARGET_PAGE_SIZE, unused, tb, n) {
/* Force execution of one insn next time. */ if (current_tb == tb &&
CPUState *cpu = current_cpu; (tb_cflags(current_tb) & CF_COUNT_MASK) != 1) {
cpu->cflags_next_tb = 1 | CF_NOIRQ | curr_cflags(current_cpu); /*
return true; * If we are modifying the current TB, we must stop its
} * execution. We could be more precise by checking that
* the modification is after the current PC, but it would
* require a specialized function to partially restore
* the CPU state.
*/
current_tb_modified = true;
cpu_restore_state_from_tb(current_cpu, current_tb, pc);
}
tb_phys_invalidate__locked(tb);
}
if (current_tb_modified) {
/* Force execution of one insn next time. */
CPUState *cpu = current_cpu;
cpu->cflags_next_tb = 1 | CF_NOIRQ | curr_cflags(current_cpu);
return true;
} }
#else
tb_invalidate_phys_page(addr);
#endif /* TARGET_HAS_PRECISE_SMC */
return false; return false;
} }
#else #else