aboutsummaryrefslogtreecommitdiff
path: root/target-ppc/mmu-hash32.c
diff options
context:
space:
mode:
Diffstat (limited to 'target-ppc/mmu-hash32.c')
-rw-r--r--target-ppc/mmu-hash32.c86
1 files changed, 28 insertions, 58 deletions
diff --git a/target-ppc/mmu-hash32.c b/target-ppc/mmu-hash32.c
index d812adbbf1..3be1002e8c 100644
--- a/target-ppc/mmu-hash32.c
+++ b/target-ppc/mmu-hash32.c
@@ -50,8 +50,6 @@ struct mmu_ctx_hash32 {
int nx; /* Non-execute area */
};
-#define PTE_CHECK_MASK (TARGET_PAGE_MASK | 0x7B)
-
static int ppc_hash32_pp_check(int key, int pp, int nx)
{
int access;
@@ -299,40 +297,32 @@ static int ppc_hash32_direct_store(CPUPPCState *env, target_ulong sr,
}
}
+static bool pte32_match(target_ulong pte0, target_ulong pte1,
+ bool secondary, target_ulong ptem)
+{
+ return (pte0 & HPTE32_V_VALID)
+ && (secondary == !!(pte0 & HPTE32_V_SECONDARY))
+ && HPTE32_V_COMPARE(pte0, ptem);
+}
+
static int pte_check_hash32(struct mmu_ctx_hash32 *ctx, target_ulong pte0,
- target_ulong pte1, int h, int rwx)
+ target_ulong pte1, int rwx)
{
- target_ulong mmask;
int access, ret, pp;
- ret = -1;
- /* Check validity and table match */
- if ((pte0 & HPTE32_V_VALID) && (h == !!(pte0 & HPTE32_V_SECONDARY))) {
- /* Check vsid & api */
- mmask = PTE_CHECK_MASK;
- pp = pte1 & HPTE32_R_PP;
- if (HPTE32_V_COMPARE(pte0, ctx->ptem)) {
- if (ctx->raddr != (hwaddr)-1ULL) {
- /* all matches should have equal RPN, WIMG & PP */
- if ((ctx->raddr & mmask) != (pte1 & mmask)) {
- qemu_log("Bad RPN/WIMG/PP\n");
- return -3;
- }
- }
- /* Compute access rights */
- access = ppc_hash32_pp_check(ctx->key, pp, ctx->nx);
- /* Keep the matching PTE informations */
- ctx->raddr = pte1;
- ctx->prot = access;
- ret = ppc_hash32_check_prot(ctx->prot, rwx);
- if (ret == 0) {
- /* Access granted */
- LOG_MMU("PTE access granted !\n");
- } else {
- /* Access right violation */
- LOG_MMU("PTE access rejected\n");
- }
- }
+ pp = pte1 & HPTE32_R_PP;
+ /* Compute access rights */
+ access = ppc_hash32_pp_check(ctx->key, pp, ctx->nx);
+ /* Keep the matching PTE informations */
+ ctx->raddr = pte1;
+ ctx->prot = access;
+ ret = ppc_hash32_check_prot(ctx->prot, rwx);
+ if (ret == 0) {
+ /* Access granted */
+ LOG_MMU("PTE access granted !\n");
+ } else {
+ /* Access right violation */
+ LOG_MMU("PTE access rejected\n");
}
return ret;
@@ -375,44 +365,26 @@ static int find_pte32(CPUPPCState *env, struct mmu_ctx_hash32 *ctx,
hwaddr pteg_off;
target_ulong pte0, pte1;
int i, good = -1;
- int ret, r;
+ int ret;
ret = -1; /* No entry found */
pteg_off = get_pteg_offset32(env, ctx->hash[h]);
for (i = 0; i < HPTES_PER_GROUP; i++) {
pte0 = ppc_hash32_load_hpte0(env, pteg_off + i*HASH_PTE_SIZE_32);
pte1 = ppc_hash32_load_hpte1(env, pteg_off + i*HASH_PTE_SIZE_32);
- r = pte_check_hash32(ctx, pte0, pte1, h, rwx);
+
LOG_MMU("Load pte from %08" HWADDR_PRIx " => " TARGET_FMT_lx " "
TARGET_FMT_lx " %d %d %d " TARGET_FMT_lx "\n",
pteg_off + (i * 8), pte0, pte1, (int)(pte0 >> 31), h,
(int)((pte0 >> 6) & 1), ctx->ptem);
- switch (r) {
- case -3:
- /* PTE inconsistency */
- return -1;
- case -2:
- /* Access violation */
- ret = -2;
+
+ if (pte32_match(pte0, pte1, h, ctx->ptem)) {
good = i;
break;
- case -1:
- default:
- /* No PTE match */
- break;
- case 0:
- /* access granted */
- /* XXX: we should go on looping to check all PTEs consistency
- * but if we can speed-up the whole thing as the
- * result would be undefined if PTEs are not consistent.
- */
- ret = 0;
- good = i;
- goto done;
}
}
if (good != -1) {
- done:
+ ret = pte_check_hash32(ctx, pte0, pte1, rwx);
LOG_MMU("found PTE at addr %08" HWADDR_PRIx " prot=%01x ret=%d\n",
ctx->raddr, ctx->prot, ret);
/* Update page flags */
@@ -498,8 +470,6 @@ static int ppc_hash32_translate(CPUPPCState *env, struct mmu_ctx_hash32 *ctx,
ctx->hash[0] = hash;
ctx->hash[1] = ~hash;
- /* Initialize real address with an invalid value */
- ctx->raddr = (hwaddr)-1ULL;
LOG_MMU("0 htab=" TARGET_FMT_plx "/" TARGET_FMT_plx
" vsid=" TARGET_FMT_lx " ptem=" TARGET_FMT_lx
" hash=" TARGET_FMT_plx "\n",
@@ -507,7 +477,7 @@ static int ppc_hash32_translate(CPUPPCState *env, struct mmu_ctx_hash32 *ctx,
ctx->hash[0]);
/* Primary table lookup */
ret = find_pte32(env, ctx, eaddr, 0, rwx, target_page_bits);
- if (ret < 0) {
+ if (ret == -1) {
/* Secondary table lookup */
LOG_MMU("1 htab=" TARGET_FMT_plx "/" TARGET_FMT_plx
" vsid=" TARGET_FMT_lx " api=" TARGET_FMT_lx