mmu-hash32: Clean up BAT matching logic

The code to search for a matching BAT for a virtual address is somewhat
longwinded and awkward.  In particular, it relies on seperate size and
validity information being returned from the hash32_bat_size() function
(and 601 specific variant).

We simplify this by having hash32_bat_size() return instead a mask of the
virtual address bits to match, and 0 for invalid (since a BAT can never
match the entire address space).

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:35 +00:00 committed by Alexander Graf
parent e1d4951593
commit 6fc76aa9ad
2 changed files with 29 additions and 47 deletions

View File

@ -113,20 +113,15 @@ static int ppc_hash32_check_prot(int prot, int rwx)
return ret; return ret;
} }
static void hash32_bat_size(CPUPPCState *env, target_ulong *blp, int *validp, static target_ulong hash32_bat_size(CPUPPCState *env,
target_ulong batu, target_ulong batl) target_ulong batu, target_ulong batl)
{ {
target_ulong bl; if ((msr_pr && !(batu & BATU32_VP))
int valid; || (!msr_pr && !(batu & BATU32_VS))) {
return 0;
bl = (batu & BATU32_BL) << 15;
valid = 0;
if (((msr_pr == 0) && (batu & BATU32_VS)) ||
((msr_pr != 0) && (batu & BATU32_VP))) {
valid = 1;
} }
*blp = bl;
*validp = valid; return BATU32_BEPI & ~((batu & BATU32_BL) << 15);
} }
static int hash32_bat_prot(CPUPPCState *env, static int hash32_bat_prot(CPUPPCState *env,
@ -145,18 +140,14 @@ static int hash32_bat_prot(CPUPPCState *env,
return prot; return prot;
} }
static void hash32_bat_601_size(CPUPPCState *env, target_ulong *blp, int *validp, static target_ulong hash32_bat_601_size(CPUPPCState *env,
target_ulong batu, target_ulong batl) target_ulong batu, target_ulong batl)
{ {
target_ulong bl; if (!(batl & BATL32_601_V)) {
int valid; return 0;
}
bl = (batl & BATL32_601_BL) << 17; return BATU32_BEPI & ~((batl & BATL32_601_BL) << 17);
LOG_BATS("b %02x ==> bl " TARGET_FMT_lx " msk " TARGET_FMT_lx "\n",
(uint8_t)(batl & BATL32_601_BL), bl, ~bl);
valid = !!(batl & BATL32_601_V);
*blp = bl;
*validp = valid;
} }
static int hash32_bat_601_prot(CPUPPCState *env, static int hash32_bat_601_prot(CPUPPCState *env,
@ -177,8 +168,7 @@ static int ppc_hash32_get_bat(CPUPPCState *env, struct mmu_ctx_hash32 *ctx,
target_ulong virtual, int rwx) target_ulong virtual, int rwx)
{ {
target_ulong *BATlt, *BATut; target_ulong *BATlt, *BATut;
target_ulong BEPIl, BEPIu, bl; int i, prot;
int i, valid, prot;
int ret = -1; int ret = -1;
LOG_BATS("%s: %cBAT v " TARGET_FMT_lx "\n", __func__, LOG_BATS("%s: %cBAT v " TARGET_FMT_lx "\n", __func__,
@ -193,37 +183,33 @@ static int ppc_hash32_get_bat(CPUPPCState *env, struct mmu_ctx_hash32 *ctx,
for (i = 0; i < env->nb_BATs; i++) { for (i = 0; i < env->nb_BATs; i++) {
target_ulong batu = BATut[i]; target_ulong batu = BATut[i];
target_ulong batl = BATlt[i]; target_ulong batl = BATlt[i];
target_ulong mask;
BEPIu = batu & BATU32_BEPIU;
BEPIl = batu & BATU32_BEPIL;
if (unlikely(env->mmu_model == POWERPC_MMU_601)) { if (unlikely(env->mmu_model == POWERPC_MMU_601)) {
hash32_bat_601_size(env, &bl, &valid, batu, batl); mask = hash32_bat_601_size(env, batu, batl);
prot = hash32_bat_601_prot(env, batu, batl); prot = hash32_bat_601_prot(env, batu, batl);
} else { } else {
hash32_bat_size(env, &bl, &valid, batu, batl); mask = hash32_bat_size(env, batu, batl);
prot = hash32_bat_prot(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, virtual, batu, batl);
if ((virtual & BATU32_BEPIU) == BEPIu &&
((virtual & BATU32_BEPIL) & ~bl) == BEPIl) { if (mask && ((virtual & mask) == (batu & BATU32_BEPI))) {
/* BAT matches */ /* BAT matches */
if (valid != 0) { /* Get physical address */
/* Get physical address */ ctx->raddr = (batl & mask) | (virtual & ~mask);
ctx->raddr = (batl & BATL32_BRPNU) | ctx->raddr &= TARGET_PAGE_MASK;
((virtual & BATU32_BEPIL & bl) | (batl & BATL32_BRPNL)) | /* Compute access rights */
(virtual & 0x0001F000); ctx->prot = prot;
/* Compute access rights */ ret = ppc_hash32_check_prot(ctx->prot, rwx);
ctx->prot = prot; if (ret == 0) {
ret = ppc_hash32_check_prot(ctx->prot, rwx); LOG_BATS("BAT %d match: r " TARGET_FMT_plx " prot=%c%c\n",
if (ret == 0) { i, ctx->raddr, ctx->prot & PAGE_READ ? 'R' : '-',
LOG_BATS("BAT %d match: r " TARGET_FMT_plx " prot=%c%c\n", ctx->prot & PAGE_WRITE ? 'W' : '-');
i, ctx->raddr, ctx->prot & PAGE_READ ? 'R' : '-',
ctx->prot & PAGE_WRITE ? 'W' : '-');
}
break;
} }
break;
} }
} }
if (ret < 0) { if (ret < 0) {

View File

@ -22,16 +22,12 @@ int ppc_hash32_handle_mmu_fault(CPUPPCState *env, target_ulong address, int rw,
* Block Address Translation (BAT) definitions * Block Address Translation (BAT) definitions
*/ */
#define BATU32_BEPIU 0xf0000000
#define BATU32_BEPIL 0x0ffe0000
#define BATU32_BEPI 0xfffe0000 #define BATU32_BEPI 0xfffe0000
#define BATU32_BL 0x00001ffc #define BATU32_BL 0x00001ffc
#define BATU32_VS 0x00000002 #define BATU32_VS 0x00000002
#define BATU32_VP 0x00000001 #define BATU32_VP 0x00000001
#define BATL32_BRPNU 0xf0000000
#define BATL32_BRPNL 0x0ffe0000
#define BATL32_BRPN 0xfffe0000 #define BATL32_BRPN 0xfffe0000
#define BATL32_WIMG 0x00000078 #define BATL32_WIMG 0x00000078
#define BATL32_PP 0x00000003 #define BATL32_PP 0x00000003