qemu-ppc
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-ppc] [PATCH 26/32] mmu-hash64: Clean up ppc_hash64_htab_lookup()


From: David Gibson
Subject: [Qemu-ppc] [PATCH 26/32] mmu-hash64: Clean up ppc_hash64_htab_lookup()
Date: Fri, 15 Feb 2013 19:01:16 +1100

This patch makes a general cleanup of the address mangling logic in
ppc_hash64_htab_lookup().  In particular it now avoids repeatedly switching
on the segment size.

Signed-off-by: David Gibson <address@hidden>
---
 target-ppc/mmu-hash64.c |   84 ++++++++++++++++++++++-------------------------
 1 file changed, 39 insertions(+), 45 deletions(-)

diff --git a/target-ppc/mmu-hash64.c b/target-ppc/mmu-hash64.c
index 396c88f..9402e2b 100644
--- a/target-ppc/mmu-hash64.c
+++ b/target-ppc/mmu-hash64.c
@@ -297,32 +297,6 @@ static int ppc_hash64_check_prot(int prot, int rwx)
     return ret;
 }
 
-static int pte64_check(struct mmu_ctx_hash64 *ctx, target_ulong pte0,
-                       target_ulong pte1, int rwx)
-{
-    int access, ret, pp;
-    bool nx;
-
-    pp = (pte1 & HPTE_R_PP) | ((pte1 & HPTE_R_PP0) >> 61);
-    /* No execute if either noexec or guarded bits set */
-    nx = (pte1 & HPTE_R_N) || (pte1 & HPTE_R_G);
-    /* Compute access rights */
-    access = ppc_hash64_pp_check(ctx->key, pp, nx);
-    /* Keep the matching PTE informations */
-    ctx->raddr = pte1;
-    ctx->prot = access;
-    ret = ppc_hash64_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;
-}
-
 static int ppc_hash64_pte_update_flags(struct mmu_ctx_hash64 *ctx,
                                        target_ulong *pte1p,
                                        int ret, int rw)
@@ -380,31 +354,29 @@ static hwaddr ppc_hash64_htab_lookup(CPUPPCState *env,
                                      ppc_hash_pte64_t *pte)
 {
     hwaddr pteg_off, pte_offset;
-    uint64_t vsid, pageaddr, ptem;
     hwaddr hash;
-    int segment_bits, target_page_bits;
+    uint64_t vsid, epnshift, epnmask, epn, ptem;
 
-    if (slb->vsid & SLB_VSID_B) {
-        vsid = (slb->vsid & SLB_VSID_VSID) >> SLB_VSID_SHIFT_1T;
-        segment_bits = 40;
-    } else {
-        vsid = (slb->vsid & SLB_VSID_VSID) >> SLB_VSID_SHIFT;
-        segment_bits = 28;
-    }
-
-    target_page_bits = (slb->vsid & SLB_VSID_L)
+    /* Page size according to the SLB, which we use to generate the
+     * EPN for hash table lookup..  When we implement more recent MMU
+     * extensions this might be different from the actual page size
+     * encoded in the PTE */
+    epnshift = (slb->vsid & SLB_VSID_L)
         ? TARGET_PAGE_BITS_16M : TARGET_PAGE_BITS;
+    epnmask = ~((1ULL << epnshift) - 1);
 
-    pageaddr = eaddr & ((1ULL << segment_bits)
-                            - (1ULL << target_page_bits));
     if (slb->vsid & SLB_VSID_B) {
-        hash = vsid ^ (vsid << 25) ^ (pageaddr >> target_page_bits);
+        /* 1TB segment */
+        vsid = (slb->vsid & SLB_VSID_VSID) >> SLB_VSID_SHIFT_1T;
+        epn = (eaddr & ~SEGMENT_MASK_1T) & epnmask;
+        hash = vsid ^ (vsid << 25) ^ (epn >> epnshift);
     } else {
-        hash = vsid ^ (pageaddr >> target_page_bits);
+        /* 256M segment */
+        vsid = (slb->vsid & SLB_VSID_VSID) >> SLB_VSID_SHIFT;
+        epn = (eaddr & ~SEGMENT_MASK_256M) & epnmask;
+        hash = vsid ^ (epn >> epnshift);
     }
-    /* Only 5 bits of the page index are used in the AVPN */
-    ptem = (slb->vsid & SLB_VSID_PTEM) |
-        ((pageaddr >> 16) & ((1ULL << segment_bits) - 0x80));
+    ptem = (slb->vsid & SLB_VSID_PTEM) | ((epn >> 16) & HPTE_V_AVPN);
 
     /* Page address translation */
     LOG_MMU("htab_base " TARGET_FMT_plx " htab_mask " TARGET_FMT_plx
@@ -442,6 +414,8 @@ static int ppc_hash64_translate(CPUPPCState *env, struct 
mmu_ctx_hash64 *ctx,
     ppc_hash_pte64_t pte;
     int target_page_bits;
 
+    assert((rwx == 0) || (rwx == 1) || (rwx == 2));
+
     /* 1. Handle real mode accesses */
     if (((rwx == 2) && (msr_ir == 0)) || ((rwx != 2) && (msr_dr == 0))) {
         /* Translation is off */
@@ -474,7 +448,27 @@ static int ppc_hash64_translate(CPUPPCState *env, struct 
mmu_ctx_hash64 *ctx,
     ctx->key = !!(msr_pr ? (slb->vsid & SLB_VSID_KP)
                   : (slb->vsid & SLB_VSID_KS));
 
-    ret = pte64_check(ctx, pte.pte0, pte.pte1, rwx);
+
+    int access, pp;
+    bool nx;
+
+    pp = (pte.pte1 & HPTE_R_PP) | ((pte.pte1 & HPTE_R_PP0) >> 61);
+    /* No execute if either noexec or guarded bits set */
+    nx = (pte.pte1 & HPTE_R_N) || (pte.pte1 & HPTE_R_G);
+    /* Compute access rights */
+    access = ppc_hash64_pp_check(ctx->key, pp, nx);
+    /* Keep the matching PTE informations */
+    ctx->raddr = pte.pte1;
+    ctx->prot = access;
+    ret = ppc_hash64_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");
+    }
+
     /* Update page flags */
     if (ppc_hash64_pte_update_flags(ctx, &pte.pte1, ret, rwx) == 1) {
         ppc_hash64_store_hpte1(env, pte_offset, pte.pte1);
-- 
1.7.10.4




reply via email to

[Prev in Thread] Current Thread [Next in Thread]