hc
2023-12-11 d2ccde1c8e90d38cee87a1b0309ad2827f3fd30d
kernel/drivers/infiniband/hw/hfi1/mmu_rb.c
....@@ -1,4 +1,5 @@
11 /*
2
+ * Copyright(c) 2020 Cornelis Networks, Inc.
23 * Copyright(c) 2016 - 2017 Intel Corporation.
34 *
45 * This file is provided under a dual BSD/GPLv2 license. When using or
....@@ -48,28 +49,15 @@
4849 #include <linux/rculist.h>
4950 #include <linux/mmu_notifier.h>
5051 #include <linux/interval_tree_generic.h>
52
+#include <linux/sched/mm.h>
5153
5254 #include "mmu_rb.h"
5355 #include "trace.h"
5456
55
-struct mmu_rb_handler {
56
- struct mmu_notifier mn;
57
- struct rb_root_cached root;
58
- void *ops_arg;
59
- spinlock_t lock; /* protect the RB tree */
60
- struct mmu_rb_ops *ops;
61
- struct mm_struct *mm;
62
- struct list_head lru_list;
63
- struct work_struct del_work;
64
- struct list_head del_list;
65
- struct workqueue_struct *wq;
66
-};
67
-
6857 static unsigned long mmu_node_start(struct mmu_rb_node *);
6958 static unsigned long mmu_node_last(struct mmu_rb_node *);
7059 static int mmu_notifier_range_start(struct mmu_notifier *,
71
- struct mm_struct *,
72
- unsigned long, unsigned long, bool);
60
+ const struct mmu_notifier_range *);
7361 static struct mmu_rb_node *__mmu_rb_search(struct mmu_rb_handler *,
7462 unsigned long, unsigned long);
7563 static void do_remove(struct mmu_rb_handler *handler,
....@@ -77,7 +65,6 @@
7765 static void handle_remove(struct work_struct *work);
7866
7967 static const struct mmu_notifier_ops mn_opts = {
80
- .flags = MMU_INVALIDATE_DOES_NOT_BLOCK,
8168 .invalidate_range_start = mmu_notifier_range_start,
8269 };
8370
....@@ -94,37 +81,36 @@
9481 return PAGE_ALIGN(node->addr + node->len) - 1;
9582 }
9683
97
-int hfi1_mmu_rb_register(void *ops_arg, struct mm_struct *mm,
84
+int hfi1_mmu_rb_register(void *ops_arg,
9885 struct mmu_rb_ops *ops,
9986 struct workqueue_struct *wq,
10087 struct mmu_rb_handler **handler)
10188 {
102
- struct mmu_rb_handler *handlr;
89
+ struct mmu_rb_handler *h;
10390 int ret;
10491
105
- handlr = kmalloc(sizeof(*handlr), GFP_KERNEL);
106
- if (!handlr)
92
+ h = kzalloc(sizeof(*h), GFP_KERNEL);
93
+ if (!h)
10794 return -ENOMEM;
10895
109
- handlr->root = RB_ROOT_CACHED;
110
- handlr->ops = ops;
111
- handlr->ops_arg = ops_arg;
112
- INIT_HLIST_NODE(&handlr->mn.hlist);
113
- spin_lock_init(&handlr->lock);
114
- handlr->mn.ops = &mn_opts;
115
- handlr->mm = mm;
116
- INIT_WORK(&handlr->del_work, handle_remove);
117
- INIT_LIST_HEAD(&handlr->del_list);
118
- INIT_LIST_HEAD(&handlr->lru_list);
119
- handlr->wq = wq;
96
+ h->root = RB_ROOT_CACHED;
97
+ h->ops = ops;
98
+ h->ops_arg = ops_arg;
99
+ INIT_HLIST_NODE(&h->mn.hlist);
100
+ spin_lock_init(&h->lock);
101
+ h->mn.ops = &mn_opts;
102
+ INIT_WORK(&h->del_work, handle_remove);
103
+ INIT_LIST_HEAD(&h->del_list);
104
+ INIT_LIST_HEAD(&h->lru_list);
105
+ h->wq = wq;
120106
121
- ret = mmu_notifier_register(&handlr->mn, handlr->mm);
107
+ ret = mmu_notifier_register(&h->mn, current->mm);
122108 if (ret) {
123
- kfree(handlr);
109
+ kfree(h);
124110 return ret;
125111 }
126112
127
- *handler = handlr;
113
+ *handler = h;
128114 return 0;
129115 }
130116
....@@ -135,8 +121,11 @@
135121 unsigned long flags;
136122 struct list_head del_list;
137123
124
+ /* Prevent freeing of mm until we are completely finished. */
125
+ mmgrab(handler->mn.mm);
126
+
138127 /* Unregister first so we don't get any more notifications. */
139
- mmu_notifier_unregister(&handler->mn, handler->mm);
128
+ mmu_notifier_unregister(&handler->mn, handler->mn.mm);
140129
141130 /*
142131 * Make sure the wq delete handler is finished running. It will not
....@@ -157,6 +146,9 @@
157146
158147 do_remove(handler, &del_list);
159148
149
+ /* Now the mm may be freed. */
150
+ mmdrop(handler->mn.mm);
151
+
160152 kfree(handler);
161153 }
162154
....@@ -168,6 +160,10 @@
168160 int ret = 0;
169161
170162 trace_hfi1_mmu_rb_insert(mnode->addr, mnode->len);
163
+
164
+ if (current->mm != handler->mn.mm)
165
+ return -EPERM;
166
+
171167 spin_lock_irqsave(&handler->lock, flags);
172168 node = __mmu_rb_search(handler, mnode->addr, mnode->len);
173169 if (node) {
....@@ -182,6 +178,7 @@
182178 __mmu_int_rb_remove(mnode, &handler->root);
183179 list_del(&mnode->list); /* remove from LRU list */
184180 }
181
+ mnode->handler = handler;
185182 unlock:
186183 spin_unlock_irqrestore(&handler->lock, flags);
187184 return ret;
....@@ -219,6 +216,9 @@
219216 unsigned long flags;
220217 bool ret = false;
221218
219
+ if (current->mm != handler->mn.mm)
220
+ return ret;
221
+
222222 spin_lock_irqsave(&handler->lock, flags);
223223 node = __mmu_rb_search(handler, addr, len);
224224 if (node) {
....@@ -240,6 +240,9 @@
240240 struct list_head del_list;
241241 unsigned long flags;
242242 bool stop = false;
243
+
244
+ if (current->mm != handler->mn.mm)
245
+ return;
243246
244247 INIT_LIST_HEAD(&del_list);
245248
....@@ -274,6 +277,9 @@
274277 {
275278 unsigned long flags;
276279
280
+ if (current->mm != handler->mn.mm)
281
+ return;
282
+
277283 /* Validity of handler and node pointers has been checked by caller. */
278284 trace_hfi1_mmu_rb_remove(node->addr, node->len);
279285 spin_lock_irqsave(&handler->lock, flags);
....@@ -285,10 +291,7 @@
285291 }
286292
287293 static int mmu_notifier_range_start(struct mmu_notifier *mn,
288
- struct mm_struct *mm,
289
- unsigned long start,
290
- unsigned long end,
291
- bool blockable)
294
+ const struct mmu_notifier_range *range)
292295 {
293296 struct mmu_rb_handler *handler =
294297 container_of(mn, struct mmu_rb_handler, mn);
....@@ -298,10 +301,11 @@
298301 bool added = false;
299302
300303 spin_lock_irqsave(&handler->lock, flags);
301
- for (node = __mmu_int_rb_iter_first(root, start, end - 1);
304
+ for (node = __mmu_int_rb_iter_first(root, range->start, range->end-1);
302305 node; node = ptr) {
303306 /* Guard against node removal. */
304
- ptr = __mmu_int_rb_iter_next(node, start, end - 1);
307
+ ptr = __mmu_int_rb_iter_next(node, range->start,
308
+ range->end - 1);
305309 trace_hfi1_mmu_mem_invalidate(node->addr, node->len);
306310 if (handler->ops->invalidate(handler->ops_arg, node)) {
307311 __mmu_int_rb_remove(node, root);
....@@ -337,7 +341,7 @@
337341
338342 /*
339343 * Work queue function to remove all nodes that have been queued up to
340
- * be removed. The key feature is that mm->mmap_sem is not being held
344
+ * be removed. The key feature is that mm->mmap_lock is not being held
341345 * and the remove callback can sleep while taking it, if needed.
342346 */
343347 static void handle_remove(struct work_struct *work)