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#include <linux/srcu.h>
8
9struct mmu_notifier;
10struct mmu_notifier_ops;
11
12#ifdef CONFIG_MMU_NOTIFIER
13
14
15
16
17
18
19
20struct mmu_notifier_mm {
21
22 struct hlist_head list;
23
24 spinlock_t lock;
25};
26
27struct mmu_notifier_ops {
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51 void (*release)(struct mmu_notifier *mn,
52 struct mm_struct *mm);
53
54
55
56
57
58
59
60
61 int (*clear_flush_young)(struct mmu_notifier *mn,
62 struct mm_struct *mm,
63 unsigned long address);
64
65
66
67
68
69
70
71 int (*test_young)(struct mmu_notifier *mn,
72 struct mm_struct *mm,
73 unsigned long address);
74
75
76
77
78
79 void (*change_pte)(struct mmu_notifier *mn,
80 struct mm_struct *mm,
81 unsigned long address,
82 pte_t pte);
83
84
85
86
87
88
89
90
91 void (*invalidate_page)(struct mmu_notifier *mn,
92 struct mm_struct *mm,
93 unsigned long address);
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
138 void (*invalidate_range_start)(struct mmu_notifier *mn,
139 struct mm_struct *mm,
140 unsigned long start, unsigned long end);
141 void (*invalidate_range_end)(struct mmu_notifier *mn,
142 struct mm_struct *mm,
143 unsigned long start, unsigned long end);
144};
145
146
147
148
149
150
151
152
153
154
155
156
157struct mmu_notifier {
158 struct hlist_node hlist;
159 const struct mmu_notifier_ops *ops;
160};
161
162static inline int mm_has_notifiers(struct mm_struct *mm)
163{
164 return unlikely(mm->mmu_notifier_mm);
165}
166
167extern int mmu_notifier_register(struct mmu_notifier *mn,
168 struct mm_struct *mm);
169extern int __mmu_notifier_register(struct mmu_notifier *mn,
170 struct mm_struct *mm);
171extern void mmu_notifier_unregister(struct mmu_notifier *mn,
172 struct mm_struct *mm);
173extern void __mmu_notifier_mm_destroy(struct mm_struct *mm);
174extern void __mmu_notifier_release(struct mm_struct *mm);
175extern int __mmu_notifier_clear_flush_young(struct mm_struct *mm,
176 unsigned long address);
177extern int __mmu_notifier_test_young(struct mm_struct *mm,
178 unsigned long address);
179extern void __mmu_notifier_change_pte(struct mm_struct *mm,
180 unsigned long address, pte_t pte);
181extern void __mmu_notifier_invalidate_page(struct mm_struct *mm,
182 unsigned long address);
183extern void __mmu_notifier_invalidate_range_start(struct mm_struct *mm,
184 unsigned long start, unsigned long end);
185extern void __mmu_notifier_invalidate_range_end(struct mm_struct *mm,
186 unsigned long start, unsigned long end);
187
188static inline void mmu_notifier_release(struct mm_struct *mm)
189{
190 if (mm_has_notifiers(mm))
191 __mmu_notifier_release(mm);
192}
193
194static inline int mmu_notifier_clear_flush_young(struct mm_struct *mm,
195 unsigned long address)
196{
197 if (mm_has_notifiers(mm))
198 return __mmu_notifier_clear_flush_young(mm, address);
199 return 0;
200}
201
202static inline int mmu_notifier_test_young(struct mm_struct *mm,
203 unsigned long address)
204{
205 if (mm_has_notifiers(mm))
206 return __mmu_notifier_test_young(mm, address);
207 return 0;
208}
209
210static inline void mmu_notifier_change_pte(struct mm_struct *mm,
211 unsigned long address, pte_t pte)
212{
213 if (mm_has_notifiers(mm))
214 __mmu_notifier_change_pte(mm, address, pte);
215}
216
217static inline void mmu_notifier_invalidate_page(struct mm_struct *mm,
218 unsigned long address)
219{
220 if (mm_has_notifiers(mm))
221 __mmu_notifier_invalidate_page(mm, address);
222}
223
224static inline void mmu_notifier_invalidate_range_start(struct mm_struct *mm,
225 unsigned long start, unsigned long end)
226{
227 if (mm_has_notifiers(mm))
228 __mmu_notifier_invalidate_range_start(mm, start, end);
229}
230
231static inline void mmu_notifier_invalidate_range_end(struct mm_struct *mm,
232 unsigned long start, unsigned long end)
233{
234 if (mm_has_notifiers(mm))
235 __mmu_notifier_invalidate_range_end(mm, start, end);
236}
237
238static inline void mmu_notifier_mm_init(struct mm_struct *mm)
239{
240 mm->mmu_notifier_mm = NULL;
241}
242
243static inline void mmu_notifier_mm_destroy(struct mm_struct *mm)
244{
245 if (mm_has_notifiers(mm))
246 __mmu_notifier_mm_destroy(mm);
247}
248
249#define ptep_clear_flush_young_notify(__vma, __address, __ptep) \
250({ \
251 int __young; \
252 struct vm_area_struct *___vma = __vma; \
253 unsigned long ___address = __address; \
254 __young = ptep_clear_flush_young(___vma, ___address, __ptep); \
255 __young |= mmu_notifier_clear_flush_young(___vma->vm_mm, \
256 ___address); \
257 __young; \
258})
259
260#define pmdp_clear_flush_young_notify(__vma, __address, __pmdp) \
261({ \
262 int __young; \
263 struct vm_area_struct *___vma = __vma; \
264 unsigned long ___address = __address; \
265 __young = pmdp_clear_flush_young(___vma, ___address, __pmdp); \
266 __young |= mmu_notifier_clear_flush_young(___vma->vm_mm, \
267 ___address); \
268 __young; \
269})
270
271
272
273
274
275
276
277
278
279
280
281#define set_pte_at_notify(__mm, __address, __ptep, __pte) \
282({ \
283 struct mm_struct *___mm = __mm; \
284 unsigned long ___address = __address; \
285 pte_t ___pte = __pte; \
286 \
287 mmu_notifier_change_pte(___mm, ___address, ___pte); \
288 set_pte_at(___mm, ___address, __ptep, ___pte); \
289})
290
291#else
292
293static inline void mmu_notifier_release(struct mm_struct *mm)
294{
295}
296
297static inline int mmu_notifier_clear_flush_young(struct mm_struct *mm,
298 unsigned long address)
299{
300 return 0;
301}
302
303static inline int mmu_notifier_test_young(struct mm_struct *mm,
304 unsigned long address)
305{
306 return 0;
307}
308
309static inline void mmu_notifier_change_pte(struct mm_struct *mm,
310 unsigned long address, pte_t pte)
311{
312}
313
314static inline void mmu_notifier_invalidate_page(struct mm_struct *mm,
315 unsigned long address)
316{
317}
318
319static inline void mmu_notifier_invalidate_range_start(struct mm_struct *mm,
320 unsigned long start, unsigned long end)
321{
322}
323
324static inline void mmu_notifier_invalidate_range_end(struct mm_struct *mm,
325 unsigned long start, unsigned long end)
326{
327}
328
329static inline void mmu_notifier_mm_init(struct mm_struct *mm)
330{
331}
332
333static inline void mmu_notifier_mm_destroy(struct mm_struct *mm)
334{
335}
336
337#define ptep_clear_flush_young_notify ptep_clear_flush_young
338#define pmdp_clear_flush_young_notify pmdp_clear_flush_young
339#define set_pte_at_notify set_pte_at
340
341#endif
342
343#endif
344