qemu-ppc
[Top][All Lists]
Advanced

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

[Qemu-ppc] [PATCH 15/32] mmu-hash64: Add hash pte load/store helpers


From: David Gibson
Subject: [Qemu-ppc] [PATCH 15/32] mmu-hash64: Add hash pte load/store helpers
Date: Fri, 15 Feb 2013 19:01:05 +1100

On real hardware the ppc hash page table is stored in memory.  Accordingly
our mmu emulation code can read a hash page table in guest memory.  But,
when paravirtualized under PAPR, however, the real hash page table is in
host memory, not guest, accessed only via hypercalls.  We model this by
also allowing the MMU emulation code to access a specially allocated hash
page table, outside the guest's memory image.

At present these two options are implemented with some ugly conditionals
at each access point in the mmu emulation code.  In the implementation of
the PAPR hypercalls, we assume the external hash table.  This patch cleans
things up by adding helpers to load and store from the hash table,
handling both cases.  These helpers are then used in both the mmu emulation
and hypercall code.

Signed-off-by: David Gibson <address@hidden>
---
 hw/spapr_hcall.c        |   38 +++++++++++++++++++-------------------
 target-ppc/mmu-hash64.c |   17 +++--------------
 target-ppc/mmu-hash64.h |   40 ++++++++++++++++++++++++++++++++++++++++
 3 files changed, 62 insertions(+), 33 deletions(-)

