Patchwork [-V2,11/26] powerpc: Fix hpte_decode to use the correct decoding for page sizes

login
register
mail settings
Submitter Aneesh Kumar K.V
Date March 6, 2013, 6:10 a.m.
Message ID <1362550227-575-12-git-send-email-aneesh.kumar@linux.vnet.ibm.com>
Download mbox | patch
Permalink /patch/225352/
State Superseded, archived
Headers show

Comments

Aneesh Kumar K.V - March 6, 2013, 6:10 a.m.
From: "Aneesh Kumar K.V" <aneesh.kumar@linux.vnet.ibm.com>

As per ISA doc, we encode base and actual page size in the LP bits of
PTE. The number of bit used to encode the page sizes depend on actual
page size.  ISA doc lists this as

   PTE LP     actual page size
rrrr rrrz 	≥8KB
rrrr rrzz	≥16KB
rrrr rzzz 	≥32KB
rrrr zzzz 	≥64KB
rrrz zzzz 	≥128KB
rrzz zzzz 	≥256KB
rzzz zzzz	≥512KB
zzzz zzzz 	≥1MB

ISA doc also says
"The values of the “z” bits used to specify each size, along with all possible
values of “r” bits in the LP field, must result in LP values distinct from
other LP values for other sizes."

based on the above update hpte_decode to use the correct decoding for LP bits.

Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
---
 arch/powerpc/mm/hash_native_64.c |   37 ++++++++++++++++++++++---------------
 1 file changed, 22 insertions(+), 15 deletions(-)
Paul Mackerras - March 13, 2013, 2:56 a.m.
On Wed, Mar 06, 2013 at 11:40:12AM +0530, Aneesh Kumar K.V wrote:
> From: "Aneesh Kumar K.V" <aneesh.kumar@linux.vnet.ibm.com>
> 
> As per ISA doc, we encode base and actual page size in the LP bits of
> PTE. The number of bit used to encode the page sizes depend on actual
> page size.  ISA doc lists this as
> 
>    PTE LP     actual page size
> rrrr rrrz 	≥8KB
> rrrr rrzz	≥16KB
> rrrr rzzz 	≥32KB
> rrrr zzzz 	≥64KB
> rrrz zzzz 	≥128KB
> rrzz zzzz 	≥256KB
> rzzz zzzz	≥512KB
> zzzz zzzz 	≥1MB
> 
> ISA doc also says
> "The values of the “z” bits used to specify each size, along with all possible
> values of “r” bits in the LP field, must result in LP values distinct from
> other LP values for other sizes."
> 
> based on the above update hpte_decode to use the correct decoding for LP bits.
> 
> Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
[snip]
> +				shift = mmu_psize_defs[a_size].shift -
> +					mmu_psize_defs[MMU_PAGE_4K].shift;

"mmu_psize_defs[MMU_PAGE_4K].shift" seems like an overly complicated
way to write "LP_SHIFT" (or even "12").  After all, you did:

> +	unsigned int lp = (hpte->r >> LP_SHIFT) & ((1 << LP_BITS) - 1);

earlier.  If LP_SHIFT is good enough in that expression it's good
enough when calculating shift.

Apart from that minor nit,

Acked-by: Paul Mackerras <paulus@samba.org>

Patch

diff --git a/arch/powerpc/mm/hash_native_64.c b/arch/powerpc/mm/hash_native_64.c
index 7b5bf94..5e7f45c 100644
--- a/arch/powerpc/mm/hash_native_64.c
+++ b/arch/powerpc/mm/hash_native_64.c
@@ -412,41 +412,48 @@  static void hpte_decode(struct hash_pte *hpte, unsigned long slot,
 			int *psize, int *apsize, int *ssize, unsigned long *vpn)
 {
 	unsigned long avpn, pteg, vpi;
-	unsigned long hpte_r = hpte->r;
 	unsigned long hpte_v = hpte->v;
 	unsigned long vsid, seg_off;
-	int i, size, a_size, shift, penc;
+	int size, a_size, shift, mask;
+	/* Look at the 8 bit LP value */
+	unsigned int lp = (hpte->r >> LP_SHIFT) & ((1 << LP_BITS) - 1);
 
 	if (!(hpte_v & HPTE_V_LARGE)) {
 		size   = MMU_PAGE_4K;
 		a_size = MMU_PAGE_4K;
 	} else {
-		for (i = 0; i < LP_BITS; i++) {
-			if ((hpte_r & LP_MASK(i+1)) == LP_MASK(i+1))
-				break;
-		}
-		penc = LP_MASK(i+1) >> LP_SHIFT;
 		for (size = 0; size < MMU_PAGE_COUNT; size++) {
 
 			/* valid entries have a shift value */
 			if (!mmu_psize_defs[size].shift)
 				continue;
-			for (a_size = 0; a_size < MMU_PAGE_COUNT; a_size++) {
-
-				/* 4K pages are not represented by LP */
-				if (a_size == MMU_PAGE_4K)
-					continue;
 
+			/* start from 1 ignoring MMU_PAGE_4K */
+			for (a_size = 1; a_size < MMU_PAGE_COUNT; a_size++) {
 				/* valid entries have a shift value */
 				if (!mmu_psize_defs[a_size].shift)
 					continue;
-
-				if (penc == mmu_psize_defs[size].penc[a_size])
+				/*
+				 * encoding bits per actual page size
+				 *        PTE LP     actual page size
+				 *    rrrr rrrz		≥8KB
+				 *    rrrr rrzz		≥16KB
+				 *    rrrr rzzz		≥32KB
+				 *    rrrr zzzz		≥64KB
+				 * .......
+				 */
+				shift = mmu_psize_defs[a_size].shift -
+					mmu_psize_defs[MMU_PAGE_4K].shift;
+				if (shift > LP_BITS)
+					shift = LP_BITS;
+				mask = (1 << shift) - 1;
+				if ((lp & mask) ==
+				    mmu_psize_defs[size].penc[a_size]) {
 					goto out;
+				}
 			}
 		}
 	}
-
 out:
 	/* This works for all page sizes, and for 256M and 1T segments */
 	*ssize = hpte_v >> HPTE_V_SSIZE_SHIFT;