Skip to content

Commit 8519e68

Browse files
LuBaoluwilldeacon
authored andcommitted
iommu: Extend domain attach group with handle support
Unlike the SVA case where each PASID of a device has an SVA domain attached to it, the I/O page faults are handled by the fault handler of the SVA domain. The I/O page faults for a user page table might be handled by the domain attached to RID or the domain attached to the PASID, depending on whether the PASID table is managed by user space or kernel. As a result, there is a need for the domain attach group interfaces to have attach handle support. The attach handle will be forwarded to the fault handler of the user domain. Add some variants of the domain attaching group interfaces so that they could support the attach handle and export them for use in IOMMUFD. Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com> Reviewed-by: Kevin Tian <kevin.tian@intel.com> Link: https://lore.kernel.org/r/20240702063444.105814-5-baolu.lu@linux.intel.com Signed-off-by: Will Deacon <will@kernel.org>
1 parent 06cdcc3 commit 8519e68

File tree

2 files changed

+111
-0
lines changed

2 files changed

+111
-0
lines changed

drivers/iommu/iommu-priv.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,12 @@ void iommu_device_unregister_bus(struct iommu_device *iommu,
3131
struct iommu_attach_handle *iommu_attach_handle_get(struct iommu_group *group,
3232
ioasid_t pasid,
3333
unsigned int type);
34+
int iommu_attach_group_handle(struct iommu_domain *domain,
35+
struct iommu_group *group,
36+
struct iommu_attach_handle *handle);
37+
void iommu_detach_group_handle(struct iommu_domain *domain,
38+
struct iommu_group *group);
39+
int iommu_replace_group_handle(struct iommu_group *group,
40+
struct iommu_domain *new_domain,
41+
struct iommu_attach_handle *handle);
3442
#endif /* __LINUX_IOMMU_PRIV_H */

drivers/iommu/iommu.c

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3478,3 +3478,106 @@ iommu_attach_handle_get(struct iommu_group *group, ioasid_t pasid, unsigned int
34783478
return handle;
34793479
}
34803480
EXPORT_SYMBOL_NS_GPL(iommu_attach_handle_get, IOMMUFD_INTERNAL);
3481+
3482+
/**
3483+
* iommu_attach_group_handle - Attach an IOMMU domain to an IOMMU group
3484+
* @domain: IOMMU domain to attach
3485+
* @group: IOMMU group that will be attached
3486+
* @handle: attach handle
3487+
*
3488+
* Returns 0 on success and error code on failure.
3489+
*
3490+
* This is a variant of iommu_attach_group(). It allows the caller to provide
3491+
* an attach handle and use it when the domain is attached. This is currently
3492+
* used by IOMMUFD to deliver the I/O page faults.
3493+
*/
3494+
int iommu_attach_group_handle(struct iommu_domain *domain,
3495+
struct iommu_group *group,
3496+
struct iommu_attach_handle *handle)
3497+
{
3498+
int ret;
3499+
3500+
if (handle)
3501+
handle->domain = domain;
3502+
3503+
mutex_lock(&group->mutex);
3504+
ret = xa_insert(&group->pasid_array, IOMMU_NO_PASID, handle, GFP_KERNEL);
3505+
if (ret)
3506+
goto err_unlock;
3507+
3508+
ret = __iommu_attach_group(domain, group);
3509+
if (ret)
3510+
goto err_erase;
3511+
mutex_unlock(&group->mutex);
3512+
3513+
return 0;
3514+
err_erase:
3515+
xa_erase(&group->pasid_array, IOMMU_NO_PASID);
3516+
err_unlock:
3517+
mutex_unlock(&group->mutex);
3518+
return ret;
3519+
}
3520+
EXPORT_SYMBOL_NS_GPL(iommu_attach_group_handle, IOMMUFD_INTERNAL);
3521+
3522+
/**
3523+
* iommu_detach_group_handle - Detach an IOMMU domain from an IOMMU group
3524+
* @domain: IOMMU domain to attach
3525+
* @group: IOMMU group that will be attached
3526+
*
3527+
* Detach the specified IOMMU domain from the specified IOMMU group.
3528+
* It must be used in conjunction with iommu_attach_group_handle().
3529+
*/
3530+
void iommu_detach_group_handle(struct iommu_domain *domain,
3531+
struct iommu_group *group)
3532+
{
3533+
mutex_lock(&group->mutex);
3534+
__iommu_group_set_core_domain(group);
3535+
xa_erase(&group->pasid_array, IOMMU_NO_PASID);
3536+
mutex_unlock(&group->mutex);
3537+
}
3538+
EXPORT_SYMBOL_NS_GPL(iommu_detach_group_handle, IOMMUFD_INTERNAL);
3539+
3540+
/**
3541+
* iommu_replace_group_handle - replace the domain that a group is attached to
3542+
* @group: IOMMU group that will be attached to the new domain
3543+
* @new_domain: new IOMMU domain to replace with
3544+
* @handle: attach handle
3545+
*
3546+
* This is a variant of iommu_group_replace_domain(). It allows the caller to
3547+
* provide an attach handle for the new domain and use it when the domain is
3548+
* attached.
3549+
*/
3550+
int iommu_replace_group_handle(struct iommu_group *group,
3551+
struct iommu_domain *new_domain,
3552+
struct iommu_attach_handle *handle)
3553+
{
3554+
void *curr;
3555+
int ret;
3556+
3557+
if (!new_domain)
3558+
return -EINVAL;
3559+
3560+
mutex_lock(&group->mutex);
3561+
if (handle) {
3562+
ret = xa_reserve(&group->pasid_array, IOMMU_NO_PASID, GFP_KERNEL);
3563+
if (ret)
3564+
goto err_unlock;
3565+
}
3566+
3567+
ret = __iommu_group_set_domain(group, new_domain);
3568+
if (ret)
3569+
goto err_release;
3570+
3571+
curr = xa_store(&group->pasid_array, IOMMU_NO_PASID, handle, GFP_KERNEL);
3572+
WARN_ON(xa_is_err(curr));
3573+
3574+
mutex_unlock(&group->mutex);
3575+
3576+
return 0;
3577+
err_release:
3578+
xa_release(&group->pasid_array, IOMMU_NO_PASID);
3579+
err_unlock:
3580+
mutex_unlock(&group->mutex);
3581+
return ret;
3582+
}
3583+
EXPORT_SYMBOL_NS_GPL(iommu_replace_group_handle, IOMMUFD_INTERNAL);

0 commit comments

Comments
 (0)