1#ifndef _LINUX_MMU_NOTIFIER_H
2#define _LINUX_MMU_NOTIFIER_H
3
4#include <linux/list.h>
5#include <linux/spinlock.h>
6#include <linux/mm_types.h>
7
8struct mmu_notifier;
9struct mmu_notifier_ops;
10
11#ifdef CONFIG_MMU_NOTIFIER
12
13
14
15
16
17
18
19struct mmu_notifier_mm {
20
21 struct hlist_head list;
22
23 spinlock_t lock;
24};
25
26struct mmu_notifier_ops {
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50 void (*release)(struct mmu_notifier *mn,
51 struct mm_struct *mm);
52
53
54
55
56
57
58
59
60 int (*clear_flush_young)(struct mmu_notifier *mn,
61 struct mm_struct *mm,
62 unsigned long address);
63
64
65
66
67
68 void (*change_pte)(struct mmu_notifier *mn,
69 struct mm_struct *mm,
70 unsigned long address,
71 pte_t pte);
72
73
74
75
76
77
78
79
80 void (*invalidate_page)(struct mmu_notifier *mn,
81 struct mm_struct *mm,
82 unsigned long address);
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127 void (*invalidate_range_start)(struct mmu_notifier *mn,
128 struct mm_struct *mm,
129 unsigned long start, unsigned long end);
130 void (*invalidate_range_end)(struct mmu_notifier *mn,
131 struct mm_struct *mm,
132 unsigned long start, unsigned long end);
133};
134
135
136
137
138
139
140
141
142
143
144
145
146struct mmu_notifier {
147 struct hlist_node hlist;
148 const struct mmu_notifier_ops *ops;
149};
150
151static inline int mm_has_notifiers(struct mm_struct *mm)
152{
153 return unlikely(mm->mmu_notifier_mm);
154}
155
156extern int mmu_notifier_register(struct mmu_notifier *mn,
157 struct mm_struct *mm);
158extern int __mmu_notifier_register(struct mmu_notifier *mn,
159 struct mm_struct *mm);
160extern void mmu_notifier_unregister(struct mmu_notifier *mn,
161 struct mm_struct *mm);
162extern void __mmu_notifier_mm_destroy(struct mm_struct *mm);
163extern void __mmu_notifier_release(struct mm_struct *mm);
164extern int __mmu_notifier_clear_flush_young(struct mm_struct *mm,
165 unsigned long address);
166extern void __mmu_notifier_change_pte(struct mm_struct *mm,
167 unsigned long address, pte_t pte);
168extern void __mmu_notifier_invalidate_page(struct mm_struct *mm,
169 unsigned long address);
170extern void __mmu_notifier_invalidate_range_start(struct mm_struct *mm,
171 unsigned long start, unsigned long end);
172extern void __mmu_notifier_invalidate_range_end(struct mm_struct *mm,
173 unsigned long start, unsigned long end);
174
175static inline void mmu_notifier_release(struct mm_struct *mm)
176{
177 if (mm_has_notifiers(mm))
178 __mmu_notifier_release(mm);
179}
180
181static inline int mmu_notifier_clear_flush_young(struct mm_struct *mm,
182 unsigned long address)
183{
184 if (mm_has_notifiers(mm))
185 return __mmu_notifier_clear_flush_young(mm, address);
186 return 0;
187}
188
189static inline void mmu_notifier_change_pte(struct mm_struct *mm,
190 unsigned long address, pte_t pte)
191{
192 if (mm_has_notifiers(mm))
193 __mmu_notifier_change_pte(mm, address, pte);
194}
195
196static inline void mmu_notifier_invalidate_page(struct mm_struct *mm,
197 unsigned long address)
198{
199 if (mm_has_notifiers(mm))
200 __mmu_notifier_invalidate_page(mm, address);
201}
202
203static inline void mmu_notifier_invalidate_range_start(struct mm_struct *mm,
204 unsigned long start, unsigned long end)
205{
206 if (mm_has_notifiers(mm))
207 __mmu_notifier_invalidate_range_start(mm, start, end);
208}
209
210static inline void mmu_notifier_invalidate_range_end(struct mm_struct *mm,
211 unsigned long start, unsigned long end)
212{
213 if (mm_has_notifiers(mm))
214 __mmu_notifier_invalidate_range_end(mm, start, end);
215}
216
217static inline void mmu_notifier_mm_init(struct mm_struct *mm)
218{
219 mm->mmu_notifier_mm = NULL;
220}
221
222static inline void mmu_notifier_mm_destroy(struct mm_struct *mm)
223{
224 if (mm_has_notifiers(mm))
225 __mmu_notifier_mm_destroy(mm);
226}
227
228
229
230
231
232
233
234
235
236#define ptep_clear_flush_notify(__vma, __address, __ptep) \
237({ \
238 pte_t __pte; \
239 struct vm_area_struct *___vma = __vma; \
240 unsigned long ___address = __address; \
241 __pte = ptep_clear_flush(___vma, ___address, __ptep); \
242 mmu_notifier_invalidate_page(___vma->vm_mm, ___address); \
243 __pte; \
244})
245
246#define ptep_clear_flush_young_notify(__vma, __address, __ptep) \
247({ \
248 int __young; \
249 struct vm_area_struct *___vma = __vma; \
250 unsigned long ___address = __address; \
251 __young = ptep_clear_flush_young(___vma, ___address, __ptep); \
252 __young |= mmu_notifier_clear_flush_young(___vma->vm_mm, \
253 ___address); \
254 __young; \
255})
256
257#define set_pte_at_notify(__mm, __address, __ptep, __pte) \
258({ \
259 struct mm_struct *___mm = __mm; \
260 unsigned long ___address = __address; \
261 pte_t ___pte = __pte; \
262 \
263 set_pte_at(___mm, ___address, __ptep, ___pte); \
264 mmu_notifier_change_pte(___mm, ___address, ___pte); \
265})
266
267#else
268
269static inline void mmu_notifier_release(struct mm_struct *mm)
270{
271}
272
273static inline int mmu_notifier_clear_flush_young(struct mm_struct *mm,
274 unsigned long address)
275{
276 return 0;
277}
278
279static inline void mmu_notifier_change_pte(struct mm_struct *mm,
280 unsigned long address, pte_t pte)
281{
282}
283
284static inline void mmu_notifier_invalidate_page(struct mm_struct *mm,
285 unsigned long address)
286{
287}
288
289static inline void mmu_notifier_invalidate_range_start(struct mm_struct *mm,
290 unsigned long start, unsigned long end)
291{
292}
293
294static inline void mmu_notifier_invalidate_range_end(struct mm_struct *mm,
295 unsigned long start, unsigned long end)
296{
297}
298
299static inline void mmu_notifier_mm_init(struct mm_struct *mm)
300{
301}
302
303static inline void mmu_notifier_mm_destroy(struct mm_struct *mm)
304{
305}
306
307#define ptep_clear_flush_young_notify ptep_clear_flush_young
308#define ptep_clear_flush_notify ptep_clear_flush
309#define set_pte_at_notify set_pte_at
310
311#endif
312
313#endif
314