From: Liu Yi L <yi.l.liu@xxxxxxxxx> VFIO exposes IOMMU nesting translation (a.k.a dual stage translation) capability to userspace. Thus applications like QEMU could support vIOMMU with hardware's nesting translation capability for pass-through devices. Before setting up nesting translation for pass-through devices, QEMU and other applications need to learn the supported 1st-lvl/stage-1 translation structure format like page table format. Take vSVA (virtual Shared Virtual Addressing) as an example, to support vSVA for pass-through devices, QEMU setup nesting translation for pass- through devices. The guest page table are configured to host as 1st-lvl/ stage-1 page table. Therefore, guest format should be compatible with host side. This patch reports the supported 1st-lvl/stage-1 page table format on the current platform to userspace. QEMU and other alike applications should use this format info when trying to setup IOMMU nesting translation on host IOMMU. Cc: Kevin Tian <kevin.tian@xxxxxxxxx> CC: Jacob Pan <jacob.jun.pan@xxxxxxxxxxxxxxx> Cc: Alex Williamson <alex.williamson@xxxxxxxxxx> Cc: Eric Auger <eric.auger@xxxxxxxxxx> Cc: Jean-Philippe Brucker <jean-philippe.brucker@xxxxxxx> Signed-off-by: Liu Yi L <yi.l.liu@xxxxxxxxx> --- drivers/vfio/vfio_iommu_type1.c | 79 +++++++++++++++++++++++++++++++++++++++++ include/uapi/linux/vfio.h | 7 ++++ 2 files changed, 86 insertions(+) diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c index 1cf75f5..e0bbcfb 100644 --- a/drivers/vfio/vfio_iommu_type1.c +++ b/drivers/vfio/vfio_iommu_type1.c @@ -2243,6 +2243,81 @@ static int vfio_iommu_type1_pasid_free(struct vfio_iommu *iommu, return ret; } +static int vfio_iommu_get_pasid_format(struct vfio_iommu *iommu, + u32 *pasid_format) +{ + struct vfio_domain *domain; + u32 format = 0, tmp_format = 0; + int ret; + + mutex_lock(&iommu->lock); + if (list_empty(&iommu->domain_list)) { + mutex_unlock(&iommu->lock); + return -EINVAL; + } + + list_for_each_entry(domain, &iommu->domain_list, next) { + if (iommu_domain_get_attr(domain->domain, + DOMAIN_ATTR_PASID_FORMAT, &format)) { + ret = -EINVAL; + format = 0; + goto out_unlock; + } + /* + * format is always non-zero (the first format is + * IOMMU_PASID_FORMAT_INTEL_VTD which is 1). For + * the reason of potential different backed IOMMU + * formats, here we expect to have identical formats + * in the domain list, no miexed formats support. + * return -EINVAL to fail the attempt of setup + * VFIO_TYPE1_NESTING_IOMMU if non-identical formats + * are detected. + */ + if (tmp_format && tmp_format != format) { + ret = -EINVAL; + format = 0; + goto out_unlock; + } + + tmp_format = format; + } + ret = 0; + +out_unlock: + if (format) + *pasid_format = format; + mutex_unlock(&iommu->lock); + return ret; +} + +static int vfio_iommu_info_add_nesting_cap(struct vfio_iommu *iommu, + struct vfio_info_cap *caps) +{ + struct vfio_info_cap_header *header; + struct vfio_iommu_type1_info_cap_nesting *nesting_cap; + u32 format = 0; + int ret; + + ret = vfio_iommu_get_pasid_format(iommu, &format); + if (ret) { + pr_warn("Failed to get domain format\n"); + return ret; + } + + header = vfio_info_cap_add(caps, sizeof(*nesting_cap) + sizeof(format), + VFIO_IOMMU_TYPE1_INFO_CAP_NESTING, 1); + if (IS_ERR(header)) + return PTR_ERR(header); + + nesting_cap = container_of(header, + struct vfio_iommu_type1_info_cap_nesting, + header); + + nesting_cap->pasid_format = format; + + return 0; +} + static int vfio_iommu_type1_set_pasid_quota(struct vfio_iommu *iommu, u32 quota) { @@ -2313,6 +2388,10 @@ static long vfio_iommu_type1_ioctl(void *iommu_data, if (ret) return ret; + ret = vfio_iommu_info_add_nesting_cap(iommu, &caps); + if (ret) + return ret; + if (caps.size) { info.flags |= VFIO_IOMMU_INFO_CAPS; diff --git a/include/uapi/linux/vfio.h b/include/uapi/linux/vfio.h index 62113be..633c07f 100644 --- a/include/uapi/linux/vfio.h +++ b/include/uapi/linux/vfio.h @@ -748,6 +748,13 @@ struct vfio_iommu_type1_info_cap_iova_range { struct vfio_iova_range iova_ranges[]; }; +#define VFIO_IOMMU_TYPE1_INFO_CAP_NESTING 2 + +struct vfio_iommu_type1_info_cap_nesting { + struct vfio_info_cap_header header; + __u32 pasid_format; +}; + #define VFIO_IOMMU_GET_INFO _IO(VFIO_TYPE, VFIO_BASE + 12) /** -- 2.7.4