Used to lookup SLB entries by address, for some reason it was missing. Signed-off-by: Benjamin Herrenschmidt <b...@kernel.crashing.org> --- target-ppc/helper.h | 1 + target-ppc/mmu-hash64.c | 24 ++++++++++++++++++++++++ target-ppc/translate.c | 25 +++++++++++++++++++++++++ 3 files changed, 50 insertions(+)
diff --git a/target-ppc/helper.h b/target-ppc/helper.h index 9890920..88ada3b 100644 --- a/target-ppc/helper.h +++ b/target-ppc/helper.h @@ -551,6 +551,7 @@ DEF_HELPER_FLAGS_2(tlbie, TCG_CALL_NO_RWG, void, env, tl) DEF_HELPER_FLAGS_3(store_slb, TCG_CALL_NO_RWG, void, env, tl, tl) DEF_HELPER_2(load_slb_esid, tl, env, tl) DEF_HELPER_2(load_slb_vsid, tl, env, tl) +DEF_HELPER_2(find_slb_esid, tl, env, tl) DEF_HELPER_FLAGS_1(slbia, TCG_CALL_NO_RWG, void, env) DEF_HELPER_FLAGS_2(slbie, TCG_CALL_NO_RWG, void, env, tl) #endif diff --git a/target-ppc/mmu-hash64.c b/target-ppc/mmu-hash64.c index 9071fe9..f1e9666 100644 --- a/target-ppc/mmu-hash64.c +++ b/target-ppc/mmu-hash64.c @@ -188,6 +188,19 @@ static int ppc_load_slb_vsid(CPUPPCState *env, target_ulong rb, return 0; } +static int ppc_find_slb_esid(CPUPPCState *env, target_ulong rb, + target_ulong *rt) +{ + ppc_slb_t *slb = slb_lookup(env, rb); + + if (!slb) { + return -1; + } + + *rt = slb->vsid; + return 0; +} + void helper_store_slb(CPUPPCState *env, target_ulong rb, target_ulong rs) { if (ppc_store_slb(env, rb, rs) < 0) { @@ -218,6 +231,17 @@ target_ulong helper_load_slb_vsid(CPUPPCState *env, target_ulong rb) return rt; } +target_ulong helper_find_slb_esid(CPUPPCState *env, target_ulong rb) +{ + target_ulong rt = 0; + + if (ppc_find_slb_esid(env, rb, &rt) < 0) { + helper_raise_exception_err(env, POWERPC_EXCP_PROGRAM, + POWERPC_EXCP_INVAL); + } + return rt; +} + /* * 64-bit hash table MMU handling */ diff --git a/target-ppc/translate.c b/target-ppc/translate.c index 1e3996d..b46ad72 100644 --- a/target-ppc/translate.c +++ b/target-ppc/translate.c @@ -4949,6 +4949,30 @@ static void gen_slbmfev(DisasContext *ctx) cpu_gpr[rB(ctx->opcode)]); #endif /* defined(CONFIG_USER_ONLY) */ } + +static void gen_slbfee_(DisasContext *ctx) +{ +#if defined(CONFIG_USER_ONLY) + GEN_PRIV; +#else + TCGLabel *l1; + TCGLabel *l2; + + CHK_SV; + + gen_helper_find_slb_esid(cpu_gpr[rS(ctx->opcode)], cpu_env, + cpu_gpr[rB(ctx->opcode)]); + l1 = gen_new_label(); + l2 = gen_new_label(); + tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_so); + tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[rS(ctx->opcode)], -1, l1); + tcg_gen_ori_i32(cpu_crf[0], cpu_crf[0], 1 << CRF_EQ); + tcg_gen_br(l2); + gen_set_label(l1); + tcg_gen_movi_tl(cpu_gpr[rS(ctx->opcode)], 0); + gen_set_label(l2); +#endif /* defined(CONFIG_USER_ONLY) */ +} #endif /* defined(TARGET_PPC64) */ /*** Lookaside buffer management ***/ @@ -9958,6 +9982,7 @@ GEN_HANDLER2(mtsrin_64b, "mtsrin", 0x1F, 0x12, 0x07, 0x001F0001, GEN_HANDLER2(slbmte, "slbmte", 0x1F, 0x12, 0x0C, 0x001F0001, PPC_SEGMENT_64B), GEN_HANDLER2(slbmfee, "slbmfee", 0x1F, 0x13, 0x1C, 0x001F0001, PPC_SEGMENT_64B), GEN_HANDLER2(slbmfev, "slbmfev", 0x1F, 0x13, 0x1A, 0x001F0001, PPC_SEGMENT_64B), +GEN_HANDLER2(slbfee_, "slbfee.", 0x1F, 0x13, 0x1E, 0x001F0000, PPC_SEGMENT_64B), #endif GEN_HANDLER(tlbia, 0x1F, 0x12, 0x0B, 0x03FFFC01, PPC_MEM_TLBIA), /* XXX Those instructions will need to be handled differently for -- 2.5.0