@@ -121,20 +121,11 @@ static int find_num_contig(struct mm_struct *mm, unsigned long addr,
121
121
122
122
static inline int num_contig_ptes (unsigned long size , size_t * pgsize )
123
123
{
124
- int contig_ptes = 0 ;
124
+ int contig_ptes = 1 ;
125
125
126
126
* pgsize = size ;
127
127
128
128
switch (size ) {
129
- #ifndef __PAGETABLE_PMD_FOLDED
130
- case PUD_SIZE :
131
- if (pud_sect_supported ())
132
- contig_ptes = 1 ;
133
- break ;
134
- #endif
135
- case PMD_SIZE :
136
- contig_ptes = 1 ;
137
- break ;
138
129
case CONT_PMD_SIZE :
139
130
* pgsize = PMD_SIZE ;
140
131
contig_ptes = CONT_PMDS ;
@@ -143,6 +134,8 @@ static inline int num_contig_ptes(unsigned long size, size_t *pgsize)
143
134
* pgsize = PAGE_SIZE ;
144
135
contig_ptes = CONT_PTES ;
145
136
break ;
137
+ default :
138
+ WARN_ON (!__hugetlb_valid_size (size ));
146
139
}
147
140
148
141
return contig_ptes ;
@@ -184,24 +177,23 @@ static pte_t get_clear_contig(struct mm_struct *mm,
184
177
unsigned long pgsize ,
185
178
unsigned long ncontig )
186
179
{
187
- pte_t orig_pte = ptep_get (ptep );
188
- unsigned long i ;
189
-
190
- for (i = 0 ; i < ncontig ; i ++ , addr += pgsize , ptep ++ ) {
191
- pte_t pte = ptep_get_and_clear (mm , addr , ptep );
192
-
193
- /*
194
- * If HW_AFDBM is enabled, then the HW could turn on
195
- * the dirty or accessed bit for any page in the set,
196
- * so check them all.
197
- */
198
- if (pte_dirty (pte ))
199
- orig_pte = pte_mkdirty (orig_pte );
200
-
201
- if (pte_young (pte ))
202
- orig_pte = pte_mkyoung (orig_pte );
180
+ pte_t pte , tmp_pte ;
181
+ bool present ;
182
+
183
+ pte = ptep_get_and_clear (mm , addr , ptep );
184
+ present = pte_present (pte );
185
+ while (-- ncontig ) {
186
+ ptep ++ ;
187
+ addr += pgsize ;
188
+ tmp_pte = ptep_get_and_clear (mm , addr , ptep );
189
+ if (present ) {
190
+ if (pte_dirty (tmp_pte ))
191
+ pte = pte_mkdirty (pte );
192
+ if (pte_young (tmp_pte ))
193
+ pte = pte_mkyoung (pte );
194
+ }
203
195
}
204
- return orig_pte ;
196
+ return pte ;
205
197
}
206
198
207
199
static pte_t get_clear_contig_flush (struct mm_struct * mm ,
@@ -403,18 +395,13 @@ void huge_pte_clear(struct mm_struct *mm, unsigned long addr,
403
395
pte_clear (mm , addr , ptep );
404
396
}
405
397
406
- pte_t huge_ptep_get_and_clear (struct mm_struct * mm ,
407
- unsigned long addr , pte_t * ptep )
398
+ pte_t huge_ptep_get_and_clear (struct mm_struct * mm , unsigned long addr ,
399
+ pte_t * ptep , unsigned long sz )
408
400
{
409
401
int ncontig ;
410
402
size_t pgsize ;
411
- pte_t orig_pte = ptep_get (ptep );
412
-
413
- if (!pte_cont (orig_pte ))
414
- return ptep_get_and_clear (mm , addr , ptep );
415
-
416
- ncontig = find_num_contig (mm , addr , ptep , & pgsize );
417
403
404
+ ncontig = num_contig_ptes (sz , & pgsize );
418
405
return get_clear_contig (mm , addr , ptep , pgsize , ncontig );
419
406
}
420
407
@@ -556,6 +543,8 @@ bool __init arch_hugetlb_valid_size(unsigned long size)
556
543
557
544
pte_t huge_ptep_modify_prot_start (struct vm_area_struct * vma , unsigned long addr , pte_t * ptep )
558
545
{
546
+ unsigned long psize = huge_page_size (hstate_vma (vma ));
547
+
559
548
if (IS_ENABLED (CONFIG_ARM64_ERRATUM_2645198 ) &&
560
549
cpus_have_const_cap (ARM64_WORKAROUND_2645198 )) {
561
550
/*
@@ -566,7 +555,7 @@ pte_t huge_ptep_modify_prot_start(struct vm_area_struct *vma, unsigned long addr
566
555
if (pte_user_exec (READ_ONCE (* ptep )))
567
556
return huge_ptep_clear_flush (vma , addr , ptep );
568
557
}
569
- return huge_ptep_get_and_clear (vma -> vm_mm , addr , ptep );
558
+ return huge_ptep_get_and_clear (vma -> vm_mm , addr , ptep , psize );
570
559
}
571
560
572
561
void huge_ptep_modify_prot_commit (struct vm_area_struct * vma , unsigned long addr , pte_t * ptep ,
0 commit comments