@@ -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 */
@@ -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));
}
@@ -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);
}
@@ -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)
{
@@ -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))));
@@ -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);
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(-)