aboutsummaryrefslogtreecommitdiffstats
path: root/include/asm-generic/pgtable.h
diff options
context:
space:
mode:
authorMatthew Wilcox <willy@linux.intel.com>2017-02-24 17:57:02 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2017-02-24 20:46:54 -0500
commita00cc7d9dd93d66a3fb83fc52aa57a4bec51c517 (patch)
tree54d78e89c63e519cb9e00fdab9efbf3189ef2f5e /include/asm-generic/pgtable.h
parenta2d581675d485eb7188f521f36efc114639a3096 (diff)
mm, x86: add support for PUD-sized transparent hugepages
The current transparent hugepage code only supports PMDs. This patch adds support for transparent use of PUDs with DAX. It does not include support for anonymous pages. x86 support code also added. Most of this patch simply parallels the work that was done for huge PMDs. The only major difference is how the new ->pud_entry method in mm_walk works. The ->pmd_entry method replaces the ->pte_entry method, whereas the ->pud_entry method works along with either ->pmd_entry or ->pte_entry. The pagewalk code takes care of locking the PUD before calling ->pud_walk, so handlers do not need to worry whether the PUD is stable. [dave.jiang@intel.com: fix SMP x86 32bit build for native_pud_clear()] Link: http://lkml.kernel.org/r/148719066814.31111.3239231168815337012.stgit@djiang5-desk3.ch.intel.com [dave.jiang@intel.com: native_pud_clear missing on i386 build] Link: http://lkml.kernel.org/r/148640375195.69754.3315433724330910314.stgit@djiang5-desk3.ch.intel.com Link: http://lkml.kernel.org/r/148545059381.17912.8602162635537598445.stgit@djiang5-desk3.ch.intel.com Signed-off-by: Matthew Wilcox <mawilcox@microsoft.com> Signed-off-by: Dave Jiang <dave.jiang@intel.com> Tested-by: Alexander Kapshuk <alexander.kapshuk@gmail.com> Cc: Dave Hansen <dave.hansen@linux.intel.com> Cc: Vlastimil Babka <vbabka@suse.cz> Cc: Jan Kara <jack@suse.com> Cc: Dan Williams <dan.j.williams@intel.com> Cc: Ross Zwisler <ross.zwisler@linux.intel.com> Cc: Kirill A. Shutemov <kirill.shutemov@linux.intel.com> Cc: Nilesh Choudhury <nilesh.choudhury@oracle.com> Cc: Ingo Molnar <mingo@elte.hu> Cc: "H. Peter Anvin" <hpa@zytor.com> Cc: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'include/asm-generic/pgtable.h')
-rw-r--r--include/asm-generic/pgtable.h80
1 files changed, 76 insertions, 4 deletions
diff --git a/include/asm-generic/pgtable.h b/include/asm-generic/pgtable.h
index 18af2bcefe6a..a0aba0f9c57b 100644
--- a/include/asm-generic/pgtable.h
+++ b/include/asm-generic/pgtable.h
@@ -36,6 +36,9 @@ extern int ptep_set_access_flags(struct vm_area_struct *vma,
36extern int pmdp_set_access_flags(struct vm_area_struct *vma, 36extern int pmdp_set_access_flags(struct vm_area_struct *vma,
37 unsigned long address, pmd_t *pmdp, 37 unsigned long address, pmd_t *pmdp,
38 pmd_t entry, int dirty); 38 pmd_t entry, int dirty);
39extern int pudp_set_access_flags(struct vm_area_struct *vma,
40 unsigned long address, pud_t *pudp,
41 pud_t entry, int dirty);
39#else 42#else
40static inline int pmdp_set_access_flags(struct vm_area_struct *vma, 43static inline int pmdp_set_access_flags(struct vm_area_struct *vma,
41 unsigned long address, pmd_t *pmdp, 44 unsigned long address, pmd_t *pmdp,
@@ -44,6 +47,13 @@ static inline int pmdp_set_access_flags(struct vm_area_struct *vma,
44 BUILD_BUG(); 47 BUILD_BUG();
45 return 0; 48 return 0;
46} 49}
50static inline int pudp_set_access_flags(struct vm_area_struct *vma,
51 unsigned long address, pud_t *pudp,
52 pud_t entry, int dirty)
53{
54 BUILD_BUG();
55 return 0;
56}
47#endif /* CONFIG_TRANSPARENT_HUGEPAGE */ 57#endif /* CONFIG_TRANSPARENT_HUGEPAGE */
48#endif 58#endif
49 59
@@ -121,8 +131,8 @@ static inline pte_t ptep_get_and_clear(struct mm_struct *mm,
121} 131}
122#endif 132#endif
123 133
124#ifndef __HAVE_ARCH_PMDP_HUGE_GET_AND_CLEAR
125#ifdef CONFIG_TRANSPARENT_HUGEPAGE 134#ifdef CONFIG_TRANSPARENT_HUGEPAGE
135#ifndef __HAVE_ARCH_PMDP_HUGE_GET_AND_CLEAR
126static inline pmd_t pmdp_huge_get_and_clear(struct mm_struct *mm, 136static inline pmd_t pmdp_huge_get_and_clear(struct mm_struct *mm,
127 unsigned long address, 137 unsigned long address,
128 pmd_t *pmdp) 138 pmd_t *pmdp)
@@ -131,20 +141,40 @@ static inline pmd_t pmdp_huge_get_and_clear(struct mm_struct *mm,
131 pmd_clear(pmdp); 141 pmd_clear(pmdp);
132 return pmd; 142 return pmd;
133} 143}
144#endif /* __HAVE_ARCH_PMDP_HUGE_GET_AND_CLEAR */
145#ifndef __HAVE_ARCH_PUDP_HUGE_GET_AND_CLEAR
146static inline pud_t pudp_huge_get_and_clear(struct mm_struct *mm,
147 unsigned long address,
148 pud_t *pudp)
149{
150 pud_t pud = *pudp;
151
152 pud_clear(pudp);
153 return pud;
154}
155#endif /* __HAVE_ARCH_PUDP_HUGE_GET_AND_CLEAR */
134#endif /* CONFIG_TRANSPARENT_HUGEPAGE */ 156#endif /* CONFIG_TRANSPARENT_HUGEPAGE */
135#endif
136 157
137#ifndef __HAVE_ARCH_PMDP_HUGE_GET_AND_CLEAR_FULL
138#ifdef CONFIG_TRANSPARENT_HUGEPAGE 158#ifdef CONFIG_TRANSPARENT_HUGEPAGE
159#ifndef __HAVE_ARCH_PMDP_HUGE_GET_AND_CLEAR_FULL
139static inline pmd_t pmdp_huge_get_and_clear_full(struct mm_struct *mm, 160static inline pmd_t pmdp_huge_get_and_clear_full(struct mm_struct *mm,
140 unsigned long address, pmd_t *pmdp, 161 unsigned long address, pmd_t *pmdp,
141 int full) 162 int full)
142{ 163{
143 return pmdp_huge_get_and_clear(mm, address, pmdp); 164 return pmdp_huge_get_and_clear(mm, address, pmdp);
144} 165}
145#endif /* CONFIG_TRANSPARENT_HUGEPAGE */
146#endif 166#endif
147 167
168#ifndef __HAVE_ARCH_PUDP_HUGE_GET_AND_CLEAR_FULL
169static inline pud_t pudp_huge_get_and_clear_full(struct mm_struct *mm,
170 unsigned long address, pud_t *pudp,
171 int full)
172{
173 return pudp_huge_get_and_clear(mm, address, pudp);
174}
175#endif
176#endif /* CONFIG_TRANSPARENT_HUGEPAGE */
177
148#ifndef __HAVE_ARCH_PTEP_GET_AND_CLEAR_FULL 178#ifndef __HAVE_ARCH_PTEP_GET_AND_CLEAR_FULL
149static inline pte_t ptep_get_and_clear_full(struct mm_struct *mm, 179static inline pte_t ptep_get_and_clear_full(struct mm_struct *mm,
150 unsigned long address, pte_t *ptep, 180 unsigned long address, pte_t *ptep,
@@ -181,6 +211,9 @@ extern pte_t ptep_clear_flush(struct vm_area_struct *vma,
181extern pmd_t pmdp_huge_clear_flush(struct vm_area_struct *vma, 211extern pmd_t pmdp_huge_clear_flush(struct vm_area_struct *vma,
182 unsigned long address, 212 unsigned long address,
183 pmd_t *pmdp); 213 pmd_t *pmdp);
214extern pud_t pudp_huge_clear_flush(struct vm_area_struct *vma,
215 unsigned long address,
216 pud_t *pudp);
184#endif 217#endif
185 218
186#ifndef __HAVE_ARCH_PTEP_SET_WRPROTECT 219#ifndef __HAVE_ARCH_PTEP_SET_WRPROTECT
@@ -208,6 +241,23 @@ static inline void pmdp_set_wrprotect(struct mm_struct *mm,
208} 241}
209#endif /* CONFIG_TRANSPARENT_HUGEPAGE */ 242#endif /* CONFIG_TRANSPARENT_HUGEPAGE */
210#endif 243#endif
244#ifndef __HAVE_ARCH_PUDP_SET_WRPROTECT
245#ifdef CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD
246static inline void pudp_set_wrprotect(struct mm_struct *mm,
247 unsigned long address, pud_t *pudp)
248{
249 pud_t old_pud = *pudp;
250
251 set_pud_at(mm, address, pudp, pud_wrprotect(old_pud));
252}
253#else
254static inline void pudp_set_wrprotect(struct mm_struct *mm,
255 unsigned long address, pud_t *pudp)
256{
257 BUILD_BUG();
258}
259#endif /* CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD */
260#endif
211 261
212#ifndef pmdp_collapse_flush 262#ifndef pmdp_collapse_flush
213#ifdef CONFIG_TRANSPARENT_HUGEPAGE 263#ifdef CONFIG_TRANSPARENT_HUGEPAGE
@@ -273,12 +323,23 @@ static inline int pmd_same(pmd_t pmd_a, pmd_t pmd_b)
273{ 323{
274 return pmd_val(pmd_a) == pmd_val(pmd_b); 324 return pmd_val(pmd_a) == pmd_val(pmd_b);
275} 325}
326
327static inline int pud_same(pud_t pud_a, pud_t pud_b)
328{
329 return pud_val(pud_a) == pud_val(pud_b);
330}
276#else /* CONFIG_TRANSPARENT_HUGEPAGE */ 331#else /* CONFIG_TRANSPARENT_HUGEPAGE */
277static inline int pmd_same(pmd_t pmd_a, pmd_t pmd_b) 332static inline int pmd_same(pmd_t pmd_a, pmd_t pmd_b)
278{ 333{
279 BUILD_BUG(); 334 BUILD_BUG();
280 return 0; 335 return 0;
281} 336}
337
338static inline int pud_same(pud_t pud_a, pud_t pud_b)
339{
340 BUILD_BUG();
341 return 0;
342}
282#endif /* CONFIG_TRANSPARENT_HUGEPAGE */ 343#endif /* CONFIG_TRANSPARENT_HUGEPAGE */
283#endif 344#endif
284 345
@@ -640,6 +701,15 @@ static inline int pmd_write(pmd_t pmd)
640#endif /* __HAVE_ARCH_PMD_WRITE */ 701#endif /* __HAVE_ARCH_PMD_WRITE */
641#endif /* CONFIG_TRANSPARENT_HUGEPAGE */ 702#endif /* CONFIG_TRANSPARENT_HUGEPAGE */
642 703
704#if !defined(CONFIG_TRANSPARENT_HUGEPAGE) || \
705 (defined(CONFIG_TRANSPARENT_HUGEPAGE) && \
706 !defined(CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD))
707static inline int pud_trans_huge(pud_t pud)
708{
709 return 0;
710}
711#endif
712
643#ifndef pmd_read_atomic 713#ifndef pmd_read_atomic
644static inline pmd_t pmd_read_atomic(pmd_t *pmdp) 714static inline pmd_t pmd_read_atomic(pmd_t *pmdp)
645{ 715{
@@ -785,8 +855,10 @@ static inline int pmd_clear_huge(pmd_t *pmd)
785 * e.g. see arch/arc: flush_pmd_tlb_range 855 * e.g. see arch/arc: flush_pmd_tlb_range
786 */ 856 */
787#define flush_pmd_tlb_range(vma, addr, end) flush_tlb_range(vma, addr, end) 857#define flush_pmd_tlb_range(vma, addr, end) flush_tlb_range(vma, addr, end)
858#define flush_pud_tlb_range(vma, addr, end) flush_tlb_range(vma, addr, end)
788#else 859#else
789#define flush_pmd_tlb_range(vma, addr, end) BUILD_BUG() 860#define flush_pmd_tlb_range(vma, addr, end) BUILD_BUG()
861#define flush_pud_tlb_range(vma, addr, end) BUILD_BUG()
790#endif 862#endif
791#endif 863#endif
792 864