On Sat, Jan 21, 2012 at 04:15, Alexander Graf <ag...@suse.de> wrote: > The PowerPC 2.06 BookE ISA defines an opcode called "tlbilx" which is used > to flush TLB entries. It's the recommended way of flushing in virtualized > environments. > > So far we got away without implementing it, but Linux for e500mc uses this > instruction, so we better add it :). > > Signed-off-by: Alexander Graf <ag...@suse.de> > > --- > > v1 -> v2: > > - remove sas/ts check > - isize is only valid for mav 2.0 > --- > target-ppc/helper.h | 1 + > target-ppc/op_helper.c | 64 > ++++++++++++++++++++++++++++++++++++++++++++++++ > target-ppc/translate.c | 25 ++++++++++++++++++ > 3 files changed, 90 insertions(+), 0 deletions(-) > > diff --git a/target-ppc/helper.h b/target-ppc/helper.h > index 470e42f..1635767 100644 > --- a/target-ppc/helper.h > +++ b/target-ppc/helper.h > @@ -336,6 +336,7 @@ DEF_HELPER_0(booke206_tlbre, void) > DEF_HELPER_0(booke206_tlbwe, void) > DEF_HELPER_1(booke206_tlbsx, void, tl) > DEF_HELPER_1(booke206_tlbivax, void, tl) > +DEF_HELPER_2(booke206_tlbilx, void, tl, i32) > DEF_HELPER_1(booke206_tlbflush, void, i32) > DEF_HELPER_2(booke_setpid, void, i32, tl) > DEF_HELPER_1(6xx_tlbd, void, tl) > diff --git a/target-ppc/op_helper.c b/target-ppc/op_helper.c > index 2c8a96f..29c3870 100644 > --- a/target-ppc/op_helper.c > +++ b/target-ppc/op_helper.c > @@ -4406,6 +4406,70 @@ void helper_booke206_tlbivax(target_ulong address) > } > } > > +void helper_booke206_tlbilx(target_ulong address, uint32_t t) > +{ > + int tlb_size; > + int i, j; > + ppcmas_tlb_t *tlb = env->tlb.tlbm; > + int tid = (env->spr[SPR_BOOKE_MAS6] & MAS6_SPID); > + int pid = tid >> MAS6_SPID_SHIFT; > + int sgs = env->spr[SPR_BOOKE_MAS5] & MAS5_SGS; > + int ind = (env->spr[SPR_BOOKE_MAS6] & MAS6_SIND) ? MAS1_IND : 0; > + /* XXX check for unsupported isize and raise an invalid opcode then */ > + int size = env->spr[SPR_BOOKE_MAS6] & MAS6_ISIZE_MASK; > + /* XXX implement MAV2 handling */ > + bool mav2 = false; > + > + /* XXX missing LPID handling */ > + switch (t) {
For better performance, this switch could be pushed to translation time and helpers introduced for each case. > + case 0: > + /* flush all */ > + booke206_flush_tlb(env, -1, 1); > + break; > + case 1: > + /* flush by pid */ > + for (i = 0; i < BOOKE206_MAX_TLBN; i++) { > + tlb_size = booke206_tlb_size(env, i); > + for (j = 0; j < tlb_size; j++) { > + if (!(tlb[j].mas1 & MAS1_IPROT) && > + ((tlb[j].mas1 & MAS1_TID_MASK) == tid)) { > + tlb[j].mas1 &= ~MAS1_VALID; > + } > + } > + tlb += booke206_tlb_size(env, i); > + } > + tlb_flush(env, 1); > + break; > + case 3: > + /* flush by pid and ea */ > + for (i = 0; i < BOOKE206_MAX_TLBN; i++) { > + int ways = booke206_tlb_ways(env, i); > + > + for (j = 0; j < ways; j++) { > + tlb = booke206_get_tlbm(env, i, address, j); > + if ((ppcmas_tlb_check(env, tlb, NULL, address, pid) != 0) || > + (tlb->mas1 & MAS1_IPROT) || > + ((tlb->mas1 & MAS1_IND) != ind) || > + ((tlb->mas8 & MAS8_TGS) != sgs)) { > + continue; > + } > + if (mav2 && ((tlb->mas1 & MAS1_TSIZE_MASK) != size)) { > + /* XXX only check when MMUCFG[TWC] || TLBnCFG[HES] */ > + continue; > + } > + /* XXX e500mc doesn't match SAS, but other cores might */ > + tlb->mas1 &= ~MAS1_VALID; > + } > + } > + tlb_flush(env, 1); > + break; > + default: > + helper_raise_exception_err(POWERPC_EXCP_PROGRAM, > + POWERPC_EXCP_INVAL | > + POWERPC_EXCP_INVAL_INVAL); > + } > +} > + > void helper_booke206_tlbflush(uint32_t type) > { > int flags = 0; > diff --git a/target-ppc/translate.c b/target-ppc/translate.c > index adde65b..7ceb210 100644 > --- a/target-ppc/translate.c > +++ b/target-ppc/translate.c > @@ -6110,6 +6110,29 @@ static void gen_tlbivax_booke206(DisasContext *ctx) > #endif > } > > +static void gen_tlbilx_booke206(DisasContext *ctx) > +{ > +#if defined(CONFIG_USER_ONLY) > + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); > +#else > + TCGv t0; > + TCGv_i32 t1; > + if (unlikely(!ctx->mem_idx)) { > + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); > + return; > + } > + > + t0 = tcg_temp_new(); > + t1 = tcg_const_i32((ctx->opcode >> 21) & 0x3); > + gen_addr_reg_index(ctx, t0); > + > + gen_helper_booke206_tlbilx(t0, t1); > + > + tcg_temp_free(t0); > + tcg_temp_free_i32(t1); > +#endif > +} > + > > /* wrtee */ > static void gen_wrtee(DisasContext *ctx) > @@ -8574,6 +8597,8 @@ GEN_HANDLER2_E(tlbwe_booke206, "tlbwe", 0x1F, 0x12, > 0x1E, 0x00000001, > PPC_NONE, PPC2_BOOKE206), > GEN_HANDLER2_E(tlbivax_booke206, "tlbivax", 0x1F, 0x12, 0x18, 0x00000001, > PPC_NONE, PPC2_BOOKE206), > +GEN_HANDLER2_E(tlbilx_booke206, "tlbilx", 0x1F, 0x12, 0x00, 0x03800001, > + PPC_NONE, PPC2_BOOKE206), > GEN_HANDLER(wrtee, 0x1F, 0x03, 0x04, 0x000FFC01, PPC_WRTEE), > GEN_HANDLER(wrteei, 0x1F, 0x03, 0x05, 0x000E7C01, PPC_WRTEE), > GEN_HANDLER(dlmzb, 0x1F, 0x0E, 0x02, 0x00000000, PPC_440_SPEC), > -- > 1.6.0.2 > >