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
69
70 int (*test_young)(struct mmu_notifier *mn,
71 struct mm_struct *mm,
72 unsigned long address);
73
74
75
76
77
78 void (*change_pte)(struct mmu_notifier *mn,
79 struct mm_struct *mm,
80 unsigned long address,
81 pte_t pte);
82
83
84
85
86
87
88
89
90 void (*invalidate_page)(struct mmu_notifier *mn,
91 struct mm_struct *mm,
92 unsigned long address);
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
128
129
130
131
132
133
134
135
136
137 void (*invalidate_range_start)(struct mmu_notifier *mn,
138 struct mm_struct *mm,
139 unsigned long start, unsigned long end);
140 void (*invalidate_range_end)(struct mmu_notifier *mn,
141 struct mm_struct *mm,
142 unsigned long start, unsigned long end);
143};
144
145
146
147
148
149
150
151
152
153
154
155
156struct mmu_notifier {
157 struct hlist_node hlist;
158 const struct mmu_notifier_ops *ops;
159};
160
161static inline int mm_has_notifiers(struct mm_struct *mm)
162{
163 return unlikely(mm->mmu_notifier_mm);
164}
165
166extern int mmu_notifier_register(struct mmu_notifier *mn,
167 struct mm_struct *mm);
168extern int __mmu_notifier_register(struct mmu_notifier *mn,
169 struct mm_struct *mm);
170extern void mmu_notifier_unregister(struct mmu_notifier *mn,
171 struct mm_struct *mm);
172extern void __mmu_notifier_mm_destroy(struct mm_struct *mm);
173extern void __mmu_notifier_release(struct mm_struct *mm);
174extern int __mmu_notifier_clear_flush_young(struct mm_struct *mm,
175 unsigned long address);
176extern int __mmu_notifier_test_young(struct mm_struct *mm,
177 unsigned long address);
178extern void __mmu_notifier_change_pte(struct mm_struct *mm,
179 unsigned long address, pte_t pte);
180extern void __mmu_notifier_invalidate_page(struct mm_struct *mm,
181 unsigned long address);
182extern void __mmu_notifier_invalidate_range_start(struct mm_struct *mm,
183 unsigned long start, unsigned long end);
184extern void __mmu_notifier_invalidate_range_end(struct mm_struct *mm,
185 unsigned long start, unsigned long end);
186
187static inline void mmu_notifier_release(struct mm_struct *mm)
188{
189 if (mm_has_notifiers(mm))
190 __mmu_notifier_release(mm);
191}
192
193static inline int mmu_notifier_clear_flush_young(struct mm_struct *mm,
194 unsigned long address)
195{
196 if (mm_has_notifiers(mm))
197 return __mmu_notifier_clear_flush_young(mm, address);
198 return 0;
199}
200
201static inline int mmu_notifier_test_young(struct mm_struct *mm,
202 unsigned long address)
203{
204 if (mm_has_notifiers(mm))
205 return __mmu_notifier_test_young(mm, address);
206 return 0;
207}
208
209static inline void mmu_notifier_change_pte(struct mm_struct *mm,
210 unsigned long address, pte_t pte)
211{
212 if (mm_has_notifiers(mm))
213 __mmu_notifier_change_pte(mm, address, pte);
214}
215
216static inline void mmu_notifier_invalidate_page(struct mm_struct *mm,
217 unsigned long address)
218{
219 if (mm_has_notifiers(mm))
220 __mmu_notifier_invalidate_page(mm, address);
221}
222
223static inline void mmu_notifier_invalidate_range_start(struct mm_struct *mm,
224 unsigned long start, unsigned long end)
225{
226 if (mm_has_notifiers(mm))
227 __mmu_notifier_invalidate_range_start(mm, start, end);
228}
229
230static inline void mmu_notifier_invalidate_range_end(struct mm_struct *mm,
231 unsigned long start, unsigned long end)
232{
233 if (mm_has_notifiers(mm))
234 __mmu_notifier_invalidate_range_end(mm, start, end);
235}
236
237static inline void mmu_notifier_mm_init(struct mm_struct *mm)
238{
239 mm->mmu_notifier_mm = NULL;
240}
241
242static inline void mmu_notifier_mm_destroy(struct mm_struct *mm)
243{
244 if (mm_has_notifiers(mm))
245 __mmu_notifier_mm_destroy(mm);
246}
247
248
249
250
251
252
253
254
255
256#define ptep_clear_flush_notify(__vma, __address, __ptep) \
257({ \
258 pte_t __pte; \
259 struct vm_area_struct *___vma = __vma; \
260 unsigned long ___address = __address; \
261 __pte = ptep_clear_flush(___vma, ___address, __ptep); \
262 mmu_notifier_invalidate_page(___vma->vm_mm, ___address); \
263 __pte; \
264})
265
266#define pmdp_clear_flush_notify(__vma, __address, __pmdp) \
267({ \
268 pmd_t __pmd; \
269 struct vm_area_struct *___vma = __vma; \
270 unsigned long ___address = __address; \
271 VM_BUG_ON(__address & ~HPAGE_PMD_MASK); \
272 mmu_notifier_invalidate_range_start(___vma->vm_mm, ___address, \
273 (__address)+HPAGE_PMD_SIZE);\
274 __pmd = pmdp_clear_flush(___vma, ___address, __pmdp); \
275 mmu_notifier_invalidate_range_end(___vma->vm_mm, ___address, \
276 (__address)+HPAGE_PMD_SIZE); \
277 __pmd; \
278})
279
280#define pmdp_splitting_flush_notify(__vma, __address, __pmdp) \
281({ \
282 struct vm_area_struct *___vma = __vma; \
283 unsigned long ___address = __address; \
284 VM_BUG_ON(__address & ~HPAGE_PMD_MASK); \
285 mmu_notifier_invalidate_range_start(___vma->vm_mm, ___address, \
286 (__address)+HPAGE_PMD_SIZE);\
287 pmdp_splitting_flush(___vma, ___address, __pmdp); \
288 mmu_notifier_invalidate_range_end(___vma->vm_mm, ___address, \
289 (__address)+HPAGE_PMD_SIZE); \
290})
291
292#define ptep_clear_flush_young_notify(__vma, __address, __ptep) \
293({ \
294 int __young; \
295 struct vm_area_struct *___vma = __vma; \
296 unsigned long ___address = __address; \
297 __young = ptep_clear_flush_young(___vma, ___address, __ptep); \
298 __young |= mmu_notifier_clear_flush_young(___vma->vm_mm, \
299 ___address); \
300 __young; \
301})
302
303#define pmdp_clear_flush_young_notify(__vma, __address, __pmdp) \
304({ \
305 int __young; \
306 struct vm_area_struct *___vma = __vma; \
307 unsigned long ___address = __address; \
308 __young = pmdp_clear_flush_young(___vma, ___address, __pmdp); \
309 __young |= mmu_notifier_clear_flush_young(___vma->vm_mm, \
310 ___address); \
311 __young; \
312})
313
314#define set_pte_at_notify(__mm, __address, __ptep, __pte) \
315({ \
316 struct mm_struct *___mm = __mm; \
317 unsigned long ___address = __address; \
318 pte_t ___pte = __pte; \
319 \
320 set_pte_at(___mm, ___address, __ptep, ___pte); \
321 mmu_notifier_change_pte(___mm, ___address, ___pte); \
322})
323
324#else
325
326static inline void mmu_notifier_release(struct mm_struct *mm)
327{
328}
329
330static inline int mmu_notifier_clear_flush_young(struct mm_struct *mm,
331 unsigned long address)
332{
333 return 0;
334}
335
336static inline int mmu_notifier_test_young(struct mm_struct *mm,
337 unsigned long address)
338{
339 return 0;
340}
341
342static inline void mmu_notifier_change_pte(struct mm_struct *mm,
343 unsigned long address, pte_t pte)
344{
345}
346
347static inline void mmu_notifier_invalidate_page(struct mm_struct *mm,
348 unsigned long address)
349{
350}
351
352static inline void mmu_notifier_invalidate_range_start(struct mm_struct *mm,
353 unsigned long start, unsigned long end)
354{
355}
356
357static inline void mmu_notifier_invalidate_range_end(struct mm_struct *mm,
358 unsigned long start, unsigned long end)
359{
360}
361
362static inline void mmu_notifier_mm_init(struct mm_struct *mm)
363{
364}
365
366static inline void mmu_notifier_mm_destroy(struct mm_struct *mm)
367{
368}
369
370#define ptep_clear_flush_young_notify ptep_clear_flush_young
371#define pmdp_clear_flush_young_notify pmdp_clear_flush_young
372#define ptep_clear_flush_notify ptep_clear_flush
373#define pmdp_clear_flush_notify pmdp_clear_flush
374#define pmdp_splitting_flush_notify pmdp_splitting_flush
375#define set_pte_at_notify set_pte_at
376
377#endif
378
379#endif
380