Call pci_device_get_viommu_flags() to get if vIOMMU supports
VIOMMU_FLAG_WANT_NESTING_PARENT.
If yes, create a nesting parent HWPT and add it to the container's hwpt_list,
letting this parent HWPT cover the entire second stage mappings (GPA=>HPA).
This allows a VFIO passthrough device to directly attach to this default HWPT
and then to use the system address space and its listener.
Introduce a vfio_device_get_viommu_flags_want_nesting() helper to facilitate
this implementation.
It is safe to do so because a vIOMMU will be able to fail in set_iommu_device()
call, if something else related to the VFIO device or vIOMMU isn't compatible.
Suggested-by: Nicolin Chen <nicolinc@nvidia.com>
Suggested-by: Yi Liu <yi.l.liu@intel.com>
Signed-off-by: Zhenzhong Duan <zhenzhong.duan@intel.com>
Reviewed-by: Nicolin Chen <nicolinc@nvidia.com>
Reviewed-by: Eric Auger <eric.auger@redhat.com>
Reviewed-by: Yi Liu <yi.l.liu@intel.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Link: https://lore.kernel.org/qemu-devel/20260106061304.314546-9-zhenzhong.duan@intel.com
Signed-off-by: Cédric Le Goater <clg@redhat.com>
#include "hw/vfio/vfio-device.h"
#include "hw/vfio/pci.h"
+#include "hw/core/iommu.h"
#include "hw/core/hw-error.h"
#include "trace.h"
#include "qapi/error.h"
vbasedev->bcontainer = NULL;
}
+bool vfio_device_get_viommu_flags_want_nesting(VFIODevice *vbasedev)
+{
+ VFIOPCIDevice *vdev = vfio_pci_from_vfio_device(vbasedev);
+
+ if (vdev) {
+ return !!(pci_device_get_viommu_flags(PCI_DEVICE(vdev)) &
+ VIOMMU_FLAG_WANT_NESTING_PARENT);
+ }
+ return false;
+}
+
/*
* Traditional ioctl() based io
*/
flags = IOMMU_HWPT_ALLOC_DIRTY_TRACKING;
}
+ /*
+ * If vIOMMU requests VFIO's cooperation to create nesting parent HWPT,
+ * force to create it so that it could be reused by vIOMMU to create
+ * nested HWPT.
+ */
+ if (vfio_device_get_viommu_flags_want_nesting(vbasedev)) {
+ flags |= IOMMU_HWPT_ALLOC_NEST_PARENT;
+ }
+
if (cpr_is_incoming()) {
hwpt_id = vbasedev->cpr.hwpt_id;
goto skip_alloc;
void vfio_device_unprepare(VFIODevice *vbasedev);
+bool vfio_device_get_viommu_flags_want_nesting(VFIODevice *vbasedev);
+
int vfio_device_get_region_info(VFIODevice *vbasedev, int index,
struct vfio_region_info **info);
int vfio_device_get_region_info_type(VFIODevice *vbasedev, uint32_t type,