diff options
-rw-r--r-- | arch/powerpc/kvm/book3s_hv_rm_mmu.c | 2 | ||||
-rw-r--r-- | arch/powerpc/mm/fault.c | 5 | ||||
-rw-r--r-- | arch/powerpc/mm/pgtable.c | 11 | ||||
-rw-r--r-- | arch/powerpc/mm/pgtable_64.c | 3 | ||||
-rw-r--r-- | arch/x86/mm/gup.c | 4 | ||||
-rw-r--r-- | include/uapi/linux/mempolicy.h | 2 | ||||
-rw-r--r-- | mm/gup.c | 10 | ||||
-rw-r--r-- | mm/huge_memory.c | 16 | ||||
-rw-r--r-- | mm/memory.c | 4 | ||||
-rw-r--r-- | mm/mprotect.c | 38 | ||||
-rw-r--r-- | mm/pgtable-generic.c | 2 |
11 files changed, 40 insertions, 57 deletions
diff --git a/arch/powerpc/kvm/book3s_hv_rm_mmu.c b/arch/powerpc/kvm/book3s_hv_rm_mmu.c index 510bdfbc4073..625407e4d3b0 100644 --- a/arch/powerpc/kvm/book3s_hv_rm_mmu.c +++ b/arch/powerpc/kvm/book3s_hv_rm_mmu.c | |||
@@ -212,7 +212,7 @@ long kvmppc_do_h_enter(struct kvm *kvm, unsigned long flags, | |||
212 | /* Look up the Linux PTE for the backing page */ | 212 | /* Look up the Linux PTE for the backing page */ |
213 | pte_size = psize; | 213 | pte_size = psize; |
214 | pte = lookup_linux_pte_and_update(pgdir, hva, writing, &pte_size); | 214 | pte = lookup_linux_pte_and_update(pgdir, hva, writing, &pte_size); |
215 | if (pte_present(pte) && !pte_numa(pte)) { | 215 | if (pte_present(pte) && !pte_protnone(pte)) { |
216 | if (writing && !pte_write(pte)) | 216 | if (writing && !pte_write(pte)) |
217 | /* make the actual HPTE be read-only */ | 217 | /* make the actual HPTE be read-only */ |
218 | ptel = hpte_make_readonly(ptel); | 218 | ptel = hpte_make_readonly(ptel); |
diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c index 6154b0a2b063..f38327b95f76 100644 --- a/arch/powerpc/mm/fault.c +++ b/arch/powerpc/mm/fault.c | |||
@@ -398,8 +398,6 @@ good_area: | |||
398 | * processors use the same I/D cache coherency mechanism | 398 | * processors use the same I/D cache coherency mechanism |
399 | * as embedded. | 399 | * as embedded. |
400 | */ | 400 | */ |
401 | if (error_code & DSISR_PROTFAULT) | ||
402 | goto bad_area; | ||
403 | #endif /* CONFIG_PPC_STD_MMU */ | 401 | #endif /* CONFIG_PPC_STD_MMU */ |
404 | 402 | ||
405 | /* | 403 | /* |
@@ -423,9 +421,6 @@ good_area: | |||
423 | flags |= FAULT_FLAG_WRITE; | 421 | flags |= FAULT_FLAG_WRITE; |
424 | /* a read */ | 422 | /* a read */ |
425 | } else { | 423 | } else { |
426 | /* protection fault */ | ||
427 | if (error_code & 0x08000000) | ||
428 | goto bad_area; | ||
429 | if (!(vma->vm_flags & (VM_READ | VM_EXEC | VM_WRITE))) | 424 | if (!(vma->vm_flags & (VM_READ | VM_EXEC | VM_WRITE))) |
430 | goto bad_area; | 425 | goto bad_area; |
431 | } | 426 | } |
diff --git a/arch/powerpc/mm/pgtable.c b/arch/powerpc/mm/pgtable.c index c90e602677c9..83dfcb55ffef 100644 --- a/arch/powerpc/mm/pgtable.c +++ b/arch/powerpc/mm/pgtable.c | |||
@@ -172,9 +172,14 @@ static pte_t set_access_flags_filter(pte_t pte, struct vm_area_struct *vma, | |||
172 | void set_pte_at(struct mm_struct *mm, unsigned long addr, pte_t *ptep, | 172 | void set_pte_at(struct mm_struct *mm, unsigned long addr, pte_t *ptep, |
173 | pte_t pte) | 173 | pte_t pte) |
174 | { | 174 | { |
175 | #ifdef CONFIG_DEBUG_VM | 175 | /* |
176 | WARN_ON(pte_val(*ptep) & _PAGE_PRESENT); | 176 | * When handling numa faults, we already have the pte marked |
177 | #endif | 177 | * _PAGE_PRESENT, but we can be sure that it is not in hpte. |
178 | * Hence we can use set_pte_at for them. | ||
179 | */ | ||
180 | VM_WARN_ON((pte_val(*ptep) & (_PAGE_PRESENT | _PAGE_USER)) == | ||
181 | (_PAGE_PRESENT | _PAGE_USER)); | ||
182 | |||
178 | /* Note: mm->context.id might not yet have been assigned as | 183 | /* Note: mm->context.id might not yet have been assigned as |
179 | * this context might not have been activated yet when this | 184 | * this context might not have been activated yet when this |
180 | * is called. | 185 | * is called. |
diff --git a/arch/powerpc/mm/pgtable_64.c b/arch/powerpc/mm/pgtable_64.c index 4fe5f64cc179..91bb8836825a 100644 --- a/arch/powerpc/mm/pgtable_64.c +++ b/arch/powerpc/mm/pgtable_64.c | |||
@@ -718,7 +718,8 @@ void set_pmd_at(struct mm_struct *mm, unsigned long addr, | |||
718 | pmd_t *pmdp, pmd_t pmd) | 718 | pmd_t *pmdp, pmd_t pmd) |
719 | { | 719 | { |
720 | #ifdef CONFIG_DEBUG_VM | 720 | #ifdef CONFIG_DEBUG_VM |
721 | WARN_ON(pmd_val(*pmdp) & _PAGE_PRESENT); | 721 | WARN_ON((pmd_val(*pmdp) & (_PAGE_PRESENT | _PAGE_USER)) == |
722 | (_PAGE_PRESENT | _PAGE_USER)); | ||
722 | assert_spin_locked(&mm->page_table_lock); | 723 | assert_spin_locked(&mm->page_table_lock); |
723 | WARN_ON(!pmd_trans_huge(pmd)); | 724 | WARN_ON(!pmd_trans_huge(pmd)); |
724 | #endif | 725 | #endif |
diff --git a/arch/x86/mm/gup.c b/arch/x86/mm/gup.c index 89df70e0caa6..81bf3d2af3eb 100644 --- a/arch/x86/mm/gup.c +++ b/arch/x86/mm/gup.c | |||
@@ -84,7 +84,7 @@ static noinline int gup_pte_range(pmd_t pmd, unsigned long addr, | |||
84 | struct page *page; | 84 | struct page *page; |
85 | 85 | ||
86 | /* Similar to the PMD case, NUMA hinting must take slow path */ | 86 | /* Similar to the PMD case, NUMA hinting must take slow path */ |
87 | if (pte_numa(pte)) { | 87 | if (pte_protnone(pte)) { |
88 | pte_unmap(ptep); | 88 | pte_unmap(ptep); |
89 | return 0; | 89 | return 0; |
90 | } | 90 | } |
@@ -178,7 +178,7 @@ static int gup_pmd_range(pud_t pud, unsigned long addr, unsigned long end, | |||
178 | * slowpath for accounting purposes and so that they | 178 | * slowpath for accounting purposes and so that they |
179 | * can be serialised against THP migration. | 179 | * can be serialised against THP migration. |
180 | */ | 180 | */ |
181 | if (pmd_numa(pmd)) | 181 | if (pmd_protnone(pmd)) |
182 | return 0; | 182 | return 0; |
183 | if (!gup_huge_pmd(pmd, addr, next, write, pages, nr)) | 183 | if (!gup_huge_pmd(pmd, addr, next, write, pages, nr)) |
184 | return 0; | 184 | return 0; |
diff --git a/include/uapi/linux/mempolicy.h b/include/uapi/linux/mempolicy.h index 0d11c3dcd3a1..9cd8b21dddbe 100644 --- a/include/uapi/linux/mempolicy.h +++ b/include/uapi/linux/mempolicy.h | |||
@@ -67,7 +67,7 @@ enum mpol_rebind_step { | |||
67 | #define MPOL_F_LOCAL (1 << 1) /* preferred local allocation */ | 67 | #define MPOL_F_LOCAL (1 << 1) /* preferred local allocation */ |
68 | #define MPOL_F_REBINDING (1 << 2) /* identify policies in rebinding */ | 68 | #define MPOL_F_REBINDING (1 << 2) /* identify policies in rebinding */ |
69 | #define MPOL_F_MOF (1 << 3) /* this policy wants migrate on fault */ | 69 | #define MPOL_F_MOF (1 << 3) /* this policy wants migrate on fault */ |
70 | #define MPOL_F_MORON (1 << 4) /* Migrate On pte_numa Reference On Node */ | 70 | #define MPOL_F_MORON (1 << 4) /* Migrate On protnone Reference On Node */ |
71 | 71 | ||
72 | 72 | ||
73 | #endif /* _UAPI_LINUX_MEMPOLICY_H */ | 73 | #endif /* _UAPI_LINUX_MEMPOLICY_H */ |
@@ -64,7 +64,7 @@ retry: | |||
64 | migration_entry_wait(mm, pmd, address); | 64 | migration_entry_wait(mm, pmd, address); |
65 | goto retry; | 65 | goto retry; |
66 | } | 66 | } |
67 | if ((flags & FOLL_NUMA) && pte_numa(pte)) | 67 | if ((flags & FOLL_NUMA) && pte_protnone(pte)) |
68 | goto no_page; | 68 | goto no_page; |
69 | if ((flags & FOLL_WRITE) && !pte_write(pte)) { | 69 | if ((flags & FOLL_WRITE) && !pte_write(pte)) { |
70 | pte_unmap_unlock(ptep, ptl); | 70 | pte_unmap_unlock(ptep, ptl); |
@@ -184,7 +184,7 @@ struct page *follow_page_mask(struct vm_area_struct *vma, | |||
184 | return page; | 184 | return page; |
185 | return no_page_table(vma, flags); | 185 | return no_page_table(vma, flags); |
186 | } | 186 | } |
187 | if ((flags & FOLL_NUMA) && pmd_numa(*pmd)) | 187 | if ((flags & FOLL_NUMA) && pmd_protnone(*pmd)) |
188 | return no_page_table(vma, flags); | 188 | return no_page_table(vma, flags); |
189 | if (pmd_trans_huge(*pmd)) { | 189 | if (pmd_trans_huge(*pmd)) { |
190 | if (flags & FOLL_SPLIT) { | 190 | if (flags & FOLL_SPLIT) { |
@@ -906,10 +906,10 @@ static int gup_pte_range(pmd_t pmd, unsigned long addr, unsigned long end, | |||
906 | 906 | ||
907 | /* | 907 | /* |
908 | * Similar to the PMD case below, NUMA hinting must take slow | 908 | * Similar to the PMD case below, NUMA hinting must take slow |
909 | * path | 909 | * path using the pte_protnone check. |
910 | */ | 910 | */ |
911 | if (!pte_present(pte) || pte_special(pte) || | 911 | if (!pte_present(pte) || pte_special(pte) || |
912 | pte_numa(pte) || (write && !pte_write(pte))) | 912 | pte_protnone(pte) || (write && !pte_write(pte))) |
913 | goto pte_unmap; | 913 | goto pte_unmap; |
914 | 914 | ||
915 | VM_BUG_ON(!pfn_valid(pte_pfn(pte))); | 915 | VM_BUG_ON(!pfn_valid(pte_pfn(pte))); |
@@ -1104,7 +1104,7 @@ static int gup_pmd_range(pud_t pud, unsigned long addr, unsigned long end, | |||
1104 | * slowpath for accounting purposes and so that they | 1104 | * slowpath for accounting purposes and so that they |
1105 | * can be serialised against THP migration. | 1105 | * can be serialised against THP migration. |
1106 | */ | 1106 | */ |
1107 | if (pmd_numa(pmd)) | 1107 | if (pmd_protnone(pmd)) |
1108 | return 0; | 1108 | return 0; |
1109 | 1109 | ||
1110 | if (!gup_huge_pmd(pmd, pmdp, addr, next, write, | 1110 | if (!gup_huge_pmd(pmd, pmdp, addr, next, write, |
diff --git a/mm/huge_memory.c b/mm/huge_memory.c index c6921362c5fc..915941c45169 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c | |||
@@ -1211,7 +1211,7 @@ struct page *follow_trans_huge_pmd(struct vm_area_struct *vma, | |||
1211 | return ERR_PTR(-EFAULT); | 1211 | return ERR_PTR(-EFAULT); |
1212 | 1212 | ||
1213 | /* Full NUMA hinting faults to serialise migration in fault paths */ | 1213 | /* Full NUMA hinting faults to serialise migration in fault paths */ |
1214 | if ((flags & FOLL_NUMA) && pmd_numa(*pmd)) | 1214 | if ((flags & FOLL_NUMA) && pmd_protnone(*pmd)) |
1215 | goto out; | 1215 | goto out; |
1216 | 1216 | ||
1217 | page = pmd_page(*pmd); | 1217 | page = pmd_page(*pmd); |
@@ -1342,7 +1342,7 @@ int do_huge_pmd_numa_page(struct mm_struct *mm, struct vm_area_struct *vma, | |||
1342 | 1342 | ||
1343 | /* | 1343 | /* |
1344 | * Migrate the THP to the requested node, returns with page unlocked | 1344 | * Migrate the THP to the requested node, returns with page unlocked |
1345 | * and pmd_numa cleared. | 1345 | * and access rights restored. |
1346 | */ | 1346 | */ |
1347 | spin_unlock(ptl); | 1347 | spin_unlock(ptl); |
1348 | migrated = migrate_misplaced_transhuge_page(mm, vma, | 1348 | migrated = migrate_misplaced_transhuge_page(mm, vma, |
@@ -1357,7 +1357,7 @@ clear_pmdnuma: | |||
1357 | BUG_ON(!PageLocked(page)); | 1357 | BUG_ON(!PageLocked(page)); |
1358 | pmd = pmd_mknonnuma(pmd); | 1358 | pmd = pmd_mknonnuma(pmd); |
1359 | set_pmd_at(mm, haddr, pmdp, pmd); | 1359 | set_pmd_at(mm, haddr, pmdp, pmd); |
1360 | VM_BUG_ON(pmd_numa(*pmdp)); | 1360 | VM_BUG_ON(pmd_protnone(*pmdp)); |
1361 | update_mmu_cache_pmd(vma, addr, pmdp); | 1361 | update_mmu_cache_pmd(vma, addr, pmdp); |
1362 | unlock_page(page); | 1362 | unlock_page(page); |
1363 | out_unlock: | 1363 | out_unlock: |
@@ -1483,7 +1483,7 @@ int change_huge_pmd(struct vm_area_struct *vma, pmd_t *pmd, | |||
1483 | ret = 1; | 1483 | ret = 1; |
1484 | if (!prot_numa) { | 1484 | if (!prot_numa) { |
1485 | entry = pmdp_get_and_clear_notify(mm, addr, pmd); | 1485 | entry = pmdp_get_and_clear_notify(mm, addr, pmd); |
1486 | if (pmd_numa(entry)) | 1486 | if (pmd_protnone(entry)) |
1487 | entry = pmd_mknonnuma(entry); | 1487 | entry = pmd_mknonnuma(entry); |
1488 | entry = pmd_modify(entry, newprot); | 1488 | entry = pmd_modify(entry, newprot); |
1489 | ret = HPAGE_PMD_NR; | 1489 | ret = HPAGE_PMD_NR; |
@@ -1499,7 +1499,7 @@ int change_huge_pmd(struct vm_area_struct *vma, pmd_t *pmd, | |||
1499 | * local vs remote hits on the zero page. | 1499 | * local vs remote hits on the zero page. |
1500 | */ | 1500 | */ |
1501 | if (!is_huge_zero_page(page) && | 1501 | if (!is_huge_zero_page(page) && |
1502 | !pmd_numa(*pmd)) { | 1502 | !pmd_protnone(*pmd)) { |
1503 | pmdp_set_numa(mm, addr, pmd); | 1503 | pmdp_set_numa(mm, addr, pmd); |
1504 | ret = HPAGE_PMD_NR; | 1504 | ret = HPAGE_PMD_NR; |
1505 | } | 1505 | } |
@@ -1767,9 +1767,9 @@ static int __split_huge_page_map(struct page *page, | |||
1767 | pte_t *pte, entry; | 1767 | pte_t *pte, entry; |
1768 | BUG_ON(PageCompound(page+i)); | 1768 | BUG_ON(PageCompound(page+i)); |
1769 | /* | 1769 | /* |
1770 | * Note that pmd_numa is not transferred deliberately | 1770 | * Note that NUMA hinting access restrictions are not |
1771 | * to avoid any possibility that pte_numa leaks to | 1771 | * transferred to avoid any possibility of altering |
1772 | * a PROT_NONE VMA by accident. | 1772 | * permissions across VMAs. |
1773 | */ | 1773 | */ |
1774 | entry = mk_pte(page + i, vma->vm_page_prot); | 1774 | entry = mk_pte(page + i, vma->vm_page_prot); |
1775 | entry = maybe_mkwrite(pte_mkdirty(entry), vma); | 1775 | entry = maybe_mkwrite(pte_mkdirty(entry), vma); |
diff --git a/mm/memory.c b/mm/memory.c index bbe6a73a899d..92e6a6299e86 100644 --- a/mm/memory.c +++ b/mm/memory.c | |||
@@ -3124,7 +3124,7 @@ static int handle_pte_fault(struct mm_struct *mm, | |||
3124 | pte, pmd, flags, entry); | 3124 | pte, pmd, flags, entry); |
3125 | } | 3125 | } |
3126 | 3126 | ||
3127 | if (pte_numa(entry)) | 3127 | if (pte_protnone(entry)) |
3128 | return do_numa_page(mm, vma, address, entry, pte, pmd); | 3128 | return do_numa_page(mm, vma, address, entry, pte, pmd); |
3129 | 3129 | ||
3130 | ptl = pte_lockptr(mm, pmd); | 3130 | ptl = pte_lockptr(mm, pmd); |
@@ -3202,7 +3202,7 @@ static int __handle_mm_fault(struct mm_struct *mm, struct vm_area_struct *vma, | |||
3202 | if (pmd_trans_splitting(orig_pmd)) | 3202 | if (pmd_trans_splitting(orig_pmd)) |
3203 | return 0; | 3203 | return 0; |
3204 | 3204 | ||
3205 | if (pmd_numa(orig_pmd)) | 3205 | if (pmd_protnone(orig_pmd)) |
3206 | return do_huge_pmd_numa_page(mm, vma, address, | 3206 | return do_huge_pmd_numa_page(mm, vma, address, |
3207 | orig_pmd, pmd); | 3207 | orig_pmd, pmd); |
3208 | 3208 | ||
diff --git a/mm/mprotect.c b/mm/mprotect.c index 33121662f08b..44ffa698484d 100644 --- a/mm/mprotect.c +++ b/mm/mprotect.c | |||
@@ -75,36 +75,18 @@ static unsigned long change_pte_range(struct vm_area_struct *vma, pmd_t *pmd, | |||
75 | oldpte = *pte; | 75 | oldpte = *pte; |
76 | if (pte_present(oldpte)) { | 76 | if (pte_present(oldpte)) { |
77 | pte_t ptent; | 77 | pte_t ptent; |
78 | bool updated = false; | ||
79 | 78 | ||
80 | if (!prot_numa) { | 79 | ptent = ptep_modify_prot_start(mm, addr, pte); |
81 | ptent = ptep_modify_prot_start(mm, addr, pte); | 80 | ptent = pte_modify(ptent, newprot); |
82 | if (pte_numa(ptent)) | 81 | |
83 | ptent = pte_mknonnuma(ptent); | 82 | /* Avoid taking write faults for known dirty pages */ |
84 | ptent = pte_modify(ptent, newprot); | 83 | if (dirty_accountable && pte_dirty(ptent) && |
85 | /* | 84 | (pte_soft_dirty(ptent) || |
86 | * Avoid taking write faults for pages we | 85 | !(vma->vm_flags & VM_SOFTDIRTY))) { |
87 | * know to be dirty. | 86 | ptent = pte_mkwrite(ptent); |
88 | */ | ||
89 | if (dirty_accountable && pte_dirty(ptent) && | ||
90 | (pte_soft_dirty(ptent) || | ||
91 | !(vma->vm_flags & VM_SOFTDIRTY))) | ||
92 | ptent = pte_mkwrite(ptent); | ||
93 | ptep_modify_prot_commit(mm, addr, pte, ptent); | ||
94 | updated = true; | ||
95 | } else { | ||
96 | struct page *page; | ||
97 | |||
98 | page = vm_normal_page(vma, addr, oldpte); | ||
99 | if (page && !PageKsm(page)) { | ||
100 | if (!pte_numa(oldpte)) { | ||
101 | ptep_set_numa(mm, addr, pte); | ||
102 | updated = true; | ||
103 | } | ||
104 | } | ||
105 | } | 87 | } |
106 | if (updated) | 88 | ptep_modify_prot_commit(mm, addr, pte, ptent); |
107 | pages++; | 89 | pages++; |
108 | } else if (IS_ENABLED(CONFIG_MIGRATION)) { | 90 | } else if (IS_ENABLED(CONFIG_MIGRATION)) { |
109 | swp_entry_t entry = pte_to_swp_entry(oldpte); | 91 | swp_entry_t entry = pte_to_swp_entry(oldpte); |
110 | 92 | ||
diff --git a/mm/pgtable-generic.c b/mm/pgtable-generic.c index dfb79e028ecb..4b8ad760dde3 100644 --- a/mm/pgtable-generic.c +++ b/mm/pgtable-generic.c | |||
@@ -193,7 +193,7 @@ void pmdp_invalidate(struct vm_area_struct *vma, unsigned long address, | |||
193 | pmd_t *pmdp) | 193 | pmd_t *pmdp) |
194 | { | 194 | { |
195 | pmd_t entry = *pmdp; | 195 | pmd_t entry = *pmdp; |
196 | if (pmd_numa(entry)) | 196 | if (pmd_protnone(entry)) |
197 | entry = pmd_mknonnuma(entry); | 197 | entry = pmd_mknonnuma(entry); |
198 | set_pmd_at(vma->vm_mm, address, pmdp, pmd_mknotpresent(entry)); | 198 | set_pmd_at(vma->vm_mm, address, pmdp, pmd_mknotpresent(entry)); |
199 | flush_tlb_range(vma, address, address + HPAGE_PMD_SIZE); | 199 | flush_tlb_range(vma, address, address + HPAGE_PMD_SIZE); |