diff options
Diffstat (limited to 'target-ppc/mmu-hash32.c')
-rw-r--r-- | target-ppc/mmu-hash32.c | 86 |
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 |