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.2-rc2 158 lines 3.9 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 /* 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 45err_unbind: 46 if (vdev->ops->unbind_iommufd) 47 vdev->ops->unbind_iommufd(vdev); 48 return ret; 49} 50 51void 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 */ 64int 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} 75EXPORT_SYMBOL_GPL(vfio_iommufd_physical_bind); 76 77void 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} 88EXPORT_SYMBOL_GPL(vfio_iommufd_physical_unbind); 89 90int 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} 100EXPORT_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 108static 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 116static const struct iommufd_access_ops vfio_user_ops = { 117 .needs_pin_pages = 1, 118 .unmap = vfio_emulated_unmap, 119}; 120 121int 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} 130EXPORT_SYMBOL_GPL(vfio_iommufd_emulated_bind); 131 132void 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} 143EXPORT_SYMBOL_GPL(vfio_iommufd_emulated_unbind); 144 145int 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} 158EXPORT_SYMBOL_GPL(vfio_iommufd_emulated_attach_ioas);