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
>
>

Reply via email to