Linux IOMMU Development
 help / color / mirror / Atom feed
* [PATCH v3] iommu: Fix iommu selftest running test mock domain fail
@ 2025-09-24  7:43 Guixin Liu
  2025-09-24 12:53 ` Jason Gunthorpe
  0 siblings, 1 reply; 3+ messages in thread
From: Guixin Liu @ 2025-09-24  7:43 UTC (permalink / raw)
  To: Joerg Roedel, Will Deacon, Robin Murphy, Jason Gunthorpe,
	Kevin Tian; +Cc: iommu

When intel_iommu=on is enabled and the iommu selftests are executed,
we observed multiple test case failures. Our investigation revealed
that both the Intel iommu driver and the mock iommu driver registered
iommu_device instances with fwnode=NULL, and both were added to the
iommu_device_list. Later, when the mock iommu driver attempted to
create a device, iommu_init_device attempted to retrieve the iommu_ops
by searching the iommu_device_list using the provided fwnode
(which was NULL).
Since the iommu_device registered by the Intel iommu driver appeared
earlier in the list, it was matched first instead of the mock iommu
driver's iommu_device. This ultimately caused probe_device to fail.

Fix this by alloc a software fwnode for mock iommu driver's iommu_device,
and set it to the device which mock iommu driver created.

Test by "make -C toosl/testing/selftests TARGETS=iommu run_tests":
PASSED: 229 / 229 tests passed.

In addition, this issue is also can be found on amd platform, and
also tested on a amd machine.

Signed-off-by: Guixin Liu <kanie@linux.alibaba.com>
Tested-by: Qinyun Tan <qinyuntan@linux.alibaba.com>
---
Changes from v2 to v3:
- Add export symbol iommu_mock_device_init() and iommu_mock_device_abort()
in iommu.c instead of export iommu_probe_device_lock and iommu_fwspec_free().

Changes from v1 to v2:
- Remove print when iommu_fwspec_init() fail.
 drivers/iommu/iommu-priv.h       |  3 +++
 drivers/iommu/iommu.c            | 28 ++++++++++++++++++++++++++++
 drivers/iommu/iommufd/selftest.c |  5 +++++
 3 files changed, 36 insertions(+)

diff --git a/drivers/iommu/iommu-priv.h b/drivers/iommu/iommu-priv.h
index e236b932e766..40c477db3cd9 100644
--- a/drivers/iommu/iommu-priv.h
+++ b/drivers/iommu/iommu-priv.h
@@ -37,6 +37,9 @@ void iommu_device_unregister_bus(struct iommu_device *iommu,
 				 const struct bus_type *bus,
 				 struct notifier_block *nb);
 
+int iommu_mock_device_init(struct device *dev, struct iommu_device *iommu);
+void iommu_mock_device_abort(struct device *dev);
+
 struct iommu_attach_handle *iommu_attach_handle_get(struct iommu_group *group,
 						    ioasid_t pasid,
 						    unsigned int type);
diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index 060ebe330ee1..6e51cfbebd64 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -304,6 +304,7 @@ void iommu_device_unregister_bus(struct iommu_device *iommu,
 				 struct notifier_block *nb)
 {
 	bus_unregister_notifier(bus, nb);
+	fwnode_remove_software_node(iommu->fwnode);
 	iommu_device_unregister(iommu);
 }
 EXPORT_SYMBOL_GPL(iommu_device_unregister_bus);
@@ -326,6 +327,14 @@ int iommu_device_register_bus(struct iommu_device *iommu,
 	if (err)
 		return err;
 
+	iommu->fwnode = fwnode_create_software_node(NULL, NULL);
+	if (IS_ERR(iommu->fwnode)) {
+		iommu->fwnode = NULL;
+		dev_err(iommu->dev, "add property failed:%d\n", err);
+		bus_unregister_notifier(bus, nb);
+		return err;
+	}
+
 	spin_lock(&iommu_device_lock);
 	list_add_tail(&iommu->list, &iommu_device_list);
 	spin_unlock(&iommu_device_lock);
@@ -335,9 +344,28 @@ int iommu_device_register_bus(struct iommu_device *iommu,
 		iommu_device_unregister_bus(iommu, bus, nb);
 		return err;
 	}
+	WRITE_ONCE(iommu->ready, true);
 	return 0;
 }
 EXPORT_SYMBOL_GPL(iommu_device_register_bus);
+
+int iommu_mock_device_init(struct device *dev, struct iommu_device *iommu)
+{
+	int rc;
+
+	mutex_lock(&iommu_probe_device_lock);
+	rc = iommu_fwspec_init(dev, iommu->fwnode);
+	mutex_unlock(&iommu_probe_device_lock);
+
+	return rc;
+}
+EXPORT_SYMBOL_GPL(iommu_mock_device_init);
+
+void iommu_mock_device_abort(struct device *dev)
+{
+	iommu_fwspec_free(dev);
+}
+EXPORT_SYMBOL_GPL(iommu_mock_device_abort);
 #endif
 
 static struct dev_iommu *dev_iommu_get(struct device *dev)
diff --git a/drivers/iommu/iommufd/selftest.c b/drivers/iommu/iommufd/selftest.c
index 61686603c769..38aaa2b02af4 100644
--- a/drivers/iommu/iommufd/selftest.c
+++ b/drivers/iommu/iommufd/selftest.c
@@ -1077,6 +1077,7 @@ static void mock_dev_release(struct device *dev)
 {
 	struct mock_dev *mdev = to_mock_dev(dev);
 
+	iommu_mock_device_abort(&mdev->dev);
 	ida_free(&mock_dev_ida, mdev->id);
 	kfree(mdev);
 }
@@ -1126,6 +1127,10 @@ static struct mock_dev *mock_dev_create(unsigned long dev_flags)
 		goto err_put;
 	}
 
+	rc = iommu_mock_device_init(&mdev->dev, &mock_iommu.iommu_dev);
+	if (rc)
+		goto err_put;
+
 	rc = device_add(&mdev->dev);
 	if (rc)
 		goto err_put;
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCH v3] iommu: Fix iommu selftest running test mock domain fail
  2025-09-24  7:43 [PATCH v3] iommu: Fix iommu selftest running test mock domain fail Guixin Liu
@ 2025-09-24 12:53 ` Jason Gunthorpe
  2025-09-25  2:29   ` Guixin Liu
  0 siblings, 1 reply; 3+ messages in thread
From: Jason Gunthorpe @ 2025-09-24 12:53 UTC (permalink / raw)
  To: Guixin Liu; +Cc: Joerg Roedel, Will Deacon, Robin Murphy, Kevin Tian, iommu

On Wed, Sep 24, 2025 at 03:43:59PM +0800, Guixin Liu wrote:
> @@ -1077,6 +1077,7 @@ static void mock_dev_release(struct device *dev)
>  {
>  	struct mock_dev *mdev = to_mock_dev(dev);
>  
> +	iommu_mock_device_abort(&mdev->dev);
>  	ida_free(&mock_dev_ida, mdev->id);
>  	kfree(mdev);
>  }

I don't think this call is necessary? Once device_add() completes the
iommu_bus_notifier() should be active for the device.

BUS_NOTIFY_REMOVED_DEVICE triggers iommu_release_device() which does
dev_iommu_free() and frees the fwspec automatically.

The only unnatural condition is if device_add() fails then the
notifier can't run and the caller has to clean it up.

Yes?

> @@ -1126,6 +1127,10 @@ static struct mock_dev *mock_dev_create(unsigned long dev_flags)
>  		goto err_put;
>  	}
>  
> +	rc = iommu_mock_device_init(&mdev->dev, &mock_iommu.iommu_dev);
> +	if (rc)
> +		goto err_put;
> +
>  	rc = device_add(&mdev->dev);
>  	if (rc)
>  		goto err_put;

So I will suggest one further refinement to pull the device_add() into
iommu_mock_device_add() and then it can internally free the fwspec on
error and don't bother with iommu_mock_device_abort().

But other than that little note this looks fine to me.

Jason

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH v3] iommu: Fix iommu selftest running test mock domain fail
  2025-09-24 12:53 ` Jason Gunthorpe
