Skip to content

Commit 02410ac

Browse files
Ryan Robertswilldeacon
authored andcommitted
mm: hugetlb: Add huge page size param to huge_ptep_get_and_clear()
In order to fix a bug, arm64 needs to be told the size of the huge page for which the huge_pte is being cleared in huge_ptep_get_and_clear(). Provide for this by adding an `unsigned long sz` parameter to the function. This follows the same pattern as huge_pte_clear() and set_huge_pte_at(). This commit makes the required interface modifications to the core mm as well as all arches that implement this function (arm64, loongarch, mips, parisc, powerpc, riscv, s390, sparc). The actual arm64 bug will be fixed in a separate commit. Cc: stable@vger.kernel.org Fixes: 66b3923 ("arm64: hugetlb: add support for PTE contiguous bit") Acked-by: David Hildenbrand <david@redhat.com> Reviewed-by: Alexandre Ghiti <alexghiti@rivosinc.com> # riscv Reviewed-by: Christophe Leroy <christophe.leroy@csgroup.eu> Reviewed-by: Catalin Marinas <catalin.marinas@arm.com> Reviewed-by: Anshuman Khandual <anshuman.khandual@arm.com> Signed-off-by: Ryan Roberts <ryan.roberts@arm.com> Acked-by: Alexander Gordeev <agordeev@linux.ibm.com> # s390 Link: https://lore.kernel.org/r/20250226120656.2400136-2-ryan.roberts@arm.com Signed-off-by: Will Deacon <will@kernel.org>
1 parent 2b1283e commit 02410ac

File tree

16 files changed

+46
-27
lines changed

16 files changed

+46
-27
lines changed

arch/arm64/include/asm/hugetlb.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,8 @@ extern int huge_ptep_set_access_flags(struct vm_area_struct *vma,
4242
unsigned long addr, pte_t *ptep,
4343
pte_t pte, int dirty);
4444
#define __HAVE_ARCH_HUGE_PTEP_GET_AND_CLEAR
45-
extern pte_t huge_ptep_get_and_clear(struct mm_struct *mm,
46-
unsigned long addr, pte_t *ptep);
45+
extern pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr,
46+
pte_t *ptep, unsigned long sz);
4747
#define __HAVE_ARCH_HUGE_PTEP_SET_WRPROTECT
4848
extern void huge_ptep_set_wrprotect(struct mm_struct *mm,
4949
unsigned long addr, pte_t *ptep);

arch/arm64/mm/hugetlbpage.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -396,8 +396,8 @@ void huge_pte_clear(struct mm_struct *mm, unsigned long addr,
396396
__pte_clear(mm, addr, ptep);
397397
}
398398

