qemu-devel
[Top][All Lists]
Advanced

[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




reply via email to

[Prev in Thread] Current Thread [Next in Thread]