qemu-ppc
[Top][All Lists]
Advanced

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

[Qemu-ppc] [PATCH 24/32] mmu-hash64: Make find_pte64 do more of the job


From: David Gibson
Subject: [Qemu-ppc] [PATCH 24/32] mmu-hash64: Make find_pte64 do more of the job of finding a pte
Date: Fri, 15 Feb 2013 19:01:14 +1100

find_pte64() is not particularly well named.  It only "finds" a PTE within
a given PTE group, and it also does permissions checking and other things.

This patch makes it somewhat close to matching the name, by folding the
search of both primary and secondary hash bucket into it, along with the
various address bit shuffling to determine the right hash buckets.

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

diff --git a/target-ppc/mmu-hash64.c b/target-ppc/mmu-hash64.c
index cb1fc02..2399b94 100644
--- a/target-ppc/mmu-hash64.c
+++ b/target-ppc/mmu-hash64.c
@@ -43,8 +43,6 @@
 struct mmu_ctx_hash64 {
     hwaddr raddr;      /* Real address              */
     int prot;                      /* Protection bits           */
-    hwaddr hash[2];    /* Pagetable hash values     */
-    target_ulong ptem;             /* Virtual segment ID | API  */
     int key;                       /* Access key                */
 };
 
@@ -378,15 +376,67 @@ static hwaddr ppc_hash64_pteg_search(CPUPPCState *env, 
hwaddr pteg_off,
 }
 
 static int find_pte64(CPUPPCState *env, struct mmu_ctx_hash64 *ctx,
-                      target_ulong eaddr, int h, int rwx, int target_page_bits)
+                      ppc_slb_t *slb, target_ulong eaddr, int rwx)
 {
     hwaddr pteg_off, pte_offset;
     ppc_hash_pte64_t pte;
+    uint64_t vsid, pageaddr, ptem;
+    hwaddr hash;
+    int segment_bits, target_page_bits;
     int ret;
 
     ret = -1; /* No entry found */
-    pteg_off = (ctx->hash[h] * HASH_PTEG_SIZE_64) & env->htab_mask;
-    pte_offset = ppc_hash64_pteg_search(env, pteg_off, h, ctx->ptem, &pte);
+
+    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)
+        ? TARGET_PAGE_BITS_16M : TARGET_PAGE_BITS;
+    ctx->key = !!(msr_pr ? (slb->vsid & SLB_VSID_KP)
+                  : (slb->vsid & SLB_VSID_KS));
+
+    pageaddr = eaddr & ((1ULL << segment_bits)
+                            - (1ULL << target_page_bits));
+    if (slb->vsid & SLB_VSID_B) {
+        hash = vsid ^ (vsid << 25) ^ (pageaddr >> target_page_bits);
+    } else {
+        hash = vsid ^ (pageaddr >> target_page_bits);
+    }
+    /* Only 5 bits of the page index are used in the AVPN */
+    ptem = (slb->vsid & SLB_VSID_PTEM) |
+        ((pageaddr >> 16) & ((1ULL << segment_bits) - 0x80));
+
+    ret = -1;
+
+    /* Page address translation */
+    LOG_MMU("htab_base " TARGET_FMT_plx " htab_mask " TARGET_FMT_plx
+            " hash " TARGET_FMT_plx "\n",
+            env->htab_base, env->htab_mask, hash);
+
+
+    /* Primary PTEG lookup */
+    LOG_MMU("0 htab=" TARGET_FMT_plx "/" TARGET_FMT_plx
+            " vsid=" TARGET_FMT_lx " ptem=" TARGET_FMT_lx
+            " hash=" TARGET_FMT_plx "\n",
+            env->htab_base, env->htab_mask, vsid, ptem,  hash);
+    pteg_off = (hash * HASH_PTEG_SIZE_64) & env->htab_mask;
+    pte_offset = ppc_hash64_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
+                " vsid=" TARGET_FMT_lx " api=" TARGET_FMT_lx
+                " hash=" TARGET_FMT_plx "\n", env->htab_base,
+                env->htab_mask, vsid, ptem, ~hash);
+
+        pteg_off = (~hash * HASH_PTEG_SIZE_64) & env->htab_mask;
+        pte_offset = ppc_hash64_pteg_search(env, pteg_off, 1, 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",
@@ -409,13 +459,8 @@ static int find_pte64(CPUPPCState *env, struct 
mmu_ctx_hash64 *ctx,
 static int ppc_hash64_translate(CPUPPCState *env, struct mmu_ctx_hash64 *ctx,
                                 target_ulong eaddr, int rwx)
 {
-    hwaddr hash;
-    target_ulong vsid;
-    int pr, target_page_bits;
-    int ret, ret2;
+    int ret;
     ppc_slb_t *slb;
-    target_ulong pageaddr;
-    int segment_bits;
 
     /* 1. Handle real mode accesses */
     if (((rwx == 2) && (msr_ir == 0)) || ((rwx != 2) && (msr_dr == 0))) {
@@ -438,61 +483,7 @@ static int ppc_hash64_translate(CPUPPCState *env, struct 
mmu_ctx_hash64 *ctx,
         return -3;
     }
 
-    pr = msr_pr;
-
-    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)
-        ? TARGET_PAGE_BITS_16M : TARGET_PAGE_BITS;
-    ctx->key = !!(pr ? (slb->vsid & SLB_VSID_KP)
-                  : (slb->vsid & SLB_VSID_KS));
-
-    pageaddr = eaddr & ((1ULL << segment_bits)
-                            - (1ULL << target_page_bits));
-    if (slb->vsid & SLB_VSID_B) {
-        hash = vsid ^ (vsid << 25) ^ (pageaddr >> target_page_bits);
-    } else {
-        hash = vsid ^ (pageaddr >> target_page_bits);
-    }
-    /* Only 5 bits of the page index are used in the AVPN */
-    ctx->ptem = (slb->vsid & SLB_VSID_PTEM) |
-        ((pageaddr >> 16) & ((1ULL << segment_bits) - 0x80));
-
-    LOG_MMU("pte segment: key=%d nx %d vsid " TARGET_FMT_lx "\n",
-            ctx->key, !!(slb->vsid & SLB_VSID_N), vsid);
-    ret = -1;
-
-    /* Page address translation */
-    LOG_MMU("htab_base " TARGET_FMT_plx " htab_mask " TARGET_FMT_plx
-            " hash " TARGET_FMT_plx "\n",
-            env->htab_base, env->htab_mask, hash);
-    ctx->hash[0] = hash;
-    ctx->hash[1] = ~hash;
-
-    LOG_MMU("0 htab=" TARGET_FMT_plx "/" TARGET_FMT_plx
-            " vsid=" TARGET_FMT_lx " ptem=" TARGET_FMT_lx
-            " hash=" TARGET_FMT_plx "\n",
-            env->htab_base, env->htab_mask, vsid, ctx->ptem,
-            ctx->hash[0]);
-    /* Primary table lookup */
-    ret = find_pte64(env, ctx, eaddr, 0, rwx, target_page_bits);
-    if (ret == -1) {
-        /* Secondary table lookup */
-        LOG_MMU("1 htab=" TARGET_FMT_plx "/" TARGET_FMT_plx
-                " vsid=" TARGET_FMT_lx " api=" TARGET_FMT_lx
-                " hash=" TARGET_FMT_plx "\n", env->htab_base,
-                env->htab_mask, vsid, ctx->ptem, ctx->hash[1]);
-        ret2 = find_pte64(env, ctx, eaddr, 1, rwx, target_page_bits);
-        if (ret2 != -1) {
-            ret = ret2;
-        }
-    }
+    ret = find_pte64(env, ctx, slb, eaddr, rwx);
 
     return ret;
 }
-- 
1.7.10.4




reply via email to

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