qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH] tcg: fixup switching tb invalidation to volatile_re


From: Paolo Bonzini
Subject: [Qemu-devel] [PATCH] tcg: fixup switching tb invalidation to volatile_read/volatile_set
Date: Mon, 18 Jul 2016 19:35:26 +0200

Because atomic_read/atomic_set does not work on platforms that only
support 32-bit atomic writes, we need volatile_read/volatile_set.

This patch fixes up Sergey's series to use volatile_read/volatile_set
instead of atomic_read/atomic_set.  Because volatile_read/volatile_set
can cause torn writes, the invalidation mechanism for SPARC targets is
changed to use flags instead of cs_base.  Torn writes are not a problem
for targets that don't use cs_base at all, because 0xffffffff00000000
or 0x00000000ffffffff cs_bases cannot be confused with the cs_base of
a valid translation block.

The patch also includes two fixes, respectively using atomic_rcu_read in
tb_find and fixing computation of the hash index in tb_phys_invalidate.

Signed-off-by: Paolo Bonzini <address@hidden>

diff --git a/cpu-exec.c b/cpu-exec.c
index fd43de8..4068110 100644
--- a/cpu-exec.c
+++ b/cpu-exec.c
@@ -238,10 +238,10 @@ static bool tb_cmp(const void *p, const void *d)
     const TranslationBlock *tb = p;
     const struct tb_desc *desc = d;
 
-    if (tb->pc == desc->pc &&
+    if (volatile_read(&tb->pc) == desc->pc &&
         tb->page_addr[0] == desc->phys_page1 &&
-        tb->cs_base == desc->cs_base &&
-        tb->flags == desc->flags) {
+        volatile_read(&tb->cs_base) == desc->cs_base &&
+        volatile_read(&tb->flags) == desc->flags) {
         /* check next page if needed */
         if (tb->page_addr[1] == -1) {
             return true;
@@ -292,10 +292,10 @@ static inline TranslationBlock *tb_find(CPUState *cpu,
        always be the same before a given translated block
        is executed. */
     cpu_get_tb_cpu_state(env, &pc, &cs_base, &flags);
-    tb = atomic_read(&cpu->tb_jmp_cache[tb_jmp_cache_hash_func(pc)]);
-    if (unlikely(!tb || atomic_read(&tb->pc) != pc ||
-                 atomic_read(&tb->cs_base) != cs_base ||
-                 atomic_read(&tb->flags) != flags)) {
+    tb = atomic_rcu_read(&cpu->tb_jmp_cache[tb_jmp_cache_hash_func(pc)]);
+    if (unlikely(!tb || volatile_read(&tb->pc) != pc ||
+                 volatile_read(&tb->cs_base) != cs_base ||
+                 volatile_read(&tb->flags) != flags)) {
         tb = tb_htable_lookup(cpu, pc, cs_base, flags);
         if (!tb) {
 
diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h
index 8f0afcd..35e963b 100644
--- a/include/exec/exec-all.h
+++ b/include/exec/exec-all.h
@@ -262,9 +262,9 @@ static inline void tb_mark_invalid(TranslationBlock *tb)
     uint32_t flags = 0;
 
     cpu_get_invalid_tb_cpu_state(&pc, &cs_base, &flags);
-    atomic_set(&tb->pc, pc);
-    atomic_set(&tb->cs_base, cs_base);
-    atomic_set(&tb->flags, flags);
+    volatile_set(&tb->pc, pc);
+    volatile_set(&tb->cs_base, cs_base);
+    volatile_set(&tb->flags, flags);
 }
 
 static inline bool tb_is_invalid(TranslationBlock *tb)
diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h
index e327a35..3278d8a 100644
--- a/target-sparc/cpu.h
+++ b/target-sparc/cpu.h
@@ -753,14 +753,17 @@ static inline void 
cpu_get_invalid_tb_cpu_state(target_ulong *pc,
                                                 target_ulong *cs_base,
                                                 uint32_t *flags)
 {
-    *cs_base = -1; /* npc must be a multible of 4 */
+    /* TB_FLAG_MMU_MASK is not a valid MMU index, which makes it is an
+     * impossible flag combination for valid TBs.
+     */
+    *flags = TB_FLAG_MMU_MASK;
 }
 
 static inline bool cpu_tb_cpu_state_is_invalidated(target_ulong pc,
                                                    target_ulong cs_base,
                                                    uint32_t flags)
 {
-    return cs_base == -1;
+    return flags == TB_FLAG_MMU_MASK;
 }
 
 static inline bool tb_fpu_enabled(int tb_flags)
diff --git a/translate-all.c b/translate-all.c
index 6156bdc..187f782 100644
--- a/translate-all.c
+++ b/translate-all.c
@@ -990,11 +990,15 @@ void tb_phys_invalidate(TranslationBlock *tb, 
tb_page_addr_t page_addr)
     uint32_t h;
     tb_page_addr_t phys_pc;
 
+    /* Compute hash index before tb->flags is possibly destroyed
+     * by tb_mark_invalid.
+     */
+    phys_pc = tb->page_addr[0] + (tb->pc & ~TARGET_PAGE_MASK);
+    h = tb_hash_func(phys_pc, tb->pc, tb->flags);
+
     tb_mark_invalid(tb);
 
     /* 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);
     qht_remove(&tcg_ctx.tb_ctx.htable, tb, h);
 
     /* remove the TB from the page list */



reply via email to

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