aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/powerpc/kvm/book3s_hv_rm_mmu.c2
-rw-r--r--arch/powerpc/mm/fault.c5
-rw-r--r--arch/powerpc/mm/pgtable.c11
-rw-r--r--arch/powerpc/mm/pgtable_64.c3
-rw-r--r--arch/x86/mm/gup.c4
-rw-r--r--include/uapi/linux/mempolicy.h2
-rw-r--r--mm/gup.c10
-rw-r--r--mm/huge_memory.c16
-rw-r--r--mm/memory.c4
-rw-r--r--mm/mprotect.c38
-rw-r--r--mm/pgtable-generic.c2
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,
172void set_pte_at(struct mm_struct *mm, unsigned long addr, pte_t *ptep, 172void 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 */
diff --git a/mm/gup.c b/mm/gup.c
index c2da1163986a..51bf0b06ca7b 100644
--- a/mm/gup.c
+++ b/mm/gup.c
@@ -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);
1363out_unlock: 1363out_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);