Skip to content

Commit 2fb69c6

Browse files
yiliu1765jgunthorpe
authored andcommitted
iommufd: Support pasid attach/replace
This extends the below APIs to support PASID. Device drivers to manage pasid attach/replace/detach. int iommufd_device_attach(struct iommufd_device *idev, ioasid_t pasid, u32 *pt_id); int iommufd_device_replace(struct iommufd_device *idev, ioasid_t pasid, u32 *pt_id); void iommufd_device_detach(struct iommufd_device *idev, ioasid_t pasid); The pasid operations share underlying attach/replace/detach infrastructure with the device operations, but still have some different implications: - no reserved region per pasid otherwise SVA architecture is already broken (CPU address space doesn't count device reserved regions); - accordingly no sw_msi trick; Cache coherency enforcement is still applied to pasid operations since it is about memory accesses post page table walking (no matter the walk is per RID or per PASID). Link: https://patch.msgid.link/r/[email protected] Reviewed-by: Jason Gunthorpe <[email protected]> Signed-off-by: Kevin Tian <[email protected]> Reviewed-by: Nicolin Chen <[email protected]> Signed-off-by: Yi Liu <[email protected]> Tested-by: Nicolin Chen <[email protected]> Signed-off-by: Jason Gunthorpe <[email protected]>
1 parent ff3f014 commit 2fb69c6

File tree

4 files changed

+53
-33
lines changed

4 files changed

+53
-33
lines changed

drivers/iommu/iommufd/device.c

Lines changed: 37 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -428,9 +428,12 @@ static int iommufd_hwpt_attach_device(struct iommufd_hw_pagetable *hwpt,
428428
}
429429

430430
handle->idev = idev;
431-
WARN_ON(pasid != IOMMU_NO_PASID);
432-
rc = iommu_attach_group_handle(hwpt->domain, idev->igroup->group,
433-
&handle->handle);
431+
if (pasid == IOMMU_NO_PASID)
432+
rc = iommu_attach_group_handle(hwpt->domain, idev->igroup->group,
433+
&handle->handle);
434+
else
435+
rc = iommu_attach_device_pasid(hwpt->domain, idev->dev, pasid,
436+
&handle->handle);
434437
if (rc)
435438
goto out_disable_iopf;
436439

@@ -464,10 +467,12 @@ static void iommufd_hwpt_detach_device(struct iommufd_hw_pagetable *hwpt,
464467
{
465468
struct iommufd_attach_handle *handle;
466469

467-
WARN_ON(pasid != IOMMU_NO_PASID);
468-
469470
handle = iommufd_device_get_attach_handle(idev, pasid);
470-
iommu_detach_group_handle(hwpt->domain, idev->igroup->group);
471+
if (pasid == IOMMU_NO_PASID)
472+
iommu_detach_group_handle(hwpt->domain, idev->igroup->group);
473+
else
474+
iommu_detach_device_pasid(hwpt->domain, idev->dev, pasid);
475+
471476
if (hwpt->fault) {
472477
iommufd_auto_response_faults(hwpt, handle);
473478
iommufd_fault_iopf_disable(idev);
@@ -483,8 +488,6 @@ static int iommufd_hwpt_replace_device(struct iommufd_device *idev,
483488
struct iommufd_attach_handle *handle, *old_handle;
484489
int rc;
485490

486-
WARN_ON(pasid != IOMMU_NO_PASID);
487-
488491
rc = iommufd_hwpt_pasid_compat(hwpt, idev, pasid);
489492
if (rc)
490493
return rc;
@@ -502,8 +505,12 @@ static int iommufd_hwpt_replace_device(struct iommufd_device *idev,
502505
}
503506

504507
handle->idev = idev;
505-
rc = iommu_replace_group_handle(idev->igroup->group, hwpt->domain,
506-
&handle->handle);
508+
if (pasid == IOMMU_NO_PASID)
509+
rc = iommu_replace_group_handle(idev->igroup->group,
510+
hwpt->domain, &handle->handle);
511+
else
512+
rc = iommu_replace_device_pasid(hwpt->domain, idev->dev,
513+
pasid, &handle->handle);
507514
if (rc)
508515
goto out_disable_iopf;
509516

@@ -904,22 +911,25 @@ static int iommufd_device_change_pt(struct iommufd_device *idev,
904911
}
905912

906913
/**
907-
* iommufd_device_attach - Connect a device to an iommu_domain
914+
* iommufd_device_attach - Connect a device/pasid to an iommu_domain
908915
* @idev: device to attach
916+
* @pasid: pasid to attach
909917
* @pt_id: Input a IOMMUFD_OBJ_IOAS, or IOMMUFD_OBJ_HWPT_PAGING
910918
* Output the IOMMUFD_OBJ_HWPT_PAGING ID
911919
*
912-
* This connects the device to an iommu_domain, either automatically or manually
913-
* selected. Once this completes the device could do DMA.
920+
* This connects the device/pasid to an iommu_domain, either automatically
921+
* or manually selected. Once this completes the device could do DMA with
922+
* @pasid. @pasid is IOMMU_NO_PASID if this attach is for no pasid usage.
914923
*
915924
* The caller should return the resulting pt_id back to userspace.
916925
* This function is undone by calling iommufd_device_detach().
917926
*/
918-
int iommufd_device_attach(struct iommufd_device *idev, u32 *pt_id)
927+
int iommufd_device_attach(struct iommufd_device *idev, ioasid_t pasid,
928+
u32 *pt_id)
919929
{
920930
int rc;
921931

922-
rc = iommufd_device_change_pt(idev, IOMMU_NO_PASID, pt_id,
932+
rc = iommufd_device_change_pt(idev, pasid, pt_id,
923933
&iommufd_device_do_attach);
924934
if (rc)
925935
return rc;
@@ -934,8 +944,9 @@ int iommufd_device_attach(struct iommufd_device *idev, u32 *pt_id)
934944
EXPORT_SYMBOL_NS_GPL(iommufd_device_attach, "IOMMUFD");
935945

936946
/**
937-
* iommufd_device_replace - Change the device's iommu_domain
947+
* iommufd_device_replace - Change the device/pasid's iommu_domain
938948
* @idev: device to change
949+
* @pasid: pasid to change
939950
* @pt_id: Input a IOMMUFD_OBJ_IOAS, or IOMMUFD_OBJ_HWPT_PAGING
940951
* Output the IOMMUFD_OBJ_HWPT_PAGING ID
941952
*
@@ -946,27 +957,31 @@ EXPORT_SYMBOL_NS_GPL(iommufd_device_attach, "IOMMUFD");
946957
*
947958
* If it fails then no change is made to the attachment. The iommu driver may
948959
* implement this so there is no disruption in translation. This can only be
949-
* called if iommufd_device_attach() has already succeeded.
960+
* called if iommufd_device_attach() has already succeeded. @pasid is
961+
* IOMMU_NO_PASID for no pasid usage.
950962
*/
951-
int iommufd_device_replace(struct iommufd_device *idev, u32 *pt_id)
963+
int iommufd_device_replace(struct iommufd_device *idev, ioasid_t pasid,
964+
u32 *pt_id)
952965
{
953-
return iommufd_device_change_pt(idev, IOMMU_NO_PASID, pt_id,
966+
return iommufd_device_change_pt(idev, pasid, pt_id,
954967
&iommufd_device_do_replace);
955968
}
956969
EXPORT_SYMBOL_NS_GPL(iommufd_device_replace, "IOMMUFD");
957970

958971
/**
959-
* iommufd_device_detach - Disconnect a device to an iommu_domain
972+
* iommufd_device_detach - Disconnect a device/device to an iommu_domain
960973
* @idev: device to detach
974+
* @pasid: pasid to detach
961975
*
962976
* Undo iommufd_device_attach(). This disconnects the idev from the previously
963977
* attached pt_id. The device returns back to a blocked DMA translation.
978+
* @pasid is IOMMU_NO_PASID for no pasid usage.
964979
*/
965-
void iommufd_device_detach(struct iommufd_device *idev)
980+
void iommufd_device_detach(struct iommufd_device *idev, ioasid_t pasid)
966981
{
967982
struct iommufd_hw_pagetable *hwpt;
968983

969-
hwpt = iommufd_hw_pagetable_detach(idev, IOMMU_NO_PASID);
984+
hwpt = iommufd_hw_pagetable_detach(idev, pasid);
970985
iommufd_hw_pagetable_put(idev->ictx, hwpt);
971986
refcount_dec(&idev->obj.users);
972987
}

drivers/iommu/iommufd/selftest.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -945,7 +945,7 @@ static int iommufd_test_mock_domain(struct iommufd_ucmd *ucmd,
945945
}
946946
sobj->idev.idev = idev;
947947

948-
rc = iommufd_device_attach(idev, &pt_id);
948+
rc = iommufd_device_attach(idev, IOMMU_NO_PASID, &pt_id);
949949
if (rc)
950950
goto out_unbind;
951951

@@ -960,7 +960,7 @@ static int iommufd_test_mock_domain(struct iommufd_ucmd *ucmd,
960960
return 0;
961961

962962
out_detach:
963-
iommufd_device_detach(idev);
963+
iommufd_device_detach(idev, IOMMU_NO_PASID);
964964
out_unbind:
965965
iommufd_device_unbind(idev);
966966
out_mdev:
@@ -994,7 +994,7 @@ static int iommufd_test_mock_domain_replace(struct iommufd_ucmd *ucmd,
994994
goto out_dev_obj;
995995
}
996996

997-
rc = iommufd_device_replace(sobj->idev.idev, &pt_id);
997+
rc = iommufd_device_replace(sobj->idev.idev, IOMMU_NO_PASID, &pt_id);
998998
if (rc)
999999
goto out_dev_obj;
10001000

@@ -1655,7 +1655,7 @@ void iommufd_selftest_destroy(struct iommufd_object *obj)
16551655

16561656
switch (sobj->type) {
16571657
case TYPE_IDEV:
1658-
iommufd_device_detach(sobj->idev.idev);
1658+
iommufd_device_detach(sobj->idev.idev, IOMMU_NO_PASID);
16591659
iommufd_device_unbind(sobj->idev.idev);
16601660
mock_dev_destroy(sobj->idev.mock_dev);
16611661
break;

drivers/vfio/iommufd.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ void vfio_iommufd_physical_unbind(struct vfio_device *vdev)
128128
lockdep_assert_held(&vdev->dev_set->lock);
129129

130130
if (vdev->iommufd_attached) {
131-
iommufd_device_detach(vdev->iommufd_device);
131+
iommufd_device_detach(vdev->iommufd_device, IOMMU_NO_PASID);
132132
vdev->iommufd_attached = false;
133133
}
134134
iommufd_device_unbind(vdev->iommufd_device);
@@ -146,9 +146,11 @@ int vfio_iommufd_physical_attach_ioas(struct vfio_device *vdev, u32 *pt_id)
146146
return -EINVAL;
147147

148148
if (vdev->iommufd_attached)
149-
rc = iommufd_device_replace(vdev->iommufd_device, pt_id);
149+
rc = iommufd_device_replace(vdev->iommufd_device,
150+
IOMMU_NO_PASID, pt_id);
150151
else
151-
rc = iommufd_device_attach(vdev->iommufd_device, pt_id);
152+
rc = iommufd_device_attach(vdev->iommufd_device,
153+
IOMMU_NO_PASID, pt_id);
152154
if (rc)
153155
return rc;
154156
vdev->iommufd_attached = true;
@@ -163,7 +165,7 @@ void vfio_iommufd_physical_detach_ioas(struct vfio_device *vdev)
163165
if (WARN_ON(!vdev->iommufd_device) || !vdev->iommufd_attached)
164166
return;
165167

166-
iommufd_device_detach(vdev->iommufd_device);
168+
iommufd_device_detach(vdev->iommufd_device, IOMMU_NO_PASID);
167169
vdev->iommufd_attached = false;
168170
}
169171
EXPORT_SYMBOL_GPL(vfio_iommufd_physical_detach_ioas);

include/linux/iommufd.h

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
#include <linux/err.h>
1010
#include <linux/errno.h>
11+
#include <linux/iommu.h>
1112
#include <linux/refcount.h>
1213
#include <linux/types.h>
1314
#include <linux/xarray.h>
@@ -54,9 +55,11 @@ struct iommufd_device *iommufd_device_bind(struct iommufd_ctx *ictx,
5455
struct device *dev, u32 *id);
5556
void iommufd_device_unbind(struct iommufd_device *idev);
5657

57-
int iommufd_device_attach(struct iommufd_device *idev, u32 *pt_id);
58-
int iommufd_device_replace(struct iommufd_device *idev, u32 *pt_id);
59-
void iommufd_device_detach(struct iommufd_device *idev);
58+
int iommufd_device_attach(struct iommufd_device *idev, ioasid_t pasid,
59+
u32 *pt_id);
60+
int iommufd_device_replace(struct iommufd_device *idev, ioasid_t pasid,
61+
u32 *pt_id);
62+
void iommufd_device_detach(struct iommufd_device *idev, ioasid_t pasid);
6063

6164
struct iommufd_ctx *iommufd_device_to_ictx(struct iommufd_device *idev);
6265
u32 iommufd_device_to_id(struct iommufd_device *idev);

0 commit comments

Comments
 (0)