aboutsummaryrefslogtreecommitdiff
path: root/target-ppc/translate.c
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2016-06-07 12:50:22 +1000
committerDavid Gibson <david@gibson.dropbear.id.au>2016-06-07 13:10:44 +1000
commitc5a8d8f32d90058995334cfd9292ed1b98c76971 (patch)
treee9ee285957f5885754f6520dc9521d39777d207e /target-ppc/translate.c
parent3dcfb74fd4e4ab31508c80e6965a0cd477510234 (diff)
ppc: Batch TLB flushes on 32-bit 6xx/7xx/7xxx in hash mode
This ports the existing 64-bit mechanism to 32-bit, thus series of 64 tlbie's followed by a sync like some versions of Darwin (ab)use will result in a single flush. We apply a pending flush on any sync instruction though, as Darwin doesn't use tlbsync on non-SMP systems. Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Diffstat (limited to 'target-ppc/translate.c')
-rw-r--r--target-ppc/translate.c27
1 files changed, 21 insertions, 6 deletions
diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index 5fdcd220fc..5150455ef9 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -193,6 +193,7 @@ struct DisasContext {
uint32_t exception;
/* Routine used to access memory */
bool pr, hv;
+ bool lazy_tlb_flush;
int mem_idx;
int access_type;
/* Translation flags */
@@ -3290,12 +3291,17 @@ static void gen_eieio(DisasContext *ctx)
{
}
-#if !defined(CONFIG_USER_ONLY) && defined(TARGET_PPC64)
+#if !defined(CONFIG_USER_ONLY)
static inline void gen_check_tlb_flush(DisasContext *ctx)
{
- TCGv_i32 t = tcg_temp_new_i32();
- TCGLabel *l = gen_new_label();
+ TCGv_i32 t;
+ TCGLabel *l;
+ if (!ctx->lazy_tlb_flush) {
+ return;
+ }
+ l = gen_new_label();
+ t = tcg_temp_new_i32();
tcg_gen_ld_i32(t, cpu_env, offsetof(CPUPPCState, tlb_need_flush));
tcg_gen_brcondi_i32(TCG_COND_EQ, t, 0, l);
gen_helper_check_tlb_flush(cpu_env);
@@ -3475,10 +3481,14 @@ static void gen_sync(DisasContext *ctx)
uint32_t l = (ctx->opcode >> 21) & 3;
/*
- * For l == 2, it's a ptesync, We need to check for a pending TLB flush.
- * This can only happen in kernel mode however so check MSR_PR as well.
+ * We may need to check for a pending TLB flush.
+ *
+ * We do this on ptesync (l == 2) on ppc64 and any sync pn ppc32.
+ *
+ * Additionally, this can only happen in kernel mode however so
+ * check MSR_PR as well.
*/
- if (l == 2 && !ctx->pr) {
+ if (((l == 2) || !(ctx->insns_flags & PPC_64B)) && !ctx->pr) {
gen_check_tlb_flush(ctx);
}
}
@@ -11491,6 +11501,11 @@ void gen_intermediate_code(CPUPPCState *env, struct TranslationBlock *tb)
ctx.sf_mode = msr_is_64bit(env, env->msr);
ctx.has_cfar = !!(env->flags & POWERPC_FLAG_CFAR);
#endif
+ if (env->mmu_model == POWERPC_MMU_32B ||
+ env->mmu_model == POWERPC_MMU_601 ||
+ (env->mmu_model & POWERPC_MMU_64B))
+ ctx.lazy_tlb_flush = true;
+
ctx.fpu_enabled = msr_fp;
if ((env->flags & POWERPC_FLAG_SPE) && msr_spe)
ctx.spe_enabled = msr_spe;