diff options
Diffstat (limited to 'mm/hugetlb.c')
-rw-r--r-- | mm/hugetlb.c | 29 |
1 files changed, 29 insertions, 0 deletions
diff --git a/mm/hugetlb.c b/mm/hugetlb.c index 20117a4b8ab6..783098f6cf8e 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c | |||
@@ -565,3 +565,32 @@ int follow_hugetlb_page(struct mm_struct *mm, struct vm_area_struct *vma, | |||
565 | 565 | ||
566 | return i; | 566 | return i; |
567 | } | 567 | } |
568 | |||
569 | void hugetlb_change_protection(struct vm_area_struct *vma, | ||
570 | unsigned long address, unsigned long end, pgprot_t newprot) | ||
571 | { | ||
572 | struct mm_struct *mm = vma->vm_mm; | ||
573 | unsigned long start = address; | ||
574 | pte_t *ptep; | ||
575 | pte_t pte; | ||
576 | |||
577 | BUG_ON(address >= end); | ||
578 | flush_cache_range(vma, address, end); | ||
579 | |||
580 | spin_lock(&mm->page_table_lock); | ||
581 | for (; address < end; address += HPAGE_SIZE) { | ||
582 | ptep = huge_pte_offset(mm, address); | ||
583 | if (!ptep) | ||
584 | continue; | ||
585 | if (!pte_none(*ptep)) { | ||
586 | pte = huge_ptep_get_and_clear(mm, address, ptep); | ||
587 | pte = pte_mkhuge(pte_modify(pte, newprot)); | ||
588 | set_huge_pte_at(mm, address, ptep, pte); | ||
589 | lazy_mmu_prot_update(pte); | ||
590 | } | ||
591 | } | ||
592 | spin_unlock(&mm->page_table_lock); | ||
593 | |||
594 | flush_tlb_range(vma, start, end); | ||
595 | } | ||
596 | |||