diff --git a/hw/spapr_hcall.c b/hw/spapr_hcall.c
index 7fb9cde..8933ef1 100644
--- a/hw/spapr_hcall.c
+++ b/hw/spapr_hcall.c
@@ -52,7 +52,7 @@ static target_ulong h_enter(PowerPCCPU *cpu, sPAPREnvironment 
*spapr,
     target_ulong page_shift = 12;
     target_ulong raddr;
     target_ulong i;
-    uint8_t *hpte;
+    hwaddr hpte;
 
     /* only handle 4k and 16M pages for now */
     if (pteh & HPTE_V_LARGE) {
@@ -97,26 +97,26 @@ static target_ulong h_enter(PowerPCCPU *cpu, 
sPAPREnvironment *spapr,
     }
     if (likely((flags & H_EXACT) == 0)) {
         pte_index &= ~7ULL;
-        hpte = env->external_htab + (pte_index * HASH_PTE_SIZE_64);
+        hpte = pte_index * HASH_PTE_SIZE_64;
         for (i = 0; ; ++i) {
             if (i == 8) {
                 return H_PTEG_FULL;
             }
-            if ((ldq_p(hpte) & HPTE_V_VALID) == 0) {
+            if ((ppc_hash64_load_hpte0(env, hpte) & HPTE_V_VALID) == 0) {
                 break;
             }
             hpte += HASH_PTE_SIZE_64;
         }
     } else {
         i = 0;
-        hpte = env->external_htab + (pte_index * HASH_PTE_SIZE_64);
-        if (ldq_p(hpte) & HPTE_V_VALID) {
+        hpte = pte_index * HASH_PTE_SIZE_64;
+        if (ppc_hash64_load_hpte0(env, hpte) & HPTE_V_VALID) {
             return H_PTEG_FULL;
         }
     }
-    stq_p(hpte + (HASH_PTE_SIZE_64/2), ptel);
+    ppc_hash64_store_hpte1(env, hpte, ptel);
     /* eieio();  FIXME: need some sort of barrier for smp? */
-    stq_p(hpte, pteh);
+    ppc_hash64_store_hpte0(env, hpte, pteh);
 
     args[0] = pte_index + i;
     return H_SUCCESS;
@@ -134,17 +134,17 @@ static target_ulong remove_hpte(CPUPPCState *env, 
target_ulong ptex,
                                 target_ulong flags,
                                 target_ulong *vp, target_ulong *rp)
 {
-    uint8_t *hpte;
+    hwaddr hpte;
     target_ulong v, r, rb;
 
     if ((ptex * HASH_PTE_SIZE_64) & ~env->htab_mask) {
         return REMOVE_PARM;
     }
 
-    hpte = env->external_htab + (ptex * HASH_PTE_SIZE_64);
+    hpte = ptex * HASH_PTE_SIZE_64;
 
-    v = ldq_p(hpte);
-    r = ldq_p(hpte + (HASH_PTE_SIZE_64/2));
+    v = ppc_hash64_load_hpte0(env, hpte);
+    r = ppc_hash64_load_hpte1(env, hpte);
 
     if ((v & HPTE_V_VALID) == 0 ||
         ((flags & H_AVPN) && (v & ~0x7fULL) != avpn) ||
@@ -153,7 +153,7 @@ static target_ulong remove_hpte(CPUPPCState *env, 
target_ulong ptex,
     }
     *vp = v;
     *rp = r;
-    stq_p(hpte, 0);
+    ppc_hash64_store_hpte0(env, hpte, 0);
     rb = compute_tlbie_rb(v, r, ptex);
     ppc_tlb_invalidate_one(env, rb);
     return REMOVE_SUCCESS;
@@ -260,17 +260,17 @@ static target_ulong h_protect(PowerPCCPU *cpu, 
sPAPREnvironment *spapr,
     target_ulong flags = args[0];
     target_ulong pte_index = args[1];
     target_ulong avpn = args[2];
-    uint8_t *hpte;
+    hwaddr hpte;
     target_ulong v, r, rb;
 
     if ((pte_index * HASH_PTE_SIZE_64) & ~env->htab_mask) {
         return H_PARAMETER;
     }
 
-    hpte = env->external_htab + (pte_index * HASH_PTE_SIZE_64);
+    hpte = pte_index * HASH_PTE_SIZE_64;
 
-    v = ldq_p(hpte);
-    r = ldq_p(hpte + (HASH_PTE_SIZE_64/2));
+    v = ppc_hash64_load_hpte0(env, hpte);
+    r = ppc_hash64_load_hpte1(env, hpte);
 
     if ((v & HPTE_V_VALID) == 0 ||
         ((flags & H_AVPN) && (v & ~0x7fULL) != avpn)) {
@@ -283,11 +283,11 @@ static target_ulong h_protect(PowerPCCPU *cpu, 
sPAPREnvironment *spapr,
     r |= (flags << 48) & HPTE_R_KEY_HI;
     r |= flags & (HPTE_R_PP | HPTE_R_N | HPTE_R_KEY_LO);
     rb = compute_tlbie_rb(v, r, pte_index);
-    stq_p(hpte, v & ~HPTE_V_VALID);
+    ppc_hash64_store_hpte0(env, hpte, v & ~HPTE_V_VALID);
     ppc_tlb_invalidate_one(env, rb);
-    stq_p(hpte + (HASH_PTE_SIZE_64/2), r);
+    ppc_hash64_store_hpte1(env, hpte, r);
     /* Don't need a memory barrier, due to qemu's global lock */
-    stq_p(hpte, v);
+    ppc_hash64_store_hpte0(env, hpte, v);
     return H_SUCCESS;
 }
 
diff --git a/target-ppc/mmu-hash64.c b/target-ppc/mmu-hash64.c
index d3edbf0..a27d187 100644
--- a/target-ppc/mmu-hash64.c
+++ b/target-ppc/mmu-hash64.c
@@ -382,13 +382,8 @@ static int find_pte64(CPUPPCState *env, struct 
mmu_ctx_hash64 *ctx, int h,
     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++) {
-        if (env->external_htab) {
-            pte0 = ldq_p(env->external_htab + pteg_off + (i * 16));
-            pte1 = ldq_p(env->external_htab + pteg_off + (i * 16) + 8);
-        } else {
-            pte0 = ldq_phys(env->htab_base + pteg_off + (i * 16));
-            pte1 = ldq_phys(env->htab_base + pteg_off + (i * 16) + 8);
-        }
+        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);
 
         r = pte64_check(ctx, pte0, pte1, h, rw, type);
         LOG_MMU("Load pte from %016" HWADDR_PRIx " => " TARGET_FMT_lx " "
@@ -426,13 +421,7 @@ static int find_pte64(CPUPPCState *env, struct 
mmu_ctx_hash64 *ctx, int h,
         /* Update page flags */
         pte1 = ctx->raddr;
         if (ppc_hash64_pte_update_flags(ctx, &pte1, ret, rw) == 1) {
-            if (env->external_htab) {
-                stq_p(env->external_htab + pteg_off + (good * 16) + 8,
-                      pte1);
-            } else {
-                stq_phys_notdirty(env->htab_base + pteg_off +
-                                  (good * 16) + 8, pte1);
-            }
+            ppc_hash64_store_hpte1(env, pteg_off + good * HASH_PTE_SIZE_64, 
pte1);
         }
     }
 
diff --git a/target-ppc/mmu-hash64.h b/target-ppc/mmu-hash64.h
index f364518..c932c4b 100644
--- a/target-ppc/mmu-hash64.h
+++ b/target-ppc/mmu-hash64.h
@@ -63,4 +63,44 @@
 #define HPTE_V_1TB_SEG          0x4000000000000000ULL
 #define HPTE_V_VRMA_MASK        0x4001ffffff000000ULL
 
+static inline target_ulong ppc_hash64_load_hpte0(CPUPPCState *env,
+                                                 hwaddr pte_offset)
+{
+    if (env->external_htab) {
+        return  ldq_p(env->external_htab + pte_offset);
+    } else {
+        return ldq_phys(env->htab_base + pte_offset);
+    }
+}
+
+static inline target_ulong ppc_hash64_load_hpte1(CPUPPCState *env,
+                                                 hwaddr pte_offset)
+{
+    if (env->external_htab) {
+        return ldq_p(env->external_htab + pte_offset + HASH_PTE_SIZE_64/2);
+    } else {
+        return ldq_phys(env->htab_base + pte_offset + HASH_PTE_SIZE_64/2);
+    }
+}
+
+static inline void ppc_hash64_store_hpte0(CPUPPCState *env,
+                                          hwaddr pte_offset, target_ulong pte0)
+{
+    if (env->external_htab) {
+        stq_p(env->external_htab + pte_offset, pte0);
+    } else {
+        stq_phys(env->htab_base + pte_offset, pte0);
+    }
+}
+
+static inline void ppc_hash64_store_hpte1(CPUPPCState *env,
+                                          hwaddr pte_offset, target_ulong pte1)
+{
+    if (env->external_htab) {
+        stq_p(env->external_htab + pte_offset + HASH_PTE_SIZE_64/2, pte1);
+    } else {
+        stq_phys(env->htab_base + pte_offset + HASH_PTE_SIZE_64/2, pte1);
+    }
+}
+
 #endif /* !defined (__MMU_HASH64_H__) */
-- 
1.7.10.4




reply via email to

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