]> git.proxmox.com Git - qemu.git/commitdiff
mmu-hash*: Separate PTEG searching from permissions checking
authorDavid Gibson <david@gibson.dropbear.id.au>
Tue, 12 Mar 2013 00:31:28 +0000 (00:31 +0000)
committerAlexander Graf <agraf@suse.de>
Fri, 22 Mar 2013 14:28:50 +0000 (15:28 +0100)
find_pte{32,64{() do several things.  First they search through a PTEG
ooking for a PTE matching our virtual address.  Then they do permissions
checking and other processing on that PTE.

This patch separates the search by VA out from the rest.  The search is
combined with the pte{32,64}_match() functions into new
ppc_has{32,64}_pteg_search() functions.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Alexander Graf <agraf@suse.de>
target-ppc/mmu-hash32.c
target-ppc/mmu-hash32.h
target-ppc/mmu-hash64.c
target-ppc/mmu-hash64.h

index 3be1002e8cff9a31198e0087311e1d3ac3d1528b..7c13a4957f85d1e3d13ff4d4b06631b291c25242 100644 (file)
@@ -297,14 +297,6 @@ 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 rwx)
 {
@@ -328,8 +320,8 @@ static int pte_check_hash32(struct mmu_ctx_hash32 *ctx, target_ulong pte0,
     return ret;
 }
 
-static int ppc_hash32_pte_update_flags(struct mmu_ctx_hash32 *ctx, target_ulong *pte1p,
-                                       int ret, int rwx)
+static int ppc_hash32_pte_update_flags(struct mmu_ctx_hash32 *ctx,
+                                       uint32_t *pte1p, int ret, int rwx)
 {
     int store = 0;
 
@@ -358,40 +350,49 @@ hwaddr get_pteg_offset32(CPUPPCState *env, hwaddr hash)
     return (hash * HASH_PTEG_SIZE_32) & env->htab_mask;
 }
 
-/* PTE table lookup */
+static hwaddr ppc_hash32_pteg_search(CPUPPCState *env, hwaddr pteg_off,
+                                     bool secondary, target_ulong ptem,
+                                     ppc_hash_pte32_t *pte)
+{
+    hwaddr pte_offset = pteg_off;
+    target_ulong pte0, pte1;
+    int i;
+
+    for (i = 0; i < HPTES_PER_GROUP; i++) {
+        pte0 = ppc_hash32_load_hpte0(env, pte_offset);
+        pte1 = ppc_hash32_load_hpte1(env, pte_offset);
+
+        if ((pte0 & HPTE32_V_VALID)
+            && (secondary == !!(pte0 & HPTE32_V_SECONDARY))
+            && HPTE32_V_COMPARE(pte0, ptem)) {
+            pte->pte0 = pte0;
+            pte->pte1 = pte1;
+            return pte_offset;
+        }
+
+        pte_offset += HASH_PTE_SIZE_32;
+    }
+
+    return -1;
+}
+
 static int find_pte32(CPUPPCState *env, struct mmu_ctx_hash32 *ctx,
                       target_ulong eaddr, int h, int rwx, int target_page_bits)
 {
-    hwaddr pteg_off;
-    target_ulong pte0, pte1;
-    int i, good = -1;
+    hwaddr pteg_off, pte_offset;
+    ppc_hash_pte32_t pte;
     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);
-
-        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);
-
-        if (pte32_match(pte0, pte1, h, ctx->ptem)) {
-            good = i;
-            break;
-        }
-    }
-    if (good != -1) {
-        ret = pte_check_hash32(ctx, pte0, pte1, rwx);
+    pte_offset = ppc_hash32_pteg_search(env, pteg_off, h, ctx->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 */
-        pte1 = ctx->raddr;
-        if (ppc_hash32_pte_update_flags(ctx, &pte1, ret, rwx) == 1) {
-            ppc_hash32_store_hpte1(env, pteg_off + good * HASH_PTE_SIZE_32,
-                                   pte1);
+        if (ppc_hash32_pte_update_flags(ctx, &pte.pte1, ret, rwx) == 1) {
+            ppc_hash32_store_hpte1(env, pte_offset, pte.pte1);
         }
     }
 
index 2344184584af42628533491f4b16bcb08385bd29..f990edc3efefa704c129cace64417825b6eb8c3a 100644 (file)
@@ -97,6 +97,10 @@ static inline void ppc_hash32_store_hpte1(CPUPPCState *env,
     stl_phys(env->htab_base + pte_offset + HASH_PTE_SIZE_32/2, pte1);
 }
 
+typedef struct {
+    uint32_t pte0, pte1;
+} ppc_hash_pte32_t;
+
 #endif /* CONFIG_USER_ONLY */
 
 #endif /* __MMU_HASH32_H__ */
index 8664116aab877ff4ca2d46abb101852d37749251..66b2d2444b99053960365d2487f981d2e9ba3e1c 100644 (file)
@@ -299,14 +299,6 @@ static int ppc_hash64_check_prot(int prot, int rwx)
     return ret;
 }
 
-static bool pte64_match(target_ulong pte0, target_ulong pte1,
-                        bool secondary, target_ulong ptem)
-{
-    return (pte0 & HPTE64_V_VALID)
-        && (secondary == !!(pte0 & HPTE64_V_SECONDARY))
-        && HPTE64_V_COMPARE(pte0, ptem);
-}
-
 static int pte64_check(struct mmu_ctx_hash64 *ctx, target_ulong pte0,
                        target_ulong pte1, int rwx)
 {
@@ -334,8 +326,7 @@ static int pte64_check(struct mmu_ctx_hash64 *ctx, target_ulong pte0,
 }
 
 static int ppc_hash64_pte_update_flags(struct mmu_ctx_hash64 *ctx,
-                                       target_ulong *pte1p,
-                                       int ret, int rw)
+                                       uint64_t *pte1p, int ret, int rw)
 {
     int store = 0;
 
@@ -359,39 +350,49 @@ static int ppc_hash64_pte_update_flags(struct mmu_ctx_hash64 *ctx,
     return store;
 }
 
-/* PTE table lookup */
+static hwaddr ppc_hash64_pteg_search(CPUPPCState *env, hwaddr pteg_off,
+                                     bool secondary, target_ulong ptem,
+                                     ppc_hash_pte64_t *pte)
+{
+    hwaddr pte_offset = pteg_off;
+    target_ulong pte0, pte1;
+    int i;
+
+    for (i = 0; i < HPTES_PER_GROUP; i++) {
+        pte0 = ppc_hash64_load_hpte0(env, pte_offset);
+        pte1 = ppc_hash64_load_hpte1(env, pte_offset);
+
+        if ((pte0 & HPTE64_V_VALID)
+            && (secondary == !!(pte0 & HPTE64_V_SECONDARY))
+            && HPTE64_V_COMPARE(pte0, ptem)) {
+            pte->pte0 = pte0;
+            pte->pte1 = pte1;
+            return pte_offset;
+        }
+
+        pte_offset += HASH_PTE_SIZE_64;
+    }
+
+    return -1;
+}
+
 static int find_pte64(CPUPPCState *env, struct mmu_ctx_hash64 *ctx,
                       target_ulong eaddr, int h, int rwx, int target_page_bits)
 {
-    hwaddr pteg_off;
-    target_ulong pte0, pte1;
-    int i, good = -1;
+    hwaddr pteg_off, pte_offset;
+    ppc_hash_pte64_t pte;
     int ret;
 
     ret = -1; /* No entry found */
     pteg_off = (ctx->hash[h] * HASH_PTEG_SIZE_64) & env->htab_mask;
-    for (i = 0; i < HPTES_PER_GROUP; i++) {
-        pte0 = ppc_hash64_load_hpte0(env, pteg_off + i*HASH_PTE_SIZE_64);
-        pte1 = ppc_hash64_load_hpte1(env, pteg_off + i*HASH_PTE_SIZE_64);
-
-        LOG_MMU("Load pte from %016" HWADDR_PRIx " => " TARGET_FMT_lx " "
-                TARGET_FMT_lx " %d %d %d " TARGET_FMT_lx "\n",
-                pteg_off + (i * 16), pte0, pte1, !!(pte0 & HPTE64_V_VALID),
-                h, !!(pte0 & HPTE64_V_SECONDARY), ctx->ptem);
-
-        if (pte64_match(pte0, pte1, h, ctx->ptem)) {
-            good = i;
-            break;
-        }
-    }
-    if (good != -1) {
-        ret = pte64_check(ctx, pte0, pte1, rwx);
+    pte_offset = ppc_hash64_pteg_search(env, pteg_off, h, ctx->ptem, &pte);
+    if (pte_offset != -1) {
+        ret = pte64_check(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 */
-        pte1 = ctx->raddr;
-        if (ppc_hash64_pte_update_flags(ctx, &pte1, ret, rwx) == 1) {
-            ppc_hash64_store_hpte1(env, pteg_off + good * HASH_PTE_SIZE_64, pte1);
+        if (ppc_hash64_pte_update_flags(ctx, &pte.pte1, ret, rwx) == 1) {
+            ppc_hash64_store_hpte1(env, pte_offset, pte.pte1);
         }
     }
 
index 84576c0648e0d9a8c9a89989cae2be91b48140b0..37ed7ca4ef76dd65b1976a3f599c41ae069cc21d 100644 (file)
@@ -113,6 +113,10 @@ static inline void ppc_hash64_store_hpte1(CPUPPCState *env,
     }
 }
 
+typedef struct {
+    uint64_t pte0, pte1;
+} ppc_hash_pte64_t;
+
 #endif /* CONFIG_USER_ONLY */
 
 #endif /* !defined (__MMU_HASH64_H__) */