sim-card
/
qemu
Archived
10
0
Fork 0

Implement PowerPC slbmfee and slbmfev instructions

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>
Signed-off-by: Alexander Graf <agraf@suse.de>
This commit is contained in:
David Gibson 2011-04-01 15:15:11 +11:00 committed by Alexander Graf
parent d569956eaf
commit efdef95fee
5 changed files with 80 additions and 1 deletions

View File

@ -779,6 +779,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) */

View File

@ -774,6 +774,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 */

View File

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

View File

@ -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);

View File

@ -4227,6 +4227,33 @@ 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 ***/
@ -8300,7 +8327,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),