|
@@ -2695,7 +2695,7 @@ static void __split_huge_zero_page_pmd(struct vm_area_struct *vma,
|
|
}
|
|
}
|
|
|
|
|
|
static void __split_huge_pmd_locked(struct vm_area_struct *vma, pmd_t *pmd,
|
|
static void __split_huge_pmd_locked(struct vm_area_struct *vma, pmd_t *pmd,
|
|
- unsigned long haddr)
|
|
|
|
|
|
+ unsigned long haddr, bool freeze)
|
|
{
|
|
{
|
|
struct mm_struct *mm = vma->vm_mm;
|
|
struct mm_struct *mm = vma->vm_mm;
|
|
struct page *page;
|
|
struct page *page;
|
|
@@ -2739,12 +2739,18 @@ static void __split_huge_pmd_locked(struct vm_area_struct *vma, pmd_t *pmd,
|
|
* transferred to avoid any possibility of altering
|
|
* transferred to avoid any possibility of altering
|
|
* permissions across VMAs.
|
|
* permissions across VMAs.
|
|
*/
|
|
*/
|
|
- entry = mk_pte(page + i, vma->vm_page_prot);
|
|
|
|
- entry = maybe_mkwrite(pte_mkdirty(entry), vma);
|
|
|
|
- if (!write)
|
|
|
|
- entry = pte_wrprotect(entry);
|
|
|
|
- if (!young)
|
|
|
|
- entry = pte_mkold(entry);
|
|
|
|
|
|
+ if (freeze) {
|
|
|
|
+ swp_entry_t swp_entry;
|
|
|
|
+ swp_entry = make_migration_entry(page + i, write);
|
|
|
|
+ entry = swp_entry_to_pte(swp_entry);
|
|
|
|
+ } else {
|
|
|
|
+ entry = mk_pte(page + i, vma->vm_page_prot);
|
|
|
|
+ entry = maybe_mkwrite(pte_mkdirty(entry), vma);
|
|
|
|
+ if (!write)
|
|
|
|
+ entry = pte_wrprotect(entry);
|
|
|
|
+ if (!young)
|
|
|
|
+ entry = pte_mkold(entry);
|
|
|
|
+ }
|
|
pte = pte_offset_map(&_pmd, haddr);
|
|
pte = pte_offset_map(&_pmd, haddr);
|
|
BUG_ON(!pte_none(*pte));
|
|
BUG_ON(!pte_none(*pte));
|
|
set_pte_at(mm, haddr, pte, entry);
|
|
set_pte_at(mm, haddr, pte, entry);
|
|
@@ -2785,7 +2791,7 @@ void __split_huge_pmd(struct vm_area_struct *vma, pmd_t *pmd,
|
|
mmu_notifier_invalidate_range_start(mm, haddr, haddr + HPAGE_PMD_SIZE);
|
|
mmu_notifier_invalidate_range_start(mm, haddr, haddr + HPAGE_PMD_SIZE);
|
|
ptl = pmd_lock(mm, pmd);
|
|
ptl = pmd_lock(mm, pmd);
|
|
if (likely(pmd_trans_huge(*pmd)))
|
|
if (likely(pmd_trans_huge(*pmd)))
|
|
- __split_huge_pmd_locked(vma, pmd, haddr);
|
|
|
|
|
|
+ __split_huge_pmd_locked(vma, pmd, haddr, false);
|
|
spin_unlock(ptl);
|
|
spin_unlock(ptl);
|
|
mmu_notifier_invalidate_range_end(mm, haddr, haddr + HPAGE_PMD_SIZE);
|
|
mmu_notifier_invalidate_range_end(mm, haddr, haddr + HPAGE_PMD_SIZE);
|
|
}
|
|
}
|