@samitouri / QOSamiQemu / commits / 4435853689

hw/arm/smmuv3-accel: Enforce viommu association when CMDQV is active

When CMDQV is active, the first cold-plugged VFIO device establishes the viommu to host SMMUv3 association, and the guest's boot-time CMDQV configuration (VINTFs, VCMDQs) is built on top of that association. Hot-unplugging that device would release the viommu and tear down all CMDQV state. Hot-plugging another device behind a different host SMMUv3+CMDQV would then re-bind the same vSMMUv3 to new host hardware, while the guest keeps using its boot-time configuration and ends up issuing commands to the wrong host. Block hot-unplug of the establishing device to avoid this; retaining the binding across unplug is non-trivial and not required by any current use case. Also abort at machine_done if cmdqv=on is requested but no cold-plugged VFIO device was present to initialize it. Reviewed-by: Nicolin Chen <nicolinc@nvidia.com> Tested-by: Nicolin Chen <nicolinc@nvidia.com> Reviewed-by: Eric Auger <eric.auger@redhat.com> Signed-off-by: Shameer Kolothum <skolothumtho@nvidia.com> Tested-by: Eric Auger <eric.auger@redhat.com> Message-id: 20260609112552.378999-30-skolothumtho@nvidia.com Signed-off-by: Peter Maydell <peter.maydell@linaro.org>

Shameer Kolothum committed Jun 9, 2026 at 12:25 UTC 4435853689e245a8bfec9eb92fd84f3904d60d47
2 files changed +19
hw/arm/smmuv3-accel.c
+18
@@ -759,6 +759,18 @@ static bool smmuv3_accel_set_iommu_device(PCIBus *bus, void *opaque, int devfn,
759 return false;
760 }
761
762 + /*
763 + * CMDQV is active: block hot-unplug of the device that established the
764 + * viommu association. Removing it would cause the vIOMMU to host SMMUv3
765 + * association be changed via device hot-plug.
766 + */
767 + if (s->s_accel->cmdqv_ops) {
768 + PCIDevice *pdev = pci_find_device(bus, pci_bus_num(bus), devfn);
769 + error_setg(&accel_dev->unplug_blocker,
770 + "CMDQV is active: removing the device that established the "
771 + "viommu association would break the guest CMDQV");
772 + qdev_add_unplug_blocker(DEVICE(pdev), accel_dev->unplug_blocker);
773 + }
774 done:
775 accel_dev->hiodi = hiodi;
776 accel_dev->s_accel = s->s_accel;
@@ -1082,6 +1094,12 @@ static void smmuv3_accel_machine_done(Notifier *notifier, void *data)
1094 "at least one cold-plugged VFIO device");
1095 exit(1);
1096 }
1097 +
1098 + if (s->cmdqv == ON_OFF_AUTO_ON && !accel->cmdqv) {
1099 + error_report("arm-smmuv3 cmdqv=on requires at least one cold-plugged "
1100 + "VFIO device");
1101 + exit(1);
1102 + }
1103 }
1104
1105 bool smmuv3_accel_init(SMMUv3State *s, Error **errp)
hw/arm/smmuv3-accel.h
+1
@@ -84,6 +84,7 @@ typedef struct SMMUv3AccelDevice {
84 IOMMUFDVdev *vdev;
85 QLIST_ENTRY(SMMUv3AccelDevice) next;
86 SMMUv3AccelState *s_accel;
87 + Error *unplug_blocker; /* set when CMDQV is active to block hot-unplug */
88 } SMMUv3AccelDevice;
89
90 bool smmuv3_accel_init(SMMUv3State *s, Error **errp);