Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v6.3-rc4 175 lines 4.3 kB view raw
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 10MODULE_IMPORT_NS(IOMMUFD); 11MODULE_IMPORT_NS(IOMMUFD_VFIO); 12 13int 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 if (vfio_device_is_noiommu(vdev)) { 22 if (!capable(CAP_SYS_RAWIO)) 23 return -EPERM; 24 25 /* 26 * Require no compat ioas to be assigned to proceed. The basic 27 * statement is that the user cannot have done something that 28 * implies they expected translation to exist 29 */ 30 if (!iommufd_vfio_compat_ioas_get_id(ictx, &ioas_id)) 31 return -EPERM; 32 return 0; 33 } 34 35 /* 36 * If the driver doesn't provide this op then it means the device does 37 * not do DMA at all. So nothing to do. 38 */ 39 if (!vdev->ops->bind_iommufd) 40 return 0; 41 42 ret = vdev->ops->bind_iommufd(vdev, ictx, &device_id); 43 if (ret) 44 return ret; 45 46 ret = iommufd_vfio_compat_ioas_get_id(ictx, &ioas_id); 47 if (ret) 48 goto err_unbind; 49 ret = vdev->ops->attach_ioas(vdev, &ioas_id); 50 if (ret) 51 goto err_unbind; 52 53 /* 54 * The legacy path has no way to return the device id or the selected 55 * pt_id 56 */ 57 return 0; 58 59err_unbind: 60 if (vdev->ops->unbind_iommufd) 61 vdev->ops->unbind_iommufd(vdev); 62 return ret; 63} 64 65void vfio_iommufd_unbind(struct vfio_device *vdev) 66{ 67 lockdep_assert_held(&vdev->dev_set->lock); 68 69 if (vfio_device_is_noiommu(vdev)) 70 return; 71 72 if (vdev->ops->unbind_iommufd) 73 vdev->ops->unbind_iommufd(vdev); 74} 75 76/* 77 * The physical standard ops mean that the iommufd_device is bound to the 78 * physical device vdev->dev that was provided to vfio_init_group_dev(). Drivers 79 * using this ops set should call vfio_register_group_dev() 80 */ 81int vfio_iommufd_physical_bind(struct vfio_device *vdev, 82 struct iommufd_ctx *ictx, u32 *out_device_id) 83{ 84 struct iommufd_device *idev; 85 86 idev = iommufd_device_bind(ictx, vdev->dev, out_device_id); 87 if (IS_ERR(idev)) 88 return PTR_ERR(idev); 89 vdev->iommufd_device = idev; 90 return 0; 91} 92EXPORT_SYMBOL_GPL(vfio_iommufd_physical_bind); 93 94void vfio_iommufd_physical_unbind(struct vfio_device *vdev) 95{ 96 lockdep_assert_held(&vdev->dev_set->lock); 97 98 if (vdev->iommufd_attached) { 99 iommufd_device_detach(vdev->iommufd_device); 100 vdev->iommufd_attached = false; 101 } 102 iommufd_device_unbind(vdev->iommufd_device); 103 vdev->iommufd_device = NULL; 104} 105EXPORT_SYMBOL_GPL(vfio_iommufd_physical_unbind); 106 107int vfio_iommufd_physical_attach_ioas(struct vfio_device *vdev, u32 *pt_id) 108{ 109 int rc; 110 111 rc = iommufd_device_attach(vdev->iommufd_device, pt_id); 112 if (rc) 113 return rc; 114 vdev->iommufd_attached = true; 115 return 0; 116} 117EXPORT_SYMBOL_GPL(vfio_iommufd_physical_attach_ioas); 118 119/* 120 * The emulated standard ops mean that vfio_device is going to use the 121 * "mdev path" and will call vfio_pin_pages()/vfio_dma_rw(). Drivers using this 122 * ops set should call vfio_register_emulated_iommu_dev(). 123 */ 124 125static void vfio_emulated_unmap(void *data, unsigned long iova, 126 unsigned long length) 127{ 128 struct vfio_device *vdev = data; 129 130 vdev->ops->dma_unmap(vdev, iova, length); 131} 132 133static const struct iommufd_access_ops vfio_user_ops = { 134 .needs_pin_pages = 1, 135 .unmap = vfio_emulated_unmap, 136}; 137 138int vfio_iommufd_emulated_bind(struct vfio_device *vdev, 139 struct iommufd_ctx *ictx, u32 *out_device_id) 140{ 141 lockdep_assert_held(&vdev->dev_set->lock); 142 143 vdev->iommufd_ictx = ictx; 144 iommufd_ctx_get(ictx); 145 return 0; 146} 147EXPORT_SYMBOL_GPL(vfio_iommufd_emulated_bind); 148 149void vfio_iommufd_emulated_unbind(struct vfio_device *vdev) 150{ 151 lockdep_assert_held(&vdev->dev_set->lock); 152 153 if (vdev->iommufd_access) { 154 iommufd_access_destroy(vdev->iommufd_access); 155 vdev->iommufd_access = NULL; 156 } 157 iommufd_ctx_put(vdev->iommufd_ictx); 158 vdev->iommufd_ictx = NULL; 159} 160EXPORT_SYMBOL_GPL(vfio_iommufd_emulated_unbind); 161 162int vfio_iommufd_emulated_attach_ioas(struct vfio_device *vdev, u32 *pt_id) 163{ 164 struct iommufd_access *user; 165 166 lockdep_assert_held(&vdev->dev_set->lock); 167 168 user = iommufd_access_create(vdev->iommufd_ictx, *pt_id, &vfio_user_ops, 169 vdev); 170 if (IS_ERR(user)) 171 return PTR_ERR(user); 172 vdev->iommufd_access = user; 173 return 0; 174} 175EXPORT_SYMBOL_GPL(vfio_iommufd_emulated_attach_ioas);