powerpc/8xx: Support 16k hugepages with 4k pages
authorChristophe Leroy <christophe.leroy@csgroup.eu>
Mon, 31 Aug 2020 08:30:44 +0000 (08:30 +0000)
committerMichael Ellerman <mpe@ellerman.id.au>
Tue, 15 Sep 2020 12:13:31 +0000 (22:13 +1000)
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: Christophe Leroy <christophe.leroy@csgroup.eu>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/a518abc29266a708dfbccc8fce9ae6694fe4c2c6.1598862623.git.christophe.leroy@csgroup.eu
arch/powerpc/include/asm/nohash/32/hugetlb-8xx.h
arch/powerpc/include/asm/nohash/32/pgtable.h
arch/powerpc/mm/hugetlbpage.c
arch/powerpc/mm/nohash/tlb.c
arch/powerpc/mm/ptdump/8xx.c
include/uapi/asm-generic/hugetlb_encode.h
include/uapi/linux/mman.h

index e752a5807a596ae50c819c63157fef5e77fd095b..39be9aea86db6ffc142435a0cf231f0bd499684a 100644 (file)
@@ -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 */
index 80bbc21b87f0936919a5df9273814df215d21e94..ee2243ba96cfa98cec006c06f7254e5a2b891966 100644 (file)
@@ -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;
 }
index e7ae2a2c45450361e16d51e17fec46d59f9c215e..36c3800769fbfe50ddb91f6d7979a255250f3e59 100644 (file)
@@ -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));
index 14514585db980347464b3d953db8e88eee5ca9c8..5872f69141d544d4b4d95a1d71e473d48092a6ba 100644 (file)
@@ -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,
        },
index 8a797dcbf475329c80f2268c9907ad792b4e820f..86da2a669680fb9821556621f47c96c9a957ad4f 100644 (file)
 
 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  = "    ",
        }, {
index b0f8e87235bdf4b599b52895637d9bd6329887fa..4f3d5aaa11f531164beab5a47bed8478e5f17546 100644 (file)
@@ -20,6 +20,7 @@
 #define HUGETLB_FLAG_ENCODE_SHIFT      26
 #define HUGETLB_FLAG_ENCODE_MASK       0x3f
 
+#define HUGETLB_FLAG_ENCODE_16KB       (14 << HUGETLB_FLAG_ENCODE_SHIFT)
 #define HUGETLB_FLAG_ENCODE_64KB       (16 << HUGETLB_FLAG_ENCODE_SHIFT)
 #define HUGETLB_FLAG_ENCODE_512KB      (19 << HUGETLB_FLAG_ENCODE_SHIFT)
 #define HUGETLB_FLAG_ENCODE_1MB                (20 << HUGETLB_FLAG_ENCODE_SHIFT)
index 923cc162609c016dd6360d834b34abfe6e1ba459..f55bc680b5b0a45eefca46732e265a8bfe2f46aa 100644 (file)
@@ -27,6 +27,7 @@
 #define MAP_HUGE_SHIFT HUGETLB_FLAG_ENCODE_SHIFT
 #define MAP_HUGE_MASK  HUGETLB_FLAG_ENCODE_MASK
 
+#define MAP_HUGE_16KB  HUGETLB_FLAG_ENCODE_16KB
 #define MAP_HUGE_64KB  HUGETLB_FLAG_ENCODE_64KB
 #define MAP_HUGE_512KB HUGETLB_FLAG_ENCODE_512KB
 #define MAP_HUGE_1MB   HUGETLB_FLAG_ENCODE_1MB