[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 */
- [Qemu-devel] [PATCH] tcg: fixup switching tb invalidation to volatile_read/volatile_set,
Paolo Bonzini <=