diff options
Diffstat (limited to 'accel/tcg/cpu-exec.c')
-rw-r--r-- | accel/tcg/cpu-exec.c | 112 |
1 files changed, 89 insertions, 23 deletions
diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c index ad1279d2ed..e22bcb99f7 100644 --- a/accel/tcg/cpu-exec.c +++ b/accel/tcg/cpu-exec.c @@ -38,8 +38,8 @@ #include "exec/cpu-all.h" #include "sysemu/cpu-timers.h" #include "sysemu/replay.h" +#include "exec/helper-proto.h" #include "tb-hash.h" -#include "tb-lookup.h" #include "tb-context.h" #include "internal.h" @@ -145,6 +145,93 @@ static void init_delay_params(SyncClocks *sc, const CPUState *cpu) } #endif /* CONFIG USER ONLY */ +/* Might cause an exception, so have a longjmp destination ready */ +static inline TranslationBlock *tb_lookup(CPUState *cpu, target_ulong pc, + target_ulong cs_base, + uint32_t flags, uint32_t cflags) +{ + TranslationBlock *tb; + uint32_t hash; + + /* we should never be trying to look up an INVALID tb */ + tcg_debug_assert(!(cflags & CF_INVALID)); + + hash = tb_jmp_cache_hash_func(pc); + tb = qatomic_rcu_read(&cpu->tb_jmp_cache[hash]); + + if (likely(tb && + tb->pc == pc && + tb->cs_base == cs_base && + tb->flags == flags && + tb->trace_vcpu_dstate == *cpu->trace_dstate && + tb_cflags(tb) == cflags)) { + return tb; + } + tb = tb_htable_lookup(cpu, pc, cs_base, flags, cflags); + if (tb == NULL) { + return NULL; + } + qatomic_set(&cpu->tb_jmp_cache[hash], tb); + return tb; +} + +static inline void log_cpu_exec(target_ulong pc, CPUState *cpu, + const TranslationBlock *tb) +{ + if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_CPU | CPU_LOG_EXEC)) + && qemu_log_in_addr_range(pc)) { + + qemu_log_mask(CPU_LOG_EXEC, + "Trace %d: %p [" TARGET_FMT_lx + "/" TARGET_FMT_lx "/%08x/%08x] %s\n", + cpu->cpu_index, tb->tc.ptr, tb->cs_base, pc, + tb->flags, tb->cflags, lookup_symbol(pc)); + +#if defined(DEBUG_DISAS) + if (qemu_loglevel_mask(CPU_LOG_TB_CPU)) { + FILE *logfile = qemu_log_lock(); + int flags = 0; + + if (qemu_loglevel_mask(CPU_LOG_TB_FPU)) { + flags |= CPU_DUMP_FPU; + } +#if defined(TARGET_I386) + flags |= CPU_DUMP_CCOP; +#endif + log_cpu_state(cpu, flags); + qemu_log_unlock(logfile); + } +#endif /* DEBUG_DISAS */ + } +} + +/** + * helper_lookup_tb_ptr: quick check for next tb + * @env: current cpu state + * + * Look for an existing TB matching the current cpu state. + * If found, return the code pointer. If not found, return + * the tcg epilogue so that we return into cpu_tb_exec. + */ +const void *HELPER(lookup_tb_ptr)(CPUArchState *env) +{ + CPUState *cpu = env_cpu(env); + TranslationBlock *tb; + target_ulong cs_base, pc; + uint32_t flags; + + cpu_get_tb_cpu_state(env, &pc, &cs_base, &flags); + + tb = tb_lookup(cpu, pc, cs_base, flags, curr_cflags(cpu)); + if (tb == NULL) { + return tcg_code_gen_epilogue; + } + + log_cpu_exec(pc, cpu, tb); + + return tb->tc.ptr; +} + /* Execute a TB, and fix up the CPU state afterwards if necessary */ /* * Disable CFI checks. @@ -163,28 +250,7 @@ cpu_tb_exec(CPUState *cpu, TranslationBlock *itb, int *tb_exit) TranslationBlock *last_tb; const void *tb_ptr = itb->tc.ptr; - qemu_log_mask_and_addr(CPU_LOG_EXEC, itb->pc, - "Trace %d: %p [" - TARGET_FMT_lx "/" TARGET_FMT_lx "/%#x] %s\n", - cpu->cpu_index, itb->tc.ptr, - itb->cs_base, itb->pc, itb->flags, - lookup_symbol(itb->pc)); - -#if defined(DEBUG_DISAS) - if (qemu_loglevel_mask(CPU_LOG_TB_CPU) - && qemu_log_in_addr_range(itb->pc)) { - FILE *logfile = qemu_log_lock(); - int flags = 0; - if (qemu_loglevel_mask(CPU_LOG_TB_FPU)) { - flags |= CPU_DUMP_FPU; - } -#if defined(TARGET_I386) - flags |= CPU_DUMP_CCOP; -#endif - log_cpu_state(cpu, flags); - qemu_log_unlock(logfile); - } -#endif /* DEBUG_DISAS */ + log_cpu_exec(itb->pc, cpu, itb); qemu_thread_jit_execute(); ret = tcg_qemu_tb_exec(env, tb_ptr); |