Message ID | 1297522467-5975-6-git-send-email-david@gibson.dropbear.id.au |
---|---|
State | New |
Headers | show |
On 12.02.2011, at 15:54, David Gibson wrote: > From: David Gibson <dwg@au1.ibm.com> > > For a 64-bit PowerPC target, qemu correctly implements translation > through the segment lookaside buffer. Likewise it supports the > slbmte instruction which is used to load entries into the SLB. > > However, it does not emulate the slbmfee and slbmfev instructions > which read SLB entries back into registers. Because these are > only occasionally used in guests (mostly for debugging) we get > away with it. > > However, given the recent SLB cleanups, it becomes quite easy to > implement these, and thereby allow, amongst other things, a guest > Linux to use xmon's command to dump the SLB. > > Signed-off-by: David Gibson <dwg@au1.ibm.com> > --- > target-ppc/cpu.h | 2 ++ > target-ppc/helper.c | 26 ++++++++++++++++++++++++++ > target-ppc/helper.h | 2 ++ > target-ppc/op_helper.c | 20 ++++++++++++++++++++ > target-ppc/translate.c | 29 ++++++++++++++++++++++++++++- > 5 files changed, 78 insertions(+), 1 deletions(-) > > diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h > index eaddc27..9a7495a 100644 > --- a/target-ppc/cpu.h > +++ b/target-ppc/cpu.h > @@ -781,6 +781,8 @@ void ppc_store_asr (CPUPPCState *env, target_ulong value); > target_ulong ppc_load_slb (CPUPPCState *env, int slb_nr); > target_ulong ppc_load_sr (CPUPPCState *env, int sr_nr); > int ppc_store_slb (CPUPPCState *env, target_ulong rb, target_ulong rs); > +int ppc_load_slb_esid (CPUPPCState *env, target_ulong rb, target_ulong *rt); > +int ppc_load_slb_vsid (CPUPPCState *env, target_ulong rb, target_ulong *rt); > #endif /* defined(TARGET_PPC64) */ > void ppc_store_sr (CPUPPCState *env, int srnum, target_ulong value); > #endif /* !defined(CONFIG_USER_ONLY) */ > diff --git a/target-ppc/helper.c b/target-ppc/helper.c > index 19aa067..4830981 100644 > --- a/target-ppc/helper.c > +++ b/target-ppc/helper.c > @@ -770,6 +770,32 @@ int ppc_store_slb (CPUPPCState *env, target_ulong rb, target_ulong rs) > > return 0; > } > + > +int ppc_load_slb_esid (CPUPPCState *env, target_ulong rb, target_ulong *rt) > +{ > + int slot = rb & 0xfff; > + ppc_slb_t *slb = &env->slb[slot]; > + > + if (slot >= env->slb_nr) { > + return -1; > + } > + > + *rt = slb->esid; > + return 0; > +} > + > +int ppc_load_slb_vsid (CPUPPCState *env, target_ulong rb, target_ulong *rt) > +{ > + int slot = rb & 0xfff; > + ppc_slb_t *slb = &env->slb[slot]; > + > + if (slot >= env->slb_nr) { > + return -1; > + } > + > + *rt = slb->vsid; > + return 0; > +} > #endif /* defined(TARGET_PPC64) */ > > /* Perform segment based translation */ > diff --git a/target-ppc/helper.h b/target-ppc/helper.h > index d512cb0..1a69cf8 100644 > --- a/target-ppc/helper.h > +++ b/target-ppc/helper.h > @@ -341,6 +341,8 @@ DEF_HELPER_FLAGS_0(tlbia, TCG_CALL_CONST, void) > DEF_HELPER_FLAGS_1(tlbie, TCG_CALL_CONST, void, tl) > #if defined(TARGET_PPC64) > DEF_HELPER_FLAGS_2(store_slb, TCG_CALL_CONST, void, tl, tl) > +DEF_HELPER_1(load_slb_esid, tl, tl) > +DEF_HELPER_1(load_slb_vsid, tl, tl) > DEF_HELPER_FLAGS_0(slbia, TCG_CALL_CONST, void) > DEF_HELPER_FLAGS_1(slbie, TCG_CALL_CONST, void, tl) > #endif > diff --git a/target-ppc/op_helper.c b/target-ppc/op_helper.c > index bf41627..bdb1f17 100644 > --- a/target-ppc/op_helper.c > +++ b/target-ppc/op_helper.c > @@ -3753,6 +3753,26 @@ void helper_store_slb (target_ulong rb, target_ulong rs) > } > } > > +target_ulong helper_load_slb_esid (target_ulong rb) > +{ > + target_ulong rt; > + > + if (ppc_load_slb_esid(env, rb, &rt) < 0) { > + helper_raise_exception_err(POWERPC_EXCP_PROGRAM, POWERPC_EXCP_INVAL); The spec doesn't say what to do in this case. Have you checked what real hardware does? Alex
On Sat, Feb 12, 2011 at 04:23:39PM +0100, Alexander Graf wrote: > On 12.02.2011, at 15:54, David Gibson wrote: [snip] > > +target_ulong helper_load_slb_esid (target_ulong rb) > > +{ > > + target_ulong rt; > > + > > + if (ppc_load_slb_esid(env, rb, &rt) < 0) { > > + helper_raise_exception_err(POWERPC_EXCP_PROGRAM, POWERPC_EXCP_INVAL); > > The spec doesn't say what to do in this case. Have you checked what > real hardware does? Erm, I don't think I've checked this specific case, on this specific CPU. Generally I've found that invalid parameters to MMU management instructions results in invalid instruction program checks, so I assumed that's what would happen in this case.
diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h index eaddc27..9a7495a 100644 --- a/target-ppc/cpu.h +++ b/target-ppc/cpu.h @@ -781,6 +781,8 @@ void ppc_store_asr (CPUPPCState *env, target_ulong value); target_ulong ppc_load_slb (CPUPPCState *env, int slb_nr); target_ulong ppc_load_sr (CPUPPCState *env, int sr_nr); int ppc_store_slb (CPUPPCState *env, target_ulong rb, target_ulong rs); +int ppc_load_slb_esid (CPUPPCState *env, target_ulong rb, target_ulong *rt); +int ppc_load_slb_vsid (CPUPPCState *env, target_ulong rb, target_ulong *rt); #endif /* defined(TARGET_PPC64) */ void ppc_store_sr (CPUPPCState *env, int srnum, target_ulong value); #endif /* !defined(CONFIG_USER_ONLY) */ diff --git a/target-ppc/helper.c b/target-ppc/helper.c index 19aa067..4830981 100644 --- a/target-ppc/helper.c +++ b/target-ppc/helper.c @@ -770,6 +770,32 @@ int ppc_store_slb (CPUPPCState *env, target_ulong rb, target_ulong rs) return 0; } + +int ppc_load_slb_esid (CPUPPCState *env, target_ulong rb, target_ulong *rt) +{ + int slot = rb & 0xfff; + ppc_slb_t *slb = &env->slb[slot]; + + if (slot >= env->slb_nr) { + return -1; + } + + *rt = slb->esid; + return 0; +} + +int ppc_load_slb_vsid (CPUPPCState *env, target_ulong rb, target_ulong *rt) +{ + int slot = rb & 0xfff; + ppc_slb_t *slb = &env->slb[slot]; + + if (slot >= env->slb_nr) { + return -1; + } + + *rt = slb->vsid; + return 0; +} #endif /* defined(TARGET_PPC64) */ /* Perform segment based translation */ diff --git a/target-ppc/helper.h b/target-ppc/helper.h index d512cb0..1a69cf8 100644 --- a/target-ppc/helper.h +++ b/target-ppc/helper.h @@ -341,6 +341,8 @@ DEF_HELPER_FLAGS_0(tlbia, TCG_CALL_CONST, void) DEF_HELPER_FLAGS_1(tlbie, TCG_CALL_CONST, void, tl) #if defined(TARGET_PPC64) DEF_HELPER_FLAGS_2(store_slb, TCG_CALL_CONST, void, tl, tl) +DEF_HELPER_1(load_slb_esid, tl, tl) +DEF_HELPER_1(load_slb_vsid, tl, tl) DEF_HELPER_FLAGS_0(slbia, TCG_CALL_CONST, void) DEF_HELPER_FLAGS_1(slbie, TCG_CALL_CONST, void, tl) #endif diff --git a/target-ppc/op_helper.c b/target-ppc/op_helper.c index bf41627..bdb1f17 100644 --- a/target-ppc/op_helper.c +++ b/target-ppc/op_helper.c @@ -3753,6 +3753,26 @@ void helper_store_slb (target_ulong rb, target_ulong rs) } } +target_ulong helper_load_slb_esid (target_ulong rb) +{ + target_ulong rt; + + if (ppc_load_slb_esid(env, rb, &rt) < 0) { + helper_raise_exception_err(POWERPC_EXCP_PROGRAM, POWERPC_EXCP_INVAL); + } + return rt; +} + +target_ulong helper_load_slb_vsid (target_ulong rb) +{ + target_ulong rt; + + if (ppc_load_slb_vsid(env, rb, &rt) < 0) { + helper_raise_exception_err(POWERPC_EXCP_PROGRAM, POWERPC_EXCP_INVAL); + } + return rt; +} + void helper_slbia (void) { ppc_slb_invalidate_all(env); diff --git a/target-ppc/translate.c b/target-ppc/translate.c index 89413c5..2b1a851 100644 --- a/target-ppc/translate.c +++ b/target-ppc/translate.c @@ -4227,6 +4227,31 @@ static void gen_slbmte(DisasContext *ctx) #endif } +static void gen_slbmfee(DisasContext *ctx) +{ +#if defined(CONFIG_USER_ONLY) + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG); +#else + if (unlikely(!ctx->mem_idx)) { + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG); + return; + } + gen_helper_load_slb_esid(cpu_gpr[rS(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]); +#endif +} + +static void gen_slbmfev(DisasContext *ctx) +{ +#if defined(CONFIG_USER_ONLY) + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG); +#else + if (unlikely(!ctx->mem_idx)) { + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG); + return; + } + gen_helper_load_slb_vsid(cpu_gpr[rS(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]); +#endif +} #endif /* defined(TARGET_PPC64) */ /*** Lookaside buffer management ***/ @@ -8110,7 +8135,9 @@ GEN_HANDLER2(mfsrin_64b, "mfsrin", 0x1F, 0x13, 0x14, 0x001F0001, GEN_HANDLER2(mtsr_64b, "mtsr", 0x1F, 0x12, 0x06, 0x0010F801, PPC_SEGMENT_64B), GEN_HANDLER2(mtsrin_64b, "mtsrin", 0x1F, 0x12, 0x07, 0x001F0001, PPC_SEGMENT_64B), -GEN_HANDLER2(slbmte, "slbmte", 0x1F, 0x12, 0x0C, 0x00000000, PPC_SEGMENT_64B), +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), #endif GEN_HANDLER(tlbia, 0x1F, 0x12, 0x0B, 0x03FFFC01, PPC_MEM_TLBIA), GEN_HANDLER(tlbiel, 0x1F, 0x12, 0x08, 0x03FF0001, PPC_MEM_TLBIE),