Re: [PATCH v2 2/2] riscv: Introduce huge page support for 32/64bit kernel

From: Alex Ghiti
Date: Thu Apr 25 2019 - 14:52:58 EST


On 4/25/19 1:42 PM, Palmer Dabbelt wrote:
On Mon, 08 Apr 2019 23:14:49 PDT (-0700), alex@xxxxxxxx wrote:
This patch implements both 4MB huge page support for 32bit kernel
and 2MB/1GB huge pages support for 64bit kernel.

Signed-off-by: Alexandre Ghiti <alex@xxxxxxxx>
---
Âarch/riscv/KconfigÂÂÂÂÂÂÂÂÂÂÂÂÂÂ |Â 8 ++++++
Âarch/riscv/include/asm/hugetlb.h | 18 +++++++++++++
Âarch/riscv/include/asm/page.hÂÂÂ | 10 ++++++++
Âarch/riscv/include/asm/pgtable.h |Â 8 ++++--
Âarch/riscv/mm/MakefileÂÂÂÂÂÂÂÂÂÂ |Â 2 ++
Âarch/riscv/mm/hugetlbpage.cÂÂÂÂÂ | 44 ++++++++++++++++++++++++++++++++
Â6 files changed, 88 insertions(+), 2 deletions(-)
Âcreate mode 100644 arch/riscv/include/asm/hugetlb.h
Âcreate mode 100644 arch/riscv/mm/hugetlbpage.c

diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
index eb56c82d8aa1..a400d4b4e1b3 100644
--- a/arch/riscv/Kconfig
+++ b/arch/riscv/Kconfig
@@ -49,6 +49,8 @@ config RISCV
ÂÂÂÂ select GENERIC_IRQ_MULTI_HANDLER
ÂÂÂÂ select ARCH_HAS_PTE_SPECIAL
ÂÂÂÂ select HAVE_EBPF_JIT if 64BIT
+ÂÂÂ select ARCH_HAS_GIGANTIC_PAGE
+ÂÂÂ select ARCH_WANT_HUGE_PMD_SHARE if 64BIT

Âconfig MMU
ÂÂÂÂ def_bool y
@@ -63,6 +65,12 @@ config PAGE_OFFSET
ÂÂÂÂ default 0xffffffff80000000 if 64BIT && MAXPHYSMEM_2GB
ÂÂÂÂ default 0xffffffe000000000 if 64BIT && MAXPHYSMEM_128GB

+config ARCH_WANT_GENERAL_HUGETLB
+ÂÂÂ def_bool y
+
+config SYS_SUPPORTS_HUGETLBFS
+ÂÂÂ def_bool y
+
Âconfig STACKTRACE_SUPPORT
ÂÂÂÂ def_bool y

diff --git a/arch/riscv/include/asm/hugetlb.h b/arch/riscv/include/asm/hugetlb.h
new file mode 100644
index 000000000000..728a5db66597
--- /dev/null
+++ b/arch/riscv/include/asm/hugetlb.h
@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _ASM_RISCV_HUGETLB_H
+#define _ASM_RISCV_HUGETLB_H
+
+#include <asm-generic/hugetlb.h>
+#include <asm/page.h>
+
+static inline int is_hugepage_only_range(struct mm_struct *mm,
+ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ unsigned long addr,
+ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ unsigned long len) {
+ÂÂÂ return 0;
+}
+
+static inline void arch_clear_hugepage_flags(struct page *page)
+{
+}
+
+#endif /* _ASM_RISCV_HUGETLB_H */
diff --git a/arch/riscv/include/asm/page.h b/arch/riscv/include/asm/page.h
index 2a546a52f02a..4ef2936295aa 100644
--- a/arch/riscv/include/asm/page.h
+++ b/arch/riscv/include/asm/page.h
@@ -24,6 +24,16 @@
Â#define PAGE_SIZEÂÂÂ (_AC(1, UL) << PAGE_SHIFT)
Â#define PAGE_MASKÂÂÂ (~(PAGE_SIZE - 1))

