|
@@ -709,15 +709,22 @@ static int write_protect_page(struct vm_area_struct *vma, struct page *page,
|
|
|
spinlock_t *ptl;
|
|
|
int swapped;
|
|
|
int err = -EFAULT;
|
|
|
+ unsigned long mmun_start; /* For mmu_notifiers */
|
|
|
+ unsigned long mmun_end; /* For mmu_notifiers */
|
|
|
|
|
|
addr = page_address_in_vma(page, vma);
|
|
|
if (addr == -EFAULT)
|
|
|
goto out;
|
|
|
|
|
|
BUG_ON(PageTransCompound(page));
|
|
|
+
|
|
|
+ mmun_start = addr;
|
|
|
+ mmun_end = addr + PAGE_SIZE;
|
|
|
+ mmu_notifier_invalidate_range_start(mm, mmun_start, mmun_end);
|
|
|
+
|
|
|
ptep = page_check_address(page, mm, addr, &ptl, 0);
|
|
|
if (!ptep)
|
|
|
- goto out;
|
|
|
+ goto out_mn;
|
|
|
|
|
|
if (pte_write(*ptep) || pte_dirty(*ptep)) {
|
|
|
pte_t entry;
|
|
@@ -752,6 +759,8 @@ static int write_protect_page(struct vm_area_struct *vma, struct page *page,
|
|
|
|
|
|
out_unlock:
|
|
|
pte_unmap_unlock(ptep, ptl);
|
|
|
+out_mn:
|
|
|
+ mmu_notifier_invalidate_range_end(mm, mmun_start, mmun_end);
|
|
|
out:
|
|
|
return err;
|
|
|
}
|
|
@@ -776,6 +785,8 @@ static int replace_page(struct vm_area_struct *vma, struct page *page,
|
|
|
spinlock_t *ptl;
|
|
|
unsigned long addr;
|
|
|
int err = -EFAULT;
|
|
|
+ unsigned long mmun_start; /* For mmu_notifiers */
|
|
|
+ unsigned long mmun_end; /* For mmu_notifiers */
|
|
|
|
|
|
addr = page_address_in_vma(page, vma);
|
|
|
if (addr == -EFAULT)
|
|
@@ -794,10 +805,14 @@ static int replace_page(struct vm_area_struct *vma, struct page *page,
|
|
|
if (!pmd_present(*pmd))
|
|
|
goto out;
|
|
|
|
|
|
+ mmun_start = addr;
|
|
|
+ mmun_end = addr + PAGE_SIZE;
|
|
|
+ mmu_notifier_invalidate_range_start(mm, mmun_start, mmun_end);
|
|
|
+
|
|
|
ptep = pte_offset_map_lock(mm, pmd, addr, &ptl);
|
|
|
if (!pte_same(*ptep, orig_pte)) {
|
|
|
pte_unmap_unlock(ptep, ptl);
|
|
|
- goto out;
|
|
|
+ goto out_mn;
|
|
|
}
|
|
|
|
|
|
get_page(kpage);
|
|
@@ -814,6 +829,8 @@ static int replace_page(struct vm_area_struct *vma, struct page *page,
|
|
|
|
|
|
pte_unmap_unlock(ptep, ptl);
|
|
|
err = 0;
|
|
|
+out_mn:
|
|
|
+ mmu_notifier_invalidate_range_end(mm, mmun_start, mmun_end);
|
|
|
out:
|
|
|
return err;
|
|
|
}
|