summaryrefslogtreecommitdiffstats
path: root/mm/pgtable-generic.c
diff options
context:
space:
mode:
authorVineet Gupta <vgupta@synopsys.com>2015-02-20 00:06:28 -0500
committerVineet Gupta <vgupta@synopsys.com>2015-10-17 08:18:20 -0400
commit12ebc1581ad114543ae822aa3a12f76072e2f902 (patch)
tree2e80b72284497b1a45f29f0970ce13332f6896e2 /mm/pgtable-generic.c
parentbd5e88ad72b26ebf7ecb231bc22ceecd6cbdb951 (diff)
mm,thp: introduce flush_pmd_tlb_range
ARCHes with special requirements for evicting THP backing TLB entries can implement this. Otherwise also, it can help optimize TLB flush in THP regime. stock flush_tlb_range() typically has optimization to nuke the entire TLB if flush span is greater than a certain threshhold, which will likely be true for a single huge page. Thus a single thp flush will invalidate the entrire TLB which is not desirable. e.g. see arch/arc: flush_pmd_tlb_range Acked-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com> Link: http://lkml.kernel.org/r/20151009100816.GC7873@node Signed-off-by: Vineet Gupta <vgupta@synopsys.com>
Diffstat (limited to 'mm/pgtable-generic.c')
-rw-r--r--mm/pgtable-generic.c26
1 files changed, 20 insertions, 6 deletions
diff --git a/mm/pgtable-generic.c b/mm/pgtable-generic.c
index c9c59bb75a17..7d3db0247983 100644
--- a/mm/pgtable-generic.c
+++ b/mm/pgtable-generic.c
@@ -84,6 +84,20 @@ pte_t ptep_clear_flush(struct vm_area_struct *vma, unsigned long address,
84 84
85#ifdef CONFIG_TRANSPARENT_HUGEPAGE 85#ifdef CONFIG_TRANSPARENT_HUGEPAGE
86 86
87#ifndef __HAVE_ARCH_FLUSH_PMD_TLB_RANGE
88
89/*
90 * ARCHes with special requirements for evicting THP backing TLB entries can
91 * implement this. Otherwise also, it can help optimize normal TLB flush in
92 * THP regime. stock flush_tlb_range() typically has optimization to nuke the
93 * entire TLB TLB if flush span is greater than a threshhold, which will
94 * likely be true for a single huge page. Thus a single thp flush will
95 * invalidate the entire TLB which is not desitable.
96 * e.g. see arch/arc: flush_pmd_tlb_range
97 */
98#define flush_pmd_tlb_range(vma, addr, end) flush_tlb_range(vma, addr, end)
99#endif
100
87#ifndef __HAVE_ARCH_PMDP_SET_ACCESS_FLAGS 101#ifndef __HAVE_ARCH_PMDP_SET_ACCESS_FLAGS
88int pmdp_set_access_flags(struct vm_area_struct *vma, 102int pmdp_set_access_flags(struct vm_area_struct *vma,
89 unsigned long address, pmd_t *pmdp, 103 unsigned long address, pmd_t *pmdp,
@@ -93,7 +107,7 @@ int pmdp_set_access_flags(struct vm_area_struct *vma,
93 VM_BUG_ON(address & ~HPAGE_PMD_MASK); 107 VM_BUG_ON(address & ~HPAGE_PMD_MASK);
94 if (changed) { 108 if (changed) {
95 set_pmd_at(vma->vm_mm, address, pmdp, entry); 109 set_pmd_at(vma->vm_mm, address, pmdp, entry);
96 flush_tlb_range(vma, address, address + HPAGE_PMD_SIZE); 110 flush_pmd_tlb_range(vma, address, address + HPAGE_PMD_SIZE);
97 } 111 }
98 return changed; 112 return changed;
99} 113}
@@ -107,7 +121,7 @@ int pmdp_clear_flush_young(struct vm_area_struct *vma,
107 VM_BUG_ON(address & ~HPAGE_PMD_MASK); 121 VM_BUG_ON(address & ~HPAGE_PMD_MASK);
108 young = pmdp_test_and_clear_young(vma, address, pmdp); 122 young = pmdp_test_and_clear_young(vma, address, pmdp);
109 if (young) 123 if (young)
110 flush_tlb_range(vma, address, address + HPAGE_PMD_SIZE); 124 flush_pmd_tlb_range(vma, address, address + HPAGE_PMD_SIZE);
111 return young; 125 return young;
112} 126}
113#endif 127#endif
@@ -120,7 +134,7 @@ pmd_t pmdp_huge_clear_flush(struct vm_area_struct *vma, unsigned long address,
120 VM_BUG_ON(address & ~HPAGE_PMD_MASK); 134 VM_BUG_ON(address & ~HPAGE_PMD_MASK);
121 VM_BUG_ON(!pmd_trans_huge(*pmdp)); 135 VM_BUG_ON(!pmd_trans_huge(*pmdp));
122 pmd = pmdp_huge_get_and_clear(vma->vm_mm, address, pmdp); 136 pmd = pmdp_huge_get_and_clear(vma->vm_mm, address, pmdp);
123 flush_tlb_range(vma, address, address + HPAGE_PMD_SIZE); 137 flush_pmd_tlb_range(vma, address, address + HPAGE_PMD_SIZE);
124 return pmd; 138 return pmd;
125} 139}
126#endif 140#endif
@@ -133,7 +147,7 @@ void pmdp_splitting_flush(struct vm_area_struct *vma, unsigned long address,
133 VM_BUG_ON(address & ~HPAGE_PMD_MASK); 147 VM_BUG_ON(address & ~HPAGE_PMD_MASK);
134 set_pmd_at(vma->vm_mm, address, pmdp, pmd); 148 set_pmd_at(vma->vm_mm, address, pmdp, pmd);
135 /* tlb flush only to serialize against gup-fast */ 149 /* tlb flush only to serialize against gup-fast */
136 flush_tlb_range(vma, address, address + HPAGE_PMD_SIZE); 150 flush_pmd_tlb_range(vma, address, address + HPAGE_PMD_SIZE);
137} 151}
138#endif 152#endif
139 153
@@ -179,7 +193,7 @@ void pmdp_invalidate(struct vm_area_struct *vma, unsigned long address,
179{ 193{
180 pmd_t entry = *pmdp; 194 pmd_t entry = *pmdp;
181 set_pmd_at(vma->vm_mm, address, pmdp, pmd_mknotpresent(entry)); 195 set_pmd_at(vma->vm_mm, address, pmdp, pmd_mknotpresent(entry));
182 flush_tlb_range(vma, address, address + HPAGE_PMD_SIZE); 196 flush_pmd_tlb_range(vma, address, address + HPAGE_PMD_SIZE);
183} 197}
184#endif 198#endif
185 199
@@ -196,7 +210,7 @@ pmd_t pmdp_collapse_flush(struct vm_area_struct *vma, unsigned long address,
196 VM_BUG_ON(address & ~HPAGE_PMD_MASK); 210 VM_BUG_ON(address & ~HPAGE_PMD_MASK);
197 VM_BUG_ON(pmd_trans_huge(*pmdp)); 211 VM_BUG_ON(pmd_trans_huge(*pmdp));
198 pmd = pmdp_huge_get_and_clear(vma->vm_mm, address, pmdp); 212 pmd = pmdp_huge_get_and_clear(vma->vm_mm, address, pmdp);
199 flush_tlb_range(vma, address, address + HPAGE_PMD_SIZE); 213 flush_pmd_tlb_range(vma, address, address + HPAGE_PMD_SIZE);
200 return pmd; 214 return pmd;
201} 215}
202#endif 216#endif