@ 2025-09-25  2:29   ` Guixin Liu
  0 siblings, 0 replies; 3+ messages in thread
From: Guixin Liu @ 2025-09-25  2:29 UTC (permalink / raw)
  To: Jason Gunthorpe
  Cc: Joerg Roedel, Will Deacon, Robin Murphy, Kevin Tian, iommu



在 2025/9/24 20:53, Jason Gunthorpe 写道:
> On Wed, Sep 24, 2025 at 03:43:59PM +0800, Guixin Liu wrote:
>> @@ -1077,6 +1077,7 @@ static void mock_dev_release(struct device *dev)
>>   {
>>   	struct mock_dev *mdev = to_mock_dev(dev);
>>   
>> +	iommu_mock_device_abort(&mdev->dev);
>>   	ida_free(&mock_dev_ida, mdev->id);
>>   	kfree(mdev);
>>   }
> I don't think this call is necessary? Once device_add() completes the
> iommu_bus_notifier() should be active for the device.
>
> BUS_NOTIFY_REMOVED_DEVICE triggers iommu_release_device() which does
> dev_iommu_free() and frees the fwspec automatically.
>
> The only unnatural condition is if device_add() fails then the
> notifier can't run and the caller has to clean it up.
>
> Yes?
You are right, I didn't consider it comprehensively.
>
>> @@ -1126,6 +1127,10 @@ static struct mock_dev *mock_dev_create(unsigned long dev_flags)
>>   		goto err_put;
>>   	}
>>   
>> +	rc = iommu_mock_device_init(&mdev->dev, &mock_iommu.iommu_dev);
>> +	if (rc)
>> +		goto err_put;
>> +
>>   	rc = device_add(&mdev->dev);
>>   	if (rc)
>>   		goto err_put;
> So I will suggest one further refinement to pull the device_add() into
> iommu_mock_device_add() and then it can internally free the fwspec on
> error and don't bother with iommu_mock_device_abort().
Nice idea, I will change it in v4, thanks.

Best Regards,
Guixin Liu
> But other than that little note this looks fine to me.
>
> Jason


^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2025-09-25  2:29 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-09-24  7:43 [PATCH v3] iommu: Fix iommu selftest running test mock domain fail Guixin Liu
2025-09-24 12:53 ` Jason Gunthorpe
2025-09-25  2:29   ` Guixin Liu

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox