@@ -214,6 +214,19 @@ static pte_t get_clear_contig(struct mm_struct *mm,
214214 return orig_pte ;
215215}
216216
217+ static pte_t get_clear_contig_flush (struct mm_struct * mm ,
218+ unsigned long addr ,
219+ pte_t * ptep ,
220+ unsigned long pgsize ,
221+ unsigned long ncontig )
222+ {
223+ pte_t orig_pte = get_clear_contig (mm , addr , ptep , pgsize , ncontig );
224+ struct vm_area_struct vma = TLB_FLUSH_VMA (mm , 0 );
225+
226+ flush_tlb_range (& vma , addr , addr + (pgsize * ncontig ));
227+ return orig_pte ;
228+ }
229+
217230/*
218231 * Changing some bits of contiguous entries requires us to follow a
219232 * Break-Before-Make approach, breaking the whole contiguous set
@@ -447,19 +460,20 @@ int huge_ptep_set_access_flags(struct vm_area_struct *vma,
447460 int ncontig , i ;
448461 size_t pgsize = 0 ;
449462 unsigned long pfn = pte_pfn (pte ), dpfn ;
463+ struct mm_struct * mm = vma -> vm_mm ;
450464 pgprot_t hugeprot ;
451465 pte_t orig_pte ;
452466
453467 if (!pte_cont (pte ))
454468 return ptep_set_access_flags (vma , addr , ptep , pte , dirty );
455469
456- ncontig = find_num_contig (vma -> vm_mm , addr , ptep , & pgsize );
470+ ncontig = find_num_contig (mm , addr , ptep , & pgsize );
457471 dpfn = pgsize >> PAGE_SHIFT ;
458472
459473 if (!__cont_access_flags_changed (ptep , pte , ncontig ))
460474 return 0 ;
461475
462- orig_pte = get_clear_contig ( vma -> vm_mm , addr , ptep , pgsize , ncontig );
476+ orig_pte = get_clear_contig_flush ( mm , addr , ptep , pgsize , ncontig );
463477
464478 /* Make sure we don't lose the dirty or young state */
465479 if (pte_dirty (orig_pte ))
@@ -470,7 +484,7 @@ int huge_ptep_set_access_flags(struct vm_area_struct *vma,
470484
471485 hugeprot = pte_pgprot (pte );
472486 for (i = 0 ; i < ncontig ; i ++ , ptep ++ , addr += pgsize , pfn += dpfn )
473- set_pte_at (vma -> vm_mm , addr , ptep , pfn_pte (pfn , hugeprot ));
487+ set_pte_at (mm , addr , ptep , pfn_pte (pfn , hugeprot ));
474488
475489 return 1 ;
476490}
@@ -492,7 +506,7 @@ void huge_ptep_set_wrprotect(struct mm_struct *mm,
492506 ncontig = find_num_contig (mm , addr , ptep , & pgsize );
493507 dpfn = pgsize >> PAGE_SHIFT ;
494508
495- pte = get_clear_contig (mm , addr , ptep , pgsize , ncontig );
509+ pte = get_clear_contig_flush (mm , addr , ptep , pgsize , ncontig );
496510 pte = pte_wrprotect (pte );
497511
498512 hugeprot = pte_pgprot (pte );
@@ -505,17 +519,15 @@ void huge_ptep_set_wrprotect(struct mm_struct *mm,
505519pte_t huge_ptep_clear_flush (struct vm_area_struct * vma ,
506520 unsigned long addr , pte_t * ptep )
507521{
522+ struct mm_struct * mm = vma -> vm_mm ;
508523 size_t pgsize ;
509524 int ncontig ;
510- pte_t orig_pte ;
511525
512526 if (!pte_cont (READ_ONCE (* ptep )))
513527 return ptep_clear_flush (vma , addr , ptep );
514528
515- ncontig = find_num_contig (vma -> vm_mm , addr , ptep , & pgsize );
516- orig_pte = get_clear_contig (vma -> vm_mm , addr , ptep , pgsize , ncontig );
517- flush_tlb_range (vma , addr , addr + pgsize * ncontig );
518- return orig_pte ;
529+ ncontig = find_num_contig (mm , addr , ptep , & pgsize );
530+ return get_clear_contig_flush (mm , addr , ptep , pgsize , ncontig );
519531}
520532
521533static int __init hugetlbpage_init (void )
0 commit comments