Re: [PATCH -V5 08/25] powerpc: Decode the pte-lp-encoding bits correctly.
From: Aneesh Kumar K.V <hidden>
Date: 2013-04-10 17:49:55
Also in:
linux-mm
Subsystem:
linux for powerpc (32-bit and 64-bit), the rest · Maintainers:
Madhavan Srinivasan, Linus Torvalds
"Aneesh Kumar K.V" [off-list ref] writes:
quoted
quoted
static void hpte_decode(struct hash_pte *hpte, unsigned long slot, - int *psize, int *ssize, unsigned long *vpn) + 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, shift, penc; + int i, size, a_size, shift, penc; - if (!(hpte_v & HPTE_V_LARGE)) - size = MMU_PAGE_4K; - else { + 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;@@ -388,19 +444,26 @@ static void hpte_decode(struct hash_pte *hpte, unsigned long slot, penc = LP_MASK(i+1) >> LP_SHIFT; for (size = 0; size < MMU_PAGE_COUNT; size++) {quoted
- /* 4K pages are not represented by LP */ - if (size == MMU_PAGE_4K) - continue; - /* valid entries have a shift value */ if (!mmu_psize_defs[size].shift) continue; + for (a_size = 0; a_size < MMU_PAGE_COUNT; a_size++) {Can't you resize hpte_actual_psize() here instead of recoding the lookup?I thought about that, but re-coding avoided some repeated check. But then, if I follow your review comments of avoiding hpte valid check etc, may be I can reuse the hpte_actual_psize. Will try this.
How about below ?
diff --git a/arch/powerpc/mm/hash_native_64.c b/arch/powerpc/mm/hash_native_64.c
index 4427ca8..de235d5 100644
--- a/arch/powerpc/mm/hash_native_64.c
+++ b/arch/powerpc/mm/hash_native_64.c@@ -271,19 +271,10 @@ static long native_hpte_remove(unsigned long hpte_group) return i; } -static inline int hpte_actual_psize(struct hash_pte *hptep, int psize) +static inline int __hpte_actual_psize(unsigned int lp, int psize) { int i, shift; unsigned int mask; - /* Look at the 8 bit LP value */ - unsigned int lp = (hptep->r >> LP_SHIFT) & ((1 << LP_BITS) - 1); - - if (!(hptep->v & HPTE_V_VALID)) - return -1; - - /* First check if it is large page */ - if (!(hptep->v & HPTE_V_LARGE)) - return MMU_PAGE_4K; /* start from 1 ignoring MMU_PAGE_4K */ for (i = 1; i < MMU_PAGE_COUNT; i++) {
@@ -310,6 +301,21 @@ static inline int hpte_actual_psize(struct hash_pte *hptep, int psize) return -1; } +static inline int hpte_actual_psize(struct hash_pte *hptep, int psize) +{ + /* Look at the 8 bit LP value */ + unsigned int lp = (hptep->r >> LP_SHIFT) & ((1 << LP_BITS) - 1); + + if (!(hptep->v & HPTE_V_VALID)) + return -1; + + /* First check if it is large page */ + if (!(hptep->v & HPTE_V_LARGE)) + return MMU_PAGE_4K; + + return __hpte_actual_psize(lp, psize); +} + static long native_hpte_updatepp(unsigned long slot, unsigned long newpp, unsigned long vpn, int psize, int ssize, int local)
@@ -530,7 +536,7 @@ static void hpte_decode(struct hash_pte *hpte, unsigned long slot, unsigned long avpn, pteg, vpi; unsigned long hpte_v = hpte->v; unsigned long vsid, seg_off; - int size, a_size, shift, mask; + int size, a_size, shift; /* Look at the 8 bit LP value */ unsigned int lp = (hpte->r >> LP_SHIFT) & ((1 << LP_BITS) - 1);
@@ -544,33 +550,11 @@ static void hpte_decode(struct hash_pte *hpte, unsigned long slot, if (!mmu_psize_defs[size].shift) continue; - /* start from 1 ignoring MMU_PAGE_4K */ - for (a_size = 1; a_size < MMU_PAGE_COUNT; a_size++) { - - /* invalid penc */ - if (mmu_psize_defs[size].penc[a_size] == -1) - continue; - /* - * 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 - LP_SHIFT; - if (shift > LP_BITS) - shift = LP_BITS; - mask = (1 << shift) - 1; - if ((lp & mask) == - mmu_psize_defs[size].penc[a_size]) { - goto out; - } - } + a_size = __hpte_actual_psize(lp, size); + if (a_size != -1) + break; } } -out: /* This works for all page sizes, and for 256M and 1T segments */ *ssize = hpte_v >> HPTE_V_SSIZE_SHIFT; shift = mmu_psize_defs[size].shift;