Skip to content

Commit 29cb805

Browse files
Ryan Robertswilldeacon
authored andcommitted
arm64: hugetlb: Cleanup huge_pte size discovery mechanisms
Not all huge_pte helper APIs explicitly provide the size of the huge_pte. So the helpers have to depend on various methods to determine the size of the huge_pte. Some of these methods are dubious. Let's clean up the code to use preferred methods and retire the dubious ones. The options in order of preference: - If size is provided as parameter, use it together with num_contig_ptes(). This is explicit and works for both present and non-present ptes. - If vma is provided as a parameter, retrieve size via huge_page_size(hstate_vma(vma)) and use it together with num_contig_ptes(). This is explicit and works for both present and non-present ptes. - If the pte is present and contiguous, use find_num_contig() to walk the pgtable to find the level and infer the number of ptes from level. Only works for *present* ptes. - If the pte is present and not contiguous and you can infer from this that only 1 pte needs to be operated on. This is ok if you don't care about the absolute size, and just want to know the number of ptes. - NEVER rely on resolving the PFN of a present pte to a folio and getting the folio's size. This is fragile at best, because there is nothing to stop the core-mm from allocating a folio twice as big as the huge_pte then mapping it across 2 consecutive huge_ptes. Or just partially mapping it. Where we require that the pte is present, add warnings if not-present. Reviewed-by: Catalin Marinas <[email protected]> Reviewed-by: Anshuman Khandual <[email protected]> Signed-off-by: Ryan Roberts <[email protected]> Tested-by: Luiz Capitulino <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Will Deacon <[email protected]>
1 parent fcf8dda commit 29cb805

File tree

1 file changed

+15
-5
lines changed

1 file changed

+15
-5
lines changed

arch/arm64/mm/hugetlbpage.c

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ pte_t huge_ptep_get(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
129129
if (!pte_present(orig_pte) || !pte_cont(orig_pte))
130130
return orig_pte;
131131

132-
ncontig = num_contig_ptes(page_size(pte_page(orig_pte)), &pgsize);
132+
ncontig = find_num_contig(mm, addr, ptep, &pgsize);
133133
for (i = 0; i < ncontig; i++, ptep++) {
134134
pte_t pte = __ptep_get(ptep);
135135

@@ -438,16 +438,19 @@ int huge_ptep_set_access_flags(struct vm_area_struct *vma,
438438
pgprot_t hugeprot;
439439
pte_t orig_pte;
440440

441+
VM_WARN_ON(!pte_present(pte));
442+
441443
if (!pte_cont(pte))
442444
return __ptep_set_access_flags(vma, addr, ptep, pte, dirty);
443445

444-
ncontig = find_num_contig(mm, addr, ptep, &pgsize);
446+
ncontig = num_contig_ptes(huge_page_size(hstate_vma(vma)), &pgsize);
445447
dpfn = pgsize >> PAGE_SHIFT;
446448

447449
if (!__cont_access_flags_changed(ptep, pte, ncontig))
448450
return 0;
449451

450452
orig_pte = get_clear_contig_flush(mm, addr, ptep, pgsize, ncontig);
453+
VM_WARN_ON(!pte_present(orig_pte));
451454

452455
/* Make sure we don't lose the dirty or young state */
453456
if (pte_dirty(orig_pte))
@@ -472,7 +475,10 @@ void huge_ptep_set_wrprotect(struct mm_struct *mm,
472475
size_t pgsize;
473476
pte_t pte;
474477

475-
if (!pte_cont(__ptep_get(ptep))) {
478+
pte = __ptep_get(ptep);
479+
VM_WARN_ON(!pte_present(pte));
480+
481+
if (!pte_cont(pte)) {
476482
__ptep_set_wrprotect(mm, addr, ptep);
477483
return;
478484
}
@@ -496,11 +502,15 @@ pte_t huge_ptep_clear_flush(struct vm_area_struct *vma,
496502
struct mm_struct *mm = vma->vm_mm;
497503
size_t pgsize;
498504
int ncontig;
505+
pte_t pte;
506+
507+
pte = __ptep_get(ptep);
508+
VM_WARN_ON(!pte_present(pte));
499509

500-
if (!pte_cont(__ptep_get(ptep)))
510+
if (!pte_cont(pte))
501511
return ptep_clear_flush(vma, addr, ptep);
502512

503-
ncontig = find_num_contig(mm, addr, ptep, &pgsize);
513+
ncontig = num_contig_ptes(huge_page_size(hstate_vma(vma)), &pgsize);
504514
return get_clear_contig_flush(mm, addr, ptep, pgsize, ncontig);
505515
}
506516

0 commit comments

Comments
 (0)