[PATCH 4/7] riscv: hugetlb: switch NAPOT mappings to raw PTE helpers
Yunhui Cui <[email protected]>
| Newsgroups | org.kernel.vger.linux-efi,org.infradead.lists.kvm-riscv,org.infradead.lists.linux-riscv,org.kernel.vger.kvm,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <[email protected]> |
Use raw PTE helpers in hugetlb code to operate directly on the underlying PTE entries. This lets hugetlb manage NAPOT folding/unfolding explicitly instead of going through Svnapot-aware public wrappers. Add explicit NAPOT unfolding in set_huge_pte_at() before replacing an existing NAPOT mapping with non-NAPOT entries. No functional change intended. Signed-off-by: Yunhui Cui <[email protected]> --- arch/riscv/mm/hugetlbpage.c | 55 +++++++++++++++++++++++-------------- 1 file changed, 35 insertions(+), 20 deletions(-) diff --git a/arch/riscv/mm/hugetlbpage.c b/arch/riscv/mm/hugetlbpage.c index a6d217112cf46..65a89b4fdad8b 100644 --- a/arch/riscv/mm/hugetlbpage.c +++ b/arch/riscv/mm/hugetlbpage.c @@ -7,7 +7,7 @@ pte_t huge_ptep_get(struct mm_struct *mm, unsigned long addr, pte_t *ptep) { unsigned long pte_num; int i; - pte_t orig_pte = ptep_get(ptep); + pte_t orig_pte = __ptep_get(ptep); if (!pte_present(orig_pte) || !pte_napot(orig_pte)) return orig_pte; @@ -15,7 +15,7 @@ pte_t huge_ptep_get(struct mm_struct *mm, unsigned long addr, pte_t *ptep) pte_num = napot_pte_num(napot_cont_order(orig_pte)); for (i = 0; i < pte_num; i++, ptep++) { - pte_t pte = ptep_get(ptep); + pte_t pte = __ptep_get(ptep); if (pte_dirty(pte)) orig_pte = pte_mkdirty(orig_pte); @@ -74,7 +74,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_lockless(pte); WARN_ON_ONCE(pte_present(pteval) && !pte_huge(pteval)); } @@ -153,12 +153,12 @@ static pte_t get_clear_contig(struct mm_struct *mm, pte_t pte, tmp_pte; bool present; - pte = ptep_get_and_clear(mm, addr, ptep); + pte = __ptep_get_and_clear(mm, addr, ptep); present = pte_present(pte); while (--ncontig) { ptep++; addr += PAGE_SIZE; - tmp_pte = ptep_get_and_clear(mm, addr, ptep); + tmp_pte = __ptep_get_and_clear(mm, addr, ptep); if (present) { if (pte_dirty(tmp_pte)) pte = pte_mkdirty(pte); @@ -210,7 +210,7 @@ static void clear_flush(struct mm_struct *mm, unsigned long i, saddr = addr; for (i = 0; i < ncontig; i++, addr += pgsize, ptep++) - ptep_get_and_clear(mm, addr, ptep); + __ptep_get_and_clear(mm, addr, ptep); flush_tlb_range(&vma, saddr, addr); } @@ -250,25 +250,40 @@ void set_huge_pte_at(struct mm_struct *mm, unsigned long sz) { size_t pgsize; + pte_t orig_pte; + pte_t pteval; int i, pte_num; pte_num = num_contig_ptes_from_size(sz, &pgsize); if (!pte_present(pte)) { - for (i = 0; i < pte_num; i++, ptep++, addr += pgsize) - set_ptes(mm, addr, ptep, pte, 1); + for (i = 0; i < pte_num; i++, ptep++, addr += pgsize) { + pteval = pte_mknonnapot(pte, addr); + orig_pte = __ptep_get(ptep); + + if (pte_present_napot(orig_pte)) + __napotpte_try_unfold(mm, addr, ptep, orig_pte); + + __set_ptes(mm, addr, ptep, pteval, 1); + } return; } if (!pte_napot(pte)) { - set_ptes(mm, addr, ptep, pte, 1); + pteval = pte_mknonnapot(pte, addr); + orig_pte = __ptep_get(ptep); + + if (pte_present_napot(orig_pte)) + __napotpte_try_unfold(mm, addr, ptep, orig_pte); + + __set_ptes(mm, addr, ptep, pteval, 1); return; } clear_flush(mm, addr, ptep, pgsize, pte_num); for (i = 0; i < pte_num; i++, ptep++, addr += pgsize) - set_pte_at(mm, addr, ptep, pte); + __set_ptes(mm, addr, ptep, pte, 1); } int huge_ptep_set_access_flags(struct vm_area_struct *vma, @@ -283,7 +298,7 @@ int huge_ptep_set_access_flags(struct vm_area_struct *vma, int i, pte_num; if (!pte_napot(pte)) - return ptep_set_access_flags(vma, addr, ptep, pte, dirty); + return __ptep_set_access_flags(vma, addr, ptep, pte, dirty); order = napot_cont_order(pte); pte_num = napot_pte_num(order); @@ -307,11 +322,11 @@ pte_t huge_ptep_get_and_clear(struct mm_struct *mm, pte_t *ptep, unsigned long sz) { size_t pgsize; - pte_t orig_pte = ptep_get(ptep); + pte_t orig_pte = __ptep_get(ptep); int pte_num; if (!pte_napot(orig_pte)) - return ptep_get_and_clear(mm, addr, ptep); + return __ptep_get_and_clear(mm, addr, ptep); pte_num = num_contig_ptes_from_size(sz, &pgsize); @@ -322,13 +337,13 @@ void huge_ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, pte_t *ptep) { - pte_t pte = ptep_get(ptep); + pte_t pte = __ptep_get(ptep); unsigned long order; pte_t orig_pte; int i, pte_num; if (!pte_napot(pte)) { - ptep_set_wrprotect(mm, addr, ptep); + __ptep_set_wrprotect(mm, addr, ptep); return; } @@ -347,11 +362,11 @@ pte_t huge_ptep_clear_flush(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep) { - pte_t pte = ptep_get(ptep); + pte_t pte = __ptep_get(ptep); int pte_num; if (!pte_napot(pte)) - return ptep_clear_flush(vma, addr, ptep); + return __ptep_clear_flush(vma, addr, ptep); pte_num = napot_pte_num(napot_cont_order(pte)); @@ -364,18 +379,18 @@ void huge_pte_clear(struct mm_struct *mm, unsigned long sz) { size_t pgsize; - pte_t pte = ptep_get(ptep); + pte_t pte = __ptep_get(ptep); int i, pte_num; if (!pte_napot(pte)) { - pte_clear(mm, addr, ptep); + __pte_clear(mm, addr, ptep); return; } pte_num = num_contig_ptes_from_size(sz, &pgsize); for (i = 0; i < pte_num; i++, addr += pgsize, ptep++) - pte_clear(mm, addr, ptep); + __pte_clear(mm, addr, ptep); } static bool is_napot_size(unsigned long size) -- 2.39.5