On 2025/1/11 11:32, Nicolin Chen wrote:
"attach_handle" was added exclusively for the iommufd_fault_iopf_handler() used by IOPF/PRI use cases, along with the "fault_data". Now, the iommufd version of sw_msi function will resue the attach_handle and fault_data for a non-fault case.
Move the attach_handle part out of the fault.c file to make it generic for all cases. Simplify the remaining fault specific routine to attach/detach.
I guess you can send it separately since both of our series need it. :)
Signed-off-by: Nicolin Chen nicolinc@nvidia.com
drivers/iommu/iommufd/iommufd_private.h | 40 +------- drivers/iommu/iommufd/device.c | 105 +++++++++++++++++++++ drivers/iommu/iommufd/fault.c | 120 +++--------------------- 3 files changed, 122 insertions(+), 143 deletions(-)
diff --git a/drivers/iommu/iommufd/iommufd_private.h b/drivers/iommu/iommufd/iommufd_private.h index b6d706cf2c66..063c0a42f54f 100644 --- a/drivers/iommu/iommufd/iommufd_private.h +++ b/drivers/iommu/iommufd/iommufd_private.h @@ -472,42 +472,12 @@ void iommufd_fault_destroy(struct iommufd_object *obj); int iommufd_fault_iopf_handler(struct iopf_group *group); int iommufd_fault_domain_attach_dev(struct iommufd_hw_pagetable *hwpt,
struct iommufd_device *idev);
struct iommufd_device *idev,
void iommufd_fault_domain_detach_dev(struct iommufd_hw_pagetable *hwpt,bool enable_iopf);
struct iommufd_device *idev);
-int iommufd_fault_domain_replace_dev(struct iommufd_device *idev,
struct iommufd_hw_pagetable *hwpt,
struct iommufd_hw_pagetable *old);
-static inline int iommufd_hwpt_attach_device(struct iommufd_hw_pagetable *hwpt,
struct iommufd_device *idev)
-{
- if (hwpt->fault)
return iommufd_fault_domain_attach_dev(hwpt, idev);
- return iommu_attach_group(hwpt->domain, idev->igroup->group);
-}
-static inline void iommufd_hwpt_detach_device(struct iommufd_hw_pagetable *hwpt,
struct iommufd_device *idev)
-{
- if (hwpt->fault) {
iommufd_fault_domain_detach_dev(hwpt, idev);
return;
- }
- iommu_detach_group(hwpt->domain, idev->igroup->group);
-}
-static inline int iommufd_hwpt_replace_device(struct iommufd_device *idev,
struct iommufd_hw_pagetable *hwpt,
struct iommufd_hw_pagetable *old)
-{
- if (old->fault || hwpt->fault)
return iommufd_fault_domain_replace_dev(idev, hwpt, old);
- return iommu_group_replace_domain(idev->igroup->group, hwpt->domain);
-}
struct iommufd_device *idev,
struct iommufd_attach_handle *handle,
bool disable_iopf);
static inline struct iommufd_viommu * iommufd_get_viommu(struct iommufd_ucmd *ucmd, u32 id) diff --git a/drivers/iommu/iommufd/device.c b/drivers/iommu/iommufd/device.c index dfd0898fb6c1..38b31b652147 100644 --- a/drivers/iommu/iommufd/device.c +++ b/drivers/iommu/iommufd/device.c @@ -352,6 +352,111 @@ iommufd_device_attach_reserved_iova(struct iommufd_device *idev, return 0; } +/* The device attach/detach/replace helpers for attach_handle */
+static int iommufd_hwpt_attach_device(struct iommufd_hw_pagetable *hwpt,
struct iommufd_device *idev)
+{
- struct iommufd_attach_handle *handle;
- int rc;
- if (hwpt->fault) {
rc = iommufd_fault_domain_attach_dev(hwpt, idev, true);
if (rc)
return rc;
- }
- handle = kzalloc(sizeof(*handle), GFP_KERNEL);
- if (!handle) {
rc = -ENOMEM;
goto out_fault_detach;
- }
- handle->idev = idev;
- rc = iommu_attach_group_handle(hwpt->domain, idev->igroup->group,
&handle->handle);
- if (rc)
goto out_free_handle;
- return 0;
+out_free_handle:
- kfree(handle);
- handle = NULL;
+out_fault_detach:
- if (hwpt->fault)
iommufd_fault_domain_detach_dev(hwpt, idev, handle, true);
- return rc;
+}
+static struct iommufd_attach_handle * +iommufd_device_get_attach_handle(struct iommufd_device *idev) +{
- struct iommu_attach_handle *handle;
- handle =
iommu_attach_handle_get(idev->igroup->group, IOMMU_NO_PASID, 0);
- if (IS_ERR(handle))
return NULL;
- return to_iommufd_handle(handle);
+}
+static void iommufd_hwpt_detach_device(struct iommufd_hw_pagetable *hwpt,
struct iommufd_device *idev)
+{
- struct iommufd_attach_handle *handle;
- handle = iommufd_device_get_attach_handle(idev);
- iommu_detach_group_handle(hwpt->domain, idev->igroup->group);
- if (hwpt->fault)
iommufd_fault_domain_detach_dev(hwpt, idev, handle, true);
- kfree(handle);
+}
+static int iommufd_hwpt_replace_device(struct iommufd_device *idev,
struct iommufd_hw_pagetable *hwpt,
struct iommufd_hw_pagetable *old)
+{
- struct iommufd_attach_handle *old_handle =
iommufd_device_get_attach_handle(idev);
- struct iommufd_attach_handle *handle;
- int rc;
- if (hwpt->fault) {
rc = iommufd_fault_domain_attach_dev(hwpt, idev, !old->fault);
if (rc)
return rc;
- }
- handle = kzalloc(sizeof(*handle), GFP_KERNEL);
- if (!handle) {
rc = -ENOMEM;
goto out_fault_detach;
- }
- handle->idev = idev;
- rc = iommu_replace_group_handle(idev->igroup->group, hwpt->domain,
&handle->handle);
- if (rc)
goto out_free_handle;
- if (old->fault)
iommufd_fault_domain_detach_dev(old, idev, old_handle,
!hwpt->fault);
- kfree(old_handle);
- return 0;
+out_free_handle:
- kfree(handle);
- handle = NULL;
+out_fault_detach:
- if (hwpt->fault)
iommufd_fault_domain_detach_dev(hwpt, idev, handle,
!old->fault);
- return rc;
+}
- int iommufd_hw_pagetable_attach(struct iommufd_hw_pagetable *hwpt, struct iommufd_device *idev) {
diff --git a/drivers/iommu/iommufd/fault.c b/drivers/iommu/iommufd/fault.c index 06aa83a75e94..1d9bd3024b57 100644 --- a/drivers/iommu/iommufd/fault.c +++ b/drivers/iommu/iommufd/fault.c @@ -60,42 +60,17 @@ static void iommufd_fault_iopf_disable(struct iommufd_device *idev) mutex_unlock(&idev->iopf_lock); } -static int __fault_domain_attach_dev(struct iommufd_hw_pagetable *hwpt,
struct iommufd_device *idev)
-{
- struct iommufd_attach_handle *handle;
- int ret;
- handle = kzalloc(sizeof(*handle), GFP_KERNEL);
- if (!handle)
return -ENOMEM;
- handle->idev = idev;
- ret = iommu_attach_group_handle(hwpt->domain, idev->igroup->group,
&handle->handle);
- if (ret)
kfree(handle);
- return ret;
-}
- int iommufd_fault_domain_attach_dev(struct iommufd_hw_pagetable *hwpt,
struct iommufd_device *idev)
struct iommufd_device *idev,
{bool enable_iopf)
- int ret;
- int rc = 0;
if (!hwpt->fault) return -EINVAL;
- ret = iommufd_fault_iopf_enable(idev);
- if (ret)
return ret;
- ret = __fault_domain_attach_dev(hwpt, idev);
- if (ret)
iommufd_fault_iopf_disable(idev);
- return ret;
- if (enable_iopf)
rc = iommufd_fault_iopf_enable(idev);
- return rc; }
static void iommufd_auto_response_faults(struct iommufd_hw_pagetable *hwpt, @@ -127,86 +102,15 @@ static void iommufd_auto_response_faults(struct iommufd_hw_pagetable *hwpt, mutex_unlock(&fault->mutex); } -static struct iommufd_attach_handle * -iommufd_device_get_attach_handle(struct iommufd_device *idev) -{
- struct iommu_attach_handle *handle;
- handle = iommu_attach_handle_get(idev->igroup->group, IOMMU_NO_PASID, 0);
- if (IS_ERR(handle))
return NULL;
- return to_iommufd_handle(handle);
-}
- void iommufd_fault_domain_detach_dev(struct iommufd_hw_pagetable *hwpt,
struct iommufd_device *idev)
struct iommufd_device *idev,
struct iommufd_attach_handle *handle,
{bool disable_iopf)
- struct iommufd_attach_handle *handle;
- handle = iommufd_device_get_attach_handle(idev);
- iommu_detach_group_handle(hwpt->domain, idev->igroup->group);
- iommufd_auto_response_faults(hwpt, handle);
- iommufd_fault_iopf_disable(idev);
- kfree(handle);
-}
-static int __fault_domain_replace_dev(struct iommufd_device *idev,
struct iommufd_hw_pagetable *hwpt,
struct iommufd_hw_pagetable *old)
-{
- struct iommufd_attach_handle *handle, *curr = NULL;
- int ret;
- if (old->fault)
curr = iommufd_device_get_attach_handle(idev);
- if (hwpt->fault) {
handle = kzalloc(sizeof(*handle), GFP_KERNEL);
if (!handle)
return -ENOMEM;
handle->idev = idev;
ret = iommu_replace_group_handle(idev->igroup->group,
hwpt->domain, &handle->handle);
- } else {
ret = iommu_replace_group_handle(idev->igroup->group,
hwpt->domain, NULL);
- }
- if (!ret && curr) {
iommufd_auto_response_faults(old, curr);
kfree(curr);
- }
- return ret;
-}
-int iommufd_fault_domain_replace_dev(struct iommufd_device *idev,
struct iommufd_hw_pagetable *hwpt,
struct iommufd_hw_pagetable *old)
-{
- bool iopf_off = !hwpt->fault && old->fault;
- bool iopf_on = hwpt->fault && !old->fault;
- int ret;
- if (iopf_on) {
ret = iommufd_fault_iopf_enable(idev);
if (ret)
return ret;
- }
- ret = __fault_domain_replace_dev(idev, hwpt, old);
- if (ret) {
if (iopf_on)
iommufd_fault_iopf_disable(idev);
return ret;
- }
- if (iopf_off)
- if (handle)
iommufd_auto_response_faults(hwpt, handle);
no need to check handle. After this patch, both the non-fault and the fault path will allocate handle. It cannot be used to isolate fault and non-fault path. Also, the callers of iommufd_fault_domain_detach_dev() will check hwpt->fault before calling it. So just call iommufd_auto_response_faults().
- if (disable_iopf) iommufd_fault_iopf_disable(idev);
- return 0; }
void iommufd_fault_destroy(struct iommufd_object *obj)