mmu-hash32: Cleanup BAT lookup

This patch makes a general cleanup of the ppc_hash32_get_bat() function,
renaming it to ppc_hash32_bat_lookup().  In particular, the new function
only looks for a matching BAT, with the permissions check from the old
function moved to the caller.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Alexander Graf <agraf@suse.de>
This commit is contained in:
David Gibson 2013-03-12 00:31:36 +00:00 committed by Alexander Graf
parent 6fc76aa9ad
commit 145e52f318

View File

@ -164,15 +164,14 @@ static int hash32_bat_601_prot(CPUPPCState *env,
return ppc_hash32_pp_check(key, pp, 0); return ppc_hash32_pp_check(key, pp, 0);
} }
static int ppc_hash32_get_bat(CPUPPCState *env, struct mmu_ctx_hash32 *ctx, static hwaddr ppc_hash32_bat_lookup(CPUPPCState *env, target_ulong ea, int rwx,
target_ulong virtual, int rwx) int *prot)
{ {
target_ulong *BATlt, *BATut; target_ulong *BATlt, *BATut;
int i, prot; int i;
int ret = -1;
LOG_BATS("%s: %cBAT v " TARGET_FMT_lx "\n", __func__, LOG_BATS("%s: %cBAT v " TARGET_FMT_lx "\n", __func__,
rwx == 2 ? 'I' : 'D', virtual); rwx == 2 ? 'I' : 'D', ea);
if (rwx == 2) { if (rwx == 2) {
BATlt = env->IBAT[1]; BATlt = env->IBAT[1];
BATut = env->IBAT[0]; BATut = env->IBAT[0];
@ -187,35 +186,30 @@ static int ppc_hash32_get_bat(CPUPPCState *env, struct mmu_ctx_hash32 *ctx,
if (unlikely(env->mmu_model == POWERPC_MMU_601)) { if (unlikely(env->mmu_model == POWERPC_MMU_601)) {
mask = hash32_bat_601_size(env, batu, batl); mask = hash32_bat_601_size(env, batu, batl);
prot = hash32_bat_601_prot(env, batu, batl);
} else { } else {
mask = hash32_bat_size(env, batu, batl); mask = hash32_bat_size(env, batu, batl);
prot = hash32_bat_prot(env, batu, batl);
} }
LOG_BATS("%s: %cBAT%d v " TARGET_FMT_lx " BATu " TARGET_FMT_lx LOG_BATS("%s: %cBAT%d v " TARGET_FMT_lx " BATu " TARGET_FMT_lx
" BATl " TARGET_FMT_lx "\n", __func__, " BATl " TARGET_FMT_lx "\n", __func__,
type == ACCESS_CODE ? 'I' : 'D', i, virtual, batu, batl); type == ACCESS_CODE ? 'I' : 'D', i, ea, batu, batl);
if (mask && ((virtual & mask) == (batu & BATU32_BEPI))) { if (mask && ((ea & mask) == (batu & BATU32_BEPI))) {
/* BAT matches */ hwaddr raddr = (batl & mask) | (ea & ~mask);
/* Get physical address */
ctx->raddr = (batl & mask) | (virtual & ~mask); if (unlikely(env->mmu_model == POWERPC_MMU_601)) {
ctx->raddr &= TARGET_PAGE_MASK; *prot = hash32_bat_601_prot(env, batu, batl);
/* Compute access rights */ } else {
ctx->prot = prot; *prot = hash32_bat_prot(env, batu, batl);
ret = ppc_hash32_check_prot(ctx->prot, rwx);
if (ret == 0) {
LOG_BATS("BAT %d match: r " TARGET_FMT_plx " prot=%c%c\n",
i, ctx->raddr, ctx->prot & PAGE_READ ? 'R' : '-',
ctx->prot & PAGE_WRITE ? 'W' : '-');
} }
break;
return raddr & TARGET_PAGE_MASK;
} }
} }
if (ret < 0) {
/* No hit */
#if defined(DEBUG_BATS) #if defined(DEBUG_BATS)
if (qemu_log_enabled()) { if (qemu_log_enabled()) {
LOG_BATS("no BAT match for " TARGET_FMT_lx ":\n", virtual); LOG_BATS("no BAT match for " TARGET_FMT_lx ":\n", ea);
for (i = 0; i < 4; i++) { for (i = 0; i < 4; i++) {
BATu = &BATut[i]; BATu = &BATut[i];
BATl = &BATlt[i]; BATl = &BATlt[i];
@ -225,14 +219,13 @@ static int ppc_hash32_get_bat(CPUPPCState *env, struct mmu_ctx_hash32 *ctx,
LOG_BATS("%s: %cBAT%d v " TARGET_FMT_lx " BATu " TARGET_FMT_lx LOG_BATS("%s: %cBAT%d v " TARGET_FMT_lx " BATu " TARGET_FMT_lx
" BATl " TARGET_FMT_lx "\n\t" TARGET_FMT_lx " " " BATl " TARGET_FMT_lx "\n\t" TARGET_FMT_lx " "
TARGET_FMT_lx " " TARGET_FMT_lx "\n", TARGET_FMT_lx " " TARGET_FMT_lx "\n",
__func__, type == ACCESS_CODE ? 'I' : 'D', i, virtual, __func__, type == ACCESS_CODE ? 'I' : 'D', i, ea,
*BATu, *BATl, BEPIu, BEPIl, bl); *BATu, *BATl, BEPIu, BEPIl, bl);
} }
} }
#endif #endif
}
/* No hit */ return -1;
return ret;
} }
static int ppc_hash32_direct_store(CPUPPCState *env, target_ulong sr, static int ppc_hash32_direct_store(CPUPPCState *env, target_ulong sr,
@ -405,11 +398,14 @@ static int ppc_hash32_translate(CPUPPCState *env, struct mmu_ctx_hash32 *ctx,
/* 2. Check Block Address Translation entries (BATs) */ /* 2. Check Block Address Translation entries (BATs) */
if (env->nb_BATs != 0) { if (env->nb_BATs != 0) {
ret = ppc_hash32_get_bat(env, ctx, eaddr, rwx); ctx->raddr = ppc_hash32_bat_lookup(env, eaddr, rwx, &ctx->prot);
if (ctx->raddr != -1) {
ret = ppc_hash32_check_prot(ctx->prot, rwx);
if (ret == 0) { if (ret == 0) {
return 0; return 0;
} }
} }
}
/* 3. Look up the Segment Register */ /* 3. Look up the Segment Register */
sr = env->sr[eaddr >> 28]; sr = env->sr[eaddr >> 28];