[RFC PATCH] iommu/arm-smmu-v3: Allow nested attach for PCI bridges without vDEVICE
Dmitry Malkin <[email protected]>
| Newsgroups | gmane.linux.kernel.stable,gmane.linux.ports.arm.kernel,gmane.linux.kernel |
|---|---|
| Message-ID | <PA1P190MB25578C482C8A3B06A4DCC6FDDBDA2@PA1P190MB2557.EURP190.PROD.OUTLOOK.COM> |
IOMMU groups can contain passed-through endpoints and host PCI bridges.
QEMU creates vDEVICEs for the endpoints, but not for bridges that are
not visible to the guest.
Since f0ea207ed781 ("iommu/arm-smmu-v3: Introduce struct
arm_smmu_vmaster"), group-wide translated-domain attachment therefore
fails when the first bridge is visited:
pcieport 0009:00:00.0:
missing vDEVICE association for translated nested domain:
cfg=5 ret=-2
vfio-pci 0009:03:00.0:
VFIO_DEVICE_ATTACH_IOMMUFD_PT attach failed for pt_id 19: -ENOENT
The same configuration worked with Linux 6.14.
Allow PCI bridges without a vDEVICE to attach without a vmaster.
Endpoint devices still require a vDEVICE, preserving vSID handling for
invalidations and virtual events. Log when the bridge exception is used.
Fixes: f0ea207ed781 ("iommu/arm-smmu-v3: Introduce struct arm_smmu_vmaster")
Cc: [email protected]
Signed-off-by: Dmitry Malkin <[email protected]>
---
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-iommufd.c | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-iommufd.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-iommufd.c
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-iommufd.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-iommufd.c
@@ -5,6 +5,8 @@
#include <uapi/linux/iommufd.h>
+#include <linux/pci.h>
+
#include "arm-smmu-v3.h"
void *arm_smmu_hw_info(struct device *dev, u32 *length,
@@ -118,6 +120,17 @@ int arm_smmu_attach_prepare_vmaster(struct arm_smmu_attach_state *state,
if (cfg == STRTAB_STE_0_CFG_ABORT ||
cfg == STRTAB_STE_0_CFG_BYPASS)
return 0;
+ /*
+ * Group-wide domain attachment also visits host PCI bridges. Such a
+ * bridge is not exposed to the VM and therefore has no virtual SID.
+ */
+ if (dev_is_pci(state->master->dev) &&
+ pci_is_bridge(to_pci_dev(state->master->dev))) {
+ dev_info_ratelimited(state->master->dev,
+ "skipping vDEVICE requirement for translated nested domain: cfg=%u ret=%d\n",
+ cfg, ret);
+ return 0;
+ }
return ret;
}
--
2.43.0