From patchwork Wed May 4 11:54:18 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Auger Eric X-Patchwork-Id: 67128 Delivered-To: patches@linaro.org Received: by 10.140.92.199 with SMTP id b65csp135583qge; Wed, 4 May 2016 04:55:05 -0700 (PDT) X-Received: by 10.194.143.51 with SMTP id sb19mr8295164wjb.98.1462362897013; Wed, 04 May 2016 04:54:57 -0700 (PDT) Return-Path: Received: from mail-wm0-x22e.google.com (mail-wm0-x22e.google.com. [2a00:1450:400c:c09::22e]) by mx.google.com with ESMTPS id ld8si4441001wjc.77.2016.05.04.04.54.56 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 04 May 2016 04:54:56 -0700 (PDT) Received-SPF: pass (google.com: domain of eric.auger@linaro.org designates 2a00:1450:400c:c09::22e as permitted sender) client-ip=2a00:1450:400c:c09::22e; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org; spf=pass (google.com: domain of eric.auger@linaro.org designates 2a00:1450:400c:c09::22e as permitted sender) smtp.mailfrom=eric.auger@linaro.org; dmarc=pass (p=NONE dis=NONE) header.from=linaro.org Received: by mail-wm0-x22e.google.com with SMTP id g17so89447776wme.1 for ; Wed, 04 May 2016 04:54:56 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=zzvAOQkwghmbZ23ZFQZiY61ZbF7jmjFMSX3KiJfeE9I=; b=YnPrffxHGSQcXFxdEALDnIKlMCd+d5zxHUscZ2evQNmF2wJEN6g3WEuZUqYXV1mhfM pTMgQGuuXRI3TDiGE/YGou83ues0Q36o6M/6mQGrRo1CR7NaqmTYqeKGq5jDVpQdUYrE GzIcW7qi7HNAvz9yB8giTRwNbsIhen92sTxWw= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=zzvAOQkwghmbZ23ZFQZiY61ZbF7jmjFMSX3KiJfeE9I=; b=MmoTHardp0287sd13GCZGXCxZ5CM9jsI9SMORyxhk8zUUkCQX2suxCDaf6FW0UlboU uj5PotzDzB086WDz/Cp+Lokl1ECFyWUHOVwG9EkRBdrED7v1iJTJSZQ79ohk5LomGBcd /SfocvdHMyBPZaord4RDYFwZSwnhVRLjnxDNOwhTkd4pFPtYxiqHuU//YT6Pri9tz1AK wpH066biwl/lXeyZ/2YGgRxiMe36LUcuJe4mC977SWmw1iO2h04nSuRDkcaXZB0SUuZi A+2RwsxfNDI+R0ZAy0hobi7D6U/SuGbuwWht3BCTS70/x/YVNUqgPWtWtdQRro+O5Ub8 Ay+g== X-Gm-Message-State: AOPr4FVfUcbGiYGM0uAXpOpGYQdQwt538y8w3wdlxRgjnhMbXNzflZGewSljFSXfleBK819l7xQ= X-Received: by 10.194.95.40 with SMTP id dh8mr8801117wjb.146.1462362896693; Wed, 04 May 2016 04:54:56 -0700 (PDT) Return-Path: Received: from new-host-61.home (LMontsouris-657-1-37-90.w80-11.abo.wanadoo.fr. [80.11.198.90]) by smtp.gmail.com with ESMTPSA id ck9sm3816623wjc.22.2016.05.04.04.54.52 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 04 May 2016 04:54:55 -0700 (PDT) From: Eric Auger To: eric.auger@st.com, eric.auger@linaro.org, robin.murphy@arm.com, alex.williamson@redhat.com, will.deacon@arm.com, joro@8bytes.org, tglx@linutronix.de, jason@lakedaemon.net, marc.zyngier@arm.com, christoffer.dall@linaro.org, linux-arm-kernel@lists.infradead.org Cc: patches@linaro.org, linux-kernel@vger.kernel.org, Bharat.Bhushan@freescale.com, pranav.sawargaonkar@gmail.com, p.fedin@samsung.com, iommu@lists.linux-foundation.org, Jean-Philippe.Brucker@arm.com, julien.grall@arm.com, yehuday@marvell.com Subject: [PATCH v9 7/7] vfio/type1: return MSI geometry through VFIO_IOMMU_GET_INFO capability chains Date: Wed, 4 May 2016 11:54:18 +0000 Message-Id: <1462362858-2925-8-git-send-email-eric.auger@linaro.org> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1462362858-2925-1-git-send-email-eric.auger@linaro.org> References: <1462362858-2925-1-git-send-email-eric.auger@linaro.org> This patch allows the user-space to retrieve the MSI geometry. The implementation is based on capability chains, now also added to VFIO_IOMMU_GET_INFO. The returned info comprise: - whether the MSI IOVA are constrained to a reserved range (x86 case) and in the positive, the start/end of the aperture, - or whether the IOVA aperture need to be set by the userspace. In that case, the size and alignment of the IOVA region to be provided are returned. In case the userspace must provide the IOVA range, we currently return an arbitrary number of IOVA pages (16), supposed to fulfill the needs of current ARM platforms. This may be deprecated by a more sophisticated computation later on. Signed-off-by: Eric Auger --- v8 -> v9: - use iommu_msi_supported flag instead of programmable - replace IOMMU_INFO_REQUIRE_MSI_MAP flag by a more sophisticated capability chain, reporting the MSI geometry v7 -> v8: - use iommu_domain_msi_geometry v6 -> v7: - remove the computation of the number of IOVA pages to be provisionned. This number depends on the domain/group/device topology which can dynamically change. Let's rely instead rely on an arbitrary max depending on the system v4 -> v5: - move msi_info and ret declaration within the conditional code v3 -> v4: - replace former vfio_domains_require_msi_mapping by more complex computation of MSI mapping requirements, especially the number of pages to be provided by the user-space. - reword patch title RFC v1 -> v1: - derived from [RFC PATCH 3/6] vfio: Extend iommu-info to return MSIs automap state - renamed allow_msi_reconfig into require_msi_mapping - fixed VFIO_IOMMU_GET_INFO --- drivers/vfio/vfio_iommu_type1.c | 69 +++++++++++++++++++++++++++++++++++++++++ include/uapi/linux/vfio.h | 30 +++++++++++++++++- 2 files changed, 98 insertions(+), 1 deletion(-) -- 1.9.1 diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c index 2fc8197..841360b 100644 --- a/drivers/vfio/vfio_iommu_type1.c +++ b/drivers/vfio/vfio_iommu_type1.c @@ -1134,6 +1134,50 @@ static int vfio_domains_have_iommu_cache(struct vfio_iommu *iommu) return ret; } +static int compute_msi_geometry_caps(struct vfio_iommu *iommu, + struct vfio_info_cap *caps) +{ + struct vfio_iommu_type1_info_cap_msi_geometry *vfio_msi_geometry; + struct iommu_domain_msi_geometry msi_geometry; + struct vfio_info_cap_header *header; + struct vfio_domain *d; + bool mapping_required; + size_t size; + + mutex_lock(&iommu->lock); + /* All domains have same require_msi_map property, pick first */ + d = list_first_entry(&iommu->domain_list, struct vfio_domain, next); + iommu_domain_get_attr(d->domain, DOMAIN_ATTR_MSI_GEOMETRY, + &msi_geometry); + mapping_required = msi_geometry.iommu_msi_supported; + + mutex_unlock(&iommu->lock); + + size = sizeof(*vfio_msi_geometry); + header = vfio_info_cap_add(caps, size, + VFIO_IOMMU_TYPE1_INFO_CAP_MSI_GEOMETRY, 1); + + if (IS_ERR(header)) + return PTR_ERR(header); + + vfio_msi_geometry = container_of(header, + struct vfio_iommu_type1_info_cap_msi_geometry, + header); + + vfio_msi_geometry->reserved = !mapping_required; + if (vfio_msi_geometry->reserved) { + vfio_msi_geometry->aperture_start = msi_geometry.aperture_start; + vfio_msi_geometry->aperture_end = msi_geometry.aperture_end; + return 0; + } + + vfio_msi_geometry->alignment = 1 << __ffs(vfio_pgsize_bitmap(iommu)); + /* we currently report the need for an arbitray number of 16 pages */ + vfio_msi_geometry->size = 16 * vfio_msi_geometry->alignment; + + return 0; +} + static long vfio_iommu_type1_ioctl(void *iommu_data, unsigned int cmd, unsigned long arg) { @@ -1155,6 +1199,8 @@ static long vfio_iommu_type1_ioctl(void *iommu_data, } } else if (cmd == VFIO_IOMMU_GET_INFO) { struct vfio_iommu_type1_info info; + struct vfio_info_cap caps = { .buf = NULL, .size = 0 }; + int ret; minsz = offsetofend(struct vfio_iommu_type1_info, iova_pgsizes); @@ -1168,6 +1214,29 @@ static long vfio_iommu_type1_ioctl(void *iommu_data, info.iova_pgsizes = vfio_pgsize_bitmap(iommu); + ret = compute_msi_geometry_caps(iommu, &caps); + if (ret) + return ret; + + if (caps.size) { + info.flags |= VFIO_IOMMU_INFO_CAPS; + if (info.argsz < sizeof(info) + caps.size) { + info.argsz = sizeof(info) + caps.size; + info.cap_offset = 0; + } else { + vfio_info_cap_shift(&caps, sizeof(info)); + if (copy_to_user((void __user *)arg + + sizeof(info), caps.buf, + caps.size)) { + kfree(caps.buf); + return -EFAULT; + } + info.cap_offset = sizeof(info); + } + + kfree(caps.buf); + } + return copy_to_user((void __user *)arg, &info, minsz) ? -EFAULT : 0; diff --git a/include/uapi/linux/vfio.h b/include/uapi/linux/vfio.h index 4a9dbc2..0ff6a8d 100644 --- a/include/uapi/linux/vfio.h +++ b/include/uapi/linux/vfio.h @@ -488,7 +488,33 @@ struct vfio_iommu_type1_info { __u32 argsz; __u32 flags; #define VFIO_IOMMU_INFO_PGSIZES (1 << 0) /* supported page sizes info */ - __u64 iova_pgsizes; /* Bitmap of supported page sizes */ +#define VFIO_IOMMU_INFO_CAPS (1 << 1) /* Info supports caps */ + __u32 cap_offset; /* Offset within info struct of first cap */ + __u64 iova_pgsizes; /* Bitmap of supported page sizes */ +}; + +#define VFIO_IOMMU_TYPE1_INFO_CAP_MSI_GEOMETRY 1 + +/* + * The MSI geometry capability allows to report the MSI IOVA geometry: + * - either the MSI IOVAs are constrained within a reserved IOVA aperture + * whose boundaries are given by [@aperture_start, @aperture_end]. + * this is typically the case on x86 host. The userspace is not allowed + * to map userspace memory at IOVAs intersecting this range using + * VFIO_IOMMU_MAP_DMA. + * - or the MSI IOVAs are not requested to belong to any reserved range; + * in that case the userspace must provide an IOVA window characterized by + * @size and @alignment using VFIO_IOMMU_MAP_DMA with RESERVED_MSI_IOVA flag. + */ +struct vfio_iommu_type1_info_cap_msi_geometry { + struct vfio_info_cap_header header; + bool reserved; /* Are MSI IOVAs within a reserved aperture? */ + /* reserved */ + __u64 aperture_start; + __u64 aperture_end; + /* not reserved */ + __u64 size; /* IOVA aperture size in bytes the userspace must provide */ + __u64 alignment; /* alignment of the window, in bytes */ }; #define VFIO_IOMMU_GET_INFO _IO(VFIO_TYPE, VFIO_BASE + 12) @@ -503,6 +529,8 @@ struct vfio_iommu_type1_info { * IOVA region that will be used on some platforms to map the host MSI frames. * In that specific case, vaddr is ignored. Once registered, an MSI reserved * IOVA region stays until the container is closed. + * The requirement for provisioning such reserved IOVA range can be checked by + * checking the VFIO_IOMMU_TYPE1_INFO_CAP_MSI_GEOMETRY capability. */ struct vfio_iommu_type1_dma_map { __u32 argsz;