Commit e47168f3 authored by Christophe Leroy's avatar Christophe Leroy Committed by Michael Ellerman
Browse files

powerpc/8xx: Support 16k hugepages with 4k pages



The 8xx has 4 page sizes: 4k, 16k, 512k and 8M

4k and 16k can be selected at build time as standard page sizes,
and 512k and 8M are hugepages.

When 4k standard pages are selected, 16k pages are not available.

Allow 16k pages as hugepages when 4k pages are used.

To allow that, implement arch_make_huge_pte() which receives
the necessary arguments to allow setting the PTE in accordance
with the page size:
- 512 k pages must have _PAGE_HUGE and _PAGE_SPS. They are set
by pte_mkhuge(). arch_make_huge_pte() does nothing.
- 16 k pages must have only _PAGE_SPS. arch_make_huge_pte() clears
_PAGE_HUGE.

Signed-off-by: default avatarChristophe Leroy <christophe.leroy@csgroup.eu>
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/a518abc29266a708dfbccc8fce9ae6694fe4c2c6.1598862623.git.christophe.leroy@csgroup.eu
parent 175a9999
Loading
Loading
Loading
Loading
+14 −0
Original line number Diff line number Diff line
@@ -65,4 +65,18 @@ static inline void huge_ptep_set_wrprotect(struct mm_struct *mm,
	pte_update(mm, addr, ptep, clr, set, 1);
}

#ifdef CONFIG_PPC_4K_PAGES
static inline pte_t arch_make_huge_pte(pte_t entry, struct vm_area_struct *vma,
				       struct page *page, int writable)
{
	size_t size = huge_page_size(hstate_vma(vma));

	if (size == SZ_16K)
		return __pte(pte_val(entry) & ~_PAGE_HUGE);
	else
		return entry;
}
#define arch_make_huge_pte arch_make_huge_pte
#endif

#endif /* _ASM_POWERPC_NOHASH_32_HUGETLB_8XX_H */
+2 −0
Original line number Diff line number Diff line
@@ -235,6 +235,8 @@ static int number_of_cells_per_pte(pmd_t *pmd, pte_basic_t val, int huge)
		return PAGE_SIZE / SZ_4K;
	else if (hugepd_ok(*((hugepd_t *)pmd)))
		return 1;
	else if (IS_ENABLED(CONFIG_PPC_4K_PAGES) && !(val & _PAGE_HUGE))
		return SZ_16K / SZ_4K;
	else
		return SZ_512K / SZ_4K;
}
+1 −1
Original line number Diff line number Diff line
@@ -180,7 +180,7 @@ pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr, unsigned long sz
	if (!hpdp)
		return NULL;

	if (IS_ENABLED(CONFIG_PPC_8xx) && sz == SZ_512K)
	if (IS_ENABLED(CONFIG_PPC_8xx) && pshift < PMD_SHIFT)
		return pte_alloc_map(mm, (pmd_t *)hpdp, addr);

	BUG_ON(!hugepd_none(*hpdp) && !hugepd_ok(*hpdp));
+0 −4
Original line number Diff line number Diff line
@@ -83,16 +83,12 @@ struct mmu_psize_def mmu_psize_defs[MMU_PAGE_COUNT] = {
};
#elif defined(CONFIG_PPC_8xx)
struct mmu_psize_def mmu_psize_defs[MMU_PAGE_COUNT] = {
	/* we only manage 4k and 16k pages as normal pages */
#ifdef CONFIG_PPC_4K_PAGES
	[MMU_PAGE_4K] = {
		.shift	= 12,
	},
#else
	[MMU_PAGE_16K] = {
		.shift	= 14,
	},
#endif
	[MMU_PAGE_512K] = {
		.shift	= 19,
	},
+5 −0
Original line number Diff line number Diff line
@@ -11,8 +11,13 @@

static const struct flag_info flag_array[] = {
	{
#ifdef CONFIG_PPC_16K_PAGES
		.mask	= _PAGE_HUGE,
		.val	= _PAGE_HUGE,
#else
		.mask	= _PAGE_SPS,
		.val	= _PAGE_SPS,
#endif
		.set	= "huge",
		.clear	= "    ",
	}, {
Loading