1
2
3
4
5
6
7
8
9
10
11
12#include <linux/rculist.h>
13#include <linux/mmu_notifier.h>
14#include <linux/export.h>
15#include <linux/mm.h>
16#include <linux/err.h>
17#include <linux/srcu.h>
18#include <linux/rcupdate.h>
19#include <linux/sched.h>
20#include <linux/slab.h>
21
22
23static struct srcu_struct srcu;
24
25
26
27
28
29
30
31
32
33
34
35
36
37void __mmu_notifier_release(struct mm_struct *mm)
38{
39 struct mmu_notifier *mn;
40 struct hlist_node *n;
41 int id;
42
43
44
45
46
47 id = srcu_read_lock(&srcu);
48 hlist_for_each_entry_rcu(mn, n, &mm->mmu_notifier_mm->list, hlist)
49
50
51
52
53
54
55
56 if (mn->ops->release)
57 mn->ops->release(mn, mm);
58 srcu_read_unlock(&srcu, id);
59
60 spin_lock(&mm->mmu_notifier_mm->lock);
61 while (unlikely(!hlist_empty(&mm->mmu_notifier_mm->list))) {
62 mn = hlist_entry(mm->mmu_notifier_mm->list.first,
63 struct mmu_notifier,
64 hlist);
65
66
67
68
69
70
71 hlist_del_init_rcu(&mn->hlist);
72 }
73 spin_unlock(&mm->mmu_notifier_mm->lock);
74
75
76
77
78
79
80
81
82
83
84 synchronize_srcu(&srcu);
85}
86
87
88
89
90
91
92int __mmu_notifier_clear_flush_young(struct mm_struct *mm,
93 unsigned long address)
94{
95 struct mmu_notifier *mn;
96 struct hlist_node *n;
97 int young = 0, id;
98
99 id = srcu_read_lock(&srcu);
100 hlist_for_each_entry_rcu(mn, n, &mm->mmu_notifier_mm->list, hlist) {
101 if (mn->ops->clear_flush_young)
102 young |= mn->ops->clear_flush_young(mn, mm, address);
103 }
104 srcu_read_unlock(&srcu, id);
105
106 return young;
107}
108
109int __mmu_notifier_test_young(struct mm_struct *mm,
110 unsigned long address)
111{
112 struct mmu_notifier *mn;
113 struct hlist_node *n;
114 int young = 0, id;
115
116 id = srcu_read_lock(&srcu);
117 hlist_for_each_entry_rcu(mn, n, &mm->mmu_notifier_mm->list, hlist) {
118 if (mn->ops->test_young) {
119 young = mn->ops->test_young(mn, mm, address);
120 if (young)
121 break;
122 }
123 }
124 srcu_read_unlock(&srcu, id);
125
126 return young;
127}
128
129void __mmu_notifier_change_pte(struct mm_struct *mm, unsigned long address,
130 pte_t pte)
131{
132 struct mmu_notifier *mn;
133 struct hlist_node *n;
134 int id;
135
136 id = srcu_read_lock(&srcu);
137 hlist_for_each_entry_rcu(mn, n, &mm->mmu_notifier_mm->list, hlist) {
138 if (mn->ops->change_pte)
139 mn->ops->change_pte(mn, mm, address, pte);
140 }
141 srcu_read_unlock(&srcu, id);
142}
143
144void __mmu_notifier_invalidate_page(struct mm_struct *mm,
145 unsigned long address)
146{
147 struct mmu_notifier *mn;
148 struct hlist_node *n;
149 int id;
150
151 id = srcu_read_lock(&srcu);
152 hlist_for_each_entry_rcu(mn, n, &mm->mmu_notifier_mm->list, hlist) {
153 if (mn->ops->invalidate_page)
154 mn->ops->invalidate_page(mn, mm, address);
155 }
156 srcu_read_unlock(&srcu, id);
157}
158
159void __mmu_notifier_invalidate_range_start(struct mm_struct *mm,
160 unsigned long start, unsigned long end)
161{
162 struct mmu_notifier *mn;
163 struct hlist_node *n;
164 int id;
165
166 id = srcu_read_lock(&srcu);
167 hlist_for_each_entry_rcu(mn, n, &mm->mmu_notifier_mm->list, hlist) {
168 if (mn->ops->invalidate_range_start)
169 mn->ops->invalidate_range_start(mn, mm, start, end);
170 }
171 srcu_read_unlock(&srcu, id);
172}
173
174void __mmu_notifier_invalidate_range_end(struct mm_struct *mm,
175 unsigned long start, unsigned long end)
176{
177 struct mmu_notifier *mn;
178 struct hlist_node *n;
179 int id;
180
181 id = srcu_read_lock(&srcu);
182 hlist_for_each_entry_rcu(mn, n, &mm->mmu_notifier_mm->list, hlist) {
183 if (mn->ops->invalidate_range_end)
184 mn->ops->invalidate_range_end(mn, mm, start, end);
185 }
186 srcu_read_unlock(&srcu, id);
187}
188
189static int do_mmu_notifier_register(struct mmu_notifier *mn,
190 struct mm_struct *mm,
191 int take_mmap_sem)
192{
193 struct mmu_notifier_mm *mmu_notifier_mm;
194 int ret;
195
196 BUG_ON(atomic_read(&mm->mm_users) <= 0);
197
198
199
200
201
202 BUG_ON(!srcu.per_cpu_ref);
203
204 ret = -ENOMEM;
205 mmu_notifier_mm = kmalloc(sizeof(struct mmu_notifier_mm), GFP_KERNEL);
206 if (unlikely(!mmu_notifier_mm))
207 goto out;
208
209 if (take_mmap_sem)
210 down_write(&mm->mmap_sem);
211 ret = mm_take_all_locks(mm);
212 if (unlikely(ret))
213 goto out_clean;
214
215 if (!mm_has_notifiers(mm)) {
216 INIT_HLIST_HEAD(&mmu_notifier_mm->list);
217 spin_lock_init(&mmu_notifier_mm->lock);
218
219 mm->mmu_notifier_mm = mmu_notifier_mm;
220 mmu_notifier_mm = NULL;
221 }
222 atomic_inc(&mm->mm_count);
223
224
225
226
227
228
229
230
231
232 spin_lock(&mm->mmu_notifier_mm->lock);
233 hlist_add_head(&mn->hlist, &mm->mmu_notifier_mm->list);
234 spin_unlock(&mm->mmu_notifier_mm->lock);
235
236 mm_drop_all_locks(mm);
237out_clean:
238 if (take_mmap_sem)
239 up_write(&mm->mmap_sem);
240 kfree(mmu_notifier_mm);
241out:
242 BUG_ON(atomic_read(&mm->mm_users) <= 0);
243 return ret;
244}
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259int mmu_notifier_register(struct mmu_notifier *mn, struct mm_struct *mm)
260{
261 return do_mmu_notifier_register(mn, mm, 1);
262}
263EXPORT_SYMBOL_GPL(mmu_notifier_register);
264
265
266
267
268
269int __mmu_notifier_register(struct mmu_notifier *mn, struct mm_struct *mm)
270{
271 return do_mmu_notifier_register(mn, mm, 0);
272}
273EXPORT_SYMBOL_GPL(__mmu_notifier_register);
274
275
276void __mmu_notifier_mm_destroy(struct mm_struct *mm)
277{
278 BUG_ON(!hlist_empty(&mm->mmu_notifier_mm->list));
279 kfree(mm->mmu_notifier_mm);
280 mm->mmu_notifier_mm = LIST_POISON1;
281}
282
283
284
285
286
287
288
289
290
291
292
293void mmu_notifier_unregister(struct mmu_notifier *mn, struct mm_struct *mm)
294{
295 BUG_ON(atomic_read(&mm->mm_count) <= 0);
296
297 if (!hlist_unhashed(&mn->hlist)) {
298
299
300
301
302 int id;
303
304 id = srcu_read_lock(&srcu);
305
306
307
308
309
310 if (mn->ops->release)
311 mn->ops->release(mn, mm);
312 srcu_read_unlock(&srcu, id);
313
314 spin_lock(&mm->mmu_notifier_mm->lock);
315 hlist_del_rcu(&mn->hlist);
316 spin_unlock(&mm->mmu_notifier_mm->lock);
317 }
318
319
320
321
322
323 synchronize_srcu(&srcu);
324
325 BUG_ON(atomic_read(&mm->mm_count) <= 0);
326
327 mmdrop(mm);
328}
329EXPORT_SYMBOL_GPL(mmu_notifier_unregister);
330
331static int __init mmu_notifier_init(void)
332{
333 return init_srcu_struct(&srcu);
334}
335
336module_init(mmu_notifier_init);
337