+#ifdef CONFIG_64BIT
+#define HUGE_MAX_HSTATEÂÂÂÂÂÂÂ 2
+#else
+#define HUGE_MAX_HSTATEÂÂÂÂÂÂÂ 1
+#endif
+#define HPAGE_SHIFTÂÂÂÂÂÂÂ PMD_SHIFT
+#define HPAGE_SIZEÂÂÂÂÂÂÂ (_AC(1, UL) << HPAGE_SHIFT)
+#define HPAGE_MASKÂÂÂÂÂÂÂÂÂÂÂÂÂ (~(HPAGE_SIZE - 1))
+#define HUGETLB_PAGE_ORDERÂÂÂÂÂ (HPAGE_SHIFT - PAGE_SHIFT)
+
Â/*
 * PAGE_OFFSET -- the first address of the first page of memory.
 * When not using MMU this corresponds to the first free page in
diff --git a/arch/riscv/include/asm/pgtable.h b/arch/riscv/include/asm/pgtable.h
index 1141364d990e..f3456fcdff92 100644
--- a/arch/riscv/include/asm/pgtable.h
+++ b/arch/riscv/include/asm/pgtable.h
@@ -121,7 +121,6 @@ static inline void pmd_clear(pmd_t *pmdp)
ÂÂÂÂ set_pmd(pmdp, __pmd(0));
Â}

-
Âstatic inline pgd_t pfn_pgd(unsigned long pfn, pgprot_t prot)
Â{
ÂÂÂÂ return __pgd((pfn << _PAGE_PFN_SHIFT) | pgprot_val(prot));
@@ -258,6 +257,11 @@ static inline pte_t pte_mkspecial(pte_t pte)
ÂÂÂÂ return __pte(pte_val(pte) | _PAGE_SPECIAL);
Â}

+static inline pte_t pte_mkhuge(pte_t pte)
+{
+ÂÂÂ return pte;
+}
+
Â/* Modify page protection bits */
Âstatic inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
Â{
@@ -417,7 +421,7 @@ static inline void pgtable_cache_init(void)
Â#define VMALLOC_STARTÂÂÂ (PAGE_OFFSET - VMALLOC_SIZE)

Â/*
- * Task size is 0x40000000000 for RV64 or 0xb800000 for RV32.
+ * Task size is 0x4000000000 for RV64 or 0xb800000 for RV32.
 * Note that PGDIR_SIZE must evenly divide TASK_SIZE.
 */
Â#ifdef CONFIG_64BIT
diff --git a/arch/riscv/mm/Makefile b/arch/riscv/mm/Makefile
index b68aac701803..7bbe533d92f5 100644
--- a/arch/riscv/mm/Makefile
+++ b/arch/riscv/mm/Makefile
@@ -9,3 +9,5 @@ obj-y += fault.o
Âobj-y += extable.o
Âobj-y += ioremap.o
Âobj-y += cacheflush.o
+
+obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o
diff --git a/arch/riscv/mm/hugetlbpage.c b/arch/riscv/mm/hugetlbpage.c
new file mode 100644
index 000000000000..0d4747e9d5b5
--- /dev/null
+++ b/arch/riscv/mm/hugetlbpage.c
@@ -0,0 +1,44 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <linux/hugetlb.h>
+#include <linux/err.h>
+
+int pud_huge(pud_t pud)
+{
+ÂÂÂ return pud_present(pud) &&
+ÂÂÂÂÂÂÂ (pud_val(pud) & (_PAGE_READ | _PAGE_WRITE | _PAGE_EXEC));
+}
+
+int pmd_huge(pmd_t pmd)
+{
+ÂÂÂ return pmd_present(pmd) &&
+ÂÂÂÂÂÂÂ (pmd_val(pmd) & (_PAGE_READ | _PAGE_WRITE | _PAGE_EXEC));
+}
+
+static __init int setup_hugepagesz(char *opt)
+{
+ÂÂÂ unsigned long ps = memparse(opt, &opt);
+
+ÂÂÂ if (ps == HPAGE_SIZE) {
+ÂÂÂÂÂÂÂ hugetlb_add_hstate(HPAGE_SHIFT - PAGE_SHIFT);
+ÂÂÂ } else if (IS_ENABLED(CONFIG_64BIT) && ps == PUD_SIZE) {
+ÂÂÂÂÂÂÂ hugetlb_add_hstate(PUD_SHIFT - PAGE_SHIFT);
+ÂÂÂ } else {
+ÂÂÂÂÂÂÂ hugetlb_bad_size();
+ÂÂÂÂÂÂÂ pr_err("hugepagesz: Unsupported page size %lu M\n", ps >> 20);
+ÂÂÂÂÂÂÂ return 0;
+ÂÂÂ }
+
+ÂÂÂ return 1;
+}
+__setup("hugepagesz=", setup_hugepagesz);
+
+#ifdef CONFIG_CONTIG_ALLOC
+static __init int gigantic_pages_init(void)
+{
+ÂÂÂ /* With CONTIG_ALLOC, we can allocate gigantic pages at runtime */
+ÂÂÂ if (IS_ENABLED(CONFIG_64BIT) && !size_to_hstate(1UL << PUD_SHIFT))
+ÂÂÂÂÂÂÂ hugetlb_add_hstate(PUD_SHIFT - PAGE_SHIFT);
+ÂÂÂ return 0;
+}
+arch_initcall(gigantic_pages_init);
+#endif

I'm getting some build errors when this is applied to 5.1-c6. I think all I've
done is turn on hugetlb:

Hi Palmer,

This patchset is based on linux-next where my series "Fix free/allocation of runtime gigantic pages"
was merged, it is not yet present in v5.1-rc*.

Thanks,

Alex

ÂÂ $ diff -u arch/riscv/configs/defconfig defconfig
ÂÂ --- arch/riscv/configs/defconfigÂÂÂÂÂÂÂ 2019-04-24 16:23:39.027994174 -0700
ÂÂ +++ defconfigÂÂ 2019-04-25 10:39:34.722544413 -0700
ÂÂ @@ -5,6 +5,7 @@
ÂÂÂ CONFIG_CGROUPS=y
ÂÂÂ CONFIG_CGROUP_SCHED=y
ÂÂÂ CONFIG_CFS_BANDWIDTH=y
ÂÂ +CONFIG_CGROUP_HUGETLB=y
ÂÂÂ CONFIG_CGROUP_BPF=y
ÂÂÂ CONFIG_NAMESPACES=y
ÂÂÂ CONFIG_USER_NS=y
ÂÂ @@ -72,6 +73,7 @@
ÂÂÂ CONFIG_VFAT_FS=y
ÂÂÂ CONFIG_TMPFS=y
ÂÂÂ CONFIG_TMPFS_POSIX_ACL=y
ÂÂ +CONFIG_HUGETLBFS=y
ÂÂÂ CONFIG_NFS_FS=y
ÂÂÂ CONFIG_NFS_V4=y
ÂÂÂ CONFIG_NFS_V4_1=y