[RFC PATCH v2 11/21] riscv: mm: Reimplement mk_huge_pte function

Xu Lu
2024-12-05T10:45:02Z

Huge pte can be pud, pmd, or svnapot pte. Huge ptes from different page
table levels have different pte constructors. This commit reimplements
mk_huge_pte function. We take vma struct as argument to check the target
huge pte level and applying corresponding constructor.

Signed-off-by: Xu Lu <luxu.kernel@bytedance.com>
---
arch/riscv/include/asm/hugetlb.h | 5 +++++
arch/riscv/mm/hugetlbpage.c | 23 ++++++++++++++++++++++-
arch/s390/include/asm/hugetlb.h | 2 +-
include/asm-generic/hugetlb.h | 5 ++++-
mm/debug_vm_pgtable.c | 2 +-
mm/hugetlb.c | 4 ++--
6 files changed, 35 insertions(+), 6 deletions(-)

diff --git a/arch/riscv/include/asm/hugetlb.h b/arch/riscv/include/asm/hugetlb.h
index faf3624d8057..eafd00f4b74f 100644
--- a/arch/riscv/include/asm/hugetlb.h
+++ b/arch/riscv/include/asm/hugetlb.h
@@ -51,6 +51,11 @@ pte_t arch_make_huge_pte(pte_t entry, unsigned int shift, vm_flags_t flags);

#endif /*CONFIG_RISCV_ISA_SVNAPOT*/

+#ifdef CONFIG_RISCV_USE_SW_PAGE
+#define __HAVE_ARCH_MK_HUGE_PTE
+pte_t mk_huge_pte(struct vm_area_struct *vma, struct page *page, pgprot_t pgprot);
+#endif
+
#include <asm-generic/hugetlb.h>

#endif /* _ASM_RISCV_HUGETLB_H */
diff --git a/arch/riscv/mm/hugetlbpage.c b/arch/riscv/mm/hugetlbpage.c
index 42314f093922..8896c28ec881 100644
--- a/arch/riscv/mm/hugetlbpage.c
+++ b/arch/riscv/mm/hugetlbpage.c
@@ -2,6 +2,27 @@
#include <linux/hugetlb.h>
#include <linux/err.h>

+#ifdef CONFIG_RISCV_USE_SW_PAGE
+pte_t mk_huge_pte(struct vm_area_struct *vma, struct page *page, pgprot_t pgprot)
+{
+ pte_t pte;
+ unsigned int shift = huge_page_shift(hstate_vma(vma));
+
+ if (shift == PGDIR_SHIFT)
+ pte = pgd_pte(pfn_pgd(page_to_pfn(page), pgprot));
+ else if (shift == P4D_SHIFT)
+ pte = p4d_pte(pfn_p4d(page_to_pfn(page), pgprot));
+ else if (shift == PUD_SHIFT)
+ pte = pud_pte(pfn_pud(page_to_pfn(page), pgprot));
+ else if (shift == PMD_SHIFT)
+ pte = pmd_pte(pfn_pmd(page_to_pfn(page), pgprot));
+ else
+ pte = pfn_pte(page_to_pfn(page), pgprot);
+
+ return pte;
+}
+#endif /* CONFIG_RISCV_USE_SW_PAGE */
+
#ifdef CONFIG_RISCV_ISA_SVNAPOT
pte_t huge_ptep_get(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
{
@@ -74,7 +95,7 @@ pte_t *huge_pte_alloc(struct mm_struct *mm,

out:
if (pte) {
- pte_t pteval = ptep_get_lockless(pte);
+ pte_t pteval = ptep_get(pte);

WARN_ON_ONCE(pte_present(pteval) && !pte_huge(pteval));
}
diff --git a/arch/s390/include/asm/hugetlb.h b/arch/s390/include/asm/hugetlb.h
index cf1b5d6fb1a6..cea9118d4bba 100644
--- a/arch/s390/include/asm/hugetlb.h
+++ b/arch/s390/include/asm/hugetlb.h
@@ -79,7 +79,7 @@ static inline void huge_ptep_set_wrprotect(struct mm_struct *mm,
__set_huge_pte_at(mm, addr, ptep, pte_wrprotect(pte));
}

-static inline pte_t mk_huge_pte(struct page *page, pgprot_t pgprot)
+static inline pte_t mk_huge_pte(struct vm_area_struct *vma, struct page *page, pgprot_t pgprot)
{
return mk_pte(page, pgprot);
}
diff --git a/include/asm-generic/hugetlb.h b/include/asm-generic/hugetlb.h
index 594d5905f615..90765bc03bba 100644
--- a/include/asm-generic/hugetlb.h
+++ b/include/asm-generic/hugetlb.h
@@ -5,10 +5,13 @@
#include <linux/swap.h>
#include <linux/swapops.h>

-static inline pte_t mk_huge_pte(struct page *page, pgprot_t pgprot)
+#ifndef __HAVE_ARCH_MK_HUGE_PTE
+static inline pte_t mk_huge_pte(struct vm_area_struct *vma, struct page *page,
+ pgprot_t pgprot)
{
return mk_pte(page, pgprot);
}
+#endif

static inline unsigned long huge_pte_write(pte_t pte)
{
diff --git a/mm/debug_vm_pgtable.c b/mm/debug_vm_pgtable.c
index 1cec548cc6c7..24839883d513 100644
--- a/mm/debug_vm_pgtable.c
+++ b/mm/debug_vm_pgtable.c
@@ -919,7 +919,7 @@ static void __init hugetlb_basic_tests(struct pgtable_debug_args *args)
* as it was previously derived from a real kernel symbol.
*/
page = pfn_to_page(args->fixed_pmd_pfn);
- pte = mk_huge_pte(page, args->page_prot);
+ pte = mk_huge_pte(args->vma, page, args->page_prot);

WARN_ON(!huge_pte_dirty(huge_pte_mkdirty(pte)));
WARN_ON(!huge_pte_write(huge_pte_mkwrite(huge_pte_wrprotect(pte))));
diff --git a/mm/hugetlb.c b/mm/hugetlb.c
index 190fa05635f4..2b33eb46408f 100644
--- a/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -5140,10 +5140,10 @@ static pte_t make_huge_pte(struct vm_area_struct *vma, struct page *page,
unsigned int shift = huge_page_shift(hstate_vma(vma));

if (writable) {
- entry = huge_pte_mkwrite(huge_pte_mkdirty(mk_huge_pte(page,
+ entry = huge_pte_mkwrite(huge_pte_mkdirty(mk_huge_pte(vma, page,
vma->vm_page_prot)));
} else {
- entry = huge_pte_wrprotect(mk_huge_pte(page,
+ entry = huge_pte_wrprotect(mk_huge_pte(vma, page,
vma->vm_page_prot));
}
entry = pte_mkyoung(entry);