From patchwork Thu Sep 12 11:17:39 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Paul Durrant X-Patchwork-Id: 11142827 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 3B14213BD for ; Thu, 12 Sep 2019 11:21:12 +0000 (UTC) Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 0B0B1206CD for ; Thu, 12 Sep 2019 11:21:12 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=citrix.com header.i=@citrix.com header.b="fVjvS5rE" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 0B0B1206CD Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=citrix.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=xen-devel-bounces@lists.xenproject.org Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1i8N6z-0000kn-OC; Thu, 12 Sep 2019 11:18:05 +0000 Received: from all-amaz-eas1.inumbo.com ([34.197.232.57] helo=us1-amaz-eas2.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1i8N6y-0000kH-Ip for xen-devel@lists.xenproject.org; Thu, 12 Sep 2019 11:18:04 +0000 X-Inumbo-ID: f450435e-d54e-11e9-83e7-12813bfff9fa Received: from esa6.hc3370-68.iphmx.com (unknown [216.71.155.175]) by us1-amaz-eas2.inumbo.com (Halon) with ESMTPS id f450435e-d54e-11e9-83e7-12813bfff9fa; Thu, 12 Sep 2019 11:17:49 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=citrix.com; s=securemail; t=1568287069; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=DiqvUIW6hHY/Pzax5r4Zxv1F9b0bO2Ks7paCIOLFgVE=; b=fVjvS5rEcDa0Xn58cLz9zjs6AtaMxJ1HhqkImGFPwz+zywf0NzIXLcFI 1T0Xu/Gi6e17+EMIHvlZQUZ5DWsYp1WghjZeFvOWbxWUmWnk3rKEHJwtP mzRUF5OeUvBgP7izNT5F7gZO0jdWdFIlWPpp+WZPfBsrfX0NGLlz/9Rje 4=; Authentication-Results: esa6.hc3370-68.iphmx.com; dkim=none (message not signed) header.i=none; spf=None smtp.pra=paul.durrant@citrix.com; spf=Pass smtp.mailfrom=Paul.Durrant@citrix.com; spf=None smtp.helo=postmaster@mail.citrix.com Received-SPF: None (esa6.hc3370-68.iphmx.com: no sender authenticity information available from domain of paul.durrant@citrix.com) identity=pra; client-ip=162.221.158.21; receiver=esa6.hc3370-68.iphmx.com; envelope-from="Paul.Durrant@citrix.com"; x-sender="paul.durrant@citrix.com"; x-conformance=sidf_compatible Received-SPF: Pass (esa6.hc3370-68.iphmx.com: domain of Paul.Durrant@citrix.com designates 162.221.158.21 as permitted sender) identity=mailfrom; client-ip=162.221.158.21; receiver=esa6.hc3370-68.iphmx.com; envelope-from="Paul.Durrant@citrix.com"; x-sender="Paul.Durrant@citrix.com"; x-conformance=sidf_compatible; x-record-type="v=spf1"; x-record-text="v=spf1 ip4:209.167.231.154 ip4:178.63.86.133 ip4:195.66.111.40/30 ip4:85.115.9.32/28 ip4:199.102.83.4 ip4:192.28.146.160 ip4:192.28.146.107 ip4:216.52.6.88 ip4:216.52.6.188 ip4:162.221.158.21 ip4:162.221.156.83 ~all" Received-SPF: None (esa6.hc3370-68.iphmx.com: no sender authenticity information available from domain of postmaster@mail.citrix.com) identity=helo; client-ip=162.221.158.21; receiver=esa6.hc3370-68.iphmx.com; envelope-from="Paul.Durrant@citrix.com"; x-sender="postmaster@mail.citrix.com"; x-conformance=sidf_compatible IronPort-SDR: Fp6lbpPSJA02WG1Hm+wtOAld+ue0ZdKCcqrNY+R7q1KtzEi9ryT+gHIxvnKzPs9KTDNZxpxVMb FrFNhj9dYouUHaoUCW59YwkpRCqgVQCYGQUK9s8OYQK4QsDdNAgpuup7rSYl/7Fv6E+FVc+hQP zLYXq8C5iXGLMVQ2beoVNqPthJdkYcNz0EbUNHlWVKpDVV0+Thz1mfVJqvpuCMM/aUSEEDAtrz obYUo922d7uMGrXcVQ6oYXFVLC4fpLB4dGNQbd5gxHa8NoQDjJ6nU47jyIxfHCU1yWmx+R1iW1 4fU= X-SBRS: 2.7 X-MesageID: 5719884 X-Ironport-Server: esa6.hc3370-68.iphmx.com X-Remote-IP: 162.221.158.21 X-Policy: $RELAYED X-IronPort-AV: E=Sophos;i="5.64,495,1559534400"; d="scan'208";a="5719884" From: Paul Durrant To: Date: Thu, 12 Sep 2019 12:17:39 +0100 Message-ID: <20190912111744.40410-2-paul.durrant@citrix.com> X-Mailer: git-send-email 2.20.1.2.gb21ebb671 In-Reply-To: <20190912111744.40410-1-paul.durrant@citrix.com> References: <20190912111744.40410-1-paul.durrant@citrix.com> MIME-Version: 1.0 Subject: [Xen-devel] [PATCH v9 1/6] domain: introduce XEN_DOMCTL_CDF_iommu flag X-BeenThere: xen-devel@lists.xenproject.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Cc: Stefano Stabellini , Wei Liu , Konrad Rzeszutek Wilk , George Dunlap , Andrew Cooper , Ian Jackson , Tim Deegan , Julien Grall , Paul Durrant , Christian Lindig , Jan Beulich , David Scott , Volodymyr Babchuk , =?utf-8?q?Roger_Pau_Monn?= =?utf-8?q?=C3=A9?= Errors-To: xen-devel-bounces@lists.xenproject.org Sender: "Xen-devel" This patch introduces a common domain creation flag to determine whether the domain is permitted to make use of the IOMMU. Currently the flag is always set for both dom0 and any domU created by libxl if the IOMMU is globally enabled (i.e. iommu_enabled == 1). sanitise_domain_config() is modified to reject the flag if !iommu_enabled. A new helper function, is_iommu_enabled(), is added to test the flag and iommu_domain_init() will return immediately if !is_iommu_enabled(). This is slightly different to the previous behaviour based on !iommu_enabled where the call to arch_iommu_domain_init() was made regardless, however it appears that this call was only necessary to initialize the dt_devices list for ARM such that iommu_release_dt_devices() can be called unconditionally by domain_relinquish_resources(). Adding a simple check of is_iommu_enabled() into iommu_release_dt_devices() keeps this unconditional call working. No functional change should be observed with this patch applied. Subsequent patches will allow the toolstack to control whether use of the IOMMU is enabled for a domain. NOTE: The introduction of the is_iommu_enabled() helper function might seem excessive but its use is expected to increase with subsequent patches. Also, having iommu_domain_init() bail before calling arch_iommu_domain_init() is not strictly necessary, but I think the consequent addition of the call to is_iommu_enabled() in iommu_release_dt_devices() makes the code clearer. Signed-off-by: Paul Durrant Reviewed-by: "Roger Pau Monné" Acked-by: Jan Beulich Acked-by: Christian Lindig --- Cc: David Scott Cc: Ian Jackson Cc: Wei Liu Cc: Andrew Cooper Cc: George Dunlap Cc: Julien Grall Cc: Konrad Rzeszutek Wilk Cc: Stefano Stabellini Cc: Tim Deegan Cc: Volodymyr Babchuk Previously part of series https://lists.xenproject.org/archives/html/xen-devel/2019-07/msg02267.html v9: - Fix oversight in ARM's arch_sanitise_domain_config() to tolerate setting of XEN_DOMCTL_CDF_iommu v7: - Add a check to verify that the toolstack has not set XEN_DOMCTL_CDF_iommu - Add missing ocaml binding changes v6: - Remove the toolstack parts as there's no nice method of testing whether the IOMMU is enabled in an architecture-neutral way v5: - Move is_iommu_enabled() check into iommu_domain_init() - Reject XEN_DOMCTL_CDF_iommu in sanitise_domain_config() if !iommu_enabled - Use evaluate_nospec() in defintion of is_iommu_enabled() --- tools/ocaml/libs/xc/xenctrl.ml | 1 + tools/ocaml/libs/xc/xenctrl.mli | 1 + xen/arch/arm/domain.c | 7 +++++-- xen/arch/arm/setup.c | 3 +++ xen/arch/x86/setup.c | 3 +++ xen/common/domain.c | 9 ++++++++- xen/common/domctl.c | 13 +++++++++++++ xen/drivers/passthrough/device_tree.c | 3 +++ xen/drivers/passthrough/iommu.c | 6 +++--- xen/include/public/domctl.h | 5 ++++- xen/include/xen/sched.h | 5 +++++ 11 files changed, 49 insertions(+), 7 deletions(-) diff --git a/tools/ocaml/libs/xc/xenctrl.ml b/tools/ocaml/libs/xc/xenctrl.ml index bfb3d8e181..eaf009f0f9 100644 --- a/tools/ocaml/libs/xc/xenctrl.ml +++ b/tools/ocaml/libs/xc/xenctrl.ml @@ -63,6 +63,7 @@ type domain_create_flag = | CDF_S3_INTEGRITY | CDF_OOS_OFF | CDF_XS_DOMAIN + | CDF_IOMMU type domctl_create_config = { diff --git a/tools/ocaml/libs/xc/xenctrl.mli b/tools/ocaml/libs/xc/xenctrl.mli index 8bc36ec8f6..e0636de23a 100644 --- a/tools/ocaml/libs/xc/xenctrl.mli +++ b/tools/ocaml/libs/xc/xenctrl.mli @@ -56,6 +56,7 @@ type domain_create_flag = | CDF_S3_INTEGRITY | CDF_OOS_OFF | CDF_XS_DOMAIN + | CDF_IOMMU type domctl_create_config = { ssidref: int32; diff --git a/xen/arch/arm/domain.c b/xen/arch/arm/domain.c index a9c4113c26..ae13e47e86 100644 --- a/xen/arch/arm/domain.c +++ b/xen/arch/arm/domain.c @@ -608,9 +608,12 @@ int arch_sanitise_domain_config(struct xen_domctl_createdomain *config) { unsigned int max_vcpus; - if ( config->flags != (XEN_DOMCTL_CDF_hvm | XEN_DOMCTL_CDF_hap) ) + /* HVM and HAP must be set. IOMMU may or may not be */ + if ( (config->flags & ~XEN_DOMCTL_CDF_iommu) != + (XEN_DOMCTL_CDF_hvm | XEN_DOMCTL_CDF_hap) ) { - dprintk(XENLOG_INFO, "Unsupported configuration %#x\n", config->flags); + dprintk(XENLOG_INFO, "Unsupported configuration %#x\n", + config->flags); return -EINVAL; } diff --git a/xen/arch/arm/setup.c b/xen/arch/arm/setup.c index 1b303bde34..ad101784e6 100644 --- a/xen/arch/arm/setup.c +++ b/xen/arch/arm/setup.c @@ -961,6 +961,9 @@ void __init start_xen(unsigned long boot_phys_offset, dom0_cfg.arch.tee_type = tee_get_type(); dom0_cfg.max_vcpus = dom0_max_vcpus(); + if ( iommu_enabled ) + dom0_cfg.flags |= XEN_DOMCTL_CDF_iommu; + dom0 = domain_create(0, &dom0_cfg, true); if ( IS_ERR(dom0) || (alloc_dom0_vcpu0(dom0) == NULL) ) panic("Error creating domain 0\n"); diff --git a/xen/arch/x86/setup.c b/xen/arch/x86/setup.c index 27981adc0b..dec60d0301 100644 --- a/xen/arch/x86/setup.c +++ b/xen/arch/x86/setup.c @@ -1732,6 +1732,9 @@ void __init noreturn __start_xen(unsigned long mbi_p) } dom0_cfg.max_vcpus = dom0_max_vcpus(); + if ( iommu_enabled ) + dom0_cfg.flags |= XEN_DOMCTL_CDF_iommu; + /* Create initial domain 0. */ dom0 = domain_create(get_initial_domain_id(), &dom0_cfg, !pv_shim); if ( IS_ERR(dom0) || (alloc_dom0_vcpu0(dom0) == NULL) ) diff --git a/xen/common/domain.c b/xen/common/domain.c index 09917b2885..4681f29c8b 100644 --- a/xen/common/domain.c +++ b/xen/common/domain.c @@ -301,7 +301,8 @@ static int sanitise_domain_config(struct xen_domctl_createdomain *config) XEN_DOMCTL_CDF_hap | XEN_DOMCTL_CDF_s3_integrity | XEN_DOMCTL_CDF_oos_off | - XEN_DOMCTL_CDF_xs_domain) ) + XEN_DOMCTL_CDF_xs_domain | + XEN_DOMCTL_CDF_iommu) ) { dprintk(XENLOG_INFO, "Unknown CDF flags %#x\n", config->flags); return -EINVAL; @@ -320,6 +321,12 @@ static int sanitise_domain_config(struct xen_domctl_createdomain *config) return -EINVAL; } + if ( (config->flags & XEN_DOMCTL_CDF_iommu) && !iommu_enabled ) + { + dprintk(XENLOG_INFO, "IOMMU is not enabled\n"); + return -EINVAL; + } + return arch_sanitise_domain_config(config); } diff --git a/xen/common/domctl.c b/xen/common/domctl.c index 6e6e9b9866..5dcfe3c8f6 100644 --- a/xen/common/domctl.c +++ b/xen/common/domctl.c @@ -515,6 +515,19 @@ long do_domctl(XEN_GUEST_HANDLE_PARAM(xen_domctl_t) u_domctl) rover = dom; } + /* + * For now, make sure the createdomain IOMMU flag is set if the + * IOMMU is enabled. When the flag comes under toolstack control + * this can go away. + */ + if ( op->u.createdomain.flags & XEN_DOMCTL_CDF_iommu ) + { + ASSERT_UNREACHABLE(); + return -EINVAL; + } + if ( iommu_enabled ) + op->u.createdomain.flags |= XEN_DOMCTL_CDF_iommu; + d = domain_create(dom, &op->u.createdomain, false); if ( IS_ERR(d) ) { diff --git a/xen/drivers/passthrough/device_tree.c b/xen/drivers/passthrough/device_tree.c index b6eaae7283..d32b172664 100644 --- a/xen/drivers/passthrough/device_tree.c +++ b/xen/drivers/passthrough/device_tree.c @@ -119,6 +119,9 @@ int iommu_release_dt_devices(struct domain *d) struct dt_device_node *dev, *_dev; int rc; + if ( !is_iommu_enabled(d) ) + return 0; + list_for_each_entry_safe(dev, _dev, &hd->dt_devices, domain_list) { rc = iommu_deassign_dt_device(d, dev); diff --git a/xen/drivers/passthrough/iommu.c b/xen/drivers/passthrough/iommu.c index b82f778479..f42402bc92 100644 --- a/xen/drivers/passthrough/iommu.c +++ b/xen/drivers/passthrough/iommu.c @@ -151,6 +151,9 @@ int iommu_domain_init(struct domain *d) struct domain_iommu *hd = dom_iommu(d); int ret = 0; + if ( !is_iommu_enabled(d) ) + return 0; + #ifdef CONFIG_NUMA hd->node = NUMA_NO_NODE; #endif @@ -159,9 +162,6 @@ int iommu_domain_init(struct domain *d) if ( ret ) return ret; - if ( !iommu_enabled ) - return 0; - hd->platform_ops = iommu_get_ops(); return hd->platform_ops->init(d); } diff --git a/xen/include/public/domctl.h b/xen/include/public/domctl.h index 77f546cbb8..1b3176adb5 100644 --- a/xen/include/public/domctl.h +++ b/xen/include/public/domctl.h @@ -64,9 +64,12 @@ struct xen_domctl_createdomain { /* Is this a xenstore domain? */ #define _XEN_DOMCTL_CDF_xs_domain 4 #define XEN_DOMCTL_CDF_xs_domain (1U<<_XEN_DOMCTL_CDF_xs_domain) + /* Should this domain be permitted to use the IOMMU? */ +#define _XEN_DOMCTL_CDF_iommu 5 +#define XEN_DOMCTL_CDF_iommu (1U<<_XEN_DOMCTL_CDF_iommu) /* Max XEN_DOMCTL_CDF_* constant. Used for ABI checking. */ -#define XEN_DOMCTL_CDF_MAX XEN_DOMCTL_CDF_xs_domain +#define XEN_DOMCTL_CDF_MAX XEN_DOMCTL_CDF_iommu uint32_t flags; diff --git a/xen/include/xen/sched.h b/xen/include/xen/sched.h index e3601c1935..2d17c84915 100644 --- a/xen/include/xen/sched.h +++ b/xen/include/xen/sched.h @@ -983,6 +983,11 @@ static inline bool is_xenstore_domain(const struct domain *d) return d->options & XEN_DOMCTL_CDF_xs_domain; } +static inline bool is_iommu_enabled(const struct domain *d) +{ + return evaluate_nospec(d->options & XEN_DOMCTL_CDF_iommu); +} + extern bool sched_smt_power_savings; extern enum cpufreq_controller { From patchwork Thu Sep 12 11:17:40 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Paul Durrant X-Patchwork-Id: 11142821 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 30262912 for ; Thu, 12 Sep 2019 11:21:02 +0000 (UTC) Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 002FA2081B for ; Thu, 12 Sep 2019 11:21:01 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=citrix.com header.i=@citrix.com header.b="CR8DKsxX" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 002FA2081B Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=citrix.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=xen-devel-bounces@lists.xenproject.org Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1i8N6n-0000fh-4V; Thu, 12 Sep 2019 11:17:53 +0000 Received: from us1-rack-iad1.inumbo.com ([172.99.69.81]) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1i8N6l-0000fa-7b for xen-devel@lists.xenproject.org; Thu, 12 Sep 2019 11:17:51 +0000 X-Inumbo-ID: f3da769c-d54e-11e9-978d-bc764e2007e4 Received: from esa1.hc3370-68.iphmx.com (unknown [216.71.145.142]) by us1-rack-iad1.inumbo.com (Halon) with ESMTPS id f3da769c-d54e-11e9-978d-bc764e2007e4; Thu, 12 Sep 2019 11:17:49 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=citrix.com; s=securemail; t=1568287070; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=3DNy0euenOg8CEGK6mzqIiUDvcThifdwmjtKi5kp96s=; b=CR8DKsxXczkz3HVoOwKTxWoIVfQULkilUCg/aFwc5/6IkKVtTH2GD49m /ENbTVMr1r4dBKU5hzWspNj6loT/4pjKqsoE091PHgJOfWlVlWRq7knYw 6isj5dl1s5oRywUfWMOfj7/pZSOEeGNDpGOYfk2n6GHWmqJA35BMo1qIE 4=; Authentication-Results: esa1.hc3370-68.iphmx.com; dkim=none (message not signed) header.i=none; spf=None smtp.pra=paul.durrant@citrix.com; spf=Pass smtp.mailfrom=Paul.Durrant@citrix.com; spf=None smtp.helo=postmaster@mail.citrix.com Received-SPF: None (esa1.hc3370-68.iphmx.com: no sender authenticity information available from domain of paul.durrant@citrix.com) identity=pra; client-ip=162.221.158.21; receiver=esa1.hc3370-68.iphmx.com; envelope-from="Paul.Durrant@citrix.com"; x-sender="paul.durrant@citrix.com"; x-conformance=sidf_compatible Received-SPF: Pass (esa1.hc3370-68.iphmx.com: domain of Paul.Durrant@citrix.com designates 162.221.158.21 as permitted sender) identity=mailfrom; client-ip=162.221.158.21; receiver=esa1.hc3370-68.iphmx.com; envelope-from="Paul.Durrant@citrix.com"; x-sender="Paul.Durrant@citrix.com"; x-conformance=sidf_compatible; x-record-type="v=spf1"; x-record-text="v=spf1 ip4:209.167.231.154 ip4:178.63.86.133 ip4:195.66.111.40/30 ip4:85.115.9.32/28 ip4:199.102.83.4 ip4:192.28.146.160 ip4:192.28.146.107 ip4:216.52.6.88 ip4:216.52.6.188 ip4:162.221.158.21 ip4:162.221.156.83 ~all" Received-SPF: None (esa1.hc3370-68.iphmx.com: no sender authenticity information available from domain of postmaster@mail.citrix.com) identity=helo; client-ip=162.221.158.21; receiver=esa1.hc3370-68.iphmx.com; envelope-from="Paul.Durrant@citrix.com"; x-sender="postmaster@mail.citrix.com"; x-conformance=sidf_compatible IronPort-SDR: B4W3E+mb7Mcon/OoHx0tfv911i4NTxYPvNbsmPanZMiZQd+7QpnmqbbQEh+alrwIbBrjHroGsb VyZv+qmJmXWIoMKulIx0vVo9YL9ogSPIX4/wkPTKxGF8wcPOXhzhjzyJURouFUs+CDZNkvbXbX hiLCTOB+C+olqC+Tt1KhzKbUc8HrKlsAOPZ/S7Ifmr+uyc1DNFyD+lksGXpG4MXo5RelCRbNnC yPJ/0cvtYuFIEhtxQBZdWgYTtgGVMQ7R4D7ZEAwykRQsFcxnKxmyW8REdhCzZRnX+e0VAdqt4A cbI= X-SBRS: 2.7 X-MesageID: 5530313 X-Ironport-Server: esa1.hc3370-68.iphmx.com X-Remote-IP: 162.221.158.21 X-Policy: $RELAYED X-IronPort-AV: E=Sophos;i="5.64,495,1559534400"; d="scan'208";a="5530313" From: Paul Durrant To: Date: Thu, 12 Sep 2019 12:17:40 +0100 Message-ID: <20190912111744.40410-3-paul.durrant@citrix.com> X-Mailer: git-send-email 2.20.1.2.gb21ebb671 In-Reply-To: <20190912111744.40410-1-paul.durrant@citrix.com> References: <20190912111744.40410-1-paul.durrant@citrix.com> MIME-Version: 1.0 Subject: [Xen-devel] [PATCH v9 2/6] use is_iommu_enabled() where appropriate... X-BeenThere: xen-devel@lists.xenproject.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Cc: Kevin Tian , Stefano Stabellini , Jun Nakajima , Wei Liu , George Dunlap , Andrew Cooper , Julien Grall , Paul Durrant , Jan Beulich , Daniel De Graaf , Volodymyr Babchuk , Suravee Suthikulpanit , =?utf-8?q?Roger_Pau_?= =?utf-8?q?Monn=C3=A9?= Errors-To: xen-devel-bounces@lists.xenproject.org Sender: "Xen-devel" ...rather than testing the global iommu_enabled flag and ops pointer. Now that there is a per-domain flag indicating whether the domain is permitted to use the IOMMU (which determines whether the ops pointer will be set), many tests of the global iommu_enabled flag and ops pointer can be translated into tests of the per-domain flag. Some of the other tests of purely the global iommu_enabled flag can also be translated into tests of the per-domain flag. NOTE: The comment in iommu_share_p2m_table() is also fixed; need_iommu() disappeared some time ago. Also, whilst the style of the 'if' in flask_iommu_resource_use_perm() is fixed, I have not translated any instances of u32 into uint32_t to keep consistency. IMO such a translation would be better done globally for the source module in a separate patch. The change to the definition of iommu_call() is to keep the PV shim build happy. Without this change it will fail to compile with errors of the form: iommu.c:361:32: error: unused variable ‘hd’ [-Werror=unused-variable] const struct domain_iommu *hd = dom_iommu(d); ^~ Signed-off-by: Paul Durrant Reviewed-by: "Roger Pau Monné" Reviewed-by: Kevin Tian Acked-by: Daniel De Graaf Reviewed-by: Jan Beulich Acked-by: Julien Grall --- Cc: Stefano Stabellini Cc: Volodymyr Babchuk Cc: Andrew Cooper Cc: Wei Liu Cc: Jun Nakajima Cc: George Dunlap Cc: Suravee Suthikulpanit Previously part of series https://lists.xenproject.org/archives/html/xen-devel/2019-07/msg02267.html v7: - Fix iommu_call() rather than messing with the initializtion of 'hd' - Constify domain pointer passed to flask_iommu_resource_use_perm() v5: - Fix logic in ARM p2m_init() - Make iommu_do_domctl() return -EOPNOTSUPP rather than -ENOSYS if the IOMMU is not enabled - Fix test in pci_enable_acs() - Fix test in flask_iommu_resource_use_perm() --- xen/arch/arm/p2m.c | 2 +- xen/arch/x86/dom0_build.c | 2 +- xen/arch/x86/domctl.c | 4 +-- xen/arch/x86/hvm/hvm.c | 6 ++--- xen/arch/x86/hvm/vioapic.c | 2 +- xen/arch/x86/hvm/vmx/vmcs.c | 2 +- xen/arch/x86/hvm/vmx/vmx.c | 2 +- xen/arch/x86/mm/p2m-ept.c | 4 +-- xen/drivers/passthrough/amd/iommu_guest.c | 2 +- xen/drivers/passthrough/device_tree.c | 4 +-- xen/drivers/passthrough/io.c | 8 +++--- xen/drivers/passthrough/iommu.c | 31 ++++++++++------------- xen/drivers/passthrough/pci.c | 16 ++++++------ xen/drivers/passthrough/vtd/iommu.c | 2 +- xen/drivers/passthrough/vtd/x86/hvm.c | 2 +- xen/drivers/passthrough/x86/iommu.c | 2 +- xen/include/asm-x86/iommu.h | 11 ++++++-- xen/xsm/flask/hooks.c | 18 ++++++------- 18 files changed, 62 insertions(+), 58 deletions(-) diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c index e28ea1c85a..7f1442932a 100644 --- a/xen/arch/arm/p2m.c +++ b/xen/arch/arm/p2m.c @@ -1531,7 +1531,7 @@ int p2m_init(struct domain *d) * shared with the CPU, Xen has to make sure that the PT changes have * reached the memory */ - p2m->clean_pte = iommu_enabled && + p2m->clean_pte = is_iommu_enabled(d) && !iommu_has_feature(d, IOMMU_FEAT_COHERENT_WALK); rc = p2m_alloc_table(d); diff --git a/xen/arch/x86/dom0_build.c b/xen/arch/x86/dom0_build.c index c69570920c..d381784edd 100644 --- a/xen/arch/x86/dom0_build.c +++ b/xen/arch/x86/dom0_build.c @@ -356,7 +356,7 @@ unsigned long __init dom0_compute_nr_pages( avail -= d->max_vcpus - 1; /* Reserve memory for iommu_dom0_init() (rough estimate). */ - if ( iommu_enabled ) + if ( is_iommu_enabled(d) ) { unsigned int s; diff --git a/xen/arch/x86/domctl.c b/xen/arch/x86/domctl.c index a744696c6b..d1334c7112 100644 --- a/xen/arch/x86/domctl.c +++ b/xen/arch/x86/domctl.c @@ -708,7 +708,7 @@ long arch_do_domctl( break; ret = -ESRCH; - if ( iommu_enabled ) + if ( is_iommu_enabled(d) ) { pcidevs_lock(); ret = pt_irq_create_bind(d, bind); @@ -737,7 +737,7 @@ long arch_do_domctl( if ( ret ) break; - if ( iommu_enabled ) + if ( is_iommu_enabled(d) ) { pcidevs_lock(); ret = pt_irq_destroy_bind(d, bind); diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c index 452ac4833d..3831c6d4c1 100644 --- a/xen/arch/x86/hvm/hvm.c +++ b/xen/arch/x86/hvm/hvm.c @@ -465,7 +465,7 @@ void hvm_migrate_timers(struct vcpu *v) void hvm_migrate_pirq(struct hvm_pirq_dpci *pirq_dpci, const struct vcpu *v) { - ASSERT(iommu_enabled && + ASSERT(is_iommu_enabled(v->domain) && (is_hardware_domain(v->domain) || hvm_domain_irq(v->domain)->dpci)); if ( (pirq_dpci->flags & HVM_IRQ_DPCI_MACH_MSI) && @@ -496,7 +496,7 @@ void hvm_migrate_pirqs(struct vcpu *v) { struct domain *d = v->domain; - if ( !iommu_enabled || !hvm_domain_irq(d)->dpci ) + if ( !is_iommu_enabled(d) || !hvm_domain_irq(d)->dpci ) return; spin_lock(&d->event_lock); @@ -2264,7 +2264,7 @@ int hvm_set_cr0(unsigned long value, bool may_defer) } if ( ((value ^ old_value) & X86_CR0_CD) && - iommu_enabled && hvm_funcs.handle_cd && + is_iommu_enabled(d) && hvm_funcs.handle_cd && (!rangeset_is_empty(d->iomem_caps) || !rangeset_is_empty(d->arch.ioport_caps) || has_arch_pdevs(d)) ) diff --git a/xen/arch/x86/hvm/vioapic.c b/xen/arch/x86/hvm/vioapic.c index 9c25f72b4d..9aeef32a14 100644 --- a/xen/arch/x86/hvm/vioapic.c +++ b/xen/arch/x86/hvm/vioapic.c @@ -536,7 +536,7 @@ void vioapic_update_EOI(struct domain *d, u8 vector) ent->fields.remote_irr = 0; - if ( iommu_enabled ) + if ( is_iommu_enabled(d) ) { spin_unlock(&d->arch.hvm.irq_lock); hvm_dpci_eoi(d, vioapic->base_gsi + pin, ent); diff --git a/xen/arch/x86/hvm/vmx/vmcs.c b/xen/arch/x86/hvm/vmx/vmcs.c index 16f14abe8f..ed27e8def7 100644 --- a/xen/arch/x86/hvm/vmx/vmcs.c +++ b/xen/arch/x86/hvm/vmx/vmcs.c @@ -1087,7 +1087,7 @@ static int construct_vmcs(struct vcpu *v) vmx_clear_msr_intercept(v, MSR_IA32_SYSENTER_CS, VMX_MSR_RW); vmx_clear_msr_intercept(v, MSR_IA32_SYSENTER_ESP, VMX_MSR_RW); vmx_clear_msr_intercept(v, MSR_IA32_SYSENTER_EIP, VMX_MSR_RW); - if ( paging_mode_hap(d) && (!iommu_enabled || iommu_snoop) ) + if ( paging_mode_hap(d) && (!is_iommu_enabled(d) || iommu_snoop) ) vmx_clear_msr_intercept(v, MSR_IA32_CR_PAT, VMX_MSR_RW); if ( (vmexit_ctl & VM_EXIT_CLEAR_BNDCFGS) && (vmentry_ctl & VM_ENTRY_LOAD_BNDCFGS) ) diff --git a/xen/arch/x86/hvm/vmx/vmx.c b/xen/arch/x86/hvm/vmx/vmx.c index 0060310d74..3b3d5b6250 100644 --- a/xen/arch/x86/hvm/vmx/vmx.c +++ b/xen/arch/x86/hvm/vmx/vmx.c @@ -1210,7 +1210,7 @@ static void vmx_handle_cd(struct vcpu *v, unsigned long value) { v->arch.hvm.cache_mode = NORMAL_CACHE_MODE; vmx_set_guest_pat(v, *pat); - if ( !iommu_enabled || iommu_snoop ) + if ( !is_iommu_enabled(v->domain) || iommu_snoop ) vmx_clear_msr_intercept(v, MSR_IA32_CR_PAT, VMX_MSR_RW); hvm_asid_flush_vcpu(v); /* no need to flush cache */ } diff --git a/xen/arch/x86/mm/p2m-ept.c b/xen/arch/x86/mm/p2m-ept.c index d0e62905f8..220990f017 100644 --- a/xen/arch/x86/mm/p2m-ept.c +++ b/xen/arch/x86/mm/p2m-ept.c @@ -260,7 +260,7 @@ static bool_t ept_split_super_page(struct p2m_domain *p2m, *epte = *ept_entry; epte->sp = (level > 1); epte->mfn += i * trunk; - epte->snp = (iommu_enabled && iommu_snoop); + epte->snp = is_iommu_enabled(p2m->domain) && iommu_snoop; epte->suppress_ve = 1; ept_p2m_type_to_flags(p2m, epte, epte->sa_p2mt, epte->access); @@ -772,7 +772,7 @@ ept_set_entry(struct p2m_domain *p2m, gfn_t gfn_, mfn_t mfn, new_entry.sp = !!i; new_entry.sa_p2mt = p2mt; new_entry.access = p2ma; - new_entry.snp = (iommu_enabled && iommu_snoop); + new_entry.snp = is_iommu_enabled(d) && iommu_snoop; /* the caller should take care of the previous page */ new_entry.mfn = mfn_x(mfn); diff --git a/xen/drivers/passthrough/amd/iommu_guest.c b/xen/drivers/passthrough/amd/iommu_guest.c index 7f2dd662af..1f2bcfbe15 100644 --- a/xen/drivers/passthrough/amd/iommu_guest.c +++ b/xen/drivers/passthrough/amd/iommu_guest.c @@ -821,7 +821,7 @@ int guest_iommu_init(struct domain* d) struct guest_iommu *iommu; struct domain_iommu *hd = dom_iommu(d); - if ( !is_hvm_domain(d) || !iommu_enabled || !iommuv2_enabled || + if ( !is_hvm_domain(d) || !is_iommu_enabled(d) || !iommuv2_enabled || !has_viommu(d) ) return 0; diff --git a/xen/drivers/passthrough/device_tree.c b/xen/drivers/passthrough/device_tree.c index d32b172664..12f2c4c3f2 100644 --- a/xen/drivers/passthrough/device_tree.c +++ b/xen/drivers/passthrough/device_tree.c @@ -29,7 +29,7 @@ int iommu_assign_dt_device(struct domain *d, struct dt_device_node *dev) int rc = -EBUSY; struct domain_iommu *hd = dom_iommu(d); - if ( !iommu_enabled || !hd->platform_ops ) + if ( !is_iommu_enabled(d) ) return -EINVAL; if ( !dt_device_is_protected(dev) ) @@ -71,7 +71,7 @@ int iommu_deassign_dt_device(struct domain *d, struct dt_device_node *dev) const struct domain_iommu *hd = dom_iommu(d); int rc; - if ( !iommu_enabled || !hd->platform_ops ) + if ( !is_iommu_enabled(d) ) return -EINVAL; if ( !dt_device_is_protected(dev) ) diff --git a/xen/drivers/passthrough/io.c b/xen/drivers/passthrough/io.c index 4290c7c710..b292e79382 100644 --- a/xen/drivers/passthrough/io.c +++ b/xen/drivers/passthrough/io.c @@ -434,7 +434,7 @@ int pt_irq_create_bind( if ( vcpu ) pirq_dpci->gmsi.posted = true; } - if ( vcpu && iommu_enabled ) + if ( vcpu && is_iommu_enabled(d) ) hvm_migrate_pirq(pirq_dpci, vcpu); /* Use interrupt posting if it is supported. */ @@ -817,7 +817,7 @@ int hvm_do_IRQ_dpci(struct domain *d, struct pirq *pirq) ASSERT(is_hvm_domain(d)); - if ( !iommu_enabled || (!is_hardware_domain(d) && !dpci) || + if ( !is_iommu_enabled(d) || (!is_hardware_domain(d) && !dpci) || !pirq_dpci || !(pirq_dpci->flags & HVM_IRQ_DPCI_MAPPED) ) return 0; @@ -869,7 +869,7 @@ static int _hvm_dpci_msi_eoi(struct domain *d, void hvm_dpci_msi_eoi(struct domain *d, int vector) { - if ( !iommu_enabled || + if ( !is_iommu_enabled(d) || (!hvm_domain_irq(d)->dpci && !is_hardware_domain(d)) ) return; @@ -1001,7 +1001,7 @@ void hvm_dpci_eoi(struct domain *d, unsigned int guest_gsi, const struct hvm_irq_dpci *hvm_irq_dpci; const struct hvm_girq_dpci_mapping *girq; - if ( !iommu_enabled ) + if ( !is_iommu_enabled(d) ) return; if ( is_hardware_domain(d) ) diff --git a/xen/drivers/passthrough/iommu.c b/xen/drivers/passthrough/iommu.c index f42402bc92..09ce9d9294 100644 --- a/xen/drivers/passthrough/iommu.c +++ b/xen/drivers/passthrough/iommu.c @@ -183,7 +183,7 @@ void __hwdom_init iommu_hwdom_init(struct domain *d) check_hwdom_reqs(d); - if ( !iommu_enabled ) + if ( !is_iommu_enabled(d) ) return; register_keyhandler('o', &iommu_dump_p2m_table, "dump iommu p2m table", 0); @@ -288,7 +288,7 @@ int iommu_construct(struct domain *d) void iommu_domain_destroy(struct domain *d) { - if ( !iommu_enabled || !dom_iommu(d)->platform_ops ) + if ( !is_iommu_enabled(d) ) return; iommu_teardown(d); @@ -304,7 +304,7 @@ int iommu_map(struct domain *d, dfn_t dfn, mfn_t mfn, unsigned long i; int rc = 0; - if ( !iommu_enabled || !hd->platform_ops ) + if ( !is_iommu_enabled(d) ) return 0; ASSERT(IS_ALIGNED(dfn_x(dfn), (1ul << page_order))); @@ -364,7 +364,7 @@ int iommu_unmap(struct domain *d, dfn_t dfn, unsigned int page_order, unsigned long i; int rc = 0; - if ( !iommu_enabled || !hd->platform_ops ) + if ( !is_iommu_enabled(d) ) return 0; ASSERT(IS_ALIGNED(dfn_x(dfn), (1ul << page_order))); @@ -417,7 +417,7 @@ int iommu_lookup_page(struct domain *d, dfn_t dfn, mfn_t *mfn, { const struct domain_iommu *hd = dom_iommu(d); - if ( !iommu_enabled || !hd->platform_ops || !hd->platform_ops->lookup_page ) + if ( !is_iommu_enabled(d) || !hd->platform_ops->lookup_page ) return -EOPNOTSUPP; return iommu_call(hd->platform_ops, lookup_page, d, dfn, mfn, flags); @@ -446,8 +446,8 @@ int iommu_iotlb_flush(struct domain *d, dfn_t dfn, unsigned int page_count, const struct domain_iommu *hd = dom_iommu(d); int rc; - if ( !iommu_enabled || !hd->platform_ops || - !hd->platform_ops->iotlb_flush || !page_count || !flush_flags ) + if ( !is_iommu_enabled(d) || !hd->platform_ops->iotlb_flush || + !page_count || !flush_flags ) return 0; if ( dfn_eq(dfn, INVALID_DFN) ) @@ -474,8 +474,8 @@ int iommu_iotlb_flush_all(struct domain *d, unsigned int flush_flags) const struct domain_iommu *hd = dom_iommu(d); int rc; - if ( !iommu_enabled || !hd->platform_ops || - !hd->platform_ops->iotlb_flush_all || !flush_flags ) + if ( !is_iommu_enabled(d) || !hd->platform_ops->iotlb_flush_all || + !flush_flags ) return 0; /* @@ -560,8 +560,8 @@ int iommu_do_domctl( { int ret = -ENODEV; - if ( !iommu_enabled ) - return -ENOSYS; + if ( !is_iommu_enabled(d) ) + return -EOPNOTSUPP; #ifdef CONFIG_HAS_PCI ret = iommu_do_pci_domctl(domctl, d, u_domctl); @@ -580,9 +580,9 @@ void iommu_share_p2m_table(struct domain* d) ASSERT(hap_enabled(d)); /* * iommu_use_hap_pt(d) cannot be used here because during domain - * construction need_iommu(d) will always return false here. + * construction has_iommu_pt(d) will always return false here. */ - if ( iommu_enabled && iommu_hap_pt_share ) + if ( is_iommu_enabled(d) && iommu_hap_pt_share ) iommu_get_ops()->share_p2m(d); } @@ -612,10 +612,7 @@ int iommu_get_reserved_device_memory(iommu_grdm_t *func, void *ctxt) bool_t iommu_has_feature(struct domain *d, enum iommu_feature feature) { - if ( !iommu_enabled ) - return 0; - - return test_bit(feature, dom_iommu(d)->features); + return is_iommu_enabled(d) && test_bit(feature, dom_iommu(d)->features); } static void iommu_dump_p2m_table(unsigned char key) diff --git a/xen/drivers/passthrough/pci.c b/xen/drivers/passthrough/pci.c index af011d32dc..814106679f 100644 --- a/xen/drivers/passthrough/pci.c +++ b/xen/drivers/passthrough/pci.c @@ -595,7 +595,7 @@ static void pci_enable_acs(struct pci_dev *pdev) u16 cap, ctrl, seg = pdev->seg; u8 bus = pdev->bus; - if ( !iommu_enabled ) + if ( !is_iommu_enabled(pdev->domain) ) return; pos = pci_find_ext_capability(seg, bus, pdev->devfn, PCI_EXT_CAP_ID_ACS); @@ -864,7 +864,7 @@ static int pci_clean_dpci_irqs(struct domain *d) { struct hvm_irq_dpci *hvm_irq_dpci = NULL; - if ( !iommu_enabled ) + if ( !is_iommu_enabled(d) ) return 0; if ( !is_hvm_domain(d) ) @@ -897,7 +897,7 @@ static int deassign_device(struct domain *d, uint16_t seg, uint8_t bus, struct pci_dev *pdev; int ret = 0; - if ( !iommu_enabled || !hd->platform_ops ) + if ( !is_iommu_enabled(d) ) return -EINVAL; ASSERT(pcidevs_locked()); @@ -1383,7 +1383,7 @@ static int iommu_add_device(struct pci_dev *pdev) ASSERT(pcidevs_locked()); hd = dom_iommu(pdev->domain); - if ( !iommu_enabled || !hd->platform_ops ) + if ( !is_iommu_enabled(pdev->domain) ) return 0; rc = hd->platform_ops->add_device(pdev->devfn, pci_to_dev(pdev)); @@ -1412,7 +1412,7 @@ static int iommu_enable_device(struct pci_dev *pdev) ASSERT(pcidevs_locked()); hd = dom_iommu(pdev->domain); - if ( !iommu_enabled || !hd->platform_ops || + if ( !is_iommu_enabled(pdev->domain) || !hd->platform_ops->enable_device ) return 0; @@ -1428,7 +1428,7 @@ static int iommu_remove_device(struct pci_dev *pdev) return -EINVAL; hd = dom_iommu(pdev->domain); - if ( !iommu_enabled || !hd->platform_ops ) + if ( !is_iommu_enabled(pdev->domain) ) return 0; for ( devfn = pdev->devfn ; pdev->phantom_stride; ) @@ -1471,7 +1471,7 @@ static int assign_device(struct domain *d, u16 seg, u8 bus, u8 devfn, u32 flag) struct pci_dev *pdev; int rc = 0; - if ( !iommu_enabled || !hd->platform_ops ) + if ( !is_iommu_enabled(d) ) return 0; /* Prevent device assign if mem paging or mem sharing have been @@ -1537,7 +1537,7 @@ static int iommu_get_device_group( int i = 0; const struct iommu_ops *ops = hd->platform_ops; - if ( !iommu_enabled || !ops || !ops->get_device_group_id ) + if ( !is_iommu_enabled(d) || !ops->get_device_group_id ) return 0; group_id = ops->get_device_group_id(seg, bus, devfn); diff --git a/xen/drivers/passthrough/vtd/iommu.c b/xen/drivers/passthrough/vtd/iommu.c index 04d46f7eab..7ffafdc065 100644 --- a/xen/drivers/passthrough/vtd/iommu.c +++ b/xen/drivers/passthrough/vtd/iommu.c @@ -1719,7 +1719,7 @@ static void iommu_domain_teardown(struct domain *d) xfree(mrmrr); } - ASSERT(iommu_enabled); + ASSERT(is_iommu_enabled(d)); /* * We can't use iommu_use_hap_pt here because either IOMMU state diff --git a/xen/drivers/passthrough/vtd/x86/hvm.c b/xen/drivers/passthrough/vtd/x86/hvm.c index 6675dca027..f77b35815c 100644 --- a/xen/drivers/passthrough/vtd/x86/hvm.c +++ b/xen/drivers/passthrough/vtd/x86/hvm.c @@ -51,7 +51,7 @@ void hvm_dpci_isairq_eoi(struct domain *d, unsigned int isairq) struct hvm_irq_dpci *dpci = NULL; ASSERT(isairq < NR_ISAIRQS); - if ( !iommu_enabled ) + if ( !is_iommu_enabled(d) ) return; spin_lock(&d->event_lock); diff --git a/xen/drivers/passthrough/x86/iommu.c b/xen/drivers/passthrough/x86/iommu.c index 92c1d01edf..8319fe0a69 100644 --- a/xen/drivers/passthrough/x86/iommu.c +++ b/xen/drivers/passthrough/x86/iommu.c @@ -180,7 +180,7 @@ int arch_iommu_populate_page_table(struct domain *d) void __hwdom_init arch_iommu_check_autotranslated_hwdom(struct domain *d) { - if ( !iommu_enabled ) + if ( !is_iommu_enabled(d) ) panic("Presently, iommu must be enabled for PVH hardware domain\n"); } diff --git a/xen/include/asm-x86/iommu.h b/xen/include/asm-x86/iommu.h index facf835ada..31fda4b0cf 100644 --- a/xen/include/asm-x86/iommu.h +++ b/xen/include/asm-x86/iommu.h @@ -61,8 +61,15 @@ extern struct iommu_ops iommu_ops; #ifdef NDEBUG # include -# define iommu_call(ops, fn, args...) alternative_call(iommu_ops.fn, ## args) -# define iommu_vcall(ops, fn, args...) alternative_vcall(iommu_ops.fn, ## args) +# define iommu_call(ops, fn, args...) ({ \ + (void)(ops); \ + alternative_call(iommu_ops.fn, ## args); \ +}) + +# define iommu_vcall(ops, fn, args...) ({ \ + (void)(ops); \ + alternative_vcall(iommu_ops.fn, ## args); \ +}) #endif static inline const struct iommu_ops *iommu_get_ops(void) diff --git a/xen/xsm/flask/hooks.c b/xen/xsm/flask/hooks.c index 6800f2d9a0..a449869550 100644 --- a/xen/xsm/flask/hooks.c +++ b/xen/xsm/flask/hooks.c @@ -883,7 +883,7 @@ static int flask_map_domain_msi (struct domain *d, int irq, const void *data, #endif } -static u32 flask_iommu_resource_use_perm(void) +static u32 flask_iommu_resource_use_perm(const struct domain *d) { /* Obtain the permission level required for allowing a domain * to use an assigned device. @@ -896,7 +896,7 @@ static u32 flask_iommu_resource_use_perm(void) */ u32 perm = RESOURCE__USE_NOIOMMU; - if (iommu_enabled) + if ( is_iommu_enabled(d) ) perm = ( iommu_intremap ? RESOURCE__USE_IOMMU : RESOURCE__USE_IOMMU_NOINTREMAP ); return perm; @@ -907,7 +907,7 @@ static int flask_map_domain_irq (struct domain *d, int irq, const void *data) u32 sid, dsid; int rc = -EPERM; struct avc_audit_data ad; - u32 dperm = flask_iommu_resource_use_perm(); + u32 dperm = flask_iommu_resource_use_perm(d); if ( irq >= nr_static_irqs && data ) { rc = flask_map_domain_msi(d, irq, data, &sid, &ad); @@ -973,7 +973,7 @@ static int flask_bind_pt_irq (struct domain *d, struct xen_domctl_bind_pt_irq *b int rc = -EPERM; int irq; struct avc_audit_data ad; - u32 dperm = flask_iommu_resource_use_perm(); + u32 dperm = flask_iommu_resource_use_perm(d); rc = current_has_perm(d, SECCLASS_RESOURCE, RESOURCE__ADD); if ( rc ) @@ -1046,7 +1046,7 @@ static int flask_iomem_permission(struct domain *d, uint64_t start, uint64_t end data.ssid = domain_sid(current->domain); data.dsid = domain_sid(d); - data.use_perm = flask_iommu_resource_use_perm(); + data.use_perm = flask_iommu_resource_use_perm(d); return security_iterate_iomem_sids(start, end, _iomem_has_perm, &data); } @@ -1071,7 +1071,7 @@ static int flask_pci_config_permission(struct domain *d, uint32_t machine_bdf, u if ( access && (end >= 0x10 && start < 0x28) ) perm = RESOURCE__SETUP; else - perm = flask_iommu_resource_use_perm(); + perm = flask_iommu_resource_use_perm(d); AVC_AUDIT_DATA_INIT(&ad, DEV); ad.device = (unsigned long) machine_bdf; @@ -1296,7 +1296,7 @@ static int flask_assign_device(struct domain *d, uint32_t machine_bdf) u32 dsid, rsid; int rc = -EPERM; struct avc_audit_data ad; - u32 dperm = flask_iommu_resource_use_perm(); + u32 dperm = flask_iommu_resource_use_perm(d); if ( !d ) return flask_test_assign_device(machine_bdf); @@ -1355,7 +1355,7 @@ static int flask_assign_dtdevice(struct domain *d, const char *dtpath) u32 dsid, rsid; int rc = -EPERM; struct avc_audit_data ad; - u32 dperm = flask_iommu_resource_use_perm(); + u32 dperm = flask_iommu_resource_use_perm(d); if ( !d ) return flask_test_assign_dtdevice(dtpath); @@ -1540,7 +1540,7 @@ static int flask_ioport_permission(struct domain *d, uint32_t start, uint32_t en data.ssid = domain_sid(current->domain); data.dsid = domain_sid(d); - data.use_perm = flask_iommu_resource_use_perm(); + data.use_perm = flask_iommu_resource_use_perm(d); return security_iterate_ioport_sids(start, end, _ioport_has_perm, &data); } From patchwork Thu Sep 12 11:17:41 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Durrant X-Patchwork-Id: 11142817 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id EC94D13BD for ; Thu, 12 Sep 2019 11:20:35 +0000 (UTC) Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id C84DD20CC7 for ; Thu, 12 Sep 2019 11:20:35 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=citrix.com header.i=@citrix.com header.b="ge2Olz5Y" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org C84DD20CC7 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=citrix.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=xen-devel-bounces@lists.xenproject.org Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1i8N6k-0000fW-RA; Thu, 12 Sep 2019 11:17:50 +0000 Received: from all-amaz-eas1.inumbo.com ([34.197.232.57] helo=us1-amaz-eas2.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1i8N6j-0000fR-MD for xen-devel@lists.xenproject.org; Thu, 12 Sep 2019 11:17:49 +0000 X-Inumbo-ID: f36b1b12-d54e-11e9-83e7-12813bfff9fa Received: from esa6.hc3370-68.iphmx.com (unknown [216.71.155.175]) by us1-amaz-eas2.inumbo.com (Halon) with ESMTPS id f36b1b12-d54e-11e9-83e7-12813bfff9fa; Thu, 12 Sep 2019 11:17:48 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=citrix.com; s=securemail; t=1568287068; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=qupYcb//P6jsVtKXl66TxBBLG6EtJB73J/aNLURTLQk=; b=ge2Olz5YtSoPpjH+HS5X67fnonBaOXzaWJQGFM8tEejGJmYtvpY1OLIM 6iW9Tib2dOmit2UXcrMDOaKM6L/sMgNrwyV9FKjV4N24Kgw6rasHb/xKC yR2RY3I6aiVPDv9NpECBDDbU0WKPH+NIWtYZVbXkb3XiRcwfUjlcLAUqM w=; Authentication-Results: esa6.hc3370-68.iphmx.com; dkim=none (message not signed) header.i=none; spf=None smtp.pra=paul.durrant@citrix.com; spf=Pass smtp.mailfrom=Paul.Durrant@citrix.com; spf=None smtp.helo=postmaster@mail.citrix.com Received-SPF: None (esa6.hc3370-68.iphmx.com: no sender authenticity information available from domain of paul.durrant@citrix.com) identity=pra; client-ip=162.221.158.21; receiver=esa6.hc3370-68.iphmx.com; envelope-from="Paul.Durrant@citrix.com"; x-sender="paul.durrant@citrix.com"; x-conformance=sidf_compatible Received-SPF: Pass (esa6.hc3370-68.iphmx.com: domain of Paul.Durrant@citrix.com designates 162.221.158.21 as permitted sender) identity=mailfrom; client-ip=162.221.158.21; receiver=esa6.hc3370-68.iphmx.com; envelope-from="Paul.Durrant@citrix.com"; x-sender="Paul.Durrant@citrix.com"; x-conformance=sidf_compatible; x-record-type="v=spf1"; x-record-text="v=spf1 ip4:209.167.231.154 ip4:178.63.86.133 ip4:195.66.111.40/30 ip4:85.115.9.32/28 ip4:199.102.83.4 ip4:192.28.146.160 ip4:192.28.146.107 ip4:216.52.6.88 ip4:216.52.6.188 ip4:162.221.158.21 ip4:162.221.156.83 ~all" Received-SPF: None (esa6.hc3370-68.iphmx.com: no sender authenticity information available from domain of postmaster@mail.citrix.com) identity=helo; client-ip=162.221.158.21; receiver=esa6.hc3370-68.iphmx.com; envelope-from="Paul.Durrant@citrix.com"; x-sender="postmaster@mail.citrix.com"; x-conformance=sidf_compatible IronPort-SDR: 8MX/ktudzjJBfBFQSrkUPCSztTr5xFystpd7J5FpoKjd51bVoUwl7bYq6pjHSRVySbmHaeh+ri yxb+90YdkuJVRgYGE5IuQKzv2gL/w7Ir41OJ4/Zm135c35u3DFN/uNdVgn/ZosD6GTfeJc2P8X EVXkWvVmVP+pu9WNWncg1KTyDBeZbgPGd103LLqxvbwEMr//C5OHGDyjHMzJHuZ7GE5k5fWGNY nd4pK7lPZJ0yYAUxfSmhcvumXN2mh9l3JzDUo72veQOUV3o02/vnLd2+q/Zm1VAiBjxUSvo8bv 4gw= X-SBRS: 2.7 X-MesageID: 5719881 X-Ironport-Server: esa6.hc3370-68.iphmx.com X-Remote-IP: 162.221.158.21 X-Policy: $RELAYED X-IronPort-AV: E=Sophos;i="5.64,495,1559534400"; d="scan'208";a="5719881" From: Paul Durrant To: Date: Thu, 12 Sep 2019 12:17:41 +0100 Message-ID: <20190912111744.40410-4-paul.durrant@citrix.com> X-Mailer: git-send-email 2.20.1.2.gb21ebb671 In-Reply-To: <20190912111744.40410-1-paul.durrant@citrix.com> References: <20190912111744.40410-1-paul.durrant@citrix.com> MIME-Version: 1.0 Subject: [Xen-devel] [PATCH v9 3/6] sysctl / libxl: report whether IOMMU/HAP page table sharing is supported X-BeenThere: xen-devel@lists.xenproject.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Cc: Stefano Stabellini , Wei Liu , Konrad Rzeszutek Wilk , George Dunlap , Andrew Cooper , Ian Jackson , Tim Deegan , Julien Grall , Paul Durrant , Christian Lindig , Jan Beulich , David Scott , Anthony PERARD Errors-To: xen-devel-bounces@lists.xenproject.org Sender: "Xen-devel" This patch defines a new bit reported in the hw_cap field of struct xen_sysctl_physinfo to indicate whether the platform supports sharing of HAP page tables (i.e. the P2M) with the IOMMU. This informs the toolstack whether the domain needs extra memory to store discrete IOMMU page tables or not. Signed-off-by: Paul Durrant Acked-by: Christian Lindig --- Cc: Ian Jackson Cc: Wei Liu Cc: Anthony PERARD Cc: Andrew Cooper Cc: George Dunlap Cc: Jan Beulich Cc: Julien Grall Cc: Konrad Rzeszutek Wilk Cc: Stefano Stabellini Cc: Tim Deegan Cc: Christian Lindig Cc: David Scott v9: - New in v9 --- tools/libxl/libxl.c | 2 ++ tools/libxl/libxl.h | 7 +++++++ tools/libxl/libxl_types.idl | 1 + tools/ocaml/libs/xc/xenctrl.ml | 1 + tools/ocaml/libs/xc/xenctrl.mli | 2 +- tools/xl/xl_info.c | 5 +++-- xen/arch/arm/sysctl.c | 3 +++ xen/arch/x86/sysctl.c | 5 +++++ xen/include/public/sysctl.h | 6 +++++- 9 files changed, 28 insertions(+), 4 deletions(-) diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c index 5c0fcf320e..dd468eb18e 100644 --- a/tools/libxl/libxl.c +++ b/tools/libxl/libxl.c @@ -400,6 +400,8 @@ int libxl_get_physinfo(libxl_ctx *ctx, libxl_physinfo *physinfo) physinfo->cap_hvm_directio = !!(xcphysinfo.capabilities & XEN_SYSCTL_PHYSCAP_directio); physinfo->cap_hap = !!(xcphysinfo.capabilities & XEN_SYSCTL_PHYSCAP_hap); + physinfo->cap_iommu_hap_pt_share = + !!(xcphysinfo.capabilities & XEN_SYSCTL_PHYSCAP_iommu_hap_pt_share); GC_FREE; return 0; diff --git a/tools/libxl/libxl.h b/tools/libxl/libxl.h index 3ff67792a7..670a282c5a 100644 --- a/tools/libxl/libxl.h +++ b/tools/libxl/libxl.h @@ -401,6 +401,13 @@ */ #define LIBXL_HAVE_PHYSINFO_CAP_HAP 1 +/* + * LIBXL_HAVE_PHYSINFO_CAP_IOMMU_HAP_PT_SHARE indicates that libxl_physinfo + * has a cap_iommu_hap_pt_share field that indicates whether the hardware + * supports sharing the IOMMU and HAP page tables. + */ +#define LIBXL_HAVE_PHYSINFO_CAP_IOMMU_HAP_PT_SHARE 1 + /* * libxl ABI compatibility * diff --git a/tools/libxl/libxl_types.idl b/tools/libxl/libxl_types.idl index 9e1f8515d3..bd427def1a 100644 --- a/tools/libxl/libxl_types.idl +++ b/tools/libxl/libxl_types.idl @@ -1026,6 +1026,7 @@ libxl_physinfo = Struct("physinfo", [ ("cap_pv", bool), ("cap_hvm_directio", bool), # No longer HVM specific ("cap_hap", bool), + ("cap_iommu_hap_pt_share", bool), ], dir=DIR_OUT) libxl_connectorinfo = Struct("connectorinfo", [ diff --git a/tools/ocaml/libs/xc/xenctrl.ml b/tools/ocaml/libs/xc/xenctrl.ml index eaf009f0f9..30da6ba370 100644 --- a/tools/ocaml/libs/xc/xenctrl.ml +++ b/tools/ocaml/libs/xc/xenctrl.ml @@ -109,6 +109,7 @@ type physinfo_cap_flag = | CAP_PV | CAP_DirectIO | CAP_HAP + | CAP_IOMMU_HAP_PT_SHARE type physinfo = { diff --git a/tools/ocaml/libs/xc/xenctrl.mli b/tools/ocaml/libs/xc/xenctrl.mli index e0636de23a..64c35418e8 100644 --- a/tools/ocaml/libs/xc/xenctrl.mli +++ b/tools/ocaml/libs/xc/xenctrl.mli @@ -57,7 +57,6 @@ type domain_create_flag = | CDF_OOS_OFF | CDF_XS_DOMAIN | CDF_IOMMU - type domctl_create_config = { ssidref: int32; handle: string; @@ -94,6 +93,7 @@ type physinfo_cap_flag = | CAP_PV | CAP_DirectIO | CAP_HAP + | CAP_IOMMU_HAP_PT_SHARE type physinfo = { threads_per_core : int; cores_per_socket : int; diff --git a/tools/xl/xl_info.c b/tools/xl/xl_info.c index aa6724bc7f..94da5ec91e 100644 --- a/tools/xl/xl_info.c +++ b/tools/xl/xl_info.c @@ -210,12 +210,13 @@ static void output_physinfo(void) info.hw_cap[4], info.hw_cap[5], info.hw_cap[6], info.hw_cap[7] ); - maybe_printf("virt_caps :%s%s%s%s%s\n", + maybe_printf("virt_caps :%s%s%s%s%s%s\n", info.cap_pv ? " pv" : "", info.cap_hvm ? " hvm" : "", info.cap_hvm && info.cap_hvm_directio ? " hvm_directio" : "", info.cap_pv && info.cap_hvm_directio ? " pv_directio" : "", - info.cap_hap ? " hap" : "" + info.cap_hap ? " hap" : "", + info.cap_iommu_hap_pt_share ? " iommu_hap_pt_share" : "" ); vinfo = libxl_get_version_info(ctx); diff --git a/xen/arch/arm/sysctl.c b/xen/arch/arm/sysctl.c index f87944e847..6238c85be0 100644 --- a/xen/arch/arm/sysctl.c +++ b/xen/arch/arm/sysctl.c @@ -15,6 +15,9 @@ void arch_do_physinfo(struct xen_sysctl_physinfo *pi) { pi->capabilities |= XEN_SYSCTL_PHYSCAP_hvm | XEN_SYSCTL_PHYSCAP_hap; + + if ( iommu_enabled && iommu_hap_pt_share ) + pi->capabilities |= XEN_SYSCTL_PHYSCAP_iommu_hap_pt_share; } long arch_do_sysctl(struct xen_sysctl *sysctl, diff --git a/xen/arch/x86/sysctl.c b/xen/arch/x86/sysctl.c index 5777a05ffc..c0adfbadb5 100644 --- a/xen/arch/x86/sysctl.c +++ b/xen/arch/x86/sysctl.c @@ -164,7 +164,12 @@ void arch_do_physinfo(struct xen_sysctl_physinfo *pi) if ( IS_ENABLED(CONFIG_PV) ) pi->capabilities |= XEN_SYSCTL_PHYSCAP_pv; if ( hvm_hap_supported() ) + { pi->capabilities |= XEN_SYSCTL_PHYSCAP_hap; + + if ( iommu_enabled && iommu_hap_pt_share ) + pi->capabilities |= XEN_SYSCTL_PHYSCAP_iommu_hap_pt_share; + } } long arch_do_sysctl( diff --git a/xen/include/public/sysctl.h b/xen/include/public/sysctl.h index d4b455619c..99bac0d33e 100644 --- a/xen/include/public/sysctl.h +++ b/xen/include/public/sysctl.h @@ -93,9 +93,13 @@ struct xen_sysctl_tbuf_op { /* The platform supports Hardware Assisted Paging. */ #define _XEN_SYSCTL_PHYSCAP_hap 3 #define XEN_SYSCTL_PHYSCAP_hap (1u<<_XEN_SYSCTL_PHYSCAP_hap) +/* The platform supports sharing of HAP page tables with the IOMMU. */ +#define _XEN_SYSCTL_PHYSCAP_iommu_hap_pt_share 4 +#define XEN_SYSCTL_PHYSCAP_iommu_hap_pt_share \ + (1u << _XEN_SYSCTL_PHYSCAP_iommu_hap_pt_share) /* Max XEN_SYSCTL_PHYSCAP_* constant. Used for ABI checking. */ -#define XEN_SYSCTL_PHYSCAP_MAX XEN_SYSCTL_PHYSCAP_hap +#define XEN_SYSCTL_PHYSCAP_MAX XEN_SYSCTL_PHYSCAP_iommu_hap_pt_share struct xen_sysctl_physinfo { uint32_t threads_per_core; From patchwork Thu Sep 12 11:17:42 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Paul Durrant X-Patchwork-Id: 11142825 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 8645C13BD for ; Thu, 12 Sep 2019 11:21:09 +0000 (UTC) Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 4AA1A206CD for ; Thu, 12 Sep 2019 11:21:09 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=citrix.com header.i=@citrix.com header.b="SacoE3mj" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 4AA1A206CD Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=citrix.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=xen-devel-bounces@lists.xenproject.org Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1i8N6s-0000hW-UG; Thu, 12 Sep 2019 11:17:58 +0000 Received: from us1-rack-iad1.inumbo.com ([172.99.69.81]) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1i8N6r-0000hJ-Hi for xen-devel@lists.xenproject.org; Thu, 12 Sep 2019 11:17:57 +0000 X-Inumbo-ID: f719d8d4-d54e-11e9-978d-bc764e2007e4 Received: from esa1.hc3370-68.iphmx.com (unknown [216.71.145.142]) by us1-rack-iad1.inumbo.com (Halon) with ESMTPS id f719d8d4-d54e-11e9-978d-bc764e2007e4; Thu, 12 Sep 2019 11:17:54 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=citrix.com; s=securemail; t=1568287075; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=vxTwynLHZH5E6FHOP+mcG649/8fa1KvnzM2efMUMy2o=; b=SacoE3mjP7j97zSxQwyy45t+qSskxztWN3zaNX6KW3yHMpXI79ACV2yE 2g3Dlf+1Wcy9sHBsg9/hq2ag7EQ67iElawSSAgEUhDJGhwgbuWXFEWYZ3 /ZKjY6Uzd2Af7O9Is6ilOF/VsbGO7BljaStikLuu/xxXAjqzqRTSvhe5k 4=; Authentication-Results: esa1.hc3370-68.iphmx.com; dkim=none (message not signed) header.i=none; spf=None smtp.pra=paul.durrant@citrix.com; spf=Pass smtp.mailfrom=Paul.Durrant@citrix.com; spf=None smtp.helo=postmaster@mail.citrix.com Received-SPF: None (esa1.hc3370-68.iphmx.com: no sender authenticity information available from domain of paul.durrant@citrix.com) identity=pra; client-ip=162.221.158.21; receiver=esa1.hc3370-68.iphmx.com; envelope-from="Paul.Durrant@citrix.com"; x-sender="paul.durrant@citrix.com"; x-conformance=sidf_compatible Received-SPF: Pass (esa1.hc3370-68.iphmx.com: domain of Paul.Durrant@citrix.com designates 162.221.158.21 as permitted sender) identity=mailfrom; client-ip=162.221.158.21; receiver=esa1.hc3370-68.iphmx.com; envelope-from="Paul.Durrant@citrix.com"; x-sender="Paul.Durrant@citrix.com"; x-conformance=sidf_compatible; x-record-type="v=spf1"; x-record-text="v=spf1 ip4:209.167.231.154 ip4:178.63.86.133 ip4:195.66.111.40/30 ip4:85.115.9.32/28 ip4:199.102.83.4 ip4:192.28.146.160 ip4:192.28.146.107 ip4:216.52.6.88 ip4:216.52.6.188 ip4:162.221.158.21 ip4:162.221.156.83 ~all" Received-SPF: None (esa1.hc3370-68.iphmx.com: no sender authenticity information available from domain of postmaster@mail.citrix.com) identity=helo; client-ip=162.221.158.21; receiver=esa1.hc3370-68.iphmx.com; envelope-from="Paul.Durrant@citrix.com"; x-sender="postmaster@mail.citrix.com"; x-conformance=sidf_compatible IronPort-SDR: OgPGKAylQm+6ZktcRgfb9EIo4DFv4GJ7P8DALkrwHIYJa5mbGdVBeG22F1ciw2NGeHgxDUC0ue jjUFJoqnx3FZF12z5Fr/qgjfHVWlhFfR//UD1hdFEEqj4CGYnf+w1lNiut6g7ZlkXp0PQs1Qz/ s38BBI4CLQRy/7KJFJb4/EJxGDISMybWpIXyUExzOhb6Y3RZ7XnD819yUY1OEgoINVy4j7ApKD Muj/5CQnLol/tdx6MvZRI9+JvZhGBy/3ktjewfK1jXxeOlXp2fPFdQ5fTw14UG0ZhDiikMHFfV 0qA= X-SBRS: 2.7 X-MesageID: 5530317 X-Ironport-Server: esa1.hc3370-68.iphmx.com X-Remote-IP: 162.221.158.21 X-Policy: $RELAYED X-IronPort-AV: E=Sophos;i="5.64,495,1559534400"; d="scan'208";a="5530317" From: Paul Durrant To: Date: Thu, 12 Sep 2019 12:17:42 +0100 Message-ID: <20190912111744.40410-5-paul.durrant@citrix.com> X-Mailer: git-send-email 2.20.1.2.gb21ebb671 In-Reply-To: <20190912111744.40410-1-paul.durrant@citrix.com> References: <20190912111744.40410-1-paul.durrant@citrix.com> MIME-Version: 1.0 Subject: [Xen-devel] [PATCH v9 4/6] remove late (on-demand) construction of IOMMU page tables X-BeenThere: xen-devel@lists.xenproject.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Cc: Petre Pircalabu , Stefano Stabellini , Wei Liu , Razvan Cojocaru , Konrad Rzeszutek Wilk , George Dunlap , Andrew Cooper , Ian Jackson , Tim Deegan , Julien Grall , Paul Durrant , Tamas K Lengyel , Jan Beulich , Alexandru Isaila , Volodymyr Babchuk , =?utf-8?q?Roger_Pau_Monn?= =?utf-8?q?=C3=A9?= Errors-To: xen-devel-bounces@lists.xenproject.org Sender: "Xen-devel" Now that there is a per-domain IOMMU-enable flag, which should be set if any device is going to be passed through, stop deferring page table construction until the assignment is done. Also don't tear down the tables again when the last device is de-assigned; defer that task until domain destruction. This allows the has_iommu_pt() helper and iommu_status enumeration to be removed. Calls to has_iommu_pt() are simply replaced by calls to is_iommu_enabled(). Remaining open-coded tests of iommu_hap_pt_share can also be replaced by calls to iommu_use_hap_pt(). The arch_iommu_populate_page_table() and iommu_construct() functions become redundant, as does the 'strict mode' dom0 page_list mapping code in iommu_hwdom_init(), and iommu_teardown() can be made static is its only remaining caller, iommu_domain_destroy(), is within the same source module. All in all, about 220 lines of code are removed from the hypervisor (at the expense of some additions in the toolstack). NOTE: This patch will cause a small amount of extra resource to be used to accommodate IOMMU page tables that may never be used, since the per-domain IOMMU-enable flag is currently set to the value of the global iommu_enable flag. A subsequent patch will add an option to the toolstack to allow it to be turned off if there is no intention to assign passthrough hardware to the domain. To account for the extra resource, 'iommu_memkb' has been added to domain_build_info. This patch sets it to a value calculated based on the domain's maximum memory when the P2M sharing is either not supported or globally disabled, or zero otherwise. However, when the toolstack option mentioned above is added, it will also be zero if the per-domain IOMMU-enable flag is turned off. Signed-off-by: Paul Durrant Reviewed-by: Alexandru Isaila Acked-by: Razvan Cojocaru Reviewed-by: Jan Beulich --- Cc: Stefano Stabellini Cc: Julien Grall Cc: Volodymyr Babchuk Cc: Andrew Cooper Cc: George Dunlap Cc: Ian Jackson Cc: Konrad Rzeszutek Wilk Cc: Tim Deegan Cc: Wei Liu Cc: "Roger Pau Monné" Cc: Tamas K Lengyel Cc: George Dunlap Cc: Petre Pircalabu Previously part of series https://lists.xenproject.org/archives/html/xen-devel/2019-07/msg02267.html v9: - Avoid the iommu_memkb overhead if the IOMMU is disable or page tables are shared v7: - Add toolstack memory reservation for IOMMU page tables... Re-use of shadow calculation didn't seem appropriate so a new helper function is added v5: - Minor style fixes --- tools/libxl/libxl.h | 7 ++ tools/libxl/libxl_mem.c | 6 +- tools/libxl/libxl_types.idl | 1 + tools/libxl/libxl_utils.c | 15 +++ tools/libxl/libxl_utils.h | 1 + tools/xl/xl_parse.c | 24 ++++- xen/arch/arm/p2m.c | 2 +- xen/arch/x86/dom0_build.c | 2 +- xen/arch/x86/hvm/mtrr.c | 5 +- xen/arch/x86/mm/mem_sharing.c | 2 +- xen/arch/x86/mm/p2m.c | 4 +- xen/arch/x86/mm/paging.c | 2 +- xen/arch/x86/x86_64/mm.c | 2 +- xen/common/memory.c | 4 +- xen/common/vm_event.c | 2 +- xen/drivers/passthrough/device_tree.c | 11 --- xen/drivers/passthrough/iommu.c | 134 ++++++-------------------- xen/drivers/passthrough/pci.c | 12 --- xen/drivers/passthrough/vtd/iommu.c | 10 +- xen/drivers/passthrough/x86/iommu.c | 97 ------------------- xen/include/asm-arm/iommu.h | 2 +- xen/include/asm-x86/iommu.h | 2 +- xen/include/xen/iommu.h | 16 --- xen/include/xen/sched.h | 2 - 24 files changed, 94 insertions(+), 271 deletions(-) diff --git a/tools/libxl/libxl.h b/tools/libxl/libxl.h index 670a282c5a..a9e7cf86fd 100644 --- a/tools/libxl/libxl.h +++ b/tools/libxl/libxl.h @@ -408,6 +408,13 @@ */ #define LIBXL_HAVE_PHYSINFO_CAP_IOMMU_HAP_PT_SHARE 1 +/* + * LIBXL_HAVE_BUILDINFO_IOMMU_MEMKB indicates thate libxl_domain_build_info + * has an iommu_memkb field which should be set with the amount of memory + * overhead needed by the domain for populating IOMMU page tables. + */ +#define LIBXL_HAVE_BUILDINFO_IOMMU_MEMKB 1 + /* * libxl ABI compatibility * diff --git a/tools/libxl/libxl_mem.c b/tools/libxl/libxl_mem.c index 448a2af8fd..fd6f33312e 100644 --- a/tools/libxl/libxl_mem.c +++ b/tools/libxl/libxl_mem.c @@ -461,15 +461,17 @@ int libxl_domain_need_memory(libxl_ctx *ctx, if (rc) goto out; *need_memkb = b_info->target_memkb; + *need_memkb += b_info->shadow_memkb + b_info->iommu_memkb; + switch (b_info->type) { case LIBXL_DOMAIN_TYPE_PVH: case LIBXL_DOMAIN_TYPE_HVM: - *need_memkb += b_info->shadow_memkb + LIBXL_HVM_EXTRA_MEMORY; + *need_memkb += LIBXL_HVM_EXTRA_MEMORY; if (libxl_defbool_val(b_info->device_model_stubdomain)) *need_memkb += 32 * 1024; break; case LIBXL_DOMAIN_TYPE_PV: - *need_memkb += b_info->shadow_memkb + LIBXL_PV_EXTRA_MEMORY; + *need_memkb += LIBXL_PV_EXTRA_MEMORY; break; default: rc = ERROR_INVAL; diff --git a/tools/libxl/libxl_types.idl b/tools/libxl/libxl_types.idl index bd427def1a..e060788092 100644 --- a/tools/libxl/libxl_types.idl +++ b/tools/libxl/libxl_types.idl @@ -486,6 +486,7 @@ libxl_domain_build_info = Struct("domain_build_info",[ ("target_memkb", MemKB), ("video_memkb", MemKB), ("shadow_memkb", MemKB), + ("iommu_memkb", MemKB), ("rtc_timeoffset", uint32), ("exec_ssidref", uint32), ("exec_ssid_label", string), diff --git a/tools/libxl/libxl_utils.c b/tools/libxl/libxl_utils.c index f360f5e228..405733b7e1 100644 --- a/tools/libxl/libxl_utils.c +++ b/tools/libxl/libxl_utils.c @@ -48,6 +48,21 @@ unsigned long libxl_get_required_shadow_memory(unsigned long maxmem_kb, unsigned return 4 * (256 * smp_cpus + 2 * (maxmem_kb / 1024)); } +unsigned long libxl_get_required_iommu_memory(unsigned long maxmem_kb) +{ + unsigned long iommu_pages = 0, mem_pages = maxmem_kb / 4; + unsigned int level; + + /* Assume a 4 level page table with 512 entries per level */ + for (level = 0; level < 4; level++) + { + mem_pages = DIV_ROUNDUP(mem_pages, 512); + iommu_pages += mem_pages; + } + + return iommu_pages * 4; +} + char *libxl_domid_to_name(libxl_ctx *ctx, uint32_t domid) { unsigned int len; diff --git a/tools/libxl/libxl_utils.h b/tools/libxl/libxl_utils.h index 44409afdc4..630ccbe28a 100644 --- a/tools/libxl/libxl_utils.h +++ b/tools/libxl/libxl_utils.h @@ -24,6 +24,7 @@ const char *libxl_basename(const char *name); /* returns string from strdup */ unsigned long libxl_get_required_shadow_memory(unsigned long maxmem_kb, unsigned int smp_cpus); +unsigned long libxl_get_required_iommu_memory(unsigned long maxmem_kb); int libxl_name_to_domid(libxl_ctx *ctx, const char *name, uint32_t *domid); int libxl_domain_qualifier_to_domid(libxl_ctx *ctx, const char *name, uint32_t *domid); char *libxl_domid_to_name(libxl_ctx *ctx, uint32_t domid); diff --git a/tools/xl/xl_parse.c b/tools/xl/xl_parse.c index e105bda2bb..293f5f730e 100644 --- a/tools/xl/xl_parse.c +++ b/tools/xl/xl_parse.c @@ -1207,6 +1207,7 @@ void parse_config_data(const char *config_source, int config_len, libxl_domain_config *d_config) { + libxl_physinfo physinfo; const char *buf; long l, vcpus = 0; XLU_Config *config; @@ -1221,10 +1222,22 @@ void parse_config_data(const char *config_source, int pci_seize = 0; int i, e; char *kernel_basename; + bool iommu_enabled, iommu_hap_pt_share; libxl_domain_create_info *c_info = &d_config->c_info; libxl_domain_build_info *b_info = &d_config->b_info; + libxl_physinfo_init(&physinfo); + if (libxl_get_physinfo(ctx, &physinfo) != 0) { + libxl_physinfo_dispose(&physinfo); + fprintf(stderr, "libxl_get_physinfo failed\n"); + exit(EXIT_FAILURE); + } + + iommu_enabled = physinfo.cap_hvm_directio; + iommu_hap_pt_share = physinfo.cap_iommu_hap_pt_share; + libxl_physinfo_dispose(&physinfo); + config= xlu_cfg_init(stderr, config_source); if (!config) { fprintf(stderr, "Failed to allocate for configuration\n"); @@ -1448,14 +1461,21 @@ void parse_config_data(const char *config_source, exit(1); } - /* libxl_get_required_shadow_memory() must be called after final values + /* libxl_get_required_shadow_memory() and + * libxl_get_required_iommu_memory() must be called after final values * (default or specified) for vcpus and memory are set, because the - * calculation depends on those values. */ + * calculations depend on those values. */ b_info->shadow_memkb = !xlu_cfg_get_long(config, "shadow_memory", &l, 0) ? l * 1024 : libxl_get_required_shadow_memory(b_info->max_memkb, b_info->max_vcpus); + /* No IOMMU reservation is needed if either the IOMMU is disabled or it + * can share the P2M. */ + b_info->iommu_memkb = (!iommu_enabled || iommu_hap_pt_share) + ? 0 + : libxl_get_required_iommu_memory(b_info->max_memkb); + xlu_cfg_get_defbool(config, "nomigrate", &b_info->disable_migrate, 0); if (!xlu_cfg_get_long(config, "tsc_mode", &l, 1)) { diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c index 7f1442932a..692565757e 100644 --- a/xen/arch/arm/p2m.c +++ b/xen/arch/arm/p2m.c @@ -1056,7 +1056,7 @@ static int __p2m_set_entry(struct p2m_domain *p2m, !mfn_eq(lpae_get_mfn(*entry), lpae_get_mfn(orig_pte)) ) p2m_free_entry(p2m, orig_pte, level); - if ( has_iommu_pt(p2m->domain) && + if ( is_iommu_enabled(p2m->domain) && (lpae_is_valid(orig_pte) || lpae_is_valid(*entry)) ) { unsigned int flush_flags = 0; diff --git a/xen/arch/x86/dom0_build.c b/xen/arch/x86/dom0_build.c index d381784edd..7cfab2dc25 100644 --- a/xen/arch/x86/dom0_build.c +++ b/xen/arch/x86/dom0_build.c @@ -365,7 +365,7 @@ unsigned long __init dom0_compute_nr_pages( } need_paging = is_hvm_domain(d) && - (!iommu_hap_pt_share || !paging_mode_hap(d)); + (!iommu_use_hap_pt(d) || !paging_mode_hap(d)); for ( ; ; need_paging = false ) { nr_pages = get_memsize(&dom0_size, avail); diff --git a/xen/arch/x86/hvm/mtrr.c b/xen/arch/x86/hvm/mtrr.c index 7ccd85bcea..5ad15eafe0 100644 --- a/xen/arch/x86/hvm/mtrr.c +++ b/xen/arch/x86/hvm/mtrr.c @@ -783,7 +783,8 @@ HVM_REGISTER_SAVE_RESTORE(MTRR, hvm_save_mtrr_msr, hvm_load_mtrr_msr, 1, void memory_type_changed(struct domain *d) { - if ( (has_iommu_pt(d) || cache_flush_permitted(d)) && d->vcpu && d->vcpu[0] ) + if ( (is_iommu_enabled(d) || cache_flush_permitted(d)) && + d->vcpu && d->vcpu[0] ) { p2m_memory_type_changed(d); flush_all(FLUSH_CACHE); @@ -831,7 +832,7 @@ int epte_get_entry_emt(struct domain *d, unsigned long gfn, mfn_t mfn, return MTRR_TYPE_UNCACHABLE; } - if ( !has_iommu_pt(d) && !cache_flush_permitted(d) ) + if ( !is_iommu_enabled(d) && !cache_flush_permitted(d) ) { *ipat = 1; return MTRR_TYPE_WRBACK; diff --git a/xen/arch/x86/mm/mem_sharing.c b/xen/arch/x86/mm/mem_sharing.c index a5fe89e339..efb8821768 100644 --- a/xen/arch/x86/mm/mem_sharing.c +++ b/xen/arch/x86/mm/mem_sharing.c @@ -1664,7 +1664,7 @@ int mem_sharing_domctl(struct domain *d, struct xen_domctl_mem_sharing_op *mec) case XEN_DOMCTL_MEM_SHARING_CONTROL: { rc = 0; - if ( unlikely(has_iommu_pt(d) && mec->u.enable) ) + if ( unlikely(is_iommu_enabled(d) && mec->u.enable) ) rc = -EXDEV; else d->arch.hvm.mem_sharing_enabled = mec->u.enable; diff --git a/xen/arch/x86/mm/p2m.c b/xen/arch/x86/mm/p2m.c index 8a5229ee21..e5e4349dea 100644 --- a/xen/arch/x86/mm/p2m.c +++ b/xen/arch/x86/mm/p2m.c @@ -1341,7 +1341,7 @@ int set_identity_p2m_entry(struct domain *d, unsigned long gfn_l, if ( !paging_mode_translate(p2m->domain) ) { - if ( !has_iommu_pt(d) ) + if ( !is_iommu_enabled(d) ) return 0; return iommu_legacy_map(d, _dfn(gfn_l), _mfn(gfn_l), PAGE_ORDER_4K, IOMMUF_readable | IOMMUF_writable); @@ -1432,7 +1432,7 @@ int clear_identity_p2m_entry(struct domain *d, unsigned long gfn_l) if ( !paging_mode_translate(d) ) { - if ( !has_iommu_pt(d) ) + if ( !is_iommu_enabled(d) ) return 0; return iommu_legacy_unmap(d, _dfn(gfn_l), PAGE_ORDER_4K); } diff --git a/xen/arch/x86/mm/paging.c b/xen/arch/x86/mm/paging.c index 69aa228e46..d9a52c4db4 100644 --- a/xen/arch/x86/mm/paging.c +++ b/xen/arch/x86/mm/paging.c @@ -213,7 +213,7 @@ int paging_log_dirty_enable(struct domain *d, bool_t log_global) { int ret; - if ( has_iommu_pt(d) && log_global ) + if ( is_iommu_enabled(d) && log_global ) { /* * Refuse to turn on global log-dirty mode diff --git a/xen/arch/x86/x86_64/mm.c b/xen/arch/x86/x86_64/mm.c index 795a467462..fa55f3474e 100644 --- a/xen/arch/x86/x86_64/mm.c +++ b/xen/arch/x86/x86_64/mm.c @@ -1434,7 +1434,7 @@ int memory_add(unsigned long spfn, unsigned long epfn, unsigned int pxm) * shared or being kept in sync then newly added memory needs to be * mapped here. */ - if ( has_iommu_pt(hardware_domain) && + if ( is_iommu_enabled(hardware_domain) && !iommu_use_hap_pt(hardware_domain) && !need_iommu_pt_sync(hardware_domain) ) { diff --git a/xen/common/memory.c b/xen/common/memory.c index d5aff83f2d..7364fd2c33 100644 --- a/xen/common/memory.c +++ b/xen/common/memory.c @@ -823,7 +823,7 @@ int xenmem_add_to_physmap(struct domain *d, struct xen_add_to_physmap *xatp, xatp->gpfn += start; xatp->size -= start; - if ( has_iommu_pt(d) ) + if ( is_iommu_enabled(d) ) this_cpu(iommu_dont_flush_iotlb) = 1; while ( xatp->size > done ) @@ -844,7 +844,7 @@ int xenmem_add_to_physmap(struct domain *d, struct xen_add_to_physmap *xatp, } } - if ( has_iommu_pt(d) ) + if ( is_iommu_enabled(d) ) { int ret; diff --git a/xen/common/vm_event.c b/xen/common/vm_event.c index 2a1c87e44b..3b18195ebf 100644 --- a/xen/common/vm_event.c +++ b/xen/common/vm_event.c @@ -630,7 +630,7 @@ int vm_event_domctl(struct domain *d, struct xen_domctl_vm_event_op *vec) /* No paging if iommu is used */ rc = -EMLINK; - if ( unlikely(has_iommu_pt(d)) ) + if ( unlikely(is_iommu_enabled(d)) ) break; rc = -EXDEV; diff --git a/xen/drivers/passthrough/device_tree.c b/xen/drivers/passthrough/device_tree.c index 12f2c4c3f2..ea9fd54e3b 100644 --- a/xen/drivers/passthrough/device_tree.c +++ b/xen/drivers/passthrough/device_tree.c @@ -40,17 +40,6 @@ int iommu_assign_dt_device(struct domain *d, struct dt_device_node *dev) if ( !list_empty(&dev->domain_list) ) goto fail; - /* - * The hwdom is forced to use IOMMU for protecting assigned - * device. Therefore the IOMMU data is already set up. - */ - ASSERT(!is_hardware_domain(d) || - hd->status == IOMMU_STATUS_initialized); - - rc = iommu_construct(d); - if ( rc ) - goto fail; - /* The flag field doesn't matter to DT device. */ rc = hd->platform_ops->assign_device(d, 0, dt_to_dev(dev), 0); diff --git a/xen/drivers/passthrough/iommu.c b/xen/drivers/passthrough/iommu.c index 09ce9d9294..1410066fb3 100644 --- a/xen/drivers/passthrough/iommu.c +++ b/xen/drivers/passthrough/iommu.c @@ -146,6 +146,17 @@ static int __init parse_dom0_iommu_param(const char *s) } custom_param("dom0-iommu", parse_dom0_iommu_param); +static void __hwdom_init check_hwdom_reqs(struct domain *d) +{ + if ( iommu_hwdom_none || !paging_mode_translate(d) ) + return; + + arch_iommu_check_autotranslated_hwdom(d); + + iommu_hwdom_passthrough = false; + iommu_hwdom_strict = true; +} + int iommu_domain_init(struct domain *d) { struct domain_iommu *hd = dom_iommu(d); @@ -163,129 +174,44 @@ int iommu_domain_init(struct domain *d) return ret; hd->platform_ops = iommu_get_ops(); - return hd->platform_ops->init(d); -} + ret = hd->platform_ops->init(d); + if ( ret ) + return ret; -static void __hwdom_init check_hwdom_reqs(struct domain *d) -{ - if ( iommu_hwdom_none || !paging_mode_translate(d) ) - return; + if ( is_hardware_domain(d) ) + check_hwdom_reqs(d); /* may modify iommu_hwdom_strict */ - arch_iommu_check_autotranslated_hwdom(d); + /* + * NB: 'relaxed' h/w domains don't need the IOMMU mappings to be kept + * in-sync with their assigned pages because all host RAM will be + * mapped during hwdom_init(). + */ + if ( !is_hardware_domain(d) || iommu_hwdom_strict ) + hd->need_sync = !iommu_use_hap_pt(d); - iommu_hwdom_passthrough = false; - iommu_hwdom_strict = true; + return 0; } void __hwdom_init iommu_hwdom_init(struct domain *d) { struct domain_iommu *hd = dom_iommu(d); - check_hwdom_reqs(d); - if ( !is_iommu_enabled(d) ) return; register_keyhandler('o', &iommu_dump_p2m_table, "dump iommu p2m table", 0); - hd->status = IOMMU_STATUS_initializing; - /* - * NB: relaxed hw domains don't need sync because all ram is already - * mapped in the iommu page tables. - */ - hd->need_sync = iommu_hwdom_strict && !iommu_use_hap_pt(d); - if ( need_iommu_pt_sync(d) ) - { - struct page_info *page; - unsigned int i = 0, flush_flags = 0; - int rc = 0; - - page_list_for_each ( page, &d->page_list ) - { - unsigned long mfn = mfn_x(page_to_mfn(page)); - unsigned long dfn = mfn_to_gmfn(d, mfn); - unsigned int mapping = IOMMUF_readable; - int ret; - - if ( ((page->u.inuse.type_info & PGT_count_mask) == 0) || - ((page->u.inuse.type_info & PGT_type_mask) - == PGT_writable_page) ) - mapping |= IOMMUF_writable; - - ret = iommu_map(d, _dfn(dfn), _mfn(mfn), 0, mapping, - &flush_flags); - - if ( !rc ) - rc = ret; - - if ( !(i++ & 0xfffff) ) - process_pending_softirqs(); - } - - /* Use while-break to avoid compiler warning */ - while ( iommu_iotlb_flush_all(d, flush_flags) ) - break; - - if ( rc ) - printk(XENLOG_WARNING "d%d: IOMMU mapping failed: %d\n", - d->domain_id, rc); - } - hd->platform_ops->hwdom_init(d); - - hd->status = IOMMU_STATUS_initialized; } -void iommu_teardown(struct domain *d) +static void iommu_teardown(struct domain *d) { struct domain_iommu *hd = dom_iommu(d); - hd->status = IOMMU_STATUS_disabled; hd->platform_ops->teardown(d); tasklet_schedule(&iommu_pt_cleanup_tasklet); } -int iommu_construct(struct domain *d) -{ - struct domain_iommu *hd = dom_iommu(d); - - if ( hd->status == IOMMU_STATUS_initialized ) - return 0; - - hd->status = IOMMU_STATUS_initializing; - - if ( !iommu_use_hap_pt(d) ) - { - int rc; - - hd->need_sync = true; - - rc = arch_iommu_populate_page_table(d); - if ( rc ) - { - if ( rc != -ERESTART ) - { - hd->need_sync = false; - hd->status = IOMMU_STATUS_disabled; - } - - return rc; - } - } - - hd->status = IOMMU_STATUS_initialized; - - /* - * There may be dirty cache lines when a device is assigned - * and before has_iommu_pt(d) becoming true, this will cause - * memory_type_changed lose effect if memory type changes. - * Call memory_type_changed here to amend this. - */ - memory_type_changed(d); - - return 0; -} - void iommu_domain_destroy(struct domain *d) { if ( !is_iommu_enabled(d) ) @@ -578,11 +504,8 @@ int iommu_do_domctl( void iommu_share_p2m_table(struct domain* d) { ASSERT(hap_enabled(d)); - /* - * iommu_use_hap_pt(d) cannot be used here because during domain - * construction has_iommu_pt(d) will always return false here. - */ - if ( is_iommu_enabled(d) && iommu_hap_pt_share ) + + if ( iommu_use_hap_pt(d) ) iommu_get_ops()->share_p2m(d); } @@ -629,8 +552,7 @@ static void iommu_dump_p2m_table(unsigned char key) ops = iommu_get_ops(); for_each_domain(d) { - if ( is_hardware_domain(d) || - dom_iommu(d)->status < IOMMU_STATUS_initialized ) + if ( is_hardware_domain(d) || !is_iommu_enabled(d) ) continue; if ( iommu_use_hap_pt(d) ) diff --git a/xen/drivers/passthrough/pci.c b/xen/drivers/passthrough/pci.c index 814106679f..2315d490dc 100644 --- a/xen/drivers/passthrough/pci.c +++ b/xen/drivers/passthrough/pci.c @@ -933,9 +933,6 @@ static int deassign_device(struct domain *d, uint16_t seg, uint8_t bus, pdev->fault.count = 0; - if ( !has_arch_pdevs(d) && has_iommu_pt(d) ) - iommu_teardown(d); - return ret; } @@ -1484,13 +1481,6 @@ static int assign_device(struct domain *d, u16 seg, u8 bus, u8 devfn, u32 flag) if ( !pcidevs_trylock() ) return -ERESTART; - rc = iommu_construct(d); - if ( rc ) - { - pcidevs_unlock(); - return rc; - } - pdev = pci_get_pdev_by_domain(hardware_domain, seg, bus, devfn); if ( !pdev ) { @@ -1519,8 +1509,6 @@ static int assign_device(struct domain *d, u16 seg, u8 bus, u8 devfn, u32 flag) } done: - if ( !has_arch_pdevs(d) && has_iommu_pt(d) ) - iommu_teardown(d); pcidevs_unlock(); return rc; diff --git a/xen/drivers/passthrough/vtd/iommu.c b/xen/drivers/passthrough/vtd/iommu.c index 7ffafdc065..240f200084 100644 --- a/xen/drivers/passthrough/vtd/iommu.c +++ b/xen/drivers/passthrough/vtd/iommu.c @@ -1721,15 +1721,7 @@ static void iommu_domain_teardown(struct domain *d) ASSERT(is_iommu_enabled(d)); - /* - * We can't use iommu_use_hap_pt here because either IOMMU state - * is already changed to IOMMU_STATUS_disabled at this point or - * has always been IOMMU_STATUS_disabled. - * - * We also need to test if HAP is enabled because PV guests can - * enter this path too. - */ - if ( hap_enabled(d) && iommu_hap_pt_share ) + if ( iommu_use_hap_pt(d) ) return; spin_lock(&hd->arch.mapping_lock); diff --git a/xen/drivers/passthrough/x86/iommu.c b/xen/drivers/passthrough/x86/iommu.c index 8319fe0a69..47a3e55213 100644 --- a/xen/drivers/passthrough/x86/iommu.c +++ b/xen/drivers/passthrough/x86/iommu.c @@ -81,103 +81,6 @@ int __init iommu_setup_hpet_msi(struct msi_desc *msi) return ops->setup_hpet_msi ? ops->setup_hpet_msi(msi) : -ENODEV; } -int arch_iommu_populate_page_table(struct domain *d) -{ - struct page_info *page; - int rc = 0, n = 0; - - spin_lock(&d->page_alloc_lock); - - if ( unlikely(d->is_dying) ) - rc = -ESRCH; - - while ( !rc && (page = page_list_remove_head(&d->page_list)) ) - { - if ( is_hvm_domain(d) || - (page->u.inuse.type_info & PGT_type_mask) == PGT_writable_page ) - { - mfn_t mfn = page_to_mfn(page); - gfn_t gfn = mfn_to_gfn(d, mfn); - unsigned int flush_flags = 0; - - if ( !gfn_eq(gfn, INVALID_GFN) ) - { - dfn_t dfn = _dfn(gfn_x(gfn)); - - ASSERT(!(gfn_x(gfn) >> DEFAULT_DOMAIN_ADDRESS_WIDTH)); - BUG_ON(SHARED_M2P(gfn_x(gfn))); - rc = iommu_map(d, dfn, mfn, PAGE_ORDER_4K, - IOMMUF_readable | IOMMUF_writable, - &flush_flags); - - /* - * We may be working behind the back of a running guest, which - * may change the type of a page at any time. We can't prevent - * this (for instance, by bumping the type count while mapping - * the page) without causing legitimate guest type-change - * operations to fail. So after adding the page to the IOMMU, - * check again to make sure this is still valid. NB that the - * writable entry in the iommu is harmless until later, when - * the actual device gets assigned. - */ - if ( !rc && !is_hvm_domain(d) && - ((page->u.inuse.type_info & PGT_type_mask) != - PGT_writable_page) ) - { - rc = iommu_unmap(d, dfn, PAGE_ORDER_4K, &flush_flags); - /* If the type changed yet again, simply force a retry. */ - if ( !rc && ((page->u.inuse.type_info & PGT_type_mask) == - PGT_writable_page) ) - rc = -ERESTART; - } - } - if ( rc ) - { - page_list_add(page, &d->page_list); - break; - } - } - page_list_add_tail(page, &d->arch.relmem_list); - if ( !(++n & 0xff) && !page_list_empty(&d->page_list) && - hypercall_preempt_check() ) - rc = -ERESTART; - } - - if ( !rc ) - { - /* - * The expectation here is that generally there are many normal pages - * on relmem_list (the ones we put there) and only few being in an - * offline/broken state. The latter ones are always at the head of the - * list. Hence we first move the whole list, and then move back the - * first few entries. - */ - page_list_move(&d->page_list, &d->arch.relmem_list); - while ( !page_list_empty(&d->page_list) && - (page = page_list_first(&d->page_list), - (page->count_info & (PGC_state|PGC_broken))) ) - { - page_list_del(page, &d->page_list); - page_list_add_tail(page, &d->arch.relmem_list); - } - } - - spin_unlock(&d->page_alloc_lock); - - if ( !rc ) - /* - * flush_flags are not tracked across hypercall pre-emption so - * assume a full flush is necessary. - */ - rc = iommu_iotlb_flush_all( - d, IOMMU_FLUSHF_added | IOMMU_FLUSHF_modified); - - if ( rc && rc != -ERESTART ) - iommu_teardown(d); - - return rc; -} - void __hwdom_init arch_iommu_check_autotranslated_hwdom(struct domain *d) { if ( !is_iommu_enabled(d) ) diff --git a/xen/include/asm-arm/iommu.h b/xen/include/asm-arm/iommu.h index 904c9aec11..1577e83d2b 100644 --- a/xen/include/asm-arm/iommu.h +++ b/xen/include/asm-arm/iommu.h @@ -21,7 +21,7 @@ struct arch_iommu }; /* Always share P2M Table between the CPU and the IOMMU */ -#define iommu_use_hap_pt(d) (has_iommu_pt(d)) +#define iommu_use_hap_pt(d) is_iommu_enabled(d) const struct iommu_ops *iommu_get_ops(void); void iommu_set_ops(const struct iommu_ops *ops); diff --git a/xen/include/asm-x86/iommu.h b/xen/include/asm-x86/iommu.h index 31fda4b0cf..5071afd6a5 100644 --- a/xen/include/asm-x86/iommu.h +++ b/xen/include/asm-x86/iommu.h @@ -88,7 +88,7 @@ extern const struct iommu_init_ops *iommu_init_ops; /* Are we using the domain P2M table as its IOMMU pagetable? */ #define iommu_use_hap_pt(d) \ - (hap_enabled(d) && has_iommu_pt(d) && iommu_hap_pt_share) + (hap_enabled(d) && is_iommu_enabled(d) && iommu_hap_pt_share) void iommu_update_ire_from_apic(unsigned int apic, unsigned int reg, unsigned int value); unsigned int iommu_read_apic_from_ire(unsigned int apic, unsigned int reg); diff --git a/xen/include/xen/iommu.h b/xen/include/xen/iommu.h index ab258b848b..ccb04d9681 100644 --- a/xen/include/xen/iommu.h +++ b/xen/include/xen/iommu.h @@ -73,15 +73,9 @@ void iommu_domain_destroy(struct domain *d); void arch_iommu_domain_destroy(struct domain *d); int arch_iommu_domain_init(struct domain *d); -int arch_iommu_populate_page_table(struct domain *d); void arch_iommu_check_autotranslated_hwdom(struct domain *d); void arch_iommu_hwdom_init(struct domain *d); -int iommu_construct(struct domain *d); - -/* Function used internally, use iommu_domain_destroy */ -void iommu_teardown(struct domain *d); - /* * The following flags are passed to map operations and passed by lookup * operations. @@ -248,13 +242,6 @@ struct iommu_ops { # define iommu_vcall iommu_call #endif -enum iommu_status -{ - IOMMU_STATUS_disabled, - IOMMU_STATUS_initializing, - IOMMU_STATUS_initialized -}; - struct domain_iommu { struct arch_iommu arch; @@ -274,9 +261,6 @@ struct domain_iommu { /* Features supported by the IOMMU */ DECLARE_BITMAP(features, IOMMU_FEAT_count); - /* Status of guest IOMMU mappings */ - enum iommu_status status; - /* * Does the guest reqire mappings to be synchonized, to maintain * the default dfn == pfn map. (See comment on dfn at the top of diff --git a/xen/include/xen/sched.h b/xen/include/xen/sched.h index 2d17c84915..ae1faf70d3 100644 --- a/xen/include/xen/sched.h +++ b/xen/include/xen/sched.h @@ -966,10 +966,8 @@ static inline bool is_hwdom_pinned_vcpu(const struct vcpu *v) } #ifdef CONFIG_HAS_PASSTHROUGH -#define has_iommu_pt(d) (dom_iommu(d)->status != IOMMU_STATUS_disabled) #define need_iommu_pt_sync(d) (dom_iommu(d)->need_sync) #else -#define has_iommu_pt(d) false #define need_iommu_pt_sync(d) false #endif From patchwork Thu Sep 12 11:17:43 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Paul Durrant X-Patchwork-Id: 11142823 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id C9EFA912 for ; Thu, 12 Sep 2019 11:21:07 +0000 (UTC) Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id A56EC206CD for ; Thu, 12 Sep 2019 11:21:07 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=citrix.com header.i=@citrix.com header.b="HwT3W6b7" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org A56EC206CD Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=citrix.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=xen-devel-bounces@lists.xenproject.org Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1i8N7A-0000q9-IO; Thu, 12 Sep 2019 11:18:16 +0000 Received: from all-amaz-eas1.inumbo.com ([34.197.232.57] helo=us1-amaz-eas2.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1i8N78-0000pB-H7 for xen-devel@lists.xenproject.org; Thu, 12 Sep 2019 11:18:14 +0000 X-Inumbo-ID: f6d649a2-d54e-11e9-83e7-12813bfff9fa Received: from esa3.hc3370-68.iphmx.com (unknown [216.71.145.155]) by us1-amaz-eas2.inumbo.com (Halon) with ESMTPS id f6d649a2-d54e-11e9-83e7-12813bfff9fa; Thu, 12 Sep 2019 11:17:54 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=citrix.com; s=securemail; t=1568287074; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=Z8DAABsalk69OqEgErG8ToocIoUtksFjksiTDxqNOJ4=; b=HwT3W6b7dadJXlxnyNi2NdIhL9nBF6w/DdhKMnVJM060JDGckmb/5K6d MMideLBAOllEp6Ou07B5zW2M21pDwAsxjq4rZ7qNqSOWTrEUIUcwfCdm+ f1udyGDZ+MaV4S21++RcPv+6YP0LSsMqI6O9iXrosHyVxI3rDAifS91/W 8=; Authentication-Results: esa3.hc3370-68.iphmx.com; dkim=none (message not signed) header.i=none; spf=None smtp.pra=paul.durrant@citrix.com; spf=Pass smtp.mailfrom=Paul.Durrant@citrix.com; spf=None smtp.helo=postmaster@mail.citrix.com Received-SPF: None (esa3.hc3370-68.iphmx.com: no sender authenticity information available from domain of paul.durrant@citrix.com) identity=pra; client-ip=162.221.158.21; receiver=esa3.hc3370-68.iphmx.com; envelope-from="Paul.Durrant@citrix.com"; x-sender="paul.durrant@citrix.com"; x-conformance=sidf_compatible Received-SPF: Pass (esa3.hc3370-68.iphmx.com: domain of Paul.Durrant@citrix.com designates 162.221.158.21 as permitted sender) identity=mailfrom; client-ip=162.221.158.21; receiver=esa3.hc3370-68.iphmx.com; envelope-from="Paul.Durrant@citrix.com"; x-sender="Paul.Durrant@citrix.com"; x-conformance=sidf_compatible; x-record-type="v=spf1"; x-record-text="v=spf1 ip4:209.167.231.154 ip4:178.63.86.133 ip4:195.66.111.40/30 ip4:85.115.9.32/28 ip4:199.102.83.4 ip4:192.28.146.160 ip4:192.28.146.107 ip4:216.52.6.88 ip4:216.52.6.188 ip4:162.221.158.21 ip4:162.221.156.83 ~all" Received-SPF: None (esa3.hc3370-68.iphmx.com: no sender authenticity information available from domain of postmaster@mail.citrix.com) identity=helo; client-ip=162.221.158.21; receiver=esa3.hc3370-68.iphmx.com; envelope-from="Paul.Durrant@citrix.com"; x-sender="postmaster@mail.citrix.com"; x-conformance=sidf_compatible IronPort-SDR: 0BtvmHdl/M8hn8pcZX+DGxq/97uq+iYjvWf2Z0KU1a9nIQfnNP/ltIgTp/ccUOQQ3uXG1FqTeI Hsf3H7B8BM/LefJ5kf69MZLI+hMDYIQ/pXrQsOttnAhqBPDmuMF54SXFFYkG3YSuAVBjL28FMr UfeypsKHpqsiLnUEDtOMNS1H47ccdqHuwUUQFxOY8msteTLXoqiSeSsqPElXu7RIJtT1KDOTW+ zxMg7zjvzmbQEh8H6VgQRySyAqZs9Zss8bjDR8nm52r6U40kPGdgl/zzfc+f7l398vImj1xzvQ o2I= X-SBRS: 2.7 X-MesageID: 5478495 X-Ironport-Server: esa3.hc3370-68.iphmx.com X-Remote-IP: 162.221.158.21 X-Policy: $RELAYED X-IronPort-AV: E=Sophos;i="5.64,495,1559534400"; d="scan'208";a="5478495" From: Paul Durrant To: Date: Thu, 12 Sep 2019 12:17:43 +0100 Message-ID: <20190912111744.40410-6-paul.durrant@citrix.com> X-Mailer: git-send-email 2.20.1.2.gb21ebb671 In-Reply-To: <20190912111744.40410-1-paul.durrant@citrix.com> References: <20190912111744.40410-1-paul.durrant@citrix.com> MIME-Version: 1.0 Subject: [Xen-devel] [PATCH v9 5/6] iommu: tidy up iommu_use_hap_pt() and need_iommu_pt_sync() macros X-BeenThere: xen-devel@lists.xenproject.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Cc: Stefano Stabellini , Wei Liu , Konrad Rzeszutek Wilk , George Dunlap , Andrew Cooper , Ian Jackson , Tim Deegan , Julien Grall , Paul Durrant , Jan Beulich , Volodymyr Babchuk , =?utf-8?q?Roger_Pau_Monn?= =?utf-8?q?=C3=A9?= Errors-To: xen-devel-bounces@lists.xenproject.org Sender: "Xen-devel" Thes macros really ought to live in the common xen/iommu.h header rather then being distributed amongst architecture specific iommu headers and xen/sched.h. This patch moves them there. NOTE: Disabling 'sharept' in the command line iommu options should really be hard error on ARM (as opposed to just being ignored), so define 'iommu_hap_pt_share' to be true for ARM (via ARM-selected CONFIG_IOMMU_FORCE_PT_SHARE) then then gate parsing the command line option on '#ifndef iommu_hap_pt_share'. Signed-off-by: Paul Durrant Reviewed-by: Jan Beulich --- Cc: Andrew Cooper Cc: George Dunlap Cc: Ian Jackson Cc: Julien Grall Cc: Konrad Rzeszutek Wilk Cc: Stefano Stabellini Cc: Tim Deegan Cc: Wei Liu Cc: Volodymyr Babchuk Cc: "Roger Pau Monné" Previously part of https://lists.xenproject.org/archives/html/xen-devel/2019-07/msg02267.html v9: - Add new Kconfig option to cause 'iommu_hap_pt_share' to be defined to true, rather than using CONFIG_ARM, as requested by Julien - Assuming Jan's R-b stands since this is a mainly a cosmetic change directly requested by another maintainer v7: - Re-work the ARM handling of 'sharept' as suggested by Jan - Make sure that need_iommu_pt_sync() always evaluates its argument --- xen/arch/arm/Kconfig | 1 + xen/drivers/passthrough/Kconfig | 3 +++ xen/drivers/passthrough/iommu.c | 8 +++++++- xen/include/asm-arm/iommu.h | 3 --- xen/include/asm-x86/iommu.h | 4 ---- xen/include/xen/iommu.h | 19 ++++++++++++++++++- xen/include/xen/sched.h | 6 ------ 7 files changed, 29 insertions(+), 15 deletions(-) diff --git a/xen/arch/arm/Kconfig b/xen/arch/arm/Kconfig index c2db2a6953..a51aa7bfa8 100644 --- a/xen/arch/arm/Kconfig +++ b/xen/arch/arm/Kconfig @@ -20,6 +20,7 @@ config ARM select HAS_DEVICE_TREE select HAS_PASSTHROUGH select HAS_PDX + select IOMMU_FORCE_PT_SHARE config ARCH_DEFCONFIG string diff --git a/xen/drivers/passthrough/Kconfig b/xen/drivers/passthrough/Kconfig index a3c06491be..61f944639e 100644 --- a/xen/drivers/passthrough/Kconfig +++ b/xen/drivers/passthrough/Kconfig @@ -13,3 +13,6 @@ config ARM_SMMU Say Y here if your SoC includes an IOMMU device implementing the ARM SMMU architecture. endif + +config IOMMU_FORCE_PT_SHARE + bool diff --git a/xen/drivers/passthrough/iommu.c b/xen/drivers/passthrough/iommu.c index 1410066fb3..d533d5af78 100644 --- a/xen/drivers/passthrough/iommu.c +++ b/xen/drivers/passthrough/iommu.c @@ -49,7 +49,11 @@ int8_t __hwdom_initdata iommu_hwdom_reserved = -1; * default until we find a good solution to resolve it. */ bool_t __read_mostly iommu_intpost; -bool_t __read_mostly iommu_hap_pt_share = 1; + +#ifndef iommu_hap_pt_share +bool __read_mostly iommu_hap_pt_share = true; +#endif + bool_t __read_mostly iommu_debug; bool_t __read_mostly amd_iommu_perdev_intremap = 1; @@ -102,8 +106,10 @@ static int __init parse_iommu_param(const char *s) iommu_hwdom_passthrough = val; else if ( (val = parse_boolean("dom0-strict", s, ss)) >= 0 ) iommu_hwdom_strict = val; +#ifndef iommu_hap_pt_share else if ( (val = parse_boolean("sharept", s, ss)) >= 0 ) iommu_hap_pt_share = val; +#endif else rc = -EINVAL; diff --git a/xen/include/asm-arm/iommu.h b/xen/include/asm-arm/iommu.h index 1577e83d2b..77a94b29eb 100644 --- a/xen/include/asm-arm/iommu.h +++ b/xen/include/asm-arm/iommu.h @@ -20,9 +20,6 @@ struct arch_iommu void *priv; }; -/* Always share P2M Table between the CPU and the IOMMU */ -#define iommu_use_hap_pt(d) is_iommu_enabled(d) - const struct iommu_ops *iommu_get_ops(void); void iommu_set_ops(const struct iommu_ops *ops); diff --git a/xen/include/asm-x86/iommu.h b/xen/include/asm-x86/iommu.h index 5071afd6a5..85741f7c96 100644 --- a/xen/include/asm-x86/iommu.h +++ b/xen/include/asm-x86/iommu.h @@ -86,10 +86,6 @@ struct iommu_init_ops { extern const struct iommu_init_ops *iommu_init_ops; -/* Are we using the domain P2M table as its IOMMU pagetable? */ -#define iommu_use_hap_pt(d) \ - (hap_enabled(d) && is_iommu_enabled(d) && iommu_hap_pt_share) - void iommu_update_ire_from_apic(unsigned int apic, unsigned int reg, unsigned int value); unsigned int iommu_read_apic_from_ire(unsigned int apic, unsigned int reg); int iommu_setup_hpet_msi(struct msi_desc *); diff --git a/xen/include/xen/iommu.h b/xen/include/xen/iommu.h index ccb04d9681..e09783e395 100644 --- a/xen/include/xen/iommu.h +++ b/xen/include/xen/iommu.h @@ -55,7 +55,13 @@ static inline bool_t dfn_eq(dfn_t x, dfn_t y) extern bool_t iommu_enable, iommu_enabled; extern bool_t force_iommu, iommu_verbose, iommu_igfx; extern bool_t iommu_snoop, iommu_qinval, iommu_intremap, iommu_intpost; -extern bool_t iommu_hap_pt_share; + +#ifdef CONFIG_IOMMU_FORCE_PT_SHARE +#define iommu_hap_pt_share true +#else +extern bool iommu_hap_pt_share; +#endif + extern bool_t iommu_debug; extern bool_t amd_iommu_perdev_intremap; @@ -273,6 +279,17 @@ struct domain_iommu { #define iommu_set_feature(d, f) set_bit(f, dom_iommu(d)->features) #define iommu_clear_feature(d, f) clear_bit(f, dom_iommu(d)->features) +/* Are we using the domain P2M table as its IOMMU pagetable? */ +#define iommu_use_hap_pt(d) \ + (hap_enabled(d) && is_iommu_enabled(d) && iommu_hap_pt_share) + +/* Does the IOMMU pagetable need to be kept synchronized with the P2M */ +#ifdef CONFIG_HAS_PASSTHROUGH +#define need_iommu_pt_sync(d) (dom_iommu(d)->need_sync) +#else +#define need_iommu_pt_sync(d) ({ (void)(d); false; }) +#endif + int __must_check iommu_suspend(void); void iommu_resume(void); void iommu_crash_shutdown(void); diff --git a/xen/include/xen/sched.h b/xen/include/xen/sched.h index ae1faf70d3..a6896221f9 100644 --- a/xen/include/xen/sched.h +++ b/xen/include/xen/sched.h @@ -965,12 +965,6 @@ static inline bool is_hwdom_pinned_vcpu(const struct vcpu *v) cpumask_weight(v->cpu_hard_affinity) == 1); } -#ifdef CONFIG_HAS_PASSTHROUGH -#define need_iommu_pt_sync(d) (dom_iommu(d)->need_sync) -#else -#define need_iommu_pt_sync(d) false -#endif - static inline bool is_vcpu_online(const struct vcpu *v) { return !test_bit(_VPF_down, &v->pause_flags); From patchwork Thu Sep 12 11:17:44 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Paul Durrant X-Patchwork-Id: 11142819 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 3D76313BD for ; Thu, 12 Sep 2019 11:20:40 +0000 (UTC) Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 0D3B72081B for ; Thu, 12 Sep 2019 11:20:40 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=citrix.com header.i=@citrix.com header.b="UQ1dns1s" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 0D3B72081B Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=citrix.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=xen-devel-bounces@lists.xenproject.org Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1i8N6v-0000j0-Ct; Thu, 12 Sep 2019 11:18:01 +0000 Received: from all-amaz-eas1.inumbo.com ([34.197.232.57] helo=us1-amaz-eas2.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1i8N6t-0000i2-Gw for xen-devel@lists.xenproject.org; Thu, 12 Sep 2019 11:17:59 +0000 X-Inumbo-ID: f446b474-d54e-11e9-83e7-12813bfff9fa Received: from esa6.hc3370-68.iphmx.com (unknown [216.71.155.175]) by us1-amaz-eas2.inumbo.com (Halon) with ESMTPS id f446b474-d54e-11e9-83e7-12813bfff9fa; Thu, 12 Sep 2019 11:17:49 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=citrix.com; s=securemail; t=1568287069; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=wlhP2VUQUzaEN98t3Lol149kD3BgIdIbcDr9/tSfeiY=; b=UQ1dns1sDgUskFnYZf5NMDy9zOaFKgyCW72hAug5t51N1N6QSv4kir0d W3ZQk/YmeU2WZnHIETLXdIQz61mbydo0gddLmO0bzSO1X3/4DDaoM6tnM VZcIhmiwXw1RV9kTqFRC8YX3tw9FRAWNYD0zKle3gfbKgcQuPmsNdbZnL M=; Authentication-Results: esa6.hc3370-68.iphmx.com; dkim=none (message not signed) header.i=none; spf=None smtp.pra=paul.durrant@citrix.com; spf=Pass smtp.mailfrom=Paul.Durrant@citrix.com; spf=None smtp.helo=postmaster@mail.citrix.com Received-SPF: None (esa6.hc3370-68.iphmx.com: no sender authenticity information available from domain of paul.durrant@citrix.com) identity=pra; client-ip=162.221.158.21; receiver=esa6.hc3370-68.iphmx.com; envelope-from="Paul.Durrant@citrix.com"; x-sender="paul.durrant@citrix.com"; x-conformance=sidf_compatible Received-SPF: Pass (esa6.hc3370-68.iphmx.com: domain of Paul.Durrant@citrix.com designates 162.221.158.21 as permitted sender) identity=mailfrom; client-ip=162.221.158.21; receiver=esa6.hc3370-68.iphmx.com; envelope-from="Paul.Durrant@citrix.com"; x-sender="Paul.Durrant@citrix.com"; x-conformance=sidf_compatible; x-record-type="v=spf1"; x-record-text="v=spf1 ip4:209.167.231.154 ip4:178.63.86.133 ip4:195.66.111.40/30 ip4:85.115.9.32/28 ip4:199.102.83.4 ip4:192.28.146.160 ip4:192.28.146.107 ip4:216.52.6.88 ip4:216.52.6.188 ip4:162.221.158.21 ip4:162.221.156.83 ~all" Received-SPF: None (esa6.hc3370-68.iphmx.com: no sender authenticity information available from domain of postmaster@mail.citrix.com) identity=helo; client-ip=162.221.158.21; receiver=esa6.hc3370-68.iphmx.com; envelope-from="Paul.Durrant@citrix.com"; x-sender="postmaster@mail.citrix.com"; x-conformance=sidf_compatible IronPort-SDR: fffQBtH7heyjWeUHWLdmJLnbOpnbrPZhCUBBAYj3Zqp3ECubcVwa2+R101ns9QE3R8AIgqBxj1 pJAxeDEAMo0QCgOVZMTiLTHaZ9x8Ejz50eCu13HaqQTm/bc8m3zo9bhFIGUiEyUJvhQau/VyNH 5A/oAiMqBGGY4o1bFe0CxHy0yawRKMLfTrnujErMzh2SXMJfhtPOFa0sbY0aeyxCMfIZo20MsZ ER30v9Qoc5O1EzPpwR79fv4sBXJckXlaXCN2ICfaSG7qPCKNoG0nu8/WnDRduSblJpQCz3VGkh LgQ= X-SBRS: 2.7 X-MesageID: 5719882 X-Ironport-Server: esa6.hc3370-68.iphmx.com X-Remote-IP: 162.221.158.21 X-Policy: $RELAYED X-IronPort-AV: E=Sophos;i="5.64,495,1559534400"; d="scan'208";a="5719882" From: Paul Durrant To: Date: Thu, 12 Sep 2019 12:17:44 +0100 Message-ID: <20190912111744.40410-7-paul.durrant@citrix.com> X-Mailer: git-send-email 2.20.1.2.gb21ebb671 In-Reply-To: <20190912111744.40410-1-paul.durrant@citrix.com> References: <20190912111744.40410-1-paul.durrant@citrix.com> MIME-Version: 1.0 Subject: [Xen-devel] [PATCH v9 6/6] introduce a 'passthrough' configuration option to xl.cfg... X-BeenThere: xen-devel@lists.xenproject.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Cc: Stefano Stabellini , Wei Liu , Konrad Rzeszutek Wilk , George Dunlap , Andrew Cooper , Ian Jackson , Tim Deegan , Julien Grall , Paul Durrant , Christian Lindig , Jan Beulich , David Scott , Anthony PERARD , Volodymyr Babchuk , =?utf-8?q?Roger_Pau_Monn?= =?utf-8?q?=C3=A9?= Errors-To: xen-devel-bounces@lists.xenproject.org Sender: "Xen-devel" ...and hence the ability to disable IOMMU mappings, and control EPT sharing. This patch introduces a new 'libxl_passthrough' enumeration into libxl_domain_create_info. The value will be set by xl either when it parses a new 'passthrough' option in xl.cfg, or implicitly if there is passthrough hardware specified for the domain. If the value of the passthrough configuration option is 'disabled' then the XEN_DOMCTL_CDF_iommu flag will be clear in the xen_domctl_createdomain flags, thus allowing the toolstack to control whether the domain gets IOMMU mappings or not (where previously they were globally set). If the value of the passthrough configuration option is 'sync_pt' then a new 'iommu_opts' field in xen_domctl_createdomain will be set with the value XEN_DOMCTL_IOMMU_no_sharept. This will override the global default set in iommu_hap_pt_share, thus allowing the toolstack to control whether EPT sharing is used for the domain. If the value of passthrough is 'enabled' then xl will choose an appropriate default according to the type of domain and hardware support. NOTE: The 'iommu_memkb' overhead in libxl_domain_build_info will now only be set if passthrough is 'sync_pt' (or xl has chosen this mode as a default). Signed-off-by: Paul Durrant Reviewed-by: Jan Beulich --- Cc: Ian Jackson Cc: Wei Liu Cc: Andrew Cooper Cc: George Dunlap Cc: Julien Grall Cc: Konrad Rzeszutek Wilk Cc: Stefano Stabellini Cc: Tim Deegan Cc: Anthony PERARD Cc: Christian Lindig Cc: David Scott Cc: Volodymyr Babchuk Cc: "Roger Pau Monné" Previously part of series https://lists.xenproject.org/archives/html/xen-devel/2019-07/msg02267.html v9: - Added the passthrough='enabled' option to xl - One cosmetic change in xen - Assume Jan's R-b stands since non-cosmetic changes are only in the toolstack v7: - Added missing breaks - Added missing ocaml binding changes v6: - Remove the libxl_physinfo() call since it's usefulness is limited to x86 v5: - Expand xen_domctl_createdomain flags field and hence bump interface version - Fix spelling mistakes in context line --- docs/man/xl.cfg.5.pod.in | 56 ++++++++++ tools/libxl/libxl.h | 9 ++ tools/libxl/libxl_create.c | 9 ++ tools/libxl/libxl_types.idl | 7 ++ tools/ocaml/libs/xc/xenctrl.ml | 4 + tools/ocaml/libs/xc/xenctrl.mli | 5 + tools/ocaml/libs/xc/xenctrl_stubs.c | 16 ++- tools/xl/xl_parse.c | 158 ++++++++++++++++++---------- xen/arch/arm/domain.c | 10 +- xen/arch/x86/domain.c | 2 +- xen/common/domain.c | 7 ++ xen/common/domctl.c | 13 --- xen/drivers/passthrough/iommu.c | 13 ++- xen/include/public/domctl.h | 10 +- xen/include/xen/iommu.h | 15 +-- 15 files changed, 253 insertions(+), 81 deletions(-) diff --git a/docs/man/xl.cfg.5.pod.in b/docs/man/xl.cfg.5.pod.in index c99d40307e..154d847fb9 100644 --- a/docs/man/xl.cfg.5.pod.in +++ b/docs/man/xl.cfg.5.pod.in @@ -605,6 +605,62 @@ option should only be used with a trusted device tree. Note that the partial device tree should avoid using the phandle 65000 which is reserved by the toolstack. +=item B + +Specify whether IOMMU mappings are enabled for the domain and hence whether +it will be enabled for passthrough hardware. Valid values for this option +are: + +=over 4 + +=item B + +IOMMU mappings are disabled for the domain and so hardware may not be +passed through. + +This option is the default if no passthrough hardware is specified in the +domain's configuration. + +=item B + +This option means that IOMMU mappings will be synchronized with the +domain's P2M table as follows: + +For a PV domain, all writable pages assigned to the domain are identity +mapped by MFN in the IOMMU page table. Thus a device driver running in the +domain may program passthrough hardware for DMA using MFN values +(i.e. host/machine frame numbers) looked up in its P2M. + +For an HVM domain, all non-foreign RAM pages present in its P2M will be +mapped by GFN in the IOMMU page table. Thus a device driver running in the +domain may program passthrough hardware using GFN values (i.e. guest +physical frame numbers) without any further translation. + +This option is not currently available on Arm. + +=item B + +This option is unavailable for a PV domain. For an HVM domain, this option +means that the IOMMU will be programmed to directly reference the domain's +P2M table as its page table. From the point of view of a device driver +running in the domain this is functionally equivalent to B but +places less load on the hypervisor and so should generally be selected in +preference. However, the availability of this option is hardware specific. +If B reports B containing B then +this option may be used. + +=item B + +This option enables IOMMU mappings and selects an appropriate default +operating mode. For HVM domains running on platforms where the option is +available, this is equivalent to B. Otherwise, and also for PV +domains, this options is equivalent to B. + +This option is the default if passthrough hardware is specified in the +domain's configuration. + +=back + =back =head2 Devices diff --git a/tools/libxl/libxl.h b/tools/libxl/libxl.h index a9e7cf86fd..f992437691 100644 --- a/tools/libxl/libxl.h +++ b/tools/libxl/libxl.h @@ -415,6 +415,15 @@ */ #define LIBXL_HAVE_BUILDINFO_IOMMU_MEMKB 1 +/* + * LIBXL_HAVE_CREATEINFO_PASSTHROUGH indicates that + * libxl_domain_create_info has a passthrough field (which is a + * libxl_passthrough enumeration) that indicates whether device pass- + * through is enabled for the domain and, if so, whether the IOMMU and + * HAP page tables may be shared or not. + */ +#define LIBXL_HAVE_CREATEINFO_PASSTHROUGH 1 + /* * libxl ABI compatibility * diff --git a/tools/libxl/libxl_create.c b/tools/libxl/libxl_create.c index 3b45065597..e1bb232f40 100644 --- a/tools/libxl/libxl_create.c +++ b/tools/libxl/libxl_create.c @@ -570,6 +570,15 @@ int libxl__domain_make(libxl__gc *gc, libxl_domain_config *d_config, libxl_defbool_val(info->oos) ? 0 : XEN_DOMCTL_CDF_oos_off; } + LOG(DETAIL, "passthrough: %s", + libxl_passthrough_to_string(info->passthrough)); + + if (info->passthrough != LIBXL_PASSTHROUGH_DISABLED) + create.flags |= XEN_DOMCTL_CDF_iommu; + + if (info->passthrough == LIBXL_PASSTHROUGH_SYNC_PT) + create.iommu_opts |= XEN_DOMCTL_IOMMU_no_sharept; + /* Ultimately, handle is an array of 16 uint8_t, same as uuid */ libxl_uuid_copy(ctx, (libxl_uuid *)&create.handle, &info->uuid); diff --git a/tools/libxl/libxl_types.idl b/tools/libxl/libxl_types.idl index e060788092..1809aedf02 100644 --- a/tools/libxl/libxl_types.idl +++ b/tools/libxl/libxl_types.idl @@ -263,6 +263,12 @@ libxl_vkb_backend = Enumeration("vkb_backend", [ (2, "LINUX") ]) +libxl_passthrough = Enumeration("passthrough", [ + (0, "disabled"), + (1, "sync_pt"), + (2, "share_pt"), + ]) + # # Complex libxl types # @@ -408,6 +414,7 @@ libxl_domain_create_info = Struct("domain_create_info",[ ("pool_name", string), ("run_hotplug_scripts",libxl_defbool), ("driver_domain",libxl_defbool), + ("passthrough", libxl_passthrough), ], dir=DIR_IN) libxl_domain_restore_params = Struct("domain_restore_params", [ diff --git a/tools/ocaml/libs/xc/xenctrl.ml b/tools/ocaml/libs/xc/xenctrl.ml index 30da6ba370..46b4f748c0 100644 --- a/tools/ocaml/libs/xc/xenctrl.ml +++ b/tools/ocaml/libs/xc/xenctrl.ml @@ -65,11 +65,15 @@ type domain_create_flag = | CDF_XS_DOMAIN | CDF_IOMMU +type domain_create_iommu_opts = + | IOMMU_NO_SHAREPT + type domctl_create_config = { ssidref: int32; handle: string; flags: domain_create_flag list; + iommu_opts: domain_create_iommu_opts list; max_vcpus: int; max_evtchn_port: int; max_grant_frames: int; diff --git a/tools/ocaml/libs/xc/xenctrl.mli b/tools/ocaml/libs/xc/xenctrl.mli index 64c35418e8..824f361632 100644 --- a/tools/ocaml/libs/xc/xenctrl.mli +++ b/tools/ocaml/libs/xc/xenctrl.mli @@ -57,10 +57,15 @@ type domain_create_flag = | CDF_OOS_OFF | CDF_XS_DOMAIN | CDF_IOMMU + +type domain_create_iommu_opts = + | IOMMU_NO_SHAREPT + type domctl_create_config = { ssidref: int32; handle: string; flags: domain_create_flag list; + iommu_opts: domain_create_iommu_opts list; max_vcpus: int; max_evtchn_port: int; max_grant_frames: int; diff --git a/tools/ocaml/libs/xc/xenctrl_stubs.c b/tools/ocaml/libs/xc/xenctrl_stubs.c index 0cdd873599..41b2bf0788 100644 --- a/tools/ocaml/libs/xc/xenctrl_stubs.c +++ b/tools/ocaml/libs/xc/xenctrl_stubs.c @@ -190,11 +190,12 @@ CAMLprim value stub_xc_domain_create(value xch, value config) #define VAL_SSIDREF Field(config, 0) #define VAL_HANDLE Field(config, 1) #define VAL_FLAGS Field(config, 2) -#define VAL_MAX_VCPUS Field(config, 3) -#define VAL_MAX_EVTCHN_PORT Field(config, 4) -#define VAL_MAX_GRANT_FRAMES Field(config, 5) -#define VAL_MAX_MAPTRACK_FRAMES Field(config, 6) -#define VAL_ARCH Field(config, 7) +#define VAL_IOMMU_OPTS Field(config, 3) +#define VAL_MAX_VCPUS Field(config, 4) +#define VAL_MAX_EVTCHN_PORT Field(config, 5) +#define VAL_MAX_GRANT_FRAMES Field(config, 6) +#define VAL_MAX_MAPTRACK_FRAMES Field(config, 7) +#define VAL_ARCH Field(config, 8) uint32_t domid = 0; int result; @@ -213,6 +214,10 @@ CAMLprim value stub_xc_domain_create(value xch, value config) /* ! XEN_DOMCTL_CDF_ XEN_DOMCTL_CDF_MAX max */ (VAL_FLAGS); + cfg.iommu_opts = ocaml_list_to_c_bitmap + /* ! domain_create_iommu_opts IOMMU_ lc */ + /* ! XEN_DOMCTL_IOMMU_ XEN_DOMCTL_IOMMU_MAX max */ + arch_domconfig = Field(VAL_ARCH, 0); switch ( Tag_val(VAL_ARCH) ) { @@ -247,6 +252,7 @@ CAMLprim value stub_xc_domain_create(value xch, value config) #undef VAL_MAX_GRANT_FRAMES #undef VAL_MAX_EVTCHN_PORT #undef VAL_MAX_VCPUS +#undef VAL_IOMMU_OPTS #undef VAL_FLAGS #undef VAL_HANDLE #undef VAL_SSIDREF diff --git a/tools/xl/xl_parse.c b/tools/xl/xl_parse.c index 293f5f730e..4b2baa0403 100644 --- a/tools/xl/xl_parse.c +++ b/tools/xl/xl_parse.c @@ -1461,6 +1461,107 @@ void parse_config_data(const char *config_source, exit(1); } + if (!xlu_cfg_get_list (config, "pci", &pcis, 0, 0)) { + d_config->num_pcidevs = 0; + d_config->pcidevs = NULL; + for(i = 0; (buf = xlu_cfg_get_listitem (pcis, i)) != NULL; i++) { + libxl_device_pci *pcidev; + + pcidev = ARRAY_EXTEND_INIT_NODEVID(d_config->pcidevs, + d_config->num_pcidevs, + libxl_device_pci_init); + pcidev->msitranslate = pci_msitranslate; + pcidev->power_mgmt = pci_power_mgmt; + pcidev->permissive = pci_permissive; + pcidev->seize = pci_seize; + /* + * Like other pci option, the per-device policy always follows + * the global policy by default. + */ + pcidev->rdm_policy = b_info->u.hvm.rdm.policy; + e = xlu_pci_parse_bdf(config, pcidev, buf); + if (e) { + fprintf(stderr, + "unable to parse PCI BDF `%s' for passthrough\n", + buf); + exit(-e); + } + } + if (d_config->num_pcidevs && c_info->type == LIBXL_DOMAIN_TYPE_PV) + libxl_defbool_set(&b_info->u.pv.e820_host, true); + } + + if (!xlu_cfg_get_list (config, "dtdev", &dtdevs, 0, 0)) { + d_config->num_dtdevs = 0; + d_config->dtdevs = NULL; + for (i = 0; (buf = xlu_cfg_get_listitem(dtdevs, i)) != NULL; i++) { + libxl_device_dtdev *dtdev; + + dtdev = ARRAY_EXTEND_INIT_NODEVID(d_config->dtdevs, + d_config->num_dtdevs, + libxl_device_dtdev_init); + + dtdev->path = strdup(buf); + if (dtdev->path == NULL) { + fprintf(stderr, "unable to duplicate string for dtdevs\n"); + exit(-1); + } + } + } + + if (xlu_cfg_get_string(config, "passthrough", &buf, 0)) { + buf = (d_config->num_pcidevs || d_config->num_dtdevs) + ? "enabled" : "disabled"; + } + + if (!strncmp(buf, "enabled", strlen(buf))) { + /* Choose a suitable default */ + c_info->passthrough = + (c_info->type == LIBXL_DOMAIN_TYPE_PV) || !iommu_hap_pt_share + ? LIBXL_PASSTHROUGH_SYNC_PT : LIBXL_PASSTHROUGH_SHARE_PT; + } else { + libxl_passthrough o; + + e = libxl_passthrough_from_string(buf, &o); + if (e) { + fprintf(stderr, + "ERROR: unknown passthrough option '%s'\n", + buf); + exit(-ERROR_FAIL); + } + + switch (o) { + case LIBXL_PASSTHROUGH_DISABLED: + if (d_config->num_pcidevs || d_config->num_dtdevs) { + fprintf(stderr, + "ERROR: passthrough disabled but devices are specified\n"); + exit(-ERROR_FAIL); + } + break; + case LIBXL_PASSTHROUGH_SHARE_PT: + if (c_info->type == LIBXL_DOMAIN_TYPE_PV) { + fprintf(stderr, + "ERROR: passthrough=\"share_pt\" not valid for PV domain\n"); + exit(-ERROR_FAIL); + } else if (!iommu_hap_pt_share) { + fprintf(stderr, + "ERROR: passthrough=\"share_pt\" not supported on this platform\n"); + exit(-ERROR_FAIL); + } + break; + case LIBXL_PASSTHROUGH_SYNC_PT: + break; + } + + c_info->passthrough = o; + } + + if ((c_info->passthrough != LIBXL_PASSTHROUGH_DISABLED) && !iommu_enabled) { + fprintf(stderr, + "ERROR: passthrough not supported on this platform\n"); + exit(-ERROR_FAIL); + } + /* libxl_get_required_shadow_memory() and * libxl_get_required_iommu_memory() must be called after final values * (default or specified) for vcpus and memory are set, because the @@ -1470,11 +1571,10 @@ void parse_config_data(const char *config_source, : libxl_get_required_shadow_memory(b_info->max_memkb, b_info->max_vcpus); - /* No IOMMU reservation is needed if either the IOMMU is disabled or it - * can share the P2M. */ - b_info->iommu_memkb = (!iommu_enabled || iommu_hap_pt_share) - ? 0 - : libxl_get_required_iommu_memory(b_info->max_memkb); + /* No IOMMU reservation is needed if passthrough mode is not 'sync_pt' */ + b_info->iommu_memkb = (c_info->passthrough == LIBXL_PASSTHROUGH_SYNC_PT) + ? libxl_get_required_iommu_memory(b_info->max_memkb) + : 0; xlu_cfg_get_defbool(config, "nomigrate", &b_info->disable_migrate, 0); @@ -2298,54 +2398,6 @@ skip_vfb: } } - if (!xlu_cfg_get_list (config, "pci", &pcis, 0, 0)) { - d_config->num_pcidevs = 0; - d_config->pcidevs = NULL; - for(i = 0; (buf = xlu_cfg_get_listitem (pcis, i)) != NULL; i++) { - libxl_device_pci *pcidev; - - pcidev = ARRAY_EXTEND_INIT_NODEVID(d_config->pcidevs, - d_config->num_pcidevs, - libxl_device_pci_init); - pcidev->msitranslate = pci_msitranslate; - pcidev->power_mgmt = pci_power_mgmt; - pcidev->permissive = pci_permissive; - pcidev->seize = pci_seize; - /* - * Like other pci option, the per-device policy always follows - * the global policy by default. - */ - pcidev->rdm_policy = b_info->u.hvm.rdm.policy; - e = xlu_pci_parse_bdf(config, pcidev, buf); - if (e) { - fprintf(stderr, - "unable to parse PCI BDF `%s' for passthrough\n", - buf); - exit(-e); - } - } - if (d_config->num_pcidevs && c_info->type == LIBXL_DOMAIN_TYPE_PV) - libxl_defbool_set(&b_info->u.pv.e820_host, true); - } - - if (!xlu_cfg_get_list (config, "dtdev", &dtdevs, 0, 0)) { - d_config->num_dtdevs = 0; - d_config->dtdevs = NULL; - for (i = 0; (buf = xlu_cfg_get_listitem(dtdevs, i)) != NULL; i++) { - libxl_device_dtdev *dtdev; - - dtdev = ARRAY_EXTEND_INIT_NODEVID(d_config->dtdevs, - d_config->num_dtdevs, - libxl_device_dtdev_init); - - dtdev->path = strdup(buf); - if (dtdev->path == NULL) { - fprintf(stderr, "unable to duplicate string for dtdevs\n"); - exit(-1); - } - } - } - if (!xlu_cfg_get_list(config, "usbctrl", &usbctrls, 0, 0)) { d_config->num_usbctrls = 0; d_config->usbctrls = NULL; diff --git a/xen/arch/arm/domain.c b/xen/arch/arm/domain.c index ae13e47e86..61d35cd120 100644 --- a/xen/arch/arm/domain.c +++ b/xen/arch/arm/domain.c @@ -617,6 +617,14 @@ int arch_sanitise_domain_config(struct xen_domctl_createdomain *config) return -EINVAL; } + /* The P2M table must always be shared between the CPU and the IOMMU */ + if ( config->iommu_opts & XEN_DOMCTL_IOMMU_no_sharept ) + { + dprintk(XENLOG_INFO, + "Unsupported iommu option: XEN_DOMCTL_IOMMU_no_sharept\n"); + return -EINVAL; + } + /* Fill in the native GIC version, passed back to the toolstack. */ if ( config->arch.gic_version == XEN_DOMCTL_CONFIG_GIC_NATIVE ) { @@ -677,7 +685,7 @@ int arch_domain_create(struct domain *d, ASSERT(config != NULL); /* p2m_init relies on some value initialized by the IOMMU subsystem */ - if ( (rc = iommu_domain_init(d)) != 0 ) + if ( (rc = iommu_domain_init(d, config->iommu_opts)) != 0 ) goto fail; if ( (rc = p2m_init(d)) != 0 ) diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c index 4b0ad5e15d..fb8b397be2 100644 --- a/xen/arch/x86/domain.c +++ b/xen/arch/x86/domain.c @@ -611,7 +611,7 @@ int arch_domain_create(struct domain *d, if ( (rc = init_domain_irq_mapping(d)) != 0 ) goto fail; - if ( (rc = iommu_domain_init(d)) != 0 ) + if ( (rc = iommu_domain_init(d, config->iommu_opts)) != 0 ) goto fail; psr_domain_init(d); diff --git a/xen/common/domain.c b/xen/common/domain.c index 4681f29c8b..0733ee8b0a 100644 --- a/xen/common/domain.c +++ b/xen/common/domain.c @@ -308,6 +308,13 @@ static int sanitise_domain_config(struct xen_domctl_createdomain *config) return -EINVAL; } + if ( !(config->flags & XEN_DOMCTL_CDF_iommu) && config->iommu_opts ) + { + dprintk(XENLOG_INFO, + "IOMMU options specified but IOMMU not enabled\n"); + return -EINVAL; + } + if ( config->max_vcpus < 1 ) { dprintk(XENLOG_INFO, "No vCPUS\n"); diff --git a/xen/common/domctl.c b/xen/common/domctl.c index 5dcfe3c8f6..6e6e9b9866 100644 --- a/xen/common/domctl.c +++ b/xen/common/domctl.c @@ -515,19 +515,6 @@ long do_domctl(XEN_GUEST_HANDLE_PARAM(xen_domctl_t) u_domctl) rover = dom; } - /* - * For now, make sure the createdomain IOMMU flag is set if the - * IOMMU is enabled. When the flag comes under toolstack control - * this can go away. - */ - if ( op->u.createdomain.flags & XEN_DOMCTL_CDF_iommu ) - { - ASSERT_UNREACHABLE(); - return -EINVAL; - } - if ( iommu_enabled ) - op->u.createdomain.flags |= XEN_DOMCTL_CDF_iommu; - d = domain_create(dom, &op->u.createdomain, false); if ( IS_ERR(d) ) { diff --git a/xen/drivers/passthrough/iommu.c b/xen/drivers/passthrough/iommu.c index d533d5af78..2733b320ec 100644 --- a/xen/drivers/passthrough/iommu.c +++ b/xen/drivers/passthrough/iommu.c @@ -163,7 +163,7 @@ static void __hwdom_init check_hwdom_reqs(struct domain *d) iommu_hwdom_strict = true; } -int iommu_domain_init(struct domain *d) +int iommu_domain_init(struct domain *d, unsigned int opts) { struct domain_iommu *hd = dom_iommu(d); int ret = 0; @@ -187,6 +187,15 @@ int iommu_domain_init(struct domain *d) if ( is_hardware_domain(d) ) check_hwdom_reqs(d); /* may modify iommu_hwdom_strict */ + /* + * Use shared page tables for HAP and IOMMU if the global option + * is enabled (from which we can infer the h/w is capable) and + * the domain options do not disallow it. HAP must, of course, also + * be enabled. + */ + hd->hap_pt_share = hap_enabled(d) && iommu_hap_pt_share && + !(opts & XEN_DOMCTL_IOMMU_no_sharept); + /* * NB: 'relaxed' h/w domains don't need the IOMMU mappings to be kept * in-sync with their assigned pages because all host RAM will be @@ -195,6 +204,8 @@ int iommu_domain_init(struct domain *d) if ( !is_hardware_domain(d) || iommu_hwdom_strict ) hd->need_sync = !iommu_use_hap_pt(d); + ASSERT(!(hd->need_sync && hd->hap_pt_share)); + return 0; } diff --git a/xen/include/public/domctl.h b/xen/include/public/domctl.h index 1b3176adb5..ba84aea6ab 100644 --- a/xen/include/public/domctl.h +++ b/xen/include/public/domctl.h @@ -38,7 +38,7 @@ #include "hvm/save.h" #include "memory.h" -#define XEN_DOMCTL_INTERFACE_VERSION 0x00000011 +#define XEN_DOMCTL_INTERFACE_VERSION 0x00000012 /* * NB. xen_domctl.domain is an IN/OUT parameter for this operation. @@ -73,6 +73,14 @@ struct xen_domctl_createdomain { uint32_t flags; +#define _XEN_DOMCTL_IOMMU_no_sharept 0 +#define XEN_DOMCTL_IOMMU_no_sharept (1U << _XEN_DOMCTL_IOMMU_no_sharept) + +/* Max XEN_DOMCTL_IOMMU_* constant. Used for ABI checking. */ +#define XEN_DOMCTL_IOMMU_MAX XEN_DOMCTL_IOMMU_no_sharept + + uint32_t iommu_opts; + /* * Various domain limits, which impact the quantity of resources (global * mapping space, xenheap, etc) a guest may consume. diff --git a/xen/include/xen/iommu.h b/xen/include/xen/iommu.h index e09783e395..58520fd996 100644 --- a/xen/include/xen/iommu.h +++ b/xen/include/xen/iommu.h @@ -73,7 +73,7 @@ extern unsigned int iommu_dev_iotlb_timeout; int iommu_setup(void); int iommu_hardware_setup(void); -int iommu_domain_init(struct domain *d); +int iommu_domain_init(struct domain *d, unsigned int opts); void iommu_hwdom_init(struct domain *d); void iommu_domain_destroy(struct domain *d); @@ -267,10 +267,14 @@ struct domain_iommu { /* Features supported by the IOMMU */ DECLARE_BITMAP(features, IOMMU_FEAT_count); + /* Does the guest share HAP mapping with the IOMMU? */ + bool hap_pt_share; + /* - * Does the guest reqire mappings to be synchonized, to maintain - * the default dfn == pfn map. (See comment on dfn at the top of - * include/xen/mm.h). + * Does the guest require mappings to be synchronized, to maintain + * the default dfn == pfn map? (See comment on dfn at the top of + * include/xen/mm.h). Note that hap_pt_share == false does not + * necessarily imply this is true. */ bool need_sync; }; @@ -280,8 +284,7 @@ struct domain_iommu { #define iommu_clear_feature(d, f) clear_bit(f, dom_iommu(d)->features) /* Are we using the domain P2M table as its IOMMU pagetable? */ -#define iommu_use_hap_pt(d) \ - (hap_enabled(d) && is_iommu_enabled(d) && iommu_hap_pt_share) +#define iommu_use_hap_pt(d) (dom_iommu(d)->hap_pt_share) /* Does the IOMMU pagetable need to be kept synchronized with the P2M */ #ifdef CONFIG_HAS_PASSTHROUGH