diff options
Diffstat (limited to 'accel')
-rw-r--r-- | accel/tcg/cpu-exec.c | 112 | ||||
-rw-r--r-- | accel/tcg/tb-context.h | 1 | ||||
-rw-r--r-- | accel/tcg/tb-lookup.h | 49 | ||||
-rw-r--r-- | accel/tcg/tcg-runtime.c | 22 | ||||
-rw-r--r-- | accel/tcg/translate-all.c | 23 | ||||
-rw-r--r-- | accel/tcg/translator.c | 11 |
6 files changed, 113 insertions, 105 deletions
diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c index ad1279d..e22bcb9 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); diff --git a/accel/tcg/tb-context.h b/accel/tcg/tb-context.h index cc33979..cac62d9 100644 --- a/accel/tcg/tb-context.h +++ b/accel/tcg/tb-context.h @@ -34,6 +34,7 @@ struct TBContext { /* statistics */ unsigned tb_flush_count; + unsigned tb_phys_invalidate_count; }; extern TBContext tb_ctx; diff --git a/accel/tcg/tb-lookup.h b/accel/tcg/tb-lookup.h deleted file mode 100644 index 9c9e007..0000000 --- a/accel/tcg/tb-lookup.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (C) 2017, Emilio G. Cota <cota@braap.org> - * - * License: GNU GPL, version 2 or later. - * See the COPYING file in the top-level directory. - */ -#ifndef EXEC_TB_LOOKUP_H -#define EXEC_TB_LOOKUP_H - -#ifdef NEED_CPU_H -#include "cpu.h" -#else -#include "exec/poison.h" -#endif - -#include "exec/exec-all.h" -#include "tb-hash.h" - -/* 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; -} - -#endif /* EXEC_TB_LOOKUP_H */ diff --git a/accel/tcg/tcg-runtime.c b/accel/tcg/tcg-runtime.c index 66ac830..e4e0300 100644 --- a/accel/tcg/tcg-runtime.c +++ b/accel/tcg/tcg-runtime.c @@ -30,7 +30,6 @@ #include "disas/disas.h" #include "exec/log.h" #include "tcg/tcg.h" -#include "tb-lookup.h" /* 32-bit helpers */ @@ -145,27 +144,6 @@ uint64_t HELPER(ctpop_i64)(uint64_t arg) return ctpop64(arg); } -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; - } - qemu_log_mask_and_addr(CPU_LOG_EXEC, pc, - "Chain %d: %p [" - TARGET_FMT_lx "/" TARGET_FMT_lx "/%#x] %s\n", - cpu->cpu_index, tb->tc.ptr, cs_base, pc, flags, - lookup_symbol(pc)); - return tb->tc.ptr; -} - void HELPER(exit_atomic)(CPUArchState *env) { cpu_loop_exit_atomic(env_cpu(env), GETPC()); diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c index 7929a7e..4df26de 100644 --- a/accel/tcg/translate-all.c +++ b/accel/tcg/translate-all.c @@ -378,11 +378,6 @@ static int cpu_restore_state_from_tb(CPUState *cpu, TranslationBlock *tb, return 0; } -void tb_destroy(TranslationBlock *tb) -{ - qemu_spin_destroy(&tb->jmp_lock); -} - bool cpu_restore_state(CPUState *cpu, uintptr_t host_pc, bool will_exit) { /* @@ -1224,8 +1219,8 @@ static void do_tb_phys_invalidate(TranslationBlock *tb, bool rm_from_page_list) /* suppress any remaining jumps to this TB */ tb_jmp_unlink(tb); - qatomic_set(&tcg_ctx->tb_phys_invalidate_count, - tcg_ctx->tb_phys_invalidate_count + 1); + qatomic_set(&tb_ctx.tb_phys_invalidate_count, + tb_ctx.tb_phys_invalidate_count + 1); } static void tb_phys_invalidate__locked(TranslationBlock *tb) @@ -1657,6 +1652,13 @@ TranslationBlock *tb_gen_code(CPUState *cpu, return tb; } + /* + * Insert TB into the corresponding region tree before publishing it + * through QHT. Otherwise rewinding happened in the TB might fail to + * lookup itself using host PC. + */ + tcg_tb_insert(tb); + /* check next page if needed */ virt_page2 = (pc + tb->size - 1) & TARGET_PAGE_MASK; phys_page2 = -1; @@ -1674,10 +1676,9 @@ TranslationBlock *tb_gen_code(CPUState *cpu, orig_aligned -= ROUND_UP(sizeof(*tb), qemu_icache_linesize); qatomic_set(&tcg_ctx->code_gen_ptr, (void *)orig_aligned); - tb_destroy(tb); + tcg_tb_remove(tb); return existing_tb; } - tcg_tb_insert(tb); return tb; } @@ -2127,8 +2128,8 @@ void dump_exec_info(void) qemu_printf("\nStatistics:\n"); qemu_printf("TB flush count %u\n", qatomic_read(&tb_ctx.tb_flush_count)); - qemu_printf("TB invalidate count %zu\n", - tcg_tb_phys_invalidate_count()); + qemu_printf("TB invalidate count %u\n", + qatomic_read(&tb_ctx.tb_phys_invalidate_count)); tlb_flush_counts(&flush_full, &flush_part, &flush_elide); qemu_printf("TLB full flushes %zu\n", flush_full); diff --git a/accel/tcg/translator.c b/accel/tcg/translator.c index 1d32732..59804af 100644 --- a/accel/tcg/translator.c +++ b/accel/tcg/translator.c @@ -31,6 +31,17 @@ void translator_loop_temp_check(DisasContextBase *db) } } +bool translator_use_goto_tb(DisasContextBase *db, target_ulong dest) +{ + /* Suppress goto_tb in the case of single-steping. */ + if (db->singlestep_enabled || singlestep) { + return false; + } + + /* Check for the dest on the same page as the start of the TB. */ + return ((db->pc_first ^ dest) & TARGET_PAGE_MASK) == 0; +} + void translator_loop(const TranslatorOps *ops, DisasContextBase *db, CPUState *cpu, TranslationBlock *tb, int max_insns) { |