From: Zhenzhong Duan <[email protected]> Currently we don't support nested translation for passthrough device with emulated device under same PCI bridge, because they require different address space when x-flts=on.
In theory, we do support if devices under same PCI bridge are all passthrough devices. But emulated device can be hotplugged under same bridge. To simplify, just forbid passthrough device under PCI bridge no matter if there is, or will be emulated devices under same bridge. This is acceptable because PCIE bridge is more popular than PCI bridge now. Suggested-by: Yi Liu <[email protected]> Signed-off-by: Zhenzhong Duan <[email protected]> Reviewed-by: Eric Auger <[email protected]> Reviewed-by: Yi Liu <[email protected]> Reviewed-by: Michael S. Tsirkin <[email protected]> Link: https://lore.kernel.org/qemu-devel/[email protected] Signed-off-by: Cédric Le Goater <[email protected]> --- hw/i386/intel_iommu_accel.h | 4 ++-- hw/i386/intel_iommu.c | 7 ++++--- hw/i386/intel_iommu_accel.c | 12 +++++++++++- 3 files changed, 17 insertions(+), 6 deletions(-) diff --git a/hw/i386/intel_iommu_accel.h b/hw/i386/intel_iommu_accel.h index 79117b25a030a3d22d75b635725a6f78a21ec407..1d1fffb731a0daaf81f283e996707b25738eb5b6 100644 --- a/hw/i386/intel_iommu_accel.h +++ b/hw/i386/intel_iommu_accel.h @@ -13,11 +13,11 @@ #include CONFIG_DEVICES #ifdef CONFIG_VTD_ACCEL -bool vtd_check_hiod_accel(IntelIOMMUState *s, HostIOMMUDevice *hiod, +bool vtd_check_hiod_accel(IntelIOMMUState *s, VTDHostIOMMUDevice *vtd_hiod, Error **errp); #else static inline bool vtd_check_hiod_accel(IntelIOMMUState *s, - HostIOMMUDevice *hiod, + VTDHostIOMMUDevice *vtd_hiod, Error **errp) { error_setg(errp, "host IOMMU cannot be checked!"); diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c index b11798d4b75b7fb6961a1b2bde8851667b0d07db..0817b1777220072f6b10e13af73b1c6434447d1a 100644 --- a/hw/i386/intel_iommu.c +++ b/hw/i386/intel_iommu.c @@ -4570,9 +4570,10 @@ VTDAddressSpace *vtd_find_add_as(IntelIOMMUState *s, PCIBus *bus, return vtd_dev_as; } -static bool vtd_check_hiod(IntelIOMMUState *s, HostIOMMUDevice *hiod, +static bool vtd_check_hiod(IntelIOMMUState *s, VTDHostIOMMUDevice *vtd_hiod, Error **errp) { + HostIOMMUDevice *hiod = vtd_hiod->hiod; HostIOMMUDeviceClass *hiodc = HOST_IOMMU_DEVICE_GET_CLASS(hiod); int ret; @@ -4596,7 +4597,7 @@ static bool vtd_check_hiod(IntelIOMMUState *s, HostIOMMUDevice *hiod, return true; } - return vtd_check_hiod_accel(s, hiod, errp); + return vtd_check_hiod_accel(s, vtd_hiod, errp); } static bool vtd_dev_set_iommu_device(PCIBus *bus, void *opaque, int devfn, @@ -4632,7 +4633,7 @@ static bool vtd_dev_set_iommu_device(PCIBus *bus, void *opaque, int devfn, vtd_hiod->iommu_state = s; vtd_hiod->hiod = hiod; - if (!vtd_check_hiod(s, hiod, errp)) { + if (!vtd_check_hiod(s, vtd_hiod, errp)) { g_free(vtd_hiod); vtd_iommu_unlock(s); return false; diff --git a/hw/i386/intel_iommu_accel.c b/hw/i386/intel_iommu_accel.c index 2942eff100b9e7871326d27b58b71517ff705271..99f173b2486c4bd05d6cfeed56d03c3efc6a658d 100644 --- a/hw/i386/intel_iommu_accel.c +++ b/hw/i386/intel_iommu_accel.c @@ -12,12 +12,16 @@ #include "system/iommufd.h" #include "intel_iommu_internal.h" #include "intel_iommu_accel.h" +#include "hw/pci/pci_bus.h" -bool vtd_check_hiod_accel(IntelIOMMUState *s, HostIOMMUDevice *hiod, +bool vtd_check_hiod_accel(IntelIOMMUState *s, VTDHostIOMMUDevice *vtd_hiod, Error **errp) { + HostIOMMUDevice *hiod = vtd_hiod->hiod; struct HostIOMMUDeviceCaps *caps = &hiod->caps; struct iommu_hw_info_vtd *vtd = &caps->vendor_caps.vtd; + PCIBus *bus = vtd_hiod->bus; + PCIDevice *pdev = bus->devices[vtd_hiod->devfn]; if (!object_dynamic_cast(OBJECT(hiod), TYPE_HOST_IOMMU_DEVICE_IOMMUFD)) { error_setg(errp, "Need IOMMUFD backend when x-flts=on"); @@ -36,6 +40,12 @@ bool vtd_check_hiod_accel(IntelIOMMUState *s, HostIOMMUDevice *hiod, return false; } + if (pci_device_get_iommu_bus_devfn(pdev, &bus, NULL, NULL)) { + error_setg(errp, "Host device downstream to a PCI bridge is " + "unsupported when x-flts=on"); + return false; + } + error_setg(errp, "host IOMMU is incompatible with guest first stage translation"); return false; -- 2.52.0