399-
pte_t huge_ptep_get_and_clear(struct mm_struct *mm,
400-
unsigned long addr, pte_t *ptep)
399+
pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr,
400+
pte_t *ptep, unsigned long sz)
401401
{
402402
int ncontig;
403403
size_t pgsize;
@@ -549,6 +549,8 @@ bool __init arch_hugetlb_valid_size(unsigned long size)
549549

550550
pte_t huge_ptep_modify_prot_start(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep)
551551
{
552+
unsigned long psize = huge_page_size(hstate_vma(vma));
553+
552554
if (alternative_has_cap_unlikely(ARM64_WORKAROUND_2645198)) {
553555
/*
554556
* Break-before-make (BBM) is required for all user space mappings
@@ -558,7 +560,7 @@ pte_t huge_ptep_modify_prot_start(struct vm_area_struct *vma, unsigned long addr
558560
if (pte_user_exec(__ptep_get(ptep)))
559561
return huge_ptep_clear_flush(vma, addr, ptep);
560562
}
561-
return huge_ptep_get_and_clear(vma->vm_mm, addr, ptep);
563+
return huge_ptep_get_and_clear(vma->vm_mm, addr, ptep, psize);
562564
}
563565

564566
void huge_ptep_modify_prot_commit(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep,

arch/loongarch/include/asm/hugetlb.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,8 @@ static inline void huge_pte_clear(struct mm_struct *mm, unsigned long addr,
3636

3737
#define __HAVE_ARCH_HUGE_PTEP_GET_AND_CLEAR
3838
static inline pte_t huge_ptep_get_and_clear(struct mm_struct *mm,
39-
unsigned long addr, pte_t *ptep)
39+
unsigned long addr, pte_t *ptep,
40+
unsigned long sz)
4041
{
4142
pte_t clear;
4243
pte_t pte = ptep_get(ptep);
@@ -51,8 +52,9 @@ static inline pte_t huge_ptep_clear_flush(struct vm_area_struct *vma,
5152
unsigned long addr, pte_t *ptep)
5253
{
5354
pte_t pte;
55+
unsigned long sz = huge_page_size(hstate_vma(vma));
5456

55-
pte = huge_ptep_get_and_clear(vma->vm_mm, addr, ptep);
57+
pte = huge_ptep_get_and_clear(vma->vm_mm, addr, ptep, sz);
5658
flush_tlb_page(vma, addr);
5759
return pte;
5860
}

arch/mips/include/asm/hugetlb.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@ static inline int prepare_hugepage_range(struct file *file,
2727

2828
#define __HAVE_ARCH_HUGE_PTEP_GET_AND_CLEAR
2929
static inline pte_t huge_ptep_get_and_clear(struct mm_struct *mm,
30-
unsigned long addr, pte_t *ptep)
30+
unsigned long addr, pte_t *ptep,
31+
unsigned long sz)
3132
{
3233
pte_t clear;
3334
pte_t pte = *ptep;
@@ -42,13 +43,14 @@ static inline pte_t huge_ptep_clear_flush(struct vm_area_struct *vma,
4243
unsigned long addr, pte_t *ptep)
4344
{
4445
pte_t pte;
46+
unsigned long sz = huge_page_size(hstate_vma(vma));
4547

4648
/*
4749
* clear the huge pte entry firstly, so that the other smp threads will
4850
* not get old pte entry after finishing flush_tlb_page and before
4951
* setting new huge pte entry
5052
*/
51-
pte = huge_ptep_get_and_clear(vma->vm_mm, addr, ptep);
53+
pte = huge_ptep_get_and_clear(vma->vm_mm, addr, ptep, sz);
5254
flush_tlb_page(vma, addr);
5355
return pte;
5456
}

arch/parisc/include/asm/hugetlb.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
1010

1111
#define __HAVE_ARCH_HUGE_PTEP_GET_AND_CLEAR
1212
pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr,
13-
pte_t *ptep);
13+
pte_t *ptep, unsigned long sz);
1414

