[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[RFC PATCH 2/2] accel/tcg: replace phys_pc with asid in TB htable key
From: |
Oleg Vasilev |
Subject: |
[RFC PATCH 2/2] accel/tcg: replace phys_pc with asid in TB htable key |
Date: |
Wed, 22 Dec 2021 16:50:36 +0000 (UTC) |
From: Oleg Vasilev <vasilev.oleg@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-arm@nongnu.org
Signed-off-by: Oleg Vasilev <vasilev.oleg@huawei.com>
Signed-off-by: Oleg Vasilev <me@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