summaryrefslogtreecommitdiff
path: root/target/ppc
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2019-02-15 18:00:25 +0100
committerDavid Gibson <david@gibson.dropbear.id.au>2019-02-26 09:21:25 +1100
commit74c4912f097bab98a8b0f8ec2bee1db269505c14 (patch)
treea8ecfef30da295438ef06c2fd37a91e2125cb653 /target/ppc
parent34525595fb379796241b0f3a9946bb21c4da1178 (diff)
downloadqemu-74c4912f097bab98a8b0f8ec2bee1db269505c14.zip
target/ppc: Fix synchronization of mttcg with broadcast TLB flushes
Let's use the generic helper tlb_flush_all_cpus_synced() instead of iterating the CPUs ourselves. We do lose the optimization of clearing the "other" CPUs "need flush" flags but this shouldn't be a problem in practice. Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> Signed-off-by: Cédric Le Goater <clg@kaod.org> Message-Id: <20190215170029.15641-9-clg@kaod.org> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Diffstat (limited to 'target/ppc')
-rw-r--r--target/ppc/helper_regs.h27
1 files changed, 10 insertions, 17 deletions
diff --git a/target/ppc/helper_regs.h b/target/ppc/helper_regs.h
index 5efd18049e..a2205e1044 100644
--- a/target/ppc/helper_regs.h
+++ b/target/ppc/helper_regs.h
@@ -174,26 +174,19 @@ static inline int hreg_store_msr(CPUPPCState *env, target_ulong value,
static inline void check_tlb_flush(CPUPPCState *env, bool global)
{
CPUState *cs = CPU(ppc_env_get_cpu(env));
- if (env->tlb_need_flush & TLB_NEED_LOCAL_FLUSH) {
- tlb_flush(cs);
- env->tlb_need_flush &= ~TLB_NEED_LOCAL_FLUSH;
- }
- /* Propagate TLB invalidations to other CPUs when the guest uses broadcast
- * TLB invalidation instructions.
- */
+ /* Handle global flushes first */
if (global && (env->tlb_need_flush & TLB_NEED_GLOBAL_FLUSH)) {
- CPUState *other_cs;
- CPU_FOREACH(other_cs) {
- if (other_cs != cs) {
- PowerPCCPU *cpu = POWERPC_CPU(other_cs);
- CPUPPCState *other_env = &cpu->env;
-
- other_env->tlb_need_flush &= ~TLB_NEED_LOCAL_FLUSH;
- tlb_flush(other_cs);
- }
- }
env->tlb_need_flush &= ~TLB_NEED_GLOBAL_FLUSH;
+ env->tlb_need_flush &= ~TLB_NEED_LOCAL_FLUSH;
+ tlb_flush_all_cpus_synced(cs);
+ return;
+ }
+
+ /* Then handle local ones */
+ if (env->tlb_need_flush & TLB_NEED_LOCAL_FLUSH) {
+ env->tlb_need_flush &= ~TLB_NEED_LOCAL_FLUSH;
+ tlb_flush(cs);
}
}
#else