1515
#define __HAVE_ARCH_HUGE_PTEP_CLEAR_FLUSH
1616
static inline pte_t huge_ptep_clear_flush(struct vm_area_struct *vma,

arch/parisc/mm/hugetlbpage.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
126126

127127

128128
pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr,
129-
pte_t *ptep)
129+
pte_t *ptep, unsigned long sz)
130130
{
131131
pte_t entry;
132132

arch/powerpc/include/asm/hugetlb.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,8 @@ void set_huge_pte_at(struct mm_struct *mm, unsigned long addr, pte_t *ptep,
4545

4646
#define __HAVE_ARCH_HUGE_PTEP_GET_AND_CLEAR
4747
static inline pte_t huge_ptep_get_and_clear(struct mm_struct *mm,
48-
unsigned long addr, pte_t *ptep)
48+
unsigned long addr, pte_t *ptep,
49+
unsigned long sz)
4950
{
5051
return __pte(pte_update(mm, addr, ptep, ~0UL, 0, 1));
5152
}
@@ -55,8 +56,9 @@ static inline pte_t huge_ptep_clear_flush(struct vm_area_struct *vma,
5556
unsigned long addr, pte_t *ptep)
5657
{
5758
pte_t pte;
59+
unsigned long sz = huge_page_size(hstate_vma(vma));
5860

59-
pte = huge_ptep_get_and_clear(vma->vm_mm, addr, ptep);
61+
pte = huge_ptep_get_and_clear(vma->vm_mm, addr, ptep, sz);
6062
flush_hugetlb_page(vma, addr);
6163
return pte;
6264
}

arch/riscv/include/asm/hugetlb.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@ void set_huge_pte_at(struct mm_struct *mm,
2828

2929
#define __HAVE_ARCH_HUGE_PTEP_GET_AND_CLEAR
3030
pte_t huge_ptep_get_and_clear(struct mm_struct *mm,
31-
unsigned long addr, pte_t *ptep);
31+
unsigned long addr, pte_t *ptep,
32+
unsigned long sz);
3233

3334
#define __HAVE_ARCH_HUGE_PTEP_CLEAR_FLUSH
3435
pte_t huge_ptep_clear_flush(struct vm_area_struct *vma,

arch/riscv/mm/hugetlbpage.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -293,7 +293,7 @@ int huge_ptep_set_access_flags(struct vm_area_struct *vma,
293293

294294
pte_t huge_ptep_get_and_clear(struct mm_struct *mm,
295295
unsigned long addr,
296-
pte_t *ptep)
296+
pte_t *ptep, unsigned long sz)
297297
{
298298
pte_t orig_pte = ptep_get(ptep);
299299
int pte_num;

arch/s390/include/asm/hugetlb.h

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,16 @@ void __set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
2525
#define __HAVE_ARCH_HUGE_PTEP_GET
2626
pte_t huge_ptep_get(struct mm_struct *mm, unsigned long addr, pte_t *ptep);
2727

28+
pte_t __huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr,
29+
pte_t *ptep);
30+
2831
#define __HAVE_ARCH_HUGE_PTEP_GET_AND_CLEAR
29-
pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep);
32+
static inline pte_t huge_ptep_get_and_clear(struct mm_struct *mm,
33+
unsigned long addr, pte_t *ptep,
34+
unsigned long sz)
35+
{
36+
return __huge_ptep_get_and_clear(mm, addr, ptep);
37+
}
3038

3139
static inline void arch_clear_hugetlb_flags(struct folio *folio)
3240
{
@@ -48,7 +56,7 @@ static inline void huge_pte_clear(struct mm_struct *mm, unsigned long addr,
4856
static inline pte_t huge_ptep_clear_flush(struct vm_area_struct *vma,
4957
unsigned long address, pte_t *ptep)
5058
{
51-
return huge_ptep_get_and_clear(vma->vm_mm, address, ptep);
59+
return __huge_ptep_get_and_clear(vma->vm_mm, address, ptep);
5260
}
5361

5462
#define __HAVE_ARCH_HUGE_PTEP_SET_ACCESS_FLAGS
@@ -59,7 +67,7 @@ static inline int huge_ptep_set_access_flags(struct vm_area_struct *vma,
5967
int changed = !pte_same(huge_ptep_get(vma->vm_mm, addr, ptep), pte);
6068

6169
if (changed) {
62-
huge_ptep_get_and_clear(vma->vm_mm, addr, ptep);
70+
__huge_ptep_get_and_clear(vma->vm_mm, addr, ptep);
6371
__set_huge_pte_at(vma->vm_mm, addr, ptep, pte);
6472
}
6573
return changed;
@@ -69,7 +77,7 @@ static inline int huge_ptep_set_access_flags(struct vm_area_struct *vma,
6977
static inline void huge_ptep_set_wrprotect(struct mm_struct *mm,
7078
unsigned long addr, pte_t *ptep)
7179
{
72-
pte_t pte = huge_ptep_get_and_clear(mm, addr, ptep);
80+
pte_t pte = __huge_ptep_get_and_clear(mm, addr, ptep);
7381

7482
__set_huge_pte_at(mm, addr, ptep, pte_wrprotect(pte));
7583
}

0 commit comments

Comments
 (0)