xref: /openbmc/linux/drivers/vfio/iommufd.c (revision c0d3b831)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (c) 2021-2022, NVIDIA CORPORATION & AFFILIATES
4  */
5 #include <linux/vfio.h>
6 #include <linux/iommufd.h>
7 
8 #include "vfio.h"
9 
10 MODULE_IMPORT_NS(IOMMUFD);
11 MODULE_IMPORT_NS(IOMMUFD_VFIO);
12 
13 int vfio_iommufd_bind(struct vfio_device *vdev, struct iommufd_ctx *ictx)
14 {
15 	u32 ioas_id;
16 	u32 device_id;
17 	int ret;
18 
19 	lockdep_assert_held(&vdev->dev_set->lock);
20 
21 	/*
22 	 * If the driver doesn't provide this op then it means the device does
23 	 * not do DMA at all. So nothing to do.
24 	 */
25 	if (!vdev->ops->bind_iommufd)
26 		return 0;
27 
28 	ret = vdev->ops->bind_iommufd(vdev, ictx, &device_id);
29 	if (ret)
30 		return ret;
31 
32 	ret = iommufd_vfio_compat_ioas_id(ictx, &ioas_id);
33 	if (ret)
34 		goto err_unbind;
35 	ret = vdev->ops->attach_ioas(vdev, &ioas_id);
36 	if (ret)
37 		goto err_unbind;
38 
39 	/*
40 	 * The legacy path has no way to return the device id or the selected
41 	 * pt_id
42 	 */
43 	return 0;
44 
45 err_unbind:
46 	if (vdev->ops->unbind_iommufd)
47 		vdev->ops->unbind_iommufd(vdev);
48 	return ret;
49 }
50 
51 void vfio_iommufd_unbind(struct vfio_device *vdev)
52 {
53 	lockdep_assert_held(&vdev->dev_set->lock);
54 
55 	if (vdev->ops->unbind_iommufd)
56 		vdev->ops->unbind_iommufd(vdev);
57 }
58 
59 /*
60  * The physical standard ops mean that the iommufd_device is bound to the
61  * physical device vdev->dev that was provided to vfio_init_group_dev(). Drivers
62  * using this ops set should call vfio_register_group_dev()
63  */
64 int vfio_iommufd_physical_bind(struct vfio_device *vdev,
65 			       struct iommufd_ctx *ictx, u32 *out_device_id)
66 {
67 	struct iommufd_device *idev;
68 
69 	idev = iommufd_device_bind(ictx, vdev->dev, out_device_id);
70 	if (IS_ERR(idev))
71 		return PTR_ERR(idev);
72 	vdev->iommufd_device = idev;
73 	return 0;
74 }
75 EXPORT_SYMBOL_GPL(vfio_iommufd_physical_bind);
76 
77 void vfio_iommufd_physical_unbind(struct vfio_device *vdev)
78 {
79 	lockdep_assert_held(&vdev->dev_set->lock);
80 
81 	if (vdev->iommufd_attached) {
82 		iommufd_device_detach(vdev->iommufd_device);
83 		vdev->iommufd_attached = false;
84 	}
85 	iommufd_device_unbind(vdev->iommufd_device);
86 	vdev->iommufd_device = NULL;
87 }
88 EXPORT_SYMBOL_GPL(vfio_iommufd_physical_unbind);
89 
90 int vfio_iommufd_physical_attach_ioas(struct vfio_device *vdev, u32 *pt_id)
91 {
92 	int rc;
93 
94 	rc = iommufd_device_attach(vdev->iommufd_device, pt_id);
95 	if (rc)
96 		return rc;
97 	vdev->iommufd_attached = true;
98 	return 0;
99 }
100 EXPORT_SYMBOL_GPL(vfio_iommufd_physical_attach_ioas);
101 
102 /*
103  * The emulated standard ops mean that vfio_device is going to use the
104  * "mdev path" and will call vfio_pin_pages()/vfio_dma_rw(). Drivers using this
105  * ops set should call vfio_register_emulated_iommu_dev().
106  */
107 
108 static void vfio_emulated_unmap(void *data, unsigned long iova,
109 				unsigned long length)
110 {
111 	struct vfio_device *vdev = data;
112 
113 	vdev->ops->dma_unmap(vdev, iova, length);
114 }
115 
116 static const struct iommufd_access_ops vfio_user_ops = {
117 	.needs_pin_pages = 1,
118 	.unmap = vfio_emulated_unmap,
119 };
120 
121 int vfio_iommufd_emulated_bind(struct vfio_device *vdev,
122 			       struct iommufd_ctx *ictx, u32 *out_device_id)
123 {
124 	lockdep_assert_held(&vdev->dev_set->lock);
125 
126 	vdev->iommufd_ictx = ictx;
127 	iommufd_ctx_get(ictx);
128 	return 0;
129 }
130 EXPORT_SYMBOL_GPL(vfio_iommufd_emulated_bind);
131 
132 void vfio_iommufd_emulated_unbind(struct vfio_device *vdev)
133 {
134 	lockdep_assert_held(&vdev->dev_set->lock);
135 
136 	if (vdev->iommufd_access) {
137 		iommufd_access_destroy(vdev->iommufd_access);
138 		vdev->iommufd_access = NULL;
139 	}
140 	iommufd_ctx_put(vdev->iommufd_ictx);
141 	vdev->iommufd_ictx = NULL;
142 }
143 EXPORT_SYMBOL_GPL(vfio_iommufd_emulated_unbind);
144 
145 int vfio_iommufd_emulated_attach_ioas(struct vfio_device *vdev, u32 *pt_id)
146 {
147 	struct iommufd_access *user;
148 
149 	lockdep_assert_held(&vdev->dev_set->lock);
150 
151 	user = iommufd_access_create(vdev->iommufd_ictx, *pt_id, &vfio_user_ops,
152 				     vdev);
153 	if (IS_ERR(user))
154 		return PTR_ERR(user);
155 	vdev->iommufd_access = user;
156 	return 0;
157 }
158 EXPORT_SYMBOL_GPL(vfio_iommufd_emulated_attach_ioas);
159