Subject: 64K support for Kexec From: Luke Browning This patch decodes the page size from the pte. This code is used by kexec, which walks the hash table and issues a tlbie for each valid entry. The page size is encoded in the virtual address that is passed to the tlbie instruction. Signed-off-by: Luke Browning Signed-off-by: Arnd Bergmann Index: linux-2.6/arch/powerpc/mm/hash_native_64.c =================================================================== --- linux-2.6.orig/arch/powerpc/mm/hash_native_64.c +++ linux-2.6/arch/powerpc/mm/hash_native_64.c @@ -367,6 +367,34 @@ static unsigned long slot2va(unsigned lo return va; } +#define LP_SHIFT 12 +#define LP_BITS 8 +#define LP_MASK(i) ((((1 << LP_BITS) - 1) >> (i)) << LP_SHIFT) + +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 @@ -383,6 +411,7 @@ static void native_hpte_clear(void) hpte_t *hptep = htab_address; unsigned long hpte_v; unsigned long pteg_count; + int psize; pteg_count = htab_hash_mask + 1; @@ -408,8 +437,12 @@ static void native_hpte_clear(void) * 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); hptep->v = 0; - __tlbie(slot2va(hpte_v, slot), MMU_PAGE_4K); + __tlbie(slot2va(hpte_v, slot), psize); } }