[Cbe-oss-dev] [PATCH] 64K page support for kexec

Luke Browning lukebr at linux.vnet.ibm.com
Tue Apr 24 03:53:52 EST 2007


This patch fixes a couple of kexec problems related to 64K page 
support in the kernel.  kexec issues a tlbie for each pte.  The 
parameters for the tlbie are the page size and the virtual address.
Support was missing for the computation of these two parameters
for 64K pages.  This patch adds that support.  

Signed-off-by: Luke Browning <lukebrowning at us.ibm.com>

Index: linux-2.6.21-rc4/arch/powerpc/mm/hash_native_64.c
===================================================================
--- linux-2.6.21-rc4.orig/arch/powerpc/mm/hash_native_64.c	2007-04-23
14:31:42.000000000 -0300
+++ linux-2.6.21-rc4/arch/powerpc/mm/hash_native_64.c	2007-04-23
14:37:47.000000000 -0300
@@ -341,18 +341,16 @@
 }
 
 /*
- * XXX This need fixing based on page size. It's only used by
- * native_hpte_clear() for now which needs fixing too so they
- * make a good pair...
+ * convert the 'avpn' in the PTE to the 'va' so that it will work with
tlbie.
  */
-static unsigned long slot2va(unsigned long hpte_v, unsigned long slot)
+static unsigned long slot2va(unsigned long hpte_v, unsigned long slot,
int psize)
 {
 	unsigned long avpn = HPTE_V_AVPN_VAL(hpte_v);
 	unsigned long va;
 
 	va = avpn << 23;
 
-	if (! (hpte_v & HPTE_V_LARGE)) {
+	if (psize != MMU_PAGE_16M) {
 		unsigned long vpi, pteg;
 
 		pteg = slot / HPTES_PER_GROUP;
@@ -360,13 +358,42 @@
 			pteg = ~pteg;
 
 		vpi = ((va >> 28) ^ pteg) & htab_hash_mask;
-
-		va |= vpi << PAGE_SHIFT;
+		va |= (vpi << mmu_psize_defs[psize].shift);
 	}
 
 	return va;
 }
 
+#define LP_SHIFT	12
+#define LP_BITS		8 
+#define LP_MASK(i)	((((1 << LP_BITS) - 1) >> (i)) << LP_SHIFT)
+/*
+ * get the page size from the encoded physical address in the PTE.
+ */ 
+static int hpte_decode_lpsize(unsigned long pa)
+{
+	int penc, i;
+
+	if (pa & LP_MASK(0)) {
+		for (i = 0; i < LP_BITS; i++) {
+			if ((pa & LP_MASK(i+1)) == LP_MASK(i+1))
+				break;
+		}
+		penc = LP_MASK(i+1) >> LP_SHIFT;
+		for (i = MMU_PAGE_COUNT - 1; i > 0; i--) {
+			if (!mmu_psize_defs[i].shift)
+				continue;
+			if (penc == mmu_psize_defs[i].penc)
+				break;
+		}
+	}
+	else {
+		i = MMU_PAGE_16M;
+	}
+
+	return i;
+}
+
 /*
  * clear all mappings on kexec.  All cpus are in real mode (or they
will
  * be when they isi), and we are the only one left.  We rely on our
kernel
@@ -374,15 +401,14 @@
  *
  * TODO: add batching support when enabled.  remember, no dynamic
memory here,
  * athough there is the control page available...
- *
- * XXX FIXME: 4k only for now !
  */
 static void native_hpte_clear(void)
 {
 	unsigned long slot, slots, flags;
 	hpte_t *hptep = htab_address;
 	unsigned long hpte_v;
-	unsigned long pteg_count;
+	unsigned long pteg_count, vpn;
+	int psize;
 
 	pteg_count = htab_hash_mask + 1;
 
@@ -408,8 +434,13 @@
 		 * already hold the native_tlbie_lock.
 		 */
 		if (hpte_v & HPTE_V_VALID) {
+			if (!(hpte_v & HPTE_V_LARGE))
+				psize = MMU_PAGE_4K;
+			else
+				psize = hpte_decode_lpsize(hptep->r);
+			vpn = slot2va(hpte_v, slot, psize);
 			hptep->v = 0;
-			__tlbie(slot2va(hpte_v, slot), MMU_PAGE_4K);
+			__tlbie(vpn, psize);
 		}
 	}
 





More information about the cbe-oss-dev mailing list