Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 20717e1f authored by Aneesh Kumar K.V's avatar Aneesh Kumar K.V Committed by Michael Ellerman
Browse files

powerpc/mm: Fix little-endian 4K hugetlb



When we switched to big endian page table, we never updated the hugepd
format such that it can work for both big endian and little endian
config. This patch series update hugepd format such that it is looked at
as __be64 value in big endian page table config.

This patch also switch hugepd_t.pd from signed long to unsigned long.
I did update the FSL hugepd_ok check to check for the top bit instead
of checking > 0.

Fixes: 5dc1ef85 ("powerpc/mm: Use big endian Linux page tables for book3s 64")
Cc: stable@vger.kernel.org # v4.7+
Signed-off-by: default avatarAneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
parent ff8b8579
Loading
Loading
Loading
Loading
+3 −2
Original line number Diff line number Diff line
@@ -36,12 +36,13 @@
#ifdef CONFIG_HUGETLB_PAGE
static inline int hash__hugepd_ok(hugepd_t hpd)
{
	unsigned long hpdval = hpd_val(hpd);
	/*
	 * if it is not a pte and have hugepd shift mask
	 * set, then it is a hugepd directory pointer
	 */
	if (!(hpd.pd & _PAGE_PTE) &&
	    ((hpd.pd & HUGEPD_SHIFT_MASK) != 0))
	if (!(hpdval & _PAGE_PTE) &&
	    ((hpdval & HUGEPD_SHIFT_MASK) != 0))
		return true;
	return false;
}
+8 −6
Original line number Diff line number Diff line
@@ -21,12 +21,12 @@ static inline pte_t *hugepd_page(hugepd_t hpd)
	 * We have only four bits to encode, MMU page size
	 */
	BUILD_BUG_ON((MMU_PAGE_COUNT - 1) > 0xf);
	return __va(hpd.pd & HUGEPD_ADDR_MASK);
	return __va(hpd_val(hpd) & HUGEPD_ADDR_MASK);
}

static inline unsigned int hugepd_mmu_psize(hugepd_t hpd)
{
	return (hpd.pd & HUGEPD_SHIFT_MASK) >> 2;
	return (hpd_val(hpd) & HUGEPD_SHIFT_MASK) >> 2;
}

static inline unsigned int hugepd_shift(hugepd_t hpd)
@@ -52,18 +52,20 @@ static inline pte_t *hugepd_page(hugepd_t hpd)
{
	BUG_ON(!hugepd_ok(hpd));
#ifdef CONFIG_PPC_8xx
	return (pte_t *)__va(hpd.pd & ~(_PMD_PAGE_MASK | _PMD_PRESENT_MASK));
	return (pte_t *)__va(hpd_val(hpd) &
			     ~(_PMD_PAGE_MASK | _PMD_PRESENT_MASK));
#else
	return (pte_t *)((hpd.pd & ~HUGEPD_SHIFT_MASK) | PD_HUGE);
	return (pte_t *)((hpd_val(hpd) &
			  ~HUGEPD_SHIFT_MASK) | PD_HUGE);
#endif
}

static inline unsigned int hugepd_shift(hugepd_t hpd)
{
#ifdef CONFIG_PPC_8xx
	return ((hpd.pd & _PMD_PAGE_MASK) >> 1) + 17;
	return ((hpd_val(hpd) & _PMD_PAGE_MASK) >> 1) + 17;
#else
	return hpd.pd & HUGEPD_SHIFT_MASK;
	return hpd_val(hpd) & HUGEPD_SHIFT_MASK;
#endif
}

+3 −2
Original line number Diff line number Diff line
@@ -227,9 +227,10 @@ extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
static inline int hugepd_ok(hugepd_t hpd)
{
#ifdef CONFIG_PPC_8xx
	return ((hpd.pd & 0x4) != 0);
	return ((hpd_val(hpd) & 0x4) != 0);
#else
	return (hpd.pd > 0);
	/* We clear the top bit to indicate hugepd */
	return ((hpd_val(hpd) & PD_HUGE) ==  0);
#endif
}

+0 −3
Original line number Diff line number Diff line
@@ -294,15 +294,12 @@ extern long long virt_phys_offset;
#include <asm/pgtable-types.h>
#endif

typedef struct { signed long pd; } hugepd_t;

#ifndef CONFIG_HUGETLB_PAGE
#define is_hugepd(pdep)		(0)
#define pgd_huge(pgd)		(0)
#endif /* CONFIG_HUGETLB_PAGE */

#define __hugepd(x) ((hugepd_t) { (x) })

struct page;
extern void clear_user_page(void *page, unsigned long vaddr, struct page *pg);
extern void copy_user_page(void *to, void *from, unsigned long vaddr,
+8 −0
Original line number Diff line number Diff line
@@ -104,4 +104,12 @@ static inline bool pmd_xchg(pmd_t *pmdp, pmd_t old, pmd_t new)
	return pmd_raw(old) == prev;
}

typedef struct { __be64 pdbe; } hugepd_t;
#define __hugepd(x) ((hugepd_t) { cpu_to_be64(x) })

static inline unsigned long hpd_val(hugepd_t x)
{
	return be64_to_cpu(x.pdbe);
}

#endif /* _ASM_POWERPC_PGTABLE_BE_TYPES_H */
Loading