From 40745877755fe575207679ec7b3e49d98386a490 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Wed, 11 Apr 2018 19:48:47 -0400 Subject: [PATCH] accel/tcg/translate-all: expand cpu_restore_state addr check We are still seeing signals during translation time when we walk over a page protection boundary. This expands the check to ensure the host PC is inside the code generation buffer. The original suggestion was to check versus tcg_ctx.code_gen_ptr but as we now segment the translation buffer we have to settle for just a general check for being inside. I've also fixed up the declaration to make it clear it can deal with invalid addresses. A later patch will fix up the call sites. Backports commit d25f2a72272b9ffe0d06710d6217d1169bc2cc7d from qemu --- qemu/accel/tcg/translate-all.c | 50 ++++++++++++++++++++-------------- qemu/include/exec/exec-all.h | 11 ++++++++ 2 files changed, 40 insertions(+), 21 deletions(-) diff --git a/qemu/accel/tcg/translate-all.c b/qemu/accel/tcg/translate-all.c index 0f1a7a28..3ee894f9 100644 --- a/qemu/accel/tcg/translate-all.c +++ b/qemu/accel/tcg/translate-all.c @@ -332,35 +332,43 @@ found: return 0; } -bool cpu_restore_state(CPUState *cpu, uintptr_t retaddr) +bool cpu_restore_state(CPUState *cpu, uintptr_t host_pc) { TranslationBlock *tb; CPUArchState *env = cpu->env_ptr; + TCGContext* tcg_ctx = env->uc->tcg_ctx; + bool r = false; + uintptr_t check_offset; - /* A retaddr of zero is invalid so we really shouldn't have ended - * up here. The target code has likely forgotten to check retaddr - * != 0 before attempting to restore state. We return early to - * avoid blowing up on a recursive tb_lock(). The target must have - * previously survived a failed cpu_restore_state because - * tb_find_pc(0) would have failed anyway. It still should be - * fixed though. + /* The host_pc has to be in the region of current code buffer. If + * it is not we will not be able to resolve it here. The two cases + * where host_pc will not be correct are: + * + * - fault during translation (instruction fetch) + * - fault from helper (not using GETPC() macro) + * + * Either way we need return early to avoid blowing up on a + * recursive tb_lock() as we can't resolve it here. + * + * We are using unsigned arithmetic so if host_pc < + * tcg_init_ctx.code_gen_buffer check_offset will wrap to way + * above the code_gen_buffer_size */ + check_offset = host_pc - (uintptr_t) tcg_ctx->code_gen_buffer; - if (!retaddr) { - return false; - } - - tb = tb_find_pc(env->uc, retaddr); - if (tb) { - cpu_restore_state_from_tb(cpu, tb, retaddr); - if (tb->cflags & CF_NOCACHE) { - /* one-shot translation, invalidate it immediately */ - tb_phys_invalidate(cpu->uc, tb, -1); - tb_free(cpu->uc, tb); + if (check_offset < tcg_ctx->code_gen_buffer_size) { + tb = tb_find_pc(env->uc, host_pc); + if (tb) { + cpu_restore_state_from_tb(cpu, tb, host_pc); + if (tb->cflags & CF_NOCACHE) { + /* one-shot translation, invalidate it immediately */ + tb_phys_invalidate(cpu->uc, tb, -1); + tb_free(cpu->uc, tb); + } + r = true; } - return true; } - return false; + return r; } static void page_init(struct uc_struct *uc) diff --git a/qemu/include/exec/exec-all.h b/qemu/include/exec/exec-all.h index 97ed437f..7670a877 100644 --- a/qemu/include/exec/exec-all.h +++ b/qemu/include/exec/exec-all.h @@ -42,6 +42,17 @@ typedef ram_addr_t tb_page_addr_t; void gen_intermediate_code(CPUState *cpu, struct TranslationBlock *tb); void restore_state_to_opc(CPUArchState *env, struct TranslationBlock *tb, target_ulong *data); + +/** + * cpu_restore_state: + * @cpu: the vCPU state is to be restore to + * @searched_pc: the host PC the fault occurred at + * @return: true if state was restored, false otherwise + * + * Attempt to restore the state for a fault occurring in translated + * code. If the searched_pc is not in translated code no state is + * restored and the function returns false. + */ bool cpu_restore_state(CPUState *cpu, uintptr_t searched_pc); void QEMU_NORETURN cpu_loop_exit_noexc(CPUState *cpu);