On Thu, 21 Oct 2021 18:42:59 +0800 Peter Xu <pet...@redhat.com> wrote:
> Scan the pci bus to make sure there's no vfio-pci device attached before > vIOMMU > is realized. Sorry, I'm not onboard with this solution at all. It would be really useful though if this commit log or a code comment described exactly the incompatibility for which vfio-pci devices are being called out here. Otherwise I see this as a bit of magic voodoo that gets lost in lore and copied elsewhere and we're constantly trying to figure out specific incompatibilities when vfio-pci devices are trying really hard to be "just another device". I infer from the link of the previous alternate solution that this is to do with the fact that vfio devices attach a memory listener to the device address space. Interestingly that previous cover letter also discusses how vdpa devices might have a similar issue, which makes it confusing again that we're calling out vfio-pci devices by name rather than for a behavior. If the behavior here is that vfio-pci devices attach a listener to the device address space, then that provides a couple possible options. We could look for devices that have recorded an interest in their address space, such as by setting a flag on PCIDevice when someone calls pci_device_iommu_address_space(), where we could walk all devices using the code in this series to find a device with such a flag. Another option might be to attach owner objects to memory listeners, walk all the listeners on the system address space (that the vIOMMU is about to replace for some devices) and evaluate the owner objects against TYPE_PCI_DEVICE. Please lets not just call out arbitrary devices, especially not without a thorough explanation of the incompatibility. Thanks, Alex > Suggested-by: Igor Mammedov <imamm...@redhat.com> > Signed-off-by: Peter Xu <pet...@redhat.com> > --- > hw/i386/x86-iommu.c | 18 ++++++++++++++++++ > 1 file changed, 18 insertions(+) > > diff --git a/hw/i386/x86-iommu.c b/hw/i386/x86-iommu.c > index 86ad03972e..58abce7edc 100644 > --- a/hw/i386/x86-iommu.c > +++ b/hw/i386/x86-iommu.c > @@ -21,6 +21,7 @@ > #include "hw/sysbus.h" > #include "hw/i386/x86-iommu.h" > #include "hw/qdev-properties.h" > +#include "hw/vfio/pci.h" > #include "hw/i386/pc.h" > #include "qapi/error.h" > #include "qemu/error-report.h" > @@ -103,6 +104,16 @@ IommuType x86_iommu_get_type(void) > return x86_iommu_default->type; > } > > +static void x86_iommu_pci_dev_hook(PCIBus *bus, PCIDevice *dev, void *opaque) > +{ > + Error **errp = (Error **)opaque; > + > + if (object_dynamic_cast(OBJECT(dev), TYPE_VFIO_PCI)) { > + error_setg(errp, "Device '%s' must be specified before vIOMMUs", > + TYPE_VFIO_PCI); > + } > +} > + > static void x86_iommu_realize(DeviceState *dev, Error **errp) > { > X86IOMMUState *x86_iommu = X86_IOMMU_DEVICE(dev); > @@ -120,6 +131,12 @@ static void x86_iommu_realize(DeviceState *dev, Error > **errp) > return; > } > > + /* Make sure there's no special device plugged before vIOMMU */ > + pci_for_each_device_all(x86_iommu_pci_dev_hook, (void *)errp); > + if (*errp) { > + return; > + } > + > /* If the user didn't specify IR, choose a default value for it */ > if (x86_iommu->intr_supported == ON_OFF_AUTO_AUTO) { > x86_iommu->intr_supported = irq_all_kernel ? > @@ -151,6 +168,7 @@ static Property x86_iommu_properties[] = { > static void x86_iommu_class_init(ObjectClass *klass, void *data) > { > DeviceClass *dc = DEVICE_CLASS(klass); > + > dc->realize = x86_iommu_realize; > device_class_set_props(dc, x86_iommu_properties); > }