From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:49787) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bq5P3-0006Zz-Fe for qemu-devel@nongnu.org; Fri, 30 Sep 2016 17:31:36 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1bq5P0-0006as-1T for qemu-devel@nongnu.org; Fri, 30 Sep 2016 17:31:32 -0400 Received: from mail-wm0-x22c.google.com ([2a00:1450:400c:c09::22c]:37327) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bq5Oz-0006ah-NN for qemu-devel@nongnu.org; Fri, 30 Sep 2016 17:31:29 -0400 Received: by mail-wm0-x22c.google.com with SMTP id b80so66259713wme.0 for ; Fri, 30 Sep 2016 14:31:29 -0700 (PDT) From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Fri, 30 Sep 2016 22:31:05 +0100 Message-Id: <20160930213106.20186-15-alex.bennee@linaro.org> In-Reply-To: <20160930213106.20186-1-alex.bennee@linaro.org> References: <20160930213106.20186-1-alex.bennee@linaro.org> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Subject: [Qemu-devel] [PATCH v3 14/15] tcg: update remaining TranslationBuffer fields atomically List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org, pbonzini@redhat.com Cc: mttcg@listserver.greensocs.com, fred.konrad@greensocs.com, a.rigo@virtualopensystems.com, cota@braap.org, bobby.prani@gmail.com, nikunj@linux.vnet.ibm.com, mark.burton@greensocs.com, jan.kiszka@siemens.com, serge.fdrv@gmail.com, rth@twiddle.net, peter.maydell@linaro.org, claudio.fontana@huawei.com, =?UTF-8?q?Alex=20Benn=C3=A9e?= , Peter Crosthwaite The TranslationBuffer is one of those heavily accessed across threads. To meet defined C11 behaviour across threads we update the accesses to use the relaxed atomic helpers. Care is still taken with locking and barriers for when flags are updated and when newly generated buffers are made visible to the rest of the system. Signed-off-by: Alex Bennée --- cpu-exec.c | 16 ++++++++-------- include/exec/exec-all.h | 11 +++++++++++ translate-all.c | 11 ++++++----- 3 files changed, 25 insertions(+), 13 deletions(-) diff --git a/cpu-exec.c b/cpu-exec.c index 99c906b..0e6b3d3 100644 --- a/cpu-exec.c +++ b/cpu-exec.c @@ -185,7 +185,7 @@ static inline tcg_target_ulong cpu_tb_exec(CPUState *cpu, TranslationBlock *itb) cc->synchronize_from_tb(cpu, last_tb); } else { assert(cc->set_pc); - cc->set_pc(cpu, last_tb->pc); + cc->set_pc(cpu, atomic_read(&last_tb->pc)); } } if (tb_exit == TB_EXIT_REQUESTED) { @@ -235,13 +235,13 @@ 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 && - tb->page_addr[0] == desc->phys_page1 && - tb->cs_base == desc->cs_base && - tb->flags == desc->flags && + if (atomic_read(&tb->pc) == desc->pc && + atomic_read(&tb->page_addr[0]) == desc->phys_page1 && + atomic_read(&tb->cs_base) == desc->cs_base && + atomic_read(&tb->flags) == desc->flags && !atomic_read(&tb->invalid)) { /* check next page if needed */ - if (tb->page_addr[1] == -1) { + if (atomic_read(&tb->page_addr[1]) == -1) { return true; } else { tb_page_addr_t phys_page2; @@ -249,7 +249,7 @@ static bool tb_cmp(const void *p, const void *d) 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) { + if (atomic_read(&tb->page_addr[1]) == phys_page2) { return true; } } @@ -507,7 +507,7 @@ static inline void cpu_loop_exec_tb(CPUState *cpu, TranslationBlock *tb, return; } - trace_exec_tb(tb, tb->pc); + trace_exec_tb(tb, atomic_read(&tb->pc)); ret = cpu_tb_exec(cpu, tb); *last_tb = (TranslationBlock *)(ret & ~TB_EXIT_MASK); *tb_exit = ret & TB_EXIT_MASK; diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h index c3596a6..ff34a0d 100644 --- a/include/exec/exec-all.h +++ b/include/exec/exec-all.h @@ -200,6 +200,17 @@ static inline void tlb_flush_by_mmuidx(CPUState *cpu, ...) #define USE_DIRECT_JUMP #endif +/* + * TranslationBlock + * + * This structure represents a single translated block of code. The + * actual code is referenced via tc_ptr. This structure is accessed + * across multiple QEMU threads so for C11 compliance all fields + * should be access with at least relaxed atomic primitives. Fields + * that are updated after initial generation, mainly those involved + * with patching jumps and chaining TBs, need stronger guarantees to + * prevent corruption. + */ struct TranslationBlock { target_ulong pc; /* simulated PC corresponding to this block (EIP + CS base) */ target_ulong cs_base; /* CS base for this block */ diff --git a/translate-all.c b/translate-all.c index 0f13d4d..a6262ae 100644 --- a/translate-all.c +++ b/translate-all.c @@ -773,9 +773,10 @@ static TranslationBlock *tb_alloc(target_ulong pc) return NULL; } tb = &tcg_ctx.tb_ctx.tbs[tcg_ctx.tb_ctx.nb_tbs++]; - tb->pc = pc; - tb->cflags = 0; - tb->invalid = false; + + atomic_set(&tb->pc, pc); + atomic_set(&tb->cflags, 0); + atomic_set(&tb->invalid, false); return tb; } @@ -1095,7 +1096,7 @@ static inline void tb_alloc_page(TranslationBlock *tb, bool page_already_protected; #endif - tb->page_addr[n] = page_addr; + atomic_set(&tb->page_addr[n], page_addr); p = page_find_alloc(page_addr >> TARGET_PAGE_BITS, 1); tb->page_next[n] = p->first_tb; #ifndef CONFIG_USER_ONLY @@ -1156,7 +1157,7 @@ static void tb_link_page(TranslationBlock *tb, tb_page_addr_t phys_pc, if (phys_page2 != -1) { tb_alloc_page(tb, 1, phys_page2); } else { - tb->page_addr[1] = -1; + atomic_set(&tb->page_addr[1], -1); } /* add in the hash table */ -- 2.9.3