aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMel Gorman <mgorman@suse.de>2015-02-12 17:58:28 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2015-02-12 21:54:08 -0500
commit4d9424669946532be754a6e116618dcb58430cb4 (patch)
treeccebf7f5dbb8773bb774551d21cd95d0f30b6766
parent842915f56667f9eebd85932f08c79565148c26d6 (diff)
mm: convert p[te|md]_mknonnuma and remaining page table manipulations
With PROT_NONE, the traditional page table manipulation functions are sufficient. [andre.przywara@arm.com: fix compiler warning in pmdp_invalidate()] [akpm@linux-foundation.org: fix build with STRICT_MM_TYPECHECKS] Signed-off-by: Mel Gorman <mgorman@suse.de> Acked-by: Linus Torvalds <torvalds@linux-foundation.org> Acked-by: Aneesh Kumar <aneesh.kumar@linux.vnet.ibm.com> Tested-by: Sasha Levin <sasha.levin@oracle.com> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org> Cc: Dave Jones <davej@redhat.com> Cc: Hugh Dickins <hughd@google.com> Cc: Ingo Molnar <mingo@redhat.com> Cc: Kirill Shutemov <kirill.shutemov@linux.intel.com> Cc: Paul Mackerras <paulus@samba.org> Cc: Rik van Riel <riel@redhat.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--arch/arm/include/asm/pgtable-3level.h5
-rw-r--r--include/linux/huge_mm.h3
-rw-r--r--mm/huge_memory.c33
-rw-r--r--mm/memory.c10
-rw-r--r--mm/mempolicy.c2
-rw-r--r--mm/migrate.c2
-rw-r--r--mm/mprotect.c2
-rw-r--r--mm/pgtable-generic.c2
8 files changed, 21 insertions, 38 deletions
diff --git a/arch/arm/include/asm/pgtable-3level.h b/arch/arm/include/asm/pgtable-3level.h
index 18dbc82f85e5..423a5ac09d3a 100644
--- a/arch/arm/include/asm/pgtable-3level.h
+++ b/arch/arm/include/asm/pgtable-3level.h
@@ -257,7 +257,10 @@ PMD_BIT_FUNC(mkyoung, |= PMD_SECT_AF);
257#define mk_pmd(page,prot) pfn_pmd(page_to_pfn(page),prot) 257#define mk_pmd(page,prot) pfn_pmd(page_to_pfn(page),prot)
258 258
259/* represent a notpresent pmd by zero, this is used by pmdp_invalidate */ 259/* represent a notpresent pmd by zero, this is used by pmdp_invalidate */
260#define pmd_mknotpresent(pmd) (__pmd(0)) 260static inline pmd_t pmd_mknotpresent(pmd_t pmd)
261{
262 return __pmd(0);
263}
261 264
262static inline pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot) 265static inline pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot)
263{ 266{
diff --git a/include/linux/huge_mm.h b/include/linux/huge_mm.h
index f10b20f05159..062bd252e994 100644
--- a/include/linux/huge_mm.h
+++ b/include/linux/huge_mm.h
@@ -31,8 +31,7 @@ extern int move_huge_pmd(struct vm_area_struct *vma,
31 unsigned long new_addr, unsigned long old_end, 31 unsigned long new_addr, unsigned long old_end,
32 pmd_t *old_pmd, pmd_t *new_pmd); 32 pmd_t *old_pmd, pmd_t *new_pmd);
33extern int change_huge_pmd(struct vm_area_struct *vma, pmd_t *pmd, 33extern int change_huge_pmd(struct vm_area_struct *vma, pmd_t *pmd,
34 unsigned long addr, pgprot_t newprot, 34 unsigned long addr, pgprot_t newprot);
35 int prot_numa);
36 35
37enum transparent_hugepage_flag { 36enum transparent_hugepage_flag {
38 TRANSPARENT_HUGEPAGE_FLAG, 37 TRANSPARENT_HUGEPAGE_FLAG,
diff --git a/mm/huge_memory.c b/mm/huge_memory.c
index 915941c45169..cb9b3e847dac 100644
--- a/mm/huge_memory.c
+++ b/mm/huge_memory.c
@@ -1355,9 +1355,8 @@ int do_huge_pmd_numa_page(struct mm_struct *mm, struct vm_area_struct *vma,
1355 goto out; 1355 goto out;
1356clear_pmdnuma: 1356clear_pmdnuma:
1357 BUG_ON(!PageLocked(page)); 1357 BUG_ON(!PageLocked(page));
1358 pmd = pmd_mknonnuma(pmd); 1358 pmd = pmd_modify(pmd, vma->vm_page_prot);
1359 set_pmd_at(mm, haddr, pmdp, pmd); 1359 set_pmd_at(mm, haddr, pmdp, pmd);
1360 VM_BUG_ON(pmd_protnone(*pmdp));
1361 update_mmu_cache_pmd(vma, addr, pmdp); 1360 update_mmu_cache_pmd(vma, addr, pmdp);
1362 unlock_page(page); 1361 unlock_page(page);
1363out_unlock: 1362out_unlock:
@@ -1472,7 +1471,7 @@ out:
1472 * - HPAGE_PMD_NR is protections changed and TLB flush necessary 1471 * - HPAGE_PMD_NR is protections changed and TLB flush necessary
1473 */ 1472 */
1474int change_huge_pmd(struct vm_area_struct *vma, pmd_t *pmd, 1473int change_huge_pmd(struct vm_area_struct *vma, pmd_t *pmd,
1475 unsigned long addr, pgprot_t newprot, int prot_numa) 1474 unsigned long addr, pgprot_t newprot)
1476{ 1475{
1477 struct mm_struct *mm = vma->vm_mm; 1476 struct mm_struct *mm = vma->vm_mm;
1478 spinlock_t *ptl; 1477 spinlock_t *ptl;
@@ -1481,29 +1480,11 @@ int change_huge_pmd(struct vm_area_struct *vma, pmd_t *pmd,
1481 if (__pmd_trans_huge_lock(pmd, vma, &ptl) == 1) { 1480 if (__pmd_trans_huge_lock(pmd, vma, &ptl) == 1) {
1482 pmd_t entry; 1481 pmd_t entry;
1483 ret = 1; 1482 ret = 1;
1484 if (!prot_numa) { 1483 entry = pmdp_get_and_clear_notify(mm, addr, pmd);
1485 entry = pmdp_get_and_clear_notify(mm, addr, pmd); 1484 entry = pmd_modify(entry, newprot);
1486 if (pmd_protnone(entry)) 1485 ret = HPAGE_PMD_NR;
1487 entry = pmd_mknonnuma(entry); 1486 set_pmd_at(mm, addr, pmd, entry);
1488 entry = pmd_modify(entry, newprot); 1487 BUG_ON(pmd_write(entry));
1489 ret = HPAGE_PMD_NR;
1490 set_pmd_at(mm, addr, pmd, entry);
1491 BUG_ON(pmd_write(entry));
1492 } else {
1493 struct page *page = pmd_page(*pmd);
1494
1495 /*
1496 * Do not trap faults against the zero page. The
1497 * read-only data is likely to be read-cached on the
1498 * local CPU cache and it is less useful to know about
1499 * local vs remote hits on the zero page.
1500 */
1501 if (!is_huge_zero_page(page) &&
1502 !pmd_protnone(*pmd)) {
1503 pmdp_set_numa(mm, addr, pmd);
1504 ret = HPAGE_PMD_NR;
1505 }
1506 }
1507 spin_unlock(ptl); 1488 spin_unlock(ptl);
1508 } 1489 }
1509 1490
diff --git a/mm/memory.c b/mm/memory.c
index 92e6a6299e86..d7921760cf79 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -3018,9 +3018,9 @@ static int do_numa_page(struct mm_struct *mm, struct vm_area_struct *vma,
3018 * validation through pte_unmap_same(). It's of NUMA type but 3018 * validation through pte_unmap_same(). It's of NUMA type but
3019 * the pfn may be screwed if the read is non atomic. 3019 * the pfn may be screwed if the read is non atomic.
3020 * 3020 *
3021 * ptep_modify_prot_start is not called as this is clearing 3021 * We can safely just do a "set_pte_at()", because the old
3022 * the _PAGE_NUMA bit and it is not really expected that there 3022 * page table entry is not accessible, so there would be no
3023 * would be concurrent hardware modifications to the PTE. 3023 * concurrent hardware modifications to the PTE.
3024 */ 3024 */
3025 ptl = pte_lockptr(mm, pmd); 3025 ptl = pte_lockptr(mm, pmd);
3026 spin_lock(ptl); 3026 spin_lock(ptl);
@@ -3029,7 +3029,9 @@ static int do_numa_page(struct mm_struct *mm, struct vm_area_struct *vma,
3029 goto out; 3029 goto out;
3030 } 3030 }
3031 3031
3032 pte = pte_mknonnuma(pte); 3032 /* Make it present again */
3033 pte = pte_modify(pte, vma->vm_page_prot);
3034 pte = pte_mkyoung(pte);
3033 set_pte_at(mm, addr, ptep, pte); 3035 set_pte_at(mm, addr, ptep, pte);
3034 update_mmu_cache(vma, addr, ptep); 3036 update_mmu_cache(vma, addr, ptep);
3035 3037
diff --git a/mm/mempolicy.c b/mm/mempolicy.c
index f1bd23803576..c75f4dcec808 100644
--- a/mm/mempolicy.c
+++ b/mm/mempolicy.c
@@ -569,7 +569,7 @@ unsigned long change_prot_numa(struct vm_area_struct *vma,
569{ 569{
570 int nr_updated; 570 int nr_updated;
571 571
572 nr_updated = change_protection(vma, addr, end, vma->vm_page_prot, 0, 1); 572 nr_updated = change_protection(vma, addr, end, PAGE_NONE, 0, 1);
573 if (nr_updated) 573 if (nr_updated)
574 count_vm_numa_events(NUMA_PTE_UPDATES, nr_updated); 574 count_vm_numa_events(NUMA_PTE_UPDATES, nr_updated);
575 575
diff --git a/mm/migrate.c b/mm/migrate.c
index 5e8f03a8de2a..85e042686031 100644
--- a/mm/migrate.c
+++ b/mm/migrate.c
@@ -1847,7 +1847,7 @@ out_fail:
1847out_dropref: 1847out_dropref:
1848 ptl = pmd_lock(mm, pmd); 1848 ptl = pmd_lock(mm, pmd);
1849 if (pmd_same(*pmd, entry)) { 1849 if (pmd_same(*pmd, entry)) {
1850 entry = pmd_mknonnuma(entry); 1850 entry = pmd_modify(entry, vma->vm_page_prot);
1851 set_pmd_at(mm, mmun_start, pmd, entry); 1851 set_pmd_at(mm, mmun_start, pmd, entry);
1852 update_mmu_cache_pmd(vma, address, &entry); 1852 update_mmu_cache_pmd(vma, address, &entry);
1853 } 1853 }
diff --git a/mm/mprotect.c b/mm/mprotect.c
index 44ffa698484d..76824d73380d 100644
--- a/mm/mprotect.c
+++ b/mm/mprotect.c
@@ -142,7 +142,7 @@ static inline unsigned long change_pmd_range(struct vm_area_struct *vma,
142 split_huge_page_pmd(vma, addr, pmd); 142 split_huge_page_pmd(vma, addr, pmd);
143 else { 143 else {
144 int nr_ptes = change_huge_pmd(vma, pmd, addr, 144 int nr_ptes = change_huge_pmd(vma, pmd, addr,
145 newprot, prot_numa); 145 newprot);
146 146
147 if (nr_ptes) { 147 if (nr_ptes) {
148 if (nr_ptes == HPAGE_PMD_NR) { 148 if (nr_ptes == HPAGE_PMD_NR) {
diff --git a/mm/pgtable-generic.c b/mm/pgtable-generic.c
index 4b8ad760dde3..c25f94b33811 100644
--- a/mm/pgtable-generic.c
+++ b/mm/pgtable-generic.c
@@ -193,8 +193,6 @@ 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_protnone(entry))
197 entry = pmd_mknonnuma(entry);
198 set_pmd_at(vma->vm_mm, address, pmdp, pmd_mknotpresent(entry)); 196 set_pmd_at(vma->vm_mm, address, pmdp, pmd_mknotpresent(entry));
199 flush_tlb_range(vma, address, address + HPAGE_PMD_SIZE); 197 flush_tlb_range(vma, address, address + HPAGE_PMD_SIZE);
200} 198}