aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZhenzhong Duan <zhenzhong.duan@intel.com>2024-06-05 16:30:43 +0800
committerCédric Le Goater <clg@redhat.com>2024-06-24 23:15:30 +0200
commit77f6efc0ab93718da2bc3f908b7ff7fffa489ea1 (patch)
treee2c340ee7f20da045db0cc6c1398c36a7410029a
parenta20910ca3e283b10585c71061746ea6b1fa6ca91 (diff)
downloadqemu-77f6efc0ab93718da2bc3f908b7ff7fffa489ea1.zip
qemu-77f6efc0ab93718da2bc3f908b7ff7fffa489ea1.tar.gz
qemu-77f6efc0ab93718da2bc3f908b7ff7fffa489ea1.tar.bz2
intel_iommu: Check compatibility with host IOMMU capabilities
If check fails, host device (either VFIO or VDPA device) is not compatible with current vIOMMU config and should not be passed to guest. Only aw_bits is checked for now, we don't care about other caps before scalable modern mode is introduced. Signed-off-by: Yi Liu <yi.l.liu@intel.com> Signed-off-by: Zhenzhong Duan <zhenzhong.duan@intel.com> Reviewed-by: Eric Auger <eric.auger@redhat.com> Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
-rw-r--r--hw/i386/intel_iommu.c29
1 files changed, 29 insertions, 0 deletions
diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c
index 019d1c9..37c21a0a 100644
--- a/hw/i386/intel_iommu.c
+++ b/hw/i386/intel_iommu.c
@@ -3837,6 +3837,30 @@ VTDAddressSpace *vtd_find_add_as(IntelIOMMUState *s, PCIBus *bus,
return vtd_dev_as;
}
+static bool vtd_check_hiod(IntelIOMMUState *s, HostIOMMUDevice *hiod,
+ Error **errp)
+{
+ HostIOMMUDeviceClass *hiodc = HOST_IOMMU_DEVICE_GET_CLASS(hiod);
+ int ret;
+
+ if (!hiodc->get_cap) {
+ error_setg(errp, ".get_cap() not implemented");
+ return false;
+ }
+
+ /* Common checks */
+ ret = hiodc->get_cap(hiod, HOST_IOMMU_DEVICE_CAP_AW_BITS, errp);
+ if (ret < 0) {
+ return false;
+ }
+ if (s->aw_bits > ret) {
+ error_setg(errp, "aw-bits %d > host aw-bits %d", s->aw_bits, ret);
+ return false;
+ }
+
+ return true;
+}
+
static bool vtd_dev_set_iommu_device(PCIBus *bus, void *opaque, int devfn,
HostIOMMUDevice *hiod, Error **errp)
{
@@ -3857,6 +3881,11 @@ static bool vtd_dev_set_iommu_device(PCIBus *bus, void *opaque, int devfn,
return false;
}
+ if (!vtd_check_hiod(s, hiod, errp)) {
+ vtd_iommu_unlock(s);
+ return false;
+ }
+
new_key = g_malloc(sizeof(*new_key));
new_key->bus = bus;
new_key->devfn = devfn;