mirror of https://github.com/proxmox/mirror_qemu
target-ppc: Rework get_physical_address()
Currently get_physical_address() first checks to see if translation is enabled in the MSR, then in the translation on case switches on the mmu type. Except that for BookE MMUs, translation is always on, and so it has to switch in the "translation off" case as well and do the same thing as the translation on path for those MMUs. Plus, even translation off doesn't behave exactly the same on the various MMU types so there are further mmu type checks in the "translation off" path. As a first step to cleaning this up, this patch moves the switch on mmu type to the top level, then makes the translation on/off check just for those mmu types where it is meaningful. Signed-off-by: David Gibson <david@gibson.dropbear.id.au> Signed-off-by: Alexander Graf <agraf@suse.de>master
parent
0480884f14
commit
44bc910794
|
@ -1316,30 +1316,20 @@ static inline int check_physical(CPUPPCState *env, mmu_ctx_t *ctx,
|
||||||
static int get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx,
|
static int get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx,
|
||||||
target_ulong eaddr, int rw, int access_type)
|
target_ulong eaddr, int rw, int access_type)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret = -1;
|
||||||
|
bool real_mode = (access_type == ACCESS_CODE && msr_ir == 0)
|
||||||
|
|| (access_type != ACCESS_CODE && msr_dr == 0);
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
qemu_log("%s\n", __func__);
|
qemu_log("%s\n", __func__);
|
||||||
#endif
|
#endif
|
||||||
if ((access_type == ACCESS_CODE && msr_ir == 0) ||
|
|
||||||
(access_type != ACCESS_CODE && msr_dr == 0)) {
|
|
||||||
if (env->mmu_model == POWERPC_MMU_BOOKE) {
|
|
||||||
/* The BookE MMU always performs address translation. The
|
|
||||||
IS and DS bits only affect the address space. */
|
|
||||||
ret = mmubooke_get_physical_address(env, ctx, eaddr,
|
|
||||||
rw, access_type);
|
|
||||||
} else if (env->mmu_model == POWERPC_MMU_BOOKE206) {
|
|
||||||
ret = mmubooke206_get_physical_address(env, ctx, eaddr, rw,
|
|
||||||
access_type);
|
|
||||||
} else {
|
|
||||||
/* No address translation. */
|
|
||||||
ret = check_physical(env, ctx, eaddr, rw);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ret = -1;
|
|
||||||
switch (env->mmu_model) {
|
switch (env->mmu_model) {
|
||||||
case POWERPC_MMU_32B:
|
case POWERPC_MMU_32B:
|
||||||
case POWERPC_MMU_601:
|
case POWERPC_MMU_601:
|
||||||
|
if (real_mode) {
|
||||||
|
ret = check_physical(env, ctx, eaddr, rw);
|
||||||
|
} else {
|
||||||
/* Try to find a BAT */
|
/* Try to find a BAT */
|
||||||
if (env->nb_BATs != 0) {
|
if (env->nb_BATs != 0) {
|
||||||
ret = get_bat(env, ctx, eaddr, rw, access_type);
|
ret = get_bat(env, ctx, eaddr, rw, access_type);
|
||||||
|
@ -1348,10 +1338,14 @@ static int get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx,
|
||||||
/* We didn't match any BAT entry or don't have BATs */
|
/* We didn't match any BAT entry or don't have BATs */
|
||||||
ret = get_segment32(env, ctx, eaddr, rw, access_type);
|
ret = get_segment32(env, ctx, eaddr, rw, access_type);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case POWERPC_MMU_SOFT_6xx:
|
case POWERPC_MMU_SOFT_6xx:
|
||||||
case POWERPC_MMU_SOFT_74xx:
|
case POWERPC_MMU_SOFT_74xx:
|
||||||
|
if (real_mode) {
|
||||||
|
ret = check_physical(env, ctx, eaddr, rw);
|
||||||
|
} else {
|
||||||
/* Try to find a BAT */
|
/* Try to find a BAT */
|
||||||
if (env->nb_BATs != 0) {
|
if (env->nb_BATs != 0) {
|
||||||
ret = get_bat(env, ctx, eaddr, rw, access_type);
|
ret = get_bat(env, ctx, eaddr, rw, access_type);
|
||||||
|
@ -1360,20 +1354,29 @@ static int get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx,
|
||||||
/* We didn't match any BAT entry or don't have BATs */
|
/* We didn't match any BAT entry or don't have BATs */
|
||||||
ret = get_segment_6xx_tlb(env, ctx, eaddr, rw, access_type);
|
ret = get_segment_6xx_tlb(env, ctx, eaddr, rw, access_type);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
#if defined(TARGET_PPC64)
|
#if defined(TARGET_PPC64)
|
||||||
case POWERPC_MMU_64B:
|
case POWERPC_MMU_64B:
|
||||||
case POWERPC_MMU_2_06:
|
case POWERPC_MMU_2_06:
|
||||||
case POWERPC_MMU_2_06d:
|
case POWERPC_MMU_2_06d:
|
||||||
|
if (real_mode) {
|
||||||
|
ret = check_physical(env, ctx, eaddr, rw);
|
||||||
|
} else {
|
||||||
ret = get_segment64(env, ctx, eaddr, rw, access_type);
|
ret = get_segment64(env, ctx, eaddr, rw, access_type);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
case POWERPC_MMU_SOFT_4xx:
|
case POWERPC_MMU_SOFT_4xx:
|
||||||
case POWERPC_MMU_SOFT_4xx_Z:
|
case POWERPC_MMU_SOFT_4xx_Z:
|
||||||
|
if (real_mode) {
|
||||||
|
ret = check_physical(env, ctx, eaddr, rw);
|
||||||
|
} else {
|
||||||
ret = mmu40x_get_physical_address(env, ctx, eaddr,
|
ret = mmu40x_get_physical_address(env, ctx, eaddr,
|
||||||
rw, access_type);
|
rw, access_type);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case POWERPC_MMU_BOOKE:
|
case POWERPC_MMU_BOOKE:
|
||||||
ret = mmubooke_get_physical_address(env, ctx, eaddr,
|
ret = mmubooke_get_physical_address(env, ctx, eaddr,
|
||||||
|
@ -1388,13 +1391,16 @@ static int get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx,
|
||||||
cpu_abort(env, "MPC8xx MMU model is not implemented\n");
|
cpu_abort(env, "MPC8xx MMU model is not implemented\n");
|
||||||
break;
|
break;
|
||||||
case POWERPC_MMU_REAL:
|
case POWERPC_MMU_REAL:
|
||||||
|
if (real_mode) {
|
||||||
|
ret = check_physical(env, ctx, eaddr, rw);
|
||||||
|
} else {
|
||||||
cpu_abort(env, "PowerPC in real mode do not do any translation\n");
|
cpu_abort(env, "PowerPC in real mode do not do any translation\n");
|
||||||
|
}
|
||||||
return -1;
|
return -1;
|
||||||
default:
|
default:
|
||||||
cpu_abort(env, "Unknown or invalid MMU model\n");
|
cpu_abort(env, "Unknown or invalid MMU model\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
#if 0
|
#if 0
|
||||||
qemu_log("%s address " TARGET_FMT_lx " => %d " TARGET_FMT_plx "\n",
|
qemu_log("%s address " TARGET_FMT_lx " => %d " TARGET_FMT_plx "\n",
|
||||||
__func__, eaddr, ret, ctx->raddr);
|
__func__, eaddr, ret, ctx->raddr);
|
||||||
|
|
Loading…
Reference in New Issue