From: Oleg Vasilev <vasilev.o...@huawei.com> Using a physical pc requires to translate address every time next block needs to be found and executed. This also contaminates TLB with code-related records.
Instead, I suggest we introduce an architecture-specific address space identifier, and use it to distinguish between different AS's translation blocks. CC: qemu-...@nongnu.org Signed-off-by: Oleg Vasilev <vasilev.o...@huawei.com> Signed-off-by: Oleg Vasilev <m...@svin.in> --- accel/tcg/cpu-exec.c | 38 ++++++++------------------------ accel/tcg/tb-hash.h | 4 ++-- accel/tcg/translate-all.c | 7 +++--- hw/core/cpu-sysemu.c | 6 +++++ include/exec/exec-all.h | 1 + include/hw/core/cpu.h | 8 +++++++ include/hw/core/sysemu-cpu-ops.h | 6 +++++ target/arm/cpu.c | 13 +++++++++++ 8 files changed, 48 insertions(+), 35 deletions(-) diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c index 409ec8c38c..01b0e67d9c 100644 --- a/accel/tcg/cpu-exec.c +++ b/accel/tcg/cpu-exec.c @@ -490,7 +490,7 @@ struct tb_desc { target_ulong pc; target_ulong cs_base; CPUArchState *env; - tb_page_addr_t phys_page1; + uint64_t asid; uint32_t flags; uint32_t cflags; uint32_t trace_vcpu_dstate; @@ -501,34 +501,18 @@ static bool tb_lookup_cmp(const void *p, const void *d) const TranslationBlock *tb = p; const struct tb_desc *desc = d; - if (tb->pc == desc->pc && - tb->page_addr[0] == desc->phys_page1 && - tb->cs_base == desc->cs_base && - tb->flags == desc->flags && - tb->trace_vcpu_dstate == desc->trace_vcpu_dstate && - tb_cflags(tb) == desc->cflags) { - /* check next page if needed */ - if (tb->page_addr[1] == -1) { - return true; - } else { - tb_page_addr_t phys_page2; - target_ulong virt_page2; - - virt_page2 = (desc->pc & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE; - phys_page2 = get_page_addr_code(desc->env, virt_page2); - if (tb->page_addr[1] == phys_page2) { - return true; - } - } - } - return false; + return (tb->pc == desc->pc && + tb->asid == desc->asid && + tb->cs_base == desc->cs_base && + tb->flags == desc->flags && + tb->trace_vcpu_dstate == desc->trace_vcpu_dstate && + tb_cflags(tb) == desc->cflags); } TranslationBlock *tb_htable_lookup(CPUState *cpu, target_ulong pc, target_ulong cs_base, uint32_t flags, uint32_t cflags) { - tb_page_addr_t phys_pc; struct tb_desc desc; uint32_t h; @@ -538,12 +522,8 @@ TranslationBlock *tb_htable_lookup(CPUState *cpu, target_ulong pc, desc.cflags = cflags; desc.trace_vcpu_dstate = *cpu->trace_dstate; desc.pc = pc; - phys_pc = get_page_addr_code(desc.env, pc); - if (phys_pc == -1) { - return NULL; - } - desc.phys_page1 = phys_pc & TARGET_PAGE_MASK; - h = tb_hash_func(phys_pc, pc, flags, cflags, *cpu->trace_dstate); + desc.asid = cpu_get_asid(cpu); + h = tb_hash_func(desc.asid, pc, flags, cflags, *cpu->trace_dstate); return qht_lookup_custom(&tb_ctx.htable, &desc, h, tb_lookup_cmp); } diff --git a/accel/tcg/tb-hash.h b/accel/tcg/tb-hash.h index 0a273d9605..b5c6f87711 100644 --- a/accel/tcg/tb-hash.h +++ b/accel/tcg/tb-hash.h @@ -60,10 +60,10 @@ static inline unsigned int tb_jmp_cache_hash_func(target_ulong pc) #endif /* CONFIG_SOFTMMU */ static inline -uint32_t tb_hash_func(tb_page_addr_t phys_pc, target_ulong pc, uint32_t flags, +uint32_t tb_hash_func(uint64_t asid, target_ulong pc, uint32_t flags, uint32_t cf_mask, uint32_t trace_vcpu_dstate) { - return qemu_xxhash7(phys_pc, pc, flags, cf_mask, trace_vcpu_dstate); + return qemu_xxhash7(asid, pc, flags, cf_mask, trace_vcpu_dstate); } #endif diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c index bd71db59a9..8565691bfd 100644 --- a/accel/tcg/translate-all.c +++ b/accel/tcg/translate-all.c @@ -1174,7 +1174,6 @@ static void do_tb_phys_invalidate(TranslationBlock *tb, bool rm_from_page_list) CPUState *cpu; PageDesc *p; uint32_t h; - tb_page_addr_t phys_pc; uint32_t orig_cflags = tb_cflags(tb); assert_memory_lock(); @@ -1185,8 +1184,7 @@ static void do_tb_phys_invalidate(TranslationBlock *tb, bool rm_from_page_list) qemu_spin_unlock(&tb->jmp_lock); /* remove the TB from the hash list */ - phys_pc = tb->page_addr[0] + (tb->pc & ~TARGET_PAGE_MASK); - h = tb_hash_func(phys_pc, tb->pc, tb->flags, orig_cflags, + h = tb_hash_func(tb->asid, tb->pc, tb->flags, orig_cflags, tb->trace_vcpu_dstate); if (!qht_remove(&tb_ctx.htable, tb, h)) { return; @@ -1349,7 +1347,7 @@ tb_link_page(TranslationBlock *tb, tb_page_addr_t phys_pc, } /* add in the hash table */ - h = tb_hash_func(phys_pc, tb->pc, tb->flags, tb->cflags, + h = tb_hash_func(tb->asid, tb->pc, tb->flags, tb->cflags, tb->trace_vcpu_dstate); qht_insert(&tb_ctx.htable, tb, h, &existing_tb); @@ -1427,6 +1425,7 @@ TranslationBlock *tb_gen_code(CPUState *cpu, tb->flags = flags; tb->cflags = cflags; tb->trace_vcpu_dstate = *cpu->trace_dstate; + tb->asid = cpu_get_asid(cpu); tcg_ctx->tb_cflags = cflags; tb_overflow: diff --git a/hw/core/cpu-sysemu.c b/hw/core/cpu-sysemu.c index 00253f8929..915874ea7b 100644 --- a/hw/core/cpu-sysemu.c +++ b/hw/core/cpu-sysemu.c @@ -79,6 +79,12 @@ int cpu_asidx_from_attrs(CPUState *cpu, MemTxAttrs attrs) return ret; } +uint64_t cpu_get_asid(CPUState *cpu) { + CPUClass *cc = CPU_GET_CLASS(cpu); + + return cc->sysemu_ops->get_asid(cpu); +} + int cpu_write_elf32_qemunote(WriteCoreDumpFunction f, CPUState *cpu, void *opaque) { diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h index 35d8e93976..5554ab133d 100644 --- a/include/exec/exec-all.h +++ b/include/exec/exec-all.h @@ -560,6 +560,7 @@ struct TranslationBlock { uintptr_t jmp_list_head; uintptr_t jmp_list_next[2]; uintptr_t jmp_dest[2]; + uint64_t asid; }; /* Hide the qatomic_read to make code a little easier on the eyes */ diff --git a/include/hw/core/cpu.h b/include/hw/core/cpu.h index e948e81f1a..c935160153 100644 --- a/include/hw/core/cpu.h +++ b/include/hw/core/cpu.h @@ -579,6 +579,14 @@ hwaddr cpu_get_phys_page_debug(CPUState *cpu, vaddr addr); */ int cpu_asidx_from_attrs(CPUState *cpu, MemTxAttrs attrs); + +/** cpu_get_asid: + * @cpu: CPU + * + * Returns the identifier for a current address space. + */ +uint64_t cpu_get_asid(CPUState *cpu); + /** * cpu_virtio_is_big_endian: * @cpu: CPU diff --git a/include/hw/core/sysemu-cpu-ops.h b/include/hw/core/sysemu-cpu-ops.h index a9ba39e5f2..919f941265 100644 --- a/include/hw/core/sysemu-cpu-ops.h +++ b/include/hw/core/sysemu-cpu-ops.h @@ -43,6 +43,12 @@ typedef struct SysemuCPUOps { * a memory access with the specified memory transaction attributes. */ int (*asidx_from_attrs)(CPUState *cpu, MemTxAttrs attrs); + + /** + * @get_asid: Callback to return the identifier for a current address space. + */ + uint64_t (*get_asid)(CPUState *cpu); + /** * @get_crash_info: Callback for reporting guest crash information in * GUEST_PANICKED events. diff --git a/target/arm/cpu.c b/target/arm/cpu.c index a211804fd3..aa5440d960 100644 --- a/target/arm/cpu.c +++ b/target/arm/cpu.c @@ -2017,9 +2017,22 @@ static gchar *arm_gdb_arch_name(CPUState *cs) #ifndef CONFIG_USER_ONLY #include "hw/core/sysemu-cpu-ops.h" +/* Returns the identifier for a current address space. */ +static uint64_t arm_get_asid(CPUState *cs) +{ + ARMCPU *cpu = ARM_CPU(cs); + CPUARMState *env = &cpu->env; + ARMMMUIdx mmu_idx = arm_mmu_idx(env); + uint64_t tcr = regime_tcr(env, mmu_idx)->raw_tcr; + +#define TCR_A1 (1U << 22) + return regime_ttbr(env, mmu_idx, (tcr&TCR_A1)>0); +} + static const struct SysemuCPUOps arm_sysemu_ops = { .get_phys_page_attrs_debug = arm_cpu_get_phys_page_attrs_debug, .asidx_from_attrs = arm_asidx_from_attrs, + .get_asid = arm_get_asid, .write_elf32_note = arm_cpu_write_elf32_note, .write_elf64_note = arm_cpu_write_elf64_note, .virtio_is_big_endian = arm_cpu_virtio_is_big_endian, -- 2.33.1