aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorAndrea Arcangeli <aarcange@redhat.com>2011-01-13 18:46:40 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2011-01-13 20:32:40 -0500
commite2cda322648122dc400c85ada80eaddbc612ef6a (patch)
tree016981ea6d9d3f7448bd9e04720184b14a79302c /include
parent5f6e8da70a289d403975907371ce5738c726ad3f (diff)
thp: add pmd mangling generic functions
Some are needed to build but not actually used on archs not supporting transparent hugepages. Others like pmdp_clear_flush are used by x86 too. Signed-off-by: Andrea Arcangeli <aarcange@redhat.com> Acked-by: Rik van Riel <riel@redhat.com> Acked-by: Mel Gorman <mel@csn.ul.ie> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'include')
-rw-r--r--include/asm-generic/pgtable.h214
1 files changed, 154 insertions, 60 deletions
diff --git a/include/asm-generic/pgtable.h b/include/asm-generic/pgtable.h
index 0ab2cd27c60f..f1eddf71dd0c 100644
--- a/include/asm-generic/pgtable.h
+++ b/include/asm-generic/pgtable.h
@@ -5,67 +5,108 @@
5#ifdef CONFIG_MMU 5#ifdef CONFIG_MMU
6 6
7#ifndef __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS 7#ifndef __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS
8/* 8extern int ptep_set_access_flags(struct vm_area_struct *vma,
9 * Largely same as above, but only sets the access flags (dirty, 9 unsigned long address, pte_t *ptep,
10 * accessed, and writable). Furthermore, we know it always gets set 10 pte_t entry, int dirty);
11 * to a "more permissive" setting, which allows most architectures 11#endif
12 * to optimize this. We return whether the PTE actually changed, which 12
13 * in turn instructs the caller to do things like update__mmu_cache. 13#ifndef __HAVE_ARCH_PMDP_SET_ACCESS_FLAGS
14 * This used to be done in the caller, but sparc needs minor faults to 14extern int pmdp_set_access_flags(struct vm_area_struct *vma,
15 * force that call on sun4c so we changed this macro slightly 15 unsigned long address, pmd_t *pmdp,
16 */ 16 pmd_t entry, int dirty);
17#define ptep_set_access_flags(__vma, __address, __ptep, __entry, __dirty) \
18({ \
19 int __changed = !pte_same(*(__ptep), __entry); \
20 if (__changed) { \
21 set_pte_at((__vma)->vm_mm, (__address), __ptep, __entry); \
22 flush_tlb_page(__vma, __address); \
23 } \
24 __changed; \
25})
26#endif 17#endif
27 18
28#ifndef __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG 19#ifndef __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
29#define ptep_test_and_clear_young(__vma, __address, __ptep) \ 20static inline int ptep_test_and_clear_young(struct vm_area_struct *vma,
30({ \ 21 unsigned long address,
31 pte_t __pte = *(__ptep); \ 22 pte_t *ptep)
32 int r = 1; \ 23{
33 if (!pte_young(__pte)) \ 24 pte_t pte = *ptep;
34 r = 0; \ 25 int r = 1;
35 else \ 26 if (!pte_young(pte))
36 set_pte_at((__vma)->vm_mm, (__address), \ 27 r = 0;
37 (__ptep), pte_mkold(__pte)); \ 28 else
38 r; \ 29 set_pte_at(vma->vm_mm, address, ptep, pte_mkold(pte));
39}) 30 return r;
31}
32#endif
33
34#ifndef __HAVE_ARCH_PMDP_TEST_AND_CLEAR_YOUNG
35#ifdef CONFIG_TRANSPARENT_HUGEPAGE
36static inline int pmdp_test_and_clear_young(struct vm_area_struct *vma,
37 unsigned long address,
38 pmd_t *pmdp)
39{
40 pmd_t pmd = *pmdp;
41 int r = 1;
42 if (!pmd_young(pmd))
43 r = 0;
44 else
45 set_pmd_at(vma->vm_mm, address, pmdp, pmd_mkold(pmd));
46 return r;
47}
48#else /* CONFIG_TRANSPARENT_HUGEPAGE */
49static inline int pmdp_test_and_clear_young(struct vm_area_struct *vma,
50 unsigned long address,
51 pmd_t *pmdp)
52{
53 BUG();
54 return 0;
55}
56#endif /* CONFIG_TRANSPARENT_HUGEPAGE */
40#endif 57#endif
41 58
42#ifndef __HAVE_ARCH_PTEP_CLEAR_YOUNG_FLUSH 59#ifndef __HAVE_ARCH_PTEP_CLEAR_YOUNG_FLUSH
43#define ptep_clear_flush_young(__vma, __address, __ptep) \ 60int ptep_clear_flush_young(struct vm_area_struct *vma,
44({ \ 61 unsigned long address, pte_t *ptep);
45 int __young; \ 62#endif
46 __young = ptep_test_and_clear_young(__vma, __address, __ptep); \ 63
47 if (__young) \ 64#ifndef __HAVE_ARCH_PMDP_CLEAR_YOUNG_FLUSH
48 flush_tlb_page(__vma, __address); \ 65int pmdp_clear_flush_young(struct vm_area_struct *vma,
49 __young; \ 66 unsigned long address, pmd_t *pmdp);
50})
51#endif 67#endif
52 68
53#ifndef __HAVE_ARCH_PTEP_GET_AND_CLEAR 69#ifndef __HAVE_ARCH_PTEP_GET_AND_CLEAR
54#define ptep_get_and_clear(__mm, __address, __ptep) \ 70static inline pte_t ptep_get_and_clear(struct mm_struct *mm,
55({ \ 71 unsigned long address,
56 pte_t __pte = *(__ptep); \ 72 pte_t *ptep)
57 pte_clear((__mm), (__address), (__ptep)); \ 73{
58 __pte; \ 74 pte_t pte = *ptep;
75 pte_clear(mm, address, ptep);
76 return pte;
77}
78#endif
79
80#ifndef __HAVE_ARCH_PMDP_GET_AND_CLEAR
81#ifdef CONFIG_TRANSPARENT_HUGEPAGE
82static inline pmd_t pmdp_get_and_clear(struct mm_struct *mm,
83 unsigned long address,
84 pmd_t *pmdp)
85{
86 pmd_t pmd = *pmdp;
87 pmd_clear(mm, address, pmdp);
88 return pmd;
59}) 89})
90#else /* CONFIG_TRANSPARENT_HUGEPAGE */
91static inline pmd_t pmdp_get_and_clear(struct mm_struct *mm,
92 unsigned long address,
93 pmd_t *pmdp)
94{
95 BUG();
96 return __pmd(0);
97}
98#endif /* CONFIG_TRANSPARENT_HUGEPAGE */
60#endif 99#endif
61 100
62#ifndef __HAVE_ARCH_PTEP_GET_AND_CLEAR_FULL 101#ifndef __HAVE_ARCH_PTEP_GET_AND_CLEAR_FULL
63#define ptep_get_and_clear_full(__mm, __address, __ptep, __full) \ 102static inline pte_t ptep_get_and_clear_full(struct mm_struct *mm,
64({ \ 103 unsigned long address, pte_t *ptep,
65 pte_t __pte; \ 104 int full)
66 __pte = ptep_get_and_clear((__mm), (__address), (__ptep)); \ 105{
67 __pte; \ 106 pte_t pte;
68}) 107 pte = ptep_get_and_clear(mm, address, ptep);
108 return pte;
109}
69#endif 110#endif
70 111
71/* 112/*
@@ -74,20 +115,25 @@
74 * not present, or in the process of an address space destruction. 115 * not present, or in the process of an address space destruction.
75 */ 116 */
76#ifndef __HAVE_ARCH_PTE_CLEAR_NOT_PRESENT_FULL 117#ifndef __HAVE_ARCH_PTE_CLEAR_NOT_PRESENT_FULL
77#define pte_clear_not_present_full(__mm, __address, __ptep, __full) \ 118static inline void pte_clear_not_present_full(struct mm_struct *mm,
78do { \ 119 unsigned long address,
79 pte_clear((__mm), (__address), (__ptep)); \ 120 pte_t *ptep,
80} while (0) 121 int full)
122{
123 pte_clear(mm, address, ptep);
124}
81#endif 125#endif
82 126
83#ifndef __HAVE_ARCH_PTEP_CLEAR_FLUSH 127#ifndef __HAVE_ARCH_PTEP_CLEAR_FLUSH
84#define ptep_clear_flush(__vma, __address, __ptep) \ 128extern pte_t ptep_clear_flush(struct vm_area_struct *vma,
85({ \ 129 unsigned long address,
86 pte_t __pte; \ 130 pte_t *ptep);
87 __pte = ptep_get_and_clear((__vma)->vm_mm, __address, __ptep); \ 131#endif
88 flush_tlb_page(__vma, __address); \ 132
89 __pte; \ 133#ifndef __HAVE_ARCH_PMDP_CLEAR_FLUSH
90}) 134extern pmd_t pmdp_clear_flush(struct vm_area_struct *vma,
135 unsigned long address,
136 pmd_t *pmdp);
91#endif 137#endif
92 138
93#ifndef __HAVE_ARCH_PTEP_SET_WRPROTECT 139#ifndef __HAVE_ARCH_PTEP_SET_WRPROTECT
@@ -99,8 +145,49 @@ static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addres
99} 145}
100#endif 146#endif
101 147
148#ifndef __HAVE_ARCH_PMDP_SET_WRPROTECT
149#ifdef CONFIG_TRANSPARENT_HUGEPAGE
150static inline void pmdp_set_wrprotect(struct mm_struct *mm,
151 unsigned long address, pmd_t *pmdp)
152{
153 pmd_t old_pmd = *pmdp;
154 set_pmd_at(mm, address, pmdp, pmd_wrprotect(old_pmd));
155}
156#else /* CONFIG_TRANSPARENT_HUGEPAGE */
157static inline void pmdp_set_wrprotect(struct mm_struct *mm,
158 unsigned long address, pmd_t *pmdp)
159{
160 BUG();
161}
162#endif /* CONFIG_TRANSPARENT_HUGEPAGE */
163#endif
164
165#ifndef __HAVE_ARCH_PMDP_SPLITTING_FLUSH
166extern pmd_t pmdp_clear_flush(struct vm_area_struct *vma,
167 unsigned long address,
168 pmd_t *pmdp);
169#endif
170
102#ifndef __HAVE_ARCH_PTE_SAME 171#ifndef __HAVE_ARCH_PTE_SAME
103#define pte_same(A,B) (pte_val(A) == pte_val(B)) 172static inline int pte_same(pte_t pte_a, pte_t pte_b)
173{
174 return pte_val(pte_a) == pte_val(pte_b);
175}
176#endif
177
178#ifndef __HAVE_ARCH_PMD_SAME
179#ifdef CONFIG_TRANSPARENT_HUGEPAGE
180static inline int pmd_same(pmd_t pmd_a, pmd_t pmd_b)
181{
182 return pmd_val(pmd_a) == pmd_val(pmd_b);
183}
184#else /* CONFIG_TRANSPARENT_HUGEPAGE */
185static inline int pmd_same(pmd_t pmd_a, pmd_t pmd_b)
186{
187 BUG();
188 return 0;
189}
190#endif /* CONFIG_TRANSPARENT_HUGEPAGE */
104#endif 191#endif
105 192
106#ifndef __HAVE_ARCH_PAGE_TEST_DIRTY 193#ifndef __HAVE_ARCH_PAGE_TEST_DIRTY
@@ -357,6 +444,13 @@ static inline int pmd_trans_splitting(pmd_t pmd)
357{ 444{
358 return 0; 445 return 0;
359} 446}
447#ifndef __HAVE_ARCH_PMD_WRITE
448static inline int pmd_write(pmd_t pmd)
449{
450 BUG();
451 return 0;
452}
453#endif /* __HAVE_ARCH_PMD_WRITE */
360#endif 454#endif
361 455
362#endif /* !__ASSEMBLY__ */ 456#endif /* !__ASSEMBLY__ */