1
2#ifndef _LINUX_MMU_NOTIFIER_H
3#define _LINUX_MMU_NOTIFIER_H
4
5#include <linux/types.h>
6#include <linux/list.h>
7#include <linux/spinlock.h>
8#include <linux/mm_types.h>
9#include <linux/srcu.h>
10#include <linux/rh_kabi.h>
11
12struct mmu_notifier;
13struct mmu_notifier_ops;
14
15
16#define MMU_INVALIDATE_DOES_NOT_BLOCK (0x01)
17
18#ifdef CONFIG_MMU_NOTIFIER
19
20
21
22
23
24
25
26struct mmu_notifier_mm {
27
28 struct hlist_head list;
29
30 spinlock_t lock;
31};
32
33struct mmu_notifier_ops {
34
35
36
37
38
39
40
41 int flags;
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66 void (*release)(struct mmu_notifier *mn,
67 struct mm_struct *mm);
68
69
70
71
72
73
74
75
76
77
78 int (*clear_flush_young)(struct mmu_notifier *mn,
79 struct mm_struct *mm,
80 unsigned long start,
81 unsigned long end);
82
83
84
85
86
87
88 int (*clear_young)(struct mmu_notifier *mn,
89 struct mm_struct *mm,
90 unsigned long start,
91 unsigned long end);
92
93
94
95
96
97
98
99 int (*test_young)(struct mmu_notifier *mn,
100 struct mm_struct *mm,
101 unsigned long address);
102
103
104
105
106
107 void (*change_pte)(struct mmu_notifier *mn,
108 struct mm_struct *mm,
109 unsigned long address,
110 pte_t pte);
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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159 void (*invalidate_range_start)(struct mmu_notifier *mn,
160 struct mm_struct *mm,
161 unsigned long start, unsigned long end);
162 void (*invalidate_range_end)(struct mmu_notifier *mn,
163 struct mm_struct *mm,
164 unsigned long start, unsigned long end);
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188 void (*invalidate_range)(struct mmu_notifier *mn, struct mm_struct *mm,
189 unsigned long start, unsigned long end);
190
191 RH_KABI_RESERVE(1)
192 RH_KABI_RESERVE(2)
193 RH_KABI_RESERVE(3)
194 RH_KABI_RESERVE(4)
195};
196
197
198
199
200
201
202
203
204
205
206
207
208struct mmu_notifier {
209 struct hlist_node hlist;
210 const struct mmu_notifier_ops *ops;
211 RH_KABI_RESERVE(1)
212 RH_KABI_RESERVE(2)
213};
214
215static inline int mm_has_notifiers(struct mm_struct *mm)
216{
217 return unlikely(mm->mmu_notifier_mm);
218}
219
220extern int mmu_notifier_register(struct mmu_notifier *mn,
221 struct mm_struct *mm);
222extern int __mmu_notifier_register(struct mmu_notifier *mn,
223 struct mm_struct *mm);
224extern void mmu_notifier_unregister(struct mmu_notifier *mn,
225 struct mm_struct *mm);
226extern void mmu_notifier_unregister_no_release(struct mmu_notifier *mn,
227 struct mm_struct *mm);
228extern void __mmu_notifier_mm_destroy(struct mm_struct *mm);
229extern void __mmu_notifier_release(struct mm_struct *mm);
230extern int __mmu_notifier_clear_flush_young(struct mm_struct *mm,
231 unsigned long start,
232 unsigned long end);
233extern int __mmu_notifier_clear_young(struct mm_struct *mm,
234 unsigned long start,
235 unsigned long end);
236extern int __mmu_notifier_test_young(struct mm_struct *mm,
237 unsigned long address);
238extern void __mmu_notifier_change_pte(struct mm_struct *mm,
239 unsigned long address, pte_t pte);
240extern void __mmu_notifier_invalidate_range_start(struct mm_struct *mm,
241 unsigned long start, unsigned long end);
242extern void __mmu_notifier_invalidate_range_end(struct mm_struct *mm,
243 unsigned long start, unsigned long end,
244 bool only_end);
245extern void __mmu_notifier_invalidate_range(struct mm_struct *mm,
246 unsigned long start, unsigned long end);
247extern bool mm_has_blockable_invalidate_notifiers(struct mm_struct *mm);
248
249static inline void mmu_notifier_release(struct mm_struct *mm)
250{
251 if (mm_has_notifiers(mm))
252 __mmu_notifier_release(mm);
253}
254
255static inline int mmu_notifier_clear_flush_young(struct mm_struct *mm,
256 unsigned long start,
257 unsigned long end)
258{
259 if (mm_has_notifiers(mm))
260 return __mmu_notifier_clear_flush_young(mm, start, end);
261 return 0;
262}
263
264static inline int mmu_notifier_clear_young(struct mm_struct *mm,
265 unsigned long start,
266 unsigned long end)
267{
268 if (mm_has_notifiers(mm))
269 return __mmu_notifier_clear_young(mm, start, end);
270 return 0;
271}
272
273static inline int mmu_notifier_test_young(struct mm_struct *mm,
274 unsigned long address)
275{
276 if (mm_has_notifiers(mm))
277 return __mmu_notifier_test_young(mm, address);
278 return 0;
279}
280
281static inline void mmu_notifier_change_pte(struct mm_struct *mm,
282 unsigned long address, pte_t pte)
283{
284 if (mm_has_notifiers(mm))
285 __mmu_notifier_change_pte(mm, address, pte);
286}
287
288static inline void mmu_notifier_invalidate_range_start(struct mm_struct *mm,
289 unsigned long start, unsigned long end)
290{
291 if (mm_has_notifiers(mm))
292 __mmu_notifier_invalidate_range_start(mm, start, end);
293}
294
295static inline void mmu_notifier_invalidate_range_end(struct mm_struct *mm,
296 unsigned long start, unsigned long end)
297{
298 if (mm_has_notifiers(mm))
299 __mmu_notifier_invalidate_range_end(mm, start, end, false);
300}
301
302static inline void mmu_notifier_invalidate_range_only_end(struct mm_struct *mm,
303 unsigned long start, unsigned long end)
304{
305 if (mm_has_notifiers(mm))
306 __mmu_notifier_invalidate_range_end(mm, start, end, true);
307}
308
309static inline void mmu_notifier_invalidate_range(struct mm_struct *mm,
310 unsigned long start, unsigned long end)
311{
312 if (mm_has_notifiers(mm))
313 __mmu_notifier_invalidate_range(mm, start, end);
314}
315
316static inline void mmu_notifier_mm_init(struct mm_struct *mm)
317{
318 mm->mmu_notifier_mm = NULL;
319}
320
321static inline void mmu_notifier_mm_destroy(struct mm_struct *mm)
322{
323 if (mm_has_notifiers(mm))
324 __mmu_notifier_mm_destroy(mm);
325}
326
327#define ptep_clear_flush_young_notify(__vma, __address, __ptep) \
328({ \
329 int __young; \
330 struct vm_area_struct *___vma = __vma; \
331 unsigned long ___address = __address; \
332 __young = ptep_clear_flush_young(___vma, ___address, __ptep); \
333 __young |= mmu_notifier_clear_flush_young(___vma->vm_mm, \
334 ___address, \
335 ___address + \
336 PAGE_SIZE); \
337 __young; \
338})
339
340#define pmdp_clear_flush_young_notify(__vma, __address, __pmdp) \
341({ \
342 int __young; \
343 struct vm_area_struct *___vma = __vma; \
344 unsigned long ___address = __address; \
345 __young = pmdp_clear_flush_young(___vma, ___address, __pmdp); \
346 __young |= mmu_notifier_clear_flush_young(___vma->vm_mm, \
347 ___address, \
348 ___address + \
349 PMD_SIZE); \
350 __young; \
351})
352
353#define ptep_clear_young_notify(__vma, __address, __ptep) \
354({ \
355 int __young; \
356 struct vm_area_struct *___vma = __vma; \
357 unsigned long ___address = __address; \
358 __young = ptep_test_and_clear_young(___vma, ___address, __ptep);\
359 __young |= mmu_notifier_clear_young(___vma->vm_mm, ___address, \
360 ___address + PAGE_SIZE); \
361 __young; \
362})
363
364#define pmdp_clear_young_notify(__vma, __address, __pmdp) \
365({ \
366 int __young; \
367 struct vm_area_struct *___vma = __vma; \
368 unsigned long ___address = __address; \
369 __young = pmdp_test_and_clear_young(___vma, ___address, __pmdp);\
370 __young |= mmu_notifier_clear_young(___vma->vm_mm, ___address, \
371 ___address + PMD_SIZE); \
372 __young; \
373})
374
375#define ptep_clear_flush_notify(__vma, __address, __ptep) \
376({ \
377 unsigned long ___addr = __address & PAGE_MASK; \
378 struct mm_struct *___mm = (__vma)->vm_mm; \
379 pte_t ___pte; \
380 \
381 ___pte = ptep_clear_flush(__vma, __address, __ptep); \
382 mmu_notifier_invalidate_range(___mm, ___addr, \
383 ___addr + PAGE_SIZE); \
384 \
385 ___pte; \
386})
387
388#define pmdp_huge_clear_flush_notify(__vma, __haddr, __pmd) \
389({ \
390 unsigned long ___haddr = __haddr & HPAGE_PMD_MASK; \
391 struct mm_struct *___mm = (__vma)->vm_mm; \
392 pmd_t ___pmd; \
393 \
394 ___pmd = pmdp_huge_clear_flush(__vma, __haddr, __pmd); \
395 mmu_notifier_invalidate_range(___mm, ___haddr, \
396 ___haddr + HPAGE_PMD_SIZE); \
397 \
398 ___pmd; \
399})
400
401#define pudp_huge_clear_flush_notify(__vma, __haddr, __pud) \
402({ \
403 unsigned long ___haddr = __haddr & HPAGE_PUD_MASK; \
404 struct mm_struct *___mm = (__vma)->vm_mm; \
405 pud_t ___pud; \
406 \
407 ___pud = pudp_huge_clear_flush(__vma, __haddr, __pud); \
408 mmu_notifier_invalidate_range(___mm, ___haddr, \
409 ___haddr + HPAGE_PUD_SIZE); \
410 \
411 ___pud; \
412})
413
414
415
416
417
418
419
420
421
422
423
424#define set_pte_at_notify(__mm, __address, __ptep, __pte) \
425({ \
426 struct mm_struct *___mm = __mm; \
427 unsigned long ___address = __address; \
428 pte_t ___pte = __pte; \
429 \
430 mmu_notifier_change_pte(___mm, ___address, ___pte); \
431 set_pte_at(___mm, ___address, __ptep, ___pte); \
432})
433
434extern void mmu_notifier_call_srcu(struct rcu_head *rcu,
435 void (*func)(struct rcu_head *rcu));
436extern void mmu_notifier_synchronize(void);
437
438#else
439
440static inline int mm_has_notifiers(struct mm_struct *mm)
441{
442 return 0;
443}
444
445static inline void mmu_notifier_release(struct mm_struct *mm)
446{
447}
448
449static inline int mmu_notifier_clear_flush_young(struct mm_struct *mm,
450 unsigned long start,
451 unsigned long end)
452{
453 return 0;
454}
455
456static inline int mmu_notifier_test_young(struct mm_struct *mm,
457 unsigned long address)
458{
459 return 0;
460}
461
462static inline void mmu_notifier_change_pte(struct mm_struct *mm,
463 unsigned long address, pte_t pte)
464{
465}
466
467static inline void mmu_notifier_invalidate_range_start(struct mm_struct *mm,
468 unsigned long start, unsigned long end)
469{
470}
471
472static inline void mmu_notifier_invalidate_range_end(struct mm_struct *mm,
473 unsigned long start, unsigned long end)
474{
475}
476
477static inline void mmu_notifier_invalidate_range_only_end(struct mm_struct *mm,
478 unsigned long start, unsigned long end)
479{
480}
481
482static inline void mmu_notifier_invalidate_range(struct mm_struct *mm,
483 unsigned long start, unsigned long end)
484{
485}
486
487static inline bool mm_has_blockable_invalidate_notifiers(struct mm_struct *mm)
488{
489 return false;
490}
491
492static inline void mmu_notifier_mm_init(struct mm_struct *mm)
493{
494}
495
496static inline void mmu_notifier_mm_destroy(struct mm_struct *mm)
497{
498}
499
500#define ptep_clear_flush_young_notify ptep_clear_flush_young
501#define pmdp_clear_flush_young_notify pmdp_clear_flush_young
502#define ptep_clear_young_notify ptep_test_and_clear_young
503#define pmdp_clear_young_notify pmdp_test_and_clear_young
504#define ptep_clear_flush_notify ptep_clear_flush
505#define pmdp_huge_clear_flush_notify pmdp_huge_clear_flush
506#define pudp_huge_clear_flush_notify pudp_huge_clear_flush
507#define set_pte_at_notify set_pte_at
508
509#endif
510
511#endif
512