xref: /linux/drivers/iommu/iommufd/eventq.c (revision fbf5df34a4dbcd09d433dd4f0916bf9b2ddb16de)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /* Copyright (C) 2024 Intel Corporation
3  */
4 #define pr_fmt(fmt) "iommufd: " fmt
5 
6 #include <linux/anon_inodes.h>
7 #include <linux/file.h>
8 #include <linux/fs.h>
9 #include <linux/iommufd.h>
10 #include <linux/module.h>
11 #include <linux/mutex.h>
12 #include <linux/poll.h>
13 #include <uapi/linux/iommufd.h>
14 
15 #include "../iommu-priv.h"
16 #include "iommufd_private.h"
17 
18 /* IOMMUFD_OBJ_FAULT Functions */
19 void iommufd_auto_response_faults(struct iommufd_hw_pagetable *hwpt,
20 				  struct iommufd_attach_handle *handle)
21 {
22 	struct iommufd_fault *fault = hwpt->fault;
23 	struct iopf_group *group, *next;
24 	struct list_head free_list;
25 	unsigned long index;
26 
27 	if (!fault || !handle)
28 		return;
29 	INIT_LIST_HEAD(&free_list);
30 
31 	mutex_lock(&fault->mutex);
32 	spin_lock(&fault->common.lock);
33 	list_for_each_entry_safe(group, next, &fault->common.deliver, node) {
34 		if (group->attach_handle != &handle->handle)
35 			continue;
36 		list_move(&group->node, &free_list);
37 	}
38 	spin_unlock(&fault->common.lock);
39 
40 	list_for_each_entry_safe(group, next, &free_list, node) {
41 		list_del(&group->node);
42 		iopf_group_response(group, IOMMU_PAGE_RESP_INVALID);
43 		iopf_free_group(group);
44 	}
45 
46 	xa_for_each(&fault->response, index, group) {
47 		if (group->attach_handle != &handle->handle)
48 			continue;
49 		xa_erase(&fault->response, index);
50 		iopf_group_response(group, IOMMU_PAGE_RESP_INVALID);
51 		iopf_free_group(group);
52 	}
53 	mutex_unlock(&fault->mutex);
54 }
55 
56 void iommufd_fault_destroy(struct iommufd_object *obj)
57 {
58 	struct iommufd_eventq *eventq =
59 		container_of(obj, struct iommufd_eventq, obj);
60 	struct iommufd_fault *fault = eventq_to_fault(eventq);
61 	struct iopf_group *group, *next;
62 	unsigned long index;
63 
64 	/*
65 	 * The iommufd object's reference count is zero at this point.
66 	 * We can be confident that no other threads are currently
67 	 * accessing this pointer. Therefore, acquiring the mutex here
68 	 * is unnecessary.
69 	 */
70 	list_for_each_entry_safe(group, next, &fault->common.deliver, node) {
71 		list_del(&group->node);
72 		iopf_group_response(group, IOMMU_PAGE_RESP_INVALID);
73 		iopf_free_group(group);
74 	}
75 	xa_for_each(&fault->response, index, group) {
76 		xa_erase(&fault->response, index);
77 		iopf_group_response(group, IOMMU_PAGE_RESP_INVALID);
78 		iopf_free_group(group);
79 	}
80 	xa_destroy(&fault->response);
81 	mutex_destroy(&fault->mutex);
82 }
83 
84 static void iommufd_compose_fault_message(struct iommu_fault *fault,
85 					  struct iommu_hwpt_pgfault *hwpt_fault,
86 					  struct iommufd_device *idev,
87 					  u32 cookie)
88 {
89 	hwpt_fault->flags = fault->prm.flags;
90 	hwpt_fault->dev_id = idev->obj.id;
91 	hwpt_fault->pasid = fault->prm.pasid;
92 	hwpt_fault->grpid = fault->prm.grpid;
93 	hwpt_fault->perm = fault->prm.perm;
94 	hwpt_fault->addr = fault->prm.addr;
95 	hwpt_fault->length = 0;
96 	hwpt_fault->cookie = cookie;
97 }
98 
99 /* Fetch the first node out of the fault->deliver list */
100 static struct iopf_group *
101 iommufd_fault_deliver_fetch(struct iommufd_fault *fault)
102 {
103 	struct list_head *list = &fault->common.deliver;
104 	struct iopf_group *group = NULL;
105 
106 	spin_lock(&fault->common.lock);
107 	if (!list_empty(list)) {
108 		group = list_first_entry(list, struct iopf_group, node);
109 		list_del(&group->node);
110 	}
111 	spin_unlock(&fault->common.lock);
112 	return group;
113 }
114 
115 /* Restore a node back to the head of the fault->deliver list */
116 static void iommufd_fault_deliver_restore(struct iommufd_fault *fault,
117 					  struct iopf_group *group)
118 {
119 	spin_lock(&fault->common.lock);
120 	list_add(&group->node, &fault->common.deliver);
121 	spin_unlock(&fault->common.lock);
122 }
123 
124 static ssize_t iommufd_fault_fops_read(struct file *filep, char __user *buf,
125 				       size_t count, loff_t *ppos)
126 {
127 	size_t fault_size = sizeof(struct iommu_hwpt_pgfault);
128 	struct iommufd_eventq *eventq = filep->private_data;
129 	struct iommufd_fault *fault = eventq_to_fault(eventq);
130 	struct iommu_hwpt_pgfault data = {};
131 	struct iommufd_device *idev;
132 	struct iopf_group *group;
133 	struct iopf_fault *iopf;
134 	size_t done = 0;
135 	int rc = 0;
136 
137 	if (*ppos || count % fault_size)
138 		return -ESPIPE;
139 
140 	mutex_lock(&fault->mutex);
141 	while ((group = iommufd_fault_deliver_fetch(fault))) {
142 		if (done >= count ||
143 		    group->fault_count * fault_size > count - done) {
144 			iommufd_fault_deliver_restore(fault, group);
145 			break;
146 		}
147 
148 		rc = xa_alloc(&fault->response, &group->cookie, group,
149 			      xa_limit_32b, GFP_KERNEL);
150 		if (rc) {
151 			iommufd_fault_deliver_restore(fault, group);
152 			break;
153 		}
154 
155 		idev = to_iommufd_handle(group->attach_handle)->idev;
156 		list_for_each_entry(iopf, &group->faults, list) {
157 			iommufd_compose_fault_message(&iopf->fault,
158 						      &data, idev,
159 						      group->cookie);
160 			if (copy_to_user(buf + done, &data, fault_size)) {
161 				xa_erase(&fault->response, group->cookie);
162 				iommufd_fault_deliver_restore(fault, group);
163 				rc = -EFAULT;
164 				break;
165 			}
166 			done += fault_size;
167 		}
168 	}
169 	mutex_unlock(&fault->mutex);
170 
171 	return done == 0 ? rc : done;
172 }
173 
174 static ssize_t iommufd_fault_fops_write(struct file *filep, const char __user *buf,
175 					size_t count, loff_t *ppos)
176 {
177 	size_t response_size = sizeof(struct iommu_hwpt_page_response);
178 	struct iommufd_eventq *eventq = filep->private_data;
179 	struct iommufd_fault *fault = eventq_to_fault(eventq);
180 	struct iommu_hwpt_page_response response;
181 	struct iopf_group *group;
182 	size_t done = 0;
183 	int rc = 0;
184 
185 	if (*ppos || count % response_size)
186 		return -ESPIPE;
187 
188 	mutex_lock(&fault->mutex);
189 	while (count > done) {
190 		if (copy_from_user(&response, buf + done, response_size)) {
191 			rc = -EFAULT;
192 			break;
193 		}
194 
195 		static_assert((int)IOMMUFD_PAGE_RESP_SUCCESS ==
196 			      (int)IOMMU_PAGE_RESP_SUCCESS);
197 		static_assert((int)IOMMUFD_PAGE_RESP_INVALID ==
198 			      (int)IOMMU_PAGE_RESP_INVALID);
199 		if (response.code != IOMMUFD_PAGE_RESP_SUCCESS &&
200 		    response.code != IOMMUFD_PAGE_RESP_INVALID) {
201 			rc = -EINVAL;
202 			break;
203 		}
204 
205 		group = xa_erase(&fault->response, response.cookie);
206 		if (!group) {
207 			rc = -EINVAL;
208 			break;
209 		}
210 
211 		iopf_group_response(group, response.code);
212 		iopf_free_group(group);
213 		done += response_size;
214 	}
215 	mutex_unlock(&fault->mutex);
216 
217 	return done == 0 ? rc : done;
218 }
219 
220 /* IOMMUFD_OBJ_VEVENTQ Functions */
221 
222 void iommufd_veventq_abort(struct iommufd_object *obj)
223 {
224 	struct iommufd_eventq *eventq =
225 		container_of(obj, struct iommufd_eventq, obj);
226 	struct iommufd_veventq *veventq = eventq_to_veventq(eventq);
227 	struct iommufd_viommu *viommu = veventq->viommu;
228 	struct iommufd_vevent *cur, *next;
229 
230 	lockdep_assert_held_write(&viommu->veventqs_rwsem);
231 
232 	list_for_each_entry_safe(cur, next, &eventq->deliver, node) {
233 		list_del(&cur->node);
234 		if (cur != &veventq->lost_events_header)
235 			kfree(cur);
236 	}
237 
238 	refcount_dec(&viommu->obj.users);
239 	list_del(&veventq->node);
240 }
241 
242 void iommufd_veventq_destroy(struct iommufd_object *obj)
243 {
244 	struct iommufd_veventq *veventq = eventq_to_veventq(
245 		container_of(obj, struct iommufd_eventq, obj));
246 
247 	down_write(&veventq->viommu->veventqs_rwsem);
248 	iommufd_veventq_abort(obj);
249 	up_write(&veventq->viommu->veventqs_rwsem);
250 }
251 
252 static struct iommufd_vevent *
253 iommufd_veventq_deliver_fetch(struct iommufd_veventq *veventq)
254 {
255 	struct iommufd_eventq *eventq = &veventq->common;
256 	struct list_head *list = &eventq->deliver;
257 	struct iommufd_vevent *vevent = NULL;
258 
259 	spin_lock(&eventq->lock);
260 	if (!list_empty(list)) {
261 		struct iommufd_vevent *next;
262 
263 		next = list_first_entry(list, struct iommufd_vevent, node);
264 		/* Make a copy of the lost_events_header for copy_to_user */
265 		if (next == &veventq->lost_events_header) {
266 			vevent = kzalloc_obj(*vevent, GFP_ATOMIC);
267 			if (!vevent)
268 				goto out_unlock;
269 		}
270 		list_del(&next->node);
271 		if (vevent)
272 			memcpy(vevent, next, sizeof(*vevent));
273 		else
274 			vevent = next;
275 	}
276 out_unlock:
277 	spin_unlock(&eventq->lock);
278 	return vevent;
279 }
280 
281 static void iommufd_veventq_deliver_restore(struct iommufd_veventq *veventq,
282 					    struct iommufd_vevent *vevent)
283 {
284 	struct iommufd_eventq *eventq = &veventq->common;
285 	struct list_head *list = &eventq->deliver;
286 
287 	spin_lock(&eventq->lock);
288 	if (vevent_for_lost_events_header(vevent)) {
289 		/* Remove the copy of the lost_events_header */
290 		kfree(vevent);
291 		vevent = NULL;
292 		/* An empty list needs the lost_events_header back */
293 		if (list_empty(list))
294 			vevent = &veventq->lost_events_header;
295 	}
296 	if (vevent)
297 		list_add(&vevent->node, list);
298 	spin_unlock(&eventq->lock);
299 }
300 
301 static ssize_t iommufd_veventq_fops_read(struct file *filep, char __user *buf,
302 					 size_t count, loff_t *ppos)
303 {
304 	struct iommufd_eventq *eventq = filep->private_data;
305 	struct iommufd_veventq *veventq = eventq_to_veventq(eventq);
306 	struct iommufd_vevent_header *hdr;
307 	struct iommufd_vevent *cur;
308 	size_t done = 0;
309 	int rc = 0;
310 
311 	if (*ppos)
312 		return -ESPIPE;
313 
314 	while ((cur = iommufd_veventq_deliver_fetch(veventq))) {
315 		/* Validate the remaining bytes against the header size */
316 		if (done >= count || sizeof(*hdr) > count - done) {
317 			iommufd_veventq_deliver_restore(veventq, cur);
318 			break;
319 		}
320 		hdr = &cur->header;
321 
322 		/* If being a normal vEVENT, validate against the full size */
323 		if (!vevent_for_lost_events_header(cur) &&
324 		    sizeof(hdr) + cur->data_len > count - done) {
325 			iommufd_veventq_deliver_restore(veventq, cur);
326 			break;
327 		}
328 
329 		if (copy_to_user(buf + done, hdr, sizeof(*hdr))) {
330 			iommufd_veventq_deliver_restore(veventq, cur);
331 			rc = -EFAULT;
332 			break;
333 		}
334 		done += sizeof(*hdr);
335 
336 		if (cur->data_len &&
337 		    copy_to_user(buf + done, cur->event_data, cur->data_len)) {
338 			iommufd_veventq_deliver_restore(veventq, cur);
339 			rc = -EFAULT;
340 			break;
341 		}
342 		spin_lock(&eventq->lock);
343 		if (!vevent_for_lost_events_header(cur))
344 			veventq->num_events--;
345 		spin_unlock(&eventq->lock);
346 		done += cur->data_len;
347 		kfree(cur);
348 	}
349 
350 	return done == 0 ? rc : done;
351 }
352 
353 /* Common Event Queue Functions */
354 
355 static __poll_t iommufd_eventq_fops_poll(struct file *filep,
356 					 struct poll_table_struct *wait)
357 {
358 	struct iommufd_eventq *eventq = filep->private_data;
359 	__poll_t pollflags = 0;
360 
361 	if (eventq->obj.type == IOMMUFD_OBJ_FAULT)
362 		pollflags |= EPOLLOUT;
363 
364 	poll_wait(filep, &eventq->wait_queue, wait);
365 	spin_lock(&eventq->lock);
366 	if (!list_empty(&eventq->deliver))
367 		pollflags |= EPOLLIN | EPOLLRDNORM;
368 	spin_unlock(&eventq->lock);
369 
370 	return pollflags;
371 }
372 
373 static int iommufd_eventq_fops_release(struct inode *inode, struct file *filep)
374 {
375 	struct iommufd_eventq *eventq = filep->private_data;
376 
377 	refcount_dec(&eventq->obj.users);
378 	iommufd_ctx_put(eventq->ictx);
379 	return 0;
380 }
381 
382 #define INIT_EVENTQ_FOPS(read_op, write_op)                                    \
383 	((const struct file_operations){                                       \
384 		.owner = THIS_MODULE,                                          \
385 		.open = nonseekable_open,                                      \
386 		.read = read_op,                                               \
387 		.write = write_op,                                             \
388 		.poll = iommufd_eventq_fops_poll,                              \
389 		.release = iommufd_eventq_fops_release,                        \
390 	})
391 
392 static int iommufd_eventq_init(struct iommufd_eventq *eventq, char *name,
393 			       struct iommufd_ctx *ictx,
394 			       const struct file_operations *fops)
395 {
396 	struct file *filep;
397 
398 	spin_lock_init(&eventq->lock);
399 	INIT_LIST_HEAD(&eventq->deliver);
400 	init_waitqueue_head(&eventq->wait_queue);
401 
402 	/* The filep is fput() by the core code during failure */
403 	filep = anon_inode_getfile(name, fops, eventq, O_RDWR);
404 	if (IS_ERR(filep))
405 		return PTR_ERR(filep);
406 
407 	eventq->ictx = ictx;
408 	iommufd_ctx_get(eventq->ictx);
409 	eventq->filep = filep;
410 	refcount_inc(&eventq->obj.users);
411 
412 	return get_unused_fd_flags(O_CLOEXEC);
413 }
414 
415 static const struct file_operations iommufd_fault_fops =
416 	INIT_EVENTQ_FOPS(iommufd_fault_fops_read, iommufd_fault_fops_write);
417 
418 int iommufd_fault_alloc(struct iommufd_ucmd *ucmd)
419 {
420 	struct iommu_fault_alloc *cmd = ucmd->cmd;
421 	struct iommufd_fault *fault;
422 	int fdno;
423 	int rc;
424 
425 	if (cmd->flags)
426 		return -EOPNOTSUPP;
427 
428 	fault = __iommufd_object_alloc_ucmd(ucmd, fault, IOMMUFD_OBJ_FAULT,
429 					    common.obj);
430 	if (IS_ERR(fault))
431 		return PTR_ERR(fault);
432 
433 	xa_init_flags(&fault->response, XA_FLAGS_ALLOC1);
434 	mutex_init(&fault->mutex);
435 
436 	fdno = iommufd_eventq_init(&fault->common, "[iommufd-pgfault]",
437 				   ucmd->ictx, &iommufd_fault_fops);
438 	if (fdno < 0)
439 		return fdno;
440 
441 	cmd->out_fault_id = fault->common.obj.id;
442 	cmd->out_fault_fd = fdno;
443 
444 	rc = iommufd_ucmd_respond(ucmd, sizeof(*cmd));
445 	if (rc)
446 		goto out_put_fdno;
447 
448 	fd_install(fdno, fault->common.filep);
449 
450 	return 0;
451 out_put_fdno:
452 	put_unused_fd(fdno);
453 	return rc;
454 }
455 
456 int iommufd_fault_iopf_handler(struct iopf_group *group)
457 {
458 	struct iommufd_hw_pagetable *hwpt;
459 	struct iommufd_fault *fault;
460 
461 	hwpt = group->attach_handle->domain->iommufd_hwpt;
462 	fault = hwpt->fault;
463 
464 	spin_lock(&fault->common.lock);
465 	list_add_tail(&group->node, &fault->common.deliver);
466 	spin_unlock(&fault->common.lock);
467 
468 	wake_up_interruptible(&fault->common.wait_queue);
469 
470 	return 0;
471 }
472 
473 static const struct file_operations iommufd_veventq_fops =
474 	INIT_EVENTQ_FOPS(iommufd_veventq_fops_read, NULL);
475 
476 int iommufd_veventq_alloc(struct iommufd_ucmd *ucmd)
477 {
478 	struct iommu_veventq_alloc *cmd = ucmd->cmd;
479 	struct iommufd_veventq *veventq;
480 	struct iommufd_viommu *viommu;
481 	int fdno;
482 	int rc;
483 
484 	if (cmd->flags || cmd->__reserved ||
485 	    cmd->type == IOMMU_VEVENTQ_TYPE_DEFAULT)
486 		return -EOPNOTSUPP;
487 	if (!cmd->veventq_depth)
488 		return -EINVAL;
489 
490 	viommu = iommufd_get_viommu(ucmd, cmd->viommu_id);
491 	if (IS_ERR(viommu))
492 		return PTR_ERR(viommu);
493 
494 	down_write(&viommu->veventqs_rwsem);
495 
496 	if (iommufd_viommu_find_veventq(viommu, cmd->type)) {
497 		rc = -EEXIST;
498 		goto out_unlock_veventqs;
499 	}
500 
501 	veventq = __iommufd_object_alloc(ucmd->ictx, veventq,
502 					 IOMMUFD_OBJ_VEVENTQ, common.obj);
503 	if (IS_ERR(veventq)) {
504 		rc = PTR_ERR(veventq);
505 		goto out_unlock_veventqs;
506 	}
507 
508 	veventq->type = cmd->type;
509 	veventq->viommu = viommu;
510 	refcount_inc(&viommu->obj.users);
511 	veventq->depth = cmd->veventq_depth;
512 	list_add_tail(&veventq->node, &viommu->veventqs);
513 	veventq->lost_events_header.header.flags =
514 		IOMMU_VEVENTQ_FLAG_LOST_EVENTS;
515 
516 	fdno = iommufd_eventq_init(&veventq->common, "[iommufd-viommu-event]",
517 				   ucmd->ictx, &iommufd_veventq_fops);
518 	if (fdno < 0) {
519 		rc = fdno;
520 		goto out_abort;
521 	}
522 
523 	cmd->out_veventq_id = veventq->common.obj.id;
524 	cmd->out_veventq_fd = fdno;
525 
526 	rc = iommufd_ucmd_respond(ucmd, sizeof(*cmd));
527 	if (rc)
528 		goto out_put_fdno;
529 
530 	iommufd_object_finalize(ucmd->ictx, &veventq->common.obj);
531 	fd_install(fdno, veventq->common.filep);
532 	goto out_unlock_veventqs;
533 
534 out_put_fdno:
535 	put_unused_fd(fdno);
536 out_abort:
537 	iommufd_object_abort_and_destroy(ucmd->ictx, &veventq->common.obj);
538 out_unlock_veventqs:
539 	up_write(&viommu->veventqs_rwsem);
540 	iommufd_put_object(ucmd->ictx, &viommu->obj);
541 	return rc;
542 }
543