Now we have saved a copy of host iommu capabilities in VFIODevice, implemented hiod_iommufd_vfio_get_cap() by querying the caps copy in sub-class. This overrides .get_cap() implementation hiod_iommufd_vfio_get_cap() in TYPE_HOST_IOMMU_DEVICE_IOMMUFD parent class.
Vendor caps are checked for a specific capability, e.g., for vtd, checking code will be in hiod_iommufd_get_vtd_cap(). This also fixes an issue that calling vfio_device_get_aw_bits() in TYPE_HOST_IOMMU_DEVICE_IOMMUFD parent class .get_cap(). Signed-off-by: Zhenzhong Duan <zhenzhong.d...@intel.com> --- include/system/iommufd.h | 4 ++++ backends/iommufd.c | 40 ++++++++++++++++++++++++++++++++++++++++ hw/vfio/iommufd.c | 16 ++++++++++++++++ 3 files changed, 60 insertions(+) diff --git a/include/system/iommufd.h b/include/system/iommufd.h index 0f337585c9..baba5ec1d8 100644 --- a/include/system/iommufd.h +++ b/include/system/iommufd.h @@ -85,4 +85,8 @@ typedef struct HostIOMMUDeviceIOMMUFDCaps { uint64_t hw_caps; VendorCaps vendor_caps; } HostIOMMUDeviceIOMMUFDCaps; + +int hiod_iommufd_get_common_cap(HostIOMMUDevice *hiod, + HostIOMMUDeviceIOMMUFDCaps *caps, + int cap, Error **errp); #endif diff --git a/backends/iommufd.c b/backends/iommufd.c index 9587e4d99b..54fa3174d0 100644 --- a/backends/iommufd.c +++ b/backends/iommufd.c @@ -355,3 +355,43 @@ static const TypeInfo types[] = { }; DEFINE_TYPES(types) + +static int hiod_iommufd_get_vtd_cap(HostIOMMUDevice *hiod, + struct iommu_hw_info_vtd *vtd, + int cap, Error **errp) +{ + /* TODO: Check vtd->cap_reg/ecap_reg for capability */ + error_setg(errp, "%s: unsupported capability %x", hiod->name, cap); + return -EINVAL; +} + +static int hiod_iommufd_get_vendor_cap(HostIOMMUDevice *hiod, + HostIOMMUDeviceIOMMUFDCaps *caps, + int cap, Error **errp) +{ + enum iommu_hw_info_type type = caps->type; + + switch (type) { + case IOMMU_HW_INFO_TYPE_INTEL_VTD: + return hiod_iommufd_get_vtd_cap(hiod, &caps->vendor_caps.vtd, + cap, errp); + case IOMMU_HW_INFO_TYPE_ARM_SMMUV3: + case IOMMU_HW_INFO_TYPE_NONE: + break; + } + + error_setg(errp, "%s: unsupported capability type %x", hiod->name, type); + return -EINVAL; +} + +int hiod_iommufd_get_common_cap(HostIOMMUDevice *hiod, + HostIOMMUDeviceIOMMUFDCaps *caps, + int cap, Error **errp) +{ + switch (cap) { + case HOST_IOMMU_DEVICE_CAP_IOMMU_TYPE: + return caps->type; + default: + return hiod_iommufd_get_vendor_cap(hiod, caps, cap, errp); + } +} diff --git a/hw/vfio/iommufd.c b/hw/vfio/iommufd.c index e05b472e35..e7ca92f81f 100644 --- a/hw/vfio/iommufd.c +++ b/hw/vfio/iommufd.c @@ -833,6 +833,21 @@ static bool hiod_iommufd_vfio_realize(HostIOMMUDevice *hiod, void *opaque, return true; } +static int hiod_iommufd_vfio_get_cap(HostIOMMUDevice *hiod, int cap, + Error **errp) +{ + VFIODevice *vdev = hiod->agent; + HostIOMMUDeviceIOMMUFDCaps *caps = &vdev->caps; + + /* VFIO has its own way to get aw_bits which may be different from VDPA */ + switch (cap) { + case HOST_IOMMU_DEVICE_CAP_AW_BITS: + return vfio_device_get_aw_bits(hiod->agent); + default: + return hiod_iommufd_get_common_cap(hiod, caps, cap, errp); + } +} + static GList * hiod_iommufd_vfio_get_iova_ranges(HostIOMMUDevice *hiod) { @@ -857,6 +872,7 @@ static void hiod_iommufd_vfio_class_init(ObjectClass *oc, void *data) HostIOMMUDeviceClass *hiodc = HOST_IOMMU_DEVICE_CLASS(oc); hiodc->realize = hiod_iommufd_vfio_realize; + hiodc->get_cap = hiod_iommufd_vfio_get_cap; hiodc->get_iova_ranges = hiod_iommufd_vfio_get_iova_ranges; hiodc->get_page_size_mask = hiod_iommufd_vfio_get_page_size_mask; }; -- 2.34.1