diff options
author | David Gibson | 2013-03-12 01:31:30 +0100 |
---|---|---|
committer | Alexander Graf | 2013-03-22 15:28:50 +0100 |
commit | 7f3bdc2d8e17999a26ac0f6649caef92fedfc1c0 (patch) | |
tree | 80ea298448a08389919c1e174d8f5eef2cea7506 /target-ppc/mmu-hash32.c | |
parent | mmu-hash*: Make find_pte{32, 64} do more of the job of finding ptes (diff) | |
download | qemu-7f3bdc2d8e17999a26ac0f6649caef92fedfc1c0.tar.gz qemu-7f3bdc2d8e17999a26ac0f6649caef92fedfc1c0.tar.xz qemu-7f3bdc2d8e17999a26ac0f6649caef92fedfc1c0.zip |
mmu-hash*: Remove permission checking from find_pte{32, 64}()
find_pte{32,64}() are poorly named, since they both find a PTE and do
permissions checking of it. This patch makes them only locate a matching
PTE, moving the permission checking and other logic to the caller. We
rename the resulting search functions ppc_hash{32,64}_htab_lookup().
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Alexander Graf <agraf@suse.de>
Diffstat (limited to 'target-ppc/mmu-hash32.c')
-rw-r--r-- | target-ppc/mmu-hash32.c | 45 |
1 files changed, 24 insertions, 21 deletions
diff --git a/target-ppc/mmu-hash32.c b/target-ppc/mmu-hash32.c index b7a26a2a90..8b403fecb1 100644 --- a/target-ppc/mmu-hash32.c +++ b/target-ppc/mmu-hash32.c @@ -374,19 +374,15 @@ static hwaddr ppc_hash32_pteg_search(CPUPPCState *env, hwaddr pteg_off, return -1; } -static int find_pte32(CPUPPCState *env, struct mmu_ctx_hash32 *ctx, - target_ulong sr, target_ulong eaddr, int rwx) +static hwaddr ppc_hash32_htab_lookup(CPUPPCState *env, + target_ulong sr, target_ulong eaddr, + ppc_hash_pte32_t *pte) { hwaddr pteg_off, pte_offset; - ppc_hash_pte32_t pte; hwaddr hash; uint32_t vsid, pgidx, ptem; - int ret; - ret = -1; /* No entry found */ vsid = sr & SR32_VSID; - ctx->key = (((sr & SR32_KP) && (msr_pr != 0)) || - ((sr & SR32_KS) && (msr_pr == 0))) ? 1 : 0; pgidx = (eaddr & ~SEGMENT_MASK_256M) >> TARGET_PAGE_BITS; hash = vsid ^ pgidx; ptem = (vsid << 7) | (pgidx >> 10); @@ -402,7 +398,7 @@ static int find_pte32(CPUPPCState *env, struct mmu_ctx_hash32 *ctx, " hash=" TARGET_FMT_plx "\n", env->htab_base, env->htab_mask, vsid, ptem, hash); pteg_off = get_pteg_offset32(env, hash); - pte_offset = ppc_hash32_pteg_search(env, pteg_off, 0, ptem, &pte); + pte_offset = ppc_hash32_pteg_search(env, pteg_off, 0, ptem, pte); if (pte_offset == -1) { /* Secondary PTEG lookup */ LOG_MMU("1 htab=" TARGET_FMT_plx "/" TARGET_FMT_plx @@ -410,20 +406,10 @@ static int find_pte32(CPUPPCState *env, struct mmu_ctx_hash32 *ctx, " hash=" TARGET_FMT_plx "\n", env->htab_base, env->htab_mask, vsid, ptem, ~hash); pteg_off = get_pteg_offset32(env, ~hash); - pte_offset = ppc_hash32_pteg_search(env, pteg_off, 1, ptem, &pte); + pte_offset = ppc_hash32_pteg_search(env, pteg_off, 1, ptem, pte); } - if (pte_offset != -1) { - ret = pte_check_hash32(ctx, pte.pte0, pte.pte1, rwx); - LOG_MMU("found PTE at addr %08" HWADDR_PRIx " prot=%01x ret=%d\n", - ctx->raddr, ctx->prot, ret); - /* Update page flags */ - if (ppc_hash32_pte_update_flags(ctx, &pte.pte1, ret, rwx) == 1) { - ppc_hash32_store_hpte1(env, pte_offset, pte.pte1); - } - } - - return ret; + return pte_offset; } static int ppc_hash32_translate(CPUPPCState *env, struct mmu_ctx_hash32 *ctx, @@ -431,6 +417,8 @@ static int ppc_hash32_translate(CPUPPCState *env, struct mmu_ctx_hash32 *ctx, { int ret; target_ulong sr; + hwaddr pte_offset; + ppc_hash_pte32_t pte; /* 1. Handle real mode accesses */ if (((rwx == 2) && (msr_ir == 0)) || ((rwx != 2) && (msr_dr == 0))) { @@ -462,7 +450,22 @@ static int ppc_hash32_translate(CPUPPCState *env, struct mmu_ctx_hash32 *ctx, if ((rwx == 2) && ctx->nx) { return -3; } - ret = find_pte32(env, ctx, sr, eaddr, rwx); + + /* 6. Locate the PTE in the hash table */ + pte_offset = ppc_hash32_htab_lookup(env, sr, eaddr, &pte); + if (pte_offset == -1) { + return -1; + } + LOG_MMU("found PTE at offset %08" HWADDR_PRIx "\n", pte_offset); + + /* 7. Check access permissions */ + ctx->key = (((sr & SR32_KP) && (msr_pr != 0)) || + ((sr & SR32_KS) && (msr_pr == 0))) ? 1 : 0; + ret = pte_check_hash32(ctx, pte.pte0, pte.pte1, rwx); + /* Update page flags */ + if (ppc_hash32_pte_update_flags(ctx, &pte.pte1, ret, rwx) == 1) { + ppc_hash32_store_hpte1(env, pte_offset, pte.pte1); + } return ret; } |