diff options
author | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2016-06-07 12:50:22 +1000 |
---|---|---|
committer | David Gibson <david@gibson.dropbear.id.au> | 2016-06-07 13:10:44 +1000 |
commit | c5a8d8f32d90058995334cfd9292ed1b98c76971 (patch) | |
tree | e9ee285957f5885754f6520dc9521d39777d207e /target-ppc/translate.c | |
parent | 3dcfb74fd4e4ab31508c80e6965a0cd477510234 (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.c | 27 |
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; |