From patchwork Wed Sep 11 20:04:58 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Andrew Cooper X-Patchwork-Id: 11141853 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 D24A714E5 for ; Wed, 11 Sep 2019 20:07:37 +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 A19AA20838 for ; Wed, 11 Sep 2019 20:07:37 +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="eAczOgzI" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org A19AA20838 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 1i88rb-0002zh-5K; Wed, 11 Sep 2019 20:05:15 +0000 Received: from us1-rack-iad1.inumbo.com ([172.99.69.81]) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1i88rZ-0002zM-PW for xen-devel@lists.xenproject.org; Wed, 11 Sep 2019 20:05:13 +0000 X-Inumbo-ID: 761b2d20-d4cf-11e9-b299-bc764e2007e4 Received: from esa6.hc3370-68.iphmx.com (unknown [216.71.155.175]) by us1-rack-iad1.inumbo.com (Halon) with ESMTPS id 761b2d20-d4cf-11e9-b299-bc764e2007e4; Wed, 11 Sep 2019 20:05:12 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=citrix.com; s=securemail; t=1568232312; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=9Qy6fWZ039WeGD+8IdzKXaFvFd/qR+imJDVwqFqt+T4=; b=eAczOgzICp1fq14jdQOsEIcqisEelXM47xXQGk6VXnGEbuOylkElbem0 gh1HFT/1pvPqoigOh9aKor79k/bQm2LtCaRXRROFfJj2ASJNNbde8jMM7 9C9iKr9tXgJFL1+WmMmfQ2GJvUhSWMiq8sB6Az87dG67YqyI/DPsaNYQG o=; Authentication-Results: esa6.hc3370-68.iphmx.com; dkim=none (message not signed) header.i=none; spf=None smtp.pra=andrew.cooper3@citrix.com; spf=Pass smtp.mailfrom=Andrew.Cooper3@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 andrew.cooper3@citrix.com) identity=pra; client-ip=162.221.158.21; receiver=esa6.hc3370-68.iphmx.com; envelope-from="Andrew.Cooper3@citrix.com"; x-sender="andrew.cooper3@citrix.com"; x-conformance=sidf_compatible Received-SPF: Pass (esa6.hc3370-68.iphmx.com: domain of Andrew.Cooper3@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="Andrew.Cooper3@citrix.com"; x-sender="Andrew.Cooper3@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="Andrew.Cooper3@citrix.com"; x-sender="postmaster@mail.citrix.com"; x-conformance=sidf_compatible IronPort-SDR: tTtRTWjvKDz+ZurNtGiF2SpOjkw4oN+wk4kaP0jemPOKQ8J3MdZ9Xm/8ZiyB7jKU84Tv0+uoBV 7iiPd0Q/6YVDJXLf7Yr5o7Konsueu2V/DmyHrvMPonfRc3+hsl81BR7KLoB/S9QXGCscHJ+F4o V2CXiKm9HkPWepyT1kRjdAON9zmazkuFnvk2G/97W8I/RzDQDwgrsw5OyNJwCbKi5rSU+160/U UPBvIU30oGDyQ7KWlWcOUQa6xl8Osv2UW4PfF305DsN7N7mwRUlac6qx04hnYJVrgVT+X7K5ka 4u4= X-SBRS: 2.7 X-MesageID: 5695040 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,494,1559534400"; d="scan'208";a="5695040" From: Andrew Cooper To: Xen-devel Date: Wed, 11 Sep 2019 21:04:58 +0100 Message-ID: <20190911200504.5693-3-andrew.cooper3@citrix.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20190911200504.5693-1-andrew.cooper3@citrix.com> References: <20190911200504.5693-1-andrew.cooper3@citrix.com> MIME-Version: 1.0 Subject: [Xen-devel] [PATCH 2/8] x86/cpuid: Split update_domain_cpuid_info() in half 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: Andrew Cooper , Wei Liu , Jan Beulich , =?utf-8?q?Roger_Pau_Monn=C3=A9?= Errors-To: xen-devel-bounces@lists.xenproject.org Sender: "Xen-devel" update_domain_cpuid_info() currently serves two purposes. First to merge new CPUID data from the toolstack, and second, to perform any necessary updating of derived domain/vcpu settings. The first part of this is going to be superseded by a new and substantially more efficient hypercall. Carve the second part out into a new domain_cpu_policy_changed() helper, and call this from the remains of update_domain_cpuid_info(). This does drop the call_policy_changed, but with the new hypercall hypercall in place, the common case will be a single call per domain. Dropping the optimisation here allows for a cleaner set of following changes. Signed-off-by: Andrew Cooper Reviewed-by: Jan Beulich --- CC: Jan Beulich CC: Wei Liu CC: Roger Pau Monné --- xen/arch/x86/domctl.c | 245 ++++++++++++++++++++------------------------------ 1 file changed, 99 insertions(+), 146 deletions(-) diff --git a/xen/arch/x86/domctl.c b/xen/arch/x86/domctl.c index a744696c6b..d15ae066c3 100644 --- a/xen/arch/x86/domctl.c +++ b/xen/arch/x86/domctl.c @@ -46,101 +46,14 @@ static int gdbsx_guest_mem_io(domid_t domid, struct xen_domctl_gdbsx_memio *iop) return iop->remain ? -EFAULT : 0; } -static int update_domain_cpuid_info(struct domain *d, - const struct xen_domctl_cpuid *ctl) +static void domain_cpu_policy_changed(struct domain *d) { - struct cpuid_policy *p = d->arch.cpuid; - const struct cpuid_leaf leaf = { ctl->eax, ctl->ebx, ctl->ecx, ctl->edx }; - int old_vendor = p->x86_vendor; - unsigned int old_7d0 = p->feat.raw[0].d, old_e8b = p->extd.raw[8].b; - bool call_policy_changed = false; /* Avoid for_each_vcpu() unnecessarily */ - - /* - * Skip update for leaves we don't care about, to avoid the overhead of - * recalculate_cpuid_policy(). - */ - switch ( ctl->input[0] ) - { - case 0x00000000 ... ARRAY_SIZE(p->basic.raw) - 1: - if ( ctl->input[0] == 4 && - ctl->input[1] >= ARRAY_SIZE(p->cache.raw) ) - return 0; - - if ( ctl->input[0] == 7 && - ctl->input[1] >= ARRAY_SIZE(p->feat.raw) ) - return 0; - - if ( ctl->input[0] == 0xb && - ctl->input[1] >= ARRAY_SIZE(p->topo.raw) ) - return 0; - - BUILD_BUG_ON(ARRAY_SIZE(p->xstate.raw) < 2); - if ( ctl->input[0] == XSTATE_CPUID && - ctl->input[1] != 1 ) /* Everything else automatically calculated. */ - return 0; - break; - - case 0x40000000: case 0x40000100: - /* Only care about the max_leaf limit. */ - - case 0x80000000 ... 0x80000000 + ARRAY_SIZE(p->extd.raw) - 1: - break; - - default: - return 0; - } - - /* Insert ctl data into cpuid_policy. */ - switch ( ctl->input[0] ) - { - case 0x00000000 ... ARRAY_SIZE(p->basic.raw) - 1: - switch ( ctl->input[0] ) - { - case 4: - p->cache.raw[ctl->input[1]] = leaf; - break; - - case 7: - p->feat.raw[ctl->input[1]] = leaf; - break; - - case 0xb: - p->topo.raw[ctl->input[1]] = leaf; - break; - - case XSTATE_CPUID: - p->xstate.raw[ctl->input[1]] = leaf; - break; - - default: - p->basic.raw[ctl->input[0]] = leaf; - break; - } - break; - - case 0x40000000: - p->hv_limit = ctl->eax; - break; + const struct cpuid_policy *p = d->arch.cpuid; + struct vcpu *v; - case 0x40000100: - p->hv2_limit = ctl->eax; - break; - - case 0x80000000 ... 0x80000000 + ARRAY_SIZE(p->extd.raw) - 1: - p->extd.raw[ctl->input[0] - 0x80000000] = leaf; - break; - } - - recalculate_cpuid_policy(d); - - switch ( ctl->input[0] ) + if ( is_pv_domain(d) ) { - case 0: - call_policy_changed = (p->x86_vendor != old_vendor); - break; - - case 1: - if ( is_pv_domain(d) && ((levelling_caps & LCAP_1cd) == LCAP_1cd) ) + if ( ((levelling_caps & LCAP_1cd) == LCAP_1cd) ) { uint64_t mask = cpuidmask_defaults._1cd; uint32_t ecx = p->basic._1c; @@ -197,25 +110,18 @@ static int update_domain_cpuid_info(struct domain *d, d->arch.pv.cpuidmasks->_1cd = mask; } - break; - case 6: - if ( is_pv_domain(d) && ((levelling_caps & LCAP_6c) == LCAP_6c) ) + if ( ((levelling_caps & LCAP_6c) == LCAP_6c) ) { uint64_t mask = cpuidmask_defaults._6c; if ( boot_cpu_data.x86_vendor == X86_VENDOR_AMD ) - mask &= (~0ULL << 32) | ctl->ecx; + mask &= (~0ULL << 32) | p->basic.raw[6].c; d->arch.pv.cpuidmasks->_6c = mask; } - break; - - case 7: - if ( ctl->input[1] != 0 ) - break; - if ( is_pv_domain(d) && ((levelling_caps & LCAP_7ab0) == LCAP_7ab0) ) + if ( ((levelling_caps & LCAP_7ab0) == LCAP_7ab0) ) { uint64_t mask = cpuidmask_defaults._7ab0; @@ -232,35 +138,7 @@ static int update_domain_cpuid_info(struct domain *d, d->arch.pv.cpuidmasks->_7ab0 = mask; } - /* - * If the IBRS/IBPB policy has changed, we need to recalculate the MSR - * interception bitmaps. - */ - call_policy_changed = (is_hvm_domain(d) && - ((old_7d0 ^ p->feat.raw[0].d) & - (cpufeat_mask(X86_FEATURE_IBRSB) | - cpufeat_mask(X86_FEATURE_L1D_FLUSH)))); - break; - - case 0xa: - if ( boot_cpu_data.x86_vendor != X86_VENDOR_INTEL ) - break; - - /* If PMU version is zero then the guest doesn't have VPMU */ - if ( p->basic.pmu_version == 0 ) - { - struct vcpu *v; - - for_each_vcpu ( d, v ) - vpmu_destroy(v); - } - break; - - case 0xd: - if ( ctl->input[1] != 1 ) - break; - - if ( is_pv_domain(d) && ((levelling_caps & LCAP_Da1) == LCAP_Da1) ) + if ( ((levelling_caps & LCAP_Da1) == LCAP_Da1) ) { uint64_t mask = cpuidmask_defaults.Da1; uint32_t eax = p->xstate.Da1; @@ -270,10 +148,8 @@ static int update_domain_cpuid_info(struct domain *d, d->arch.pv.cpuidmasks->Da1 = mask; } - break; - case 0x80000001: - if ( is_pv_domain(d) && ((levelling_caps & LCAP_e1cd) == LCAP_e1cd) ) + if ( ((levelling_caps & LCAP_e1cd) == LCAP_e1cd) ) { uint64_t mask = cpuidmask_defaults.e1cd; uint32_t ecx = p->extd.e1c; @@ -317,27 +193,104 @@ static int update_domain_cpuid_info(struct domain *d, d->arch.pv.cpuidmasks->e1cd = mask; } + } + + for_each_vcpu( d, v ) + { + cpuid_policy_updated(v); + + /* If PMU version is zero then the guest doesn't have VPMU */ + if ( boot_cpu_data.x86_vendor == X86_VENDOR_INTEL && + p->basic.pmu_version == 0 ) + vpmu_destroy(v); + } +} + +static int update_domain_cpuid_info(struct domain *d, + const struct xen_domctl_cpuid *ctl) +{ + struct cpuid_policy *p = d->arch.cpuid; + const struct cpuid_leaf leaf = { ctl->eax, ctl->ebx, ctl->ecx, ctl->edx }; + + /* + * Skip update for leaves we don't care about, to avoid the overhead of + * recalculate_cpuid_policy(). + */ + switch ( ctl->input[0] ) + { + case 0x00000000 ... ARRAY_SIZE(p->basic.raw) - 1: + if ( ctl->input[0] == 4 && + ctl->input[1] >= ARRAY_SIZE(p->cache.raw) ) + return 0; + + if ( ctl->input[0] == 7 && + ctl->input[1] >= ARRAY_SIZE(p->feat.raw) ) + return 0; + + if ( ctl->input[0] == 0xb && + ctl->input[1] >= ARRAY_SIZE(p->topo.raw) ) + return 0; + + BUILD_BUG_ON(ARRAY_SIZE(p->xstate.raw) < 2); + if ( ctl->input[0] == XSTATE_CPUID && + ctl->input[1] != 1 ) /* Everything else automatically calculated. */ + return 0; break; - case 0x80000008: - /* - * If the IBPB policy has changed, we need to recalculate the MSR - * interception bitmaps. - */ - call_policy_changed = (is_hvm_domain(d) && - ((old_e8b ^ p->extd.raw[8].b) & - cpufeat_mask(X86_FEATURE_IBPB))); + case 0x40000000: case 0x40000100: + /* Only care about the max_leaf limit. */ + + case 0x80000000 ... 0x80000000 + ARRAY_SIZE(p->extd.raw) - 1: break; + + default: + return 0; } - if ( call_policy_changed ) + /* Insert ctl data into cpuid_policy. */ + switch ( ctl->input[0] ) { - struct vcpu *v; + case 0x00000000 ... ARRAY_SIZE(p->basic.raw) - 1: + switch ( ctl->input[0] ) + { + case 4: + p->cache.raw[ctl->input[1]] = leaf; + break; + + case 7: + p->feat.raw[ctl->input[1]] = leaf; + break; + + case 0xb: + p->topo.raw[ctl->input[1]] = leaf; + break; - for_each_vcpu( d, v ) - cpuid_policy_updated(v); + case XSTATE_CPUID: + p->xstate.raw[ctl->input[1]] = leaf; + break; + + default: + p->basic.raw[ctl->input[0]] = leaf; + break; + } + break; + + case 0x40000000: + p->hv_limit = ctl->eax; + break; + + case 0x40000100: + p->hv2_limit = ctl->eax; + break; + + case 0x80000000 ... 0x80000000 + ARRAY_SIZE(p->extd.raw) - 1: + p->extd.raw[ctl->input[0] - 0x80000000] = leaf; + break; } + recalculate_cpuid_policy(d); + domain_cpu_policy_changed(d); + return 0; } From patchwork Wed Sep 11 20:04:59 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Andrew Cooper X-Patchwork-Id: 11141847 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 2BB8914E5 for ; Wed, 11 Sep 2019 20:07:10 +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 EF5D520838 for ; Wed, 11 Sep 2019 20:07: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="Y/qAtP5R" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org EF5D520838 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 1i88rk-00030w-Ct; Wed, 11 Sep 2019 20:05:24 +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 1i88rj-00030Q-4o for xen-devel@lists.xenproject.org; Wed, 11 Sep 2019 20:05:23 +0000 X-Inumbo-ID: 77962363-d4cf-11e9-83dd-12813bfff9fa Received: from esa2.hc3370-68.iphmx.com (unknown [216.71.145.153]) by us1-amaz-eas2.inumbo.com (Halon) with ESMTPS id 77962363-d4cf-11e9-83dd-12813bfff9fa; Wed, 11 Sep 2019 20:05:14 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=citrix.com; s=securemail; t=1568232314; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=BIbnzCREkG77hGwoxZ3RMjH/adLjjec/0WbuotSainY=; b=Y/qAtP5RizTiEL+UN51Iu/6u8CO7vCdLHLmv9aMbKbOrRnEhQOztzP/8 6P3ROA2fhQMvTlyB/ugiIRDwoijFXQocIHgmnYagkOtnF+KYok1e1QGJ/ NhdWYL8o8Yrg8MQQYZplsMGvBEIMPll/s4aHJ3QT0drRygk74uEV1FKtV 4=; Authentication-Results: esa2.hc3370-68.iphmx.com; dkim=none (message not signed) header.i=none; spf=None smtp.pra=andrew.cooper3@citrix.com; spf=Pass smtp.mailfrom=Andrew.Cooper3@citrix.com; spf=None smtp.helo=postmaster@mail.citrix.com Received-SPF: None (esa2.hc3370-68.iphmx.com: no sender authenticity information available from domain of andrew.cooper3@citrix.com) identity=pra; client-ip=162.221.158.21; receiver=esa2.hc3370-68.iphmx.com; envelope-from="Andrew.Cooper3@citrix.com"; x-sender="andrew.cooper3@citrix.com"; x-conformance=sidf_compatible Received-SPF: Pass (esa2.hc3370-68.iphmx.com: domain of Andrew.Cooper3@citrix.com designates 162.221.158.21 as permitted sender) identity=mailfrom; client-ip=162.221.158.21; receiver=esa2.hc3370-68.iphmx.com; envelope-from="Andrew.Cooper3@citrix.com"; x-sender="Andrew.Cooper3@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 (esa2.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=esa2.hc3370-68.iphmx.com; envelope-from="Andrew.Cooper3@citrix.com"; x-sender="postmaster@mail.citrix.com"; x-conformance=sidf_compatible IronPort-SDR: iC/85lOS97iYbHxeP+m/voeXswq+JeYqBhLHZ/p93Cik7QXsMus2dDB8dA9+Yiyd4153Ec55UB 9ppGVUz3JoKeb6+ox7U6TOrlfKkAWjWAVmcXkIabxGL5lrTSCV56+Y1iSaFN45k60gWgU/4A2r vqtyNGrbzeL+OxXgXTMtTrkyVatnTfu+vxvbINgD1ytNMJEZNu8biYVsNUjYaAG1XSDqrydOKR gSK9pYZgEGQ2JK3aqAyUOCMJOoDznNrVdvbqcwe/AMLgy9bsXPW1Bsp6ddbEvWK3b57SH1+xoI 7jI= X-SBRS: 2.7 X-MesageID: 5451848 X-Ironport-Server: esa2.hc3370-68.iphmx.com X-Remote-IP: 162.221.158.21 X-Policy: $RELAYED X-IronPort-AV: E=Sophos;i="5.64,494,1559534400"; d="scan'208";a="5451848" From: Andrew Cooper To: Xen-devel Date: Wed, 11 Sep 2019 21:04:59 +0100 Message-ID: <20190911200504.5693-4-andrew.cooper3@citrix.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20190911200504.5693-1-andrew.cooper3@citrix.com> References: <20190911200504.5693-1-andrew.cooper3@citrix.com> MIME-Version: 1.0 Subject: [Xen-devel] [PATCH 3/8] x86/domctl: Implement XEN_DOMCTL_set_cpumsr_policy 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: Sergey Dyasli , Wei Liu , Andrew Cooper , Ian Jackson , Jan Beulich , Daniel De Graaf , =?utf-8?q?Roger_Pau_Monn=C3=A9?= Errors-To: xen-devel-bounces@lists.xenproject.org Sender: "Xen-devel" This hypercall allows the toolstack to present one combined CPUID and MSR policy for a domain, which can be audited in one go by Xen, which is necessary for correctness of the auditing. Reuse the existing set_cpuid XSM access vector, as this is logically the same operation. As x86_cpu_policies_are_compatible() is still only a stub, retain the call to recalculate_cpuid_policy() to discard unsafe toolstack settings. Signed-off-by: Andrew Cooper Signed-off-by: Sergey Dyasli Signed-off-by: Roger Pau Monné Reviewed-by: Jan Beulich --- CC: Jan Beulich CC: Ian Jackson CC: Wei Liu CC: Roger Pau Monné CC: Daniel De Graaf --- tools/libxc/include/xenctrl.h | 5 +++ tools/libxc/xc_cpuid_x86.c | 49 +++++++++++++++++++++++ xen/arch/x86/domctl.c | 80 +++++++++++++++++++++++++++++++++++++ xen/include/public/domctl.h | 15 +++++-- xen/xsm/flask/hooks.c | 1 + xen/xsm/flask/policy/access_vectors | 1 + 6 files changed, 147 insertions(+), 4 deletions(-) diff --git a/tools/libxc/include/xenctrl.h b/tools/libxc/include/xenctrl.h index 7559e1bc69..e47778535d 100644 --- a/tools/libxc/include/xenctrl.h +++ b/tools/libxc/include/xenctrl.h @@ -2530,6 +2530,11 @@ int xc_get_system_cpu_policy(xc_interface *xch, uint32_t index, int xc_get_domain_cpu_policy(xc_interface *xch, uint32_t domid, uint32_t *nr_leaves, xen_cpuid_leaf_t *leaves, uint32_t *nr_msrs, xen_msr_entry_t *msrs); +int xc_set_domain_cpu_policy(xc_interface *xch, uint32_t domid, + uint32_t nr_leaves, xen_cpuid_leaf_t *leaves, + uint32_t nr_msrs, xen_msr_entry_t *msrs, + uint32_t *err_leaf_p, uint32_t *err_subleaf_p, + uint32_t *err_msr_idx_p); uint32_t xc_get_cpu_featureset_size(void); diff --git a/tools/libxc/xc_cpuid_x86.c b/tools/libxc/xc_cpuid_x86.c index b829336082..33b9e9fc85 100644 --- a/tools/libxc/xc_cpuid_x86.c +++ b/tools/libxc/xc_cpuid_x86.c @@ -229,6 +229,55 @@ int xc_get_domain_cpu_policy(xc_interface *xch, uint32_t domid, return ret; } +int xc_set_domain_cpu_policy(xc_interface *xch, uint32_t domid, + uint32_t nr_leaves, xen_cpuid_leaf_t *leaves, + uint32_t nr_msrs, xen_msr_entry_t *msrs, + uint32_t *err_leaf_p, uint32_t *err_subleaf_p, + uint32_t *err_msr_idx_p) +{ + DECLARE_DOMCTL; + DECLARE_HYPERCALL_BOUNCE(leaves, + nr_leaves * sizeof(*leaves), + XC_HYPERCALL_BUFFER_BOUNCE_IN); + DECLARE_HYPERCALL_BOUNCE(msrs, + nr_msrs * sizeof(*msrs), + XC_HYPERCALL_BUFFER_BOUNCE_IN); + int ret; + + if ( xc_hypercall_bounce_pre(xch, leaves) ) + return -1; + + if ( xc_hypercall_bounce_pre(xch, msrs) ) + return -1; + + domctl.cmd = XEN_DOMCTL_set_cpu_policy; + domctl.domain = domid; + domctl.u.cpu_policy.nr_leaves = nr_leaves; + set_xen_guest_handle(domctl.u.cpu_policy.cpuid_policy, leaves); + domctl.u.cpu_policy.nr_msrs = nr_msrs; + set_xen_guest_handle(domctl.u.cpu_policy.msr_policy, msrs); + domctl.u.cpu_policy.err_leaf = ~0; + domctl.u.cpu_policy.err_subleaf = ~0; + domctl.u.cpu_policy.err_msr_idx = ~0; + + ret = do_domctl(xch, &domctl); + + xc_hypercall_bounce_post(xch, leaves); + xc_hypercall_bounce_post(xch, msrs); + + if ( ret ) + { + if ( err_leaf_p ) + *err_leaf_p = domctl.u.cpu_policy.err_leaf; + if ( err_subleaf_p ) + *err_subleaf_p = domctl.u.cpu_policy.err_subleaf; + if ( err_msr_idx_p ) + *err_msr_idx_p = domctl.u.cpu_policy.err_msr_idx; + } + + return ret; +} + struct cpuid_domain_info { unsigned int vendor; /* X86_VENDOR_* */ diff --git a/xen/arch/x86/domctl.c b/xen/arch/x86/domctl.c index d15ae066c3..99bc2fb10d 100644 --- a/xen/arch/x86/domctl.c +++ b/xen/arch/x86/domctl.c @@ -294,6 +294,65 @@ static int update_domain_cpuid_info(struct domain *d, return 0; } +static int update_domain_cpu_policy(struct domain *d, + xen_domctl_cpu_policy_t *xdpc) +{ + struct cpu_policy new = {}; + const struct cpu_policy *sys = is_pv_domain(d) + ? &system_policies[XEN_SYSCTL_cpu_policy_pv_max] + : &system_policies[XEN_SYSCTL_cpu_policy_hvm_max]; + struct cpu_policy_errors err = INIT_CPU_POLICY_ERRORS; + int ret = -ENOMEM; + + /* Start by copying the domain's existing policies. */ + if ( !(new.cpuid = xmemdup(d->arch.cpuid)) || + !(new.msr = xmemdup(d->arch.msr)) ) + goto out; + + /* Merge the toolstack provided data. */ + if ( (ret = x86_cpuid_copy_from_buffer( + new.cpuid, xdpc->cpuid_policy, xdpc->nr_leaves, + &err.leaf, &err.subleaf)) || + (ret = x86_msr_copy_from_buffer( + new.msr, xdpc->msr_policy, xdpc->nr_msrs, &err.msr)) ) + goto out; + + /* Trim any newly-stale out-of-range leaves. */ + x86_cpuid_policy_clear_out_of_range_leaves(new.cpuid); + + /* Audit the combined dataset. */ + ret = x86_cpu_policies_are_compatible(sys, &new, &err); + if ( ret ) + goto out; + + /* + * Audit was successful. Replace existing policies, leaving the old + * policies to be freed. + */ + SWAP(new.cpuid, d->arch.cpuid); + SWAP(new.msr, d->arch.msr); + + /* TODO: Drop when x86_cpu_policies_are_compatible() is completed. */ + recalculate_cpuid_policy(d); + + /* Recalculate relevant dom/vcpu state now the policy has changed. */ + domain_cpu_policy_changed(d); + + out: + /* Free whichever cpuid/msr structs are not installed in struct domain. */ + xfree(new.cpuid); + xfree(new.msr); + + if ( ret ) + { + xdpc->err_leaf = err.leaf; + xdpc->err_subleaf = err.subleaf; + xdpc->err_msr_idx = err.msr; + } + + return ret; +} + static int vcpu_set_vmce(struct vcpu *v, const struct xen_domctl_ext_vcpucontext *evc) { @@ -1476,6 +1535,27 @@ long arch_do_domctl( copyback = true; break; + case XEN_DOMCTL_set_cpu_policy: + if ( d == currd ) /* No domain_pause() */ + { + ret = -EINVAL; + break; + } + + domain_pause(d); + + if ( d->creation_finished ) + ret = -EEXIST; /* No changing once the domain is running. */ + else + { + ret = update_domain_cpu_policy(d, &domctl->u.cpu_policy); + if ( ret ) /* Copy domctl->u.cpu_policy.err_* to guest. */ + copyback = true; + } + + domain_unpause(d); + break; + default: ret = iommu_do_domctl(domctl, d, u_domctl); break; diff --git a/xen/include/public/domctl.h b/xen/include/public/domctl.h index 77f546cbb8..0471d3c680 100644 --- a/xen/include/public/domctl.h +++ b/xen/include/public/domctl.h @@ -658,17 +658,23 @@ struct xen_domctl_cpuid { }; /* - * XEN_DOMCTL_get_cpu_policy (x86 specific) + * XEN_DOMCTL_{get,set}_cpu_policy (x86 specific) * - * Query the CPUID and MSR policies for a specific domain. + * Query or set the CPUID and MSR policies for a specific domain. */ struct xen_domctl_cpu_policy { uint32_t nr_leaves; /* IN/OUT: Number of leaves in/written to * 'cpuid_policy'. */ uint32_t nr_msrs; /* IN/OUT: Number of MSRs in/written to * 'msr_domain_policy' */ - XEN_GUEST_HANDLE_64(xen_cpuid_leaf_t) cpuid_policy; /* OUT */ - XEN_GUEST_HANDLE_64(xen_msr_entry_t) msr_policy; /* OUT */ + XEN_GUEST_HANDLE_64(xen_cpuid_leaf_t) cpuid_policy; /* IN/OUT */ + XEN_GUEST_HANDLE_64(xen_msr_entry_t) msr_policy; /* IN/OUT */ + uint32_t err_leaf, err_subleaf; /* OUT, set_policy only. If not ~0, + * indicates the leaf/subleaf which + * auditing objected to. */ + uint32_t err_msr_idx; /* OUT, set_policy only. If not ~0, + * indicates the MSR idx which + * auditing objected to. */ }; typedef struct xen_domctl_cpu_policy xen_domctl_cpu_policy_t; DEFINE_XEN_GUEST_HANDLE(xen_domctl_cpu_policy_t); @@ -1193,6 +1199,7 @@ struct xen_domctl { /* #define XEN_DOMCTL_set_gnttab_limits 80 - Moved into XEN_DOMCTL_createdomain */ #define XEN_DOMCTL_vuart_op 81 #define XEN_DOMCTL_get_cpu_policy 82 +#define XEN_DOMCTL_set_cpu_policy 83 #define XEN_DOMCTL_gdbsx_guestmemio 1000 #define XEN_DOMCTL_gdbsx_pausevcpu 1001 #define XEN_DOMCTL_gdbsx_unpausevcpu 1002 diff --git a/xen/xsm/flask/hooks.c b/xen/xsm/flask/hooks.c index 6800f2d9a0..b23772786a 100644 --- a/xen/xsm/flask/hooks.c +++ b/xen/xsm/flask/hooks.c @@ -715,6 +715,7 @@ static int flask_domctl(struct domain *d, int cmd) case XEN_DOMCTL_set_virq_handler: return current_has_perm(d, SECCLASS_DOMAIN, DOMAIN__SET_VIRQ_HANDLER); + case XEN_DOMCTL_set_cpu_policy: case XEN_DOMCTL_set_cpuid: return current_has_perm(d, SECCLASS_DOMAIN2, DOMAIN2__SET_CPUID); diff --git a/xen/xsm/flask/policy/access_vectors b/xen/xsm/flask/policy/access_vectors index 76f3d60ddd..6f3f9493f8 100644 --- a/xen/xsm/flask/policy/access_vectors +++ b/xen/xsm/flask/policy/access_vectors @@ -207,6 +207,7 @@ class domain2 # source = the domain making the hypercall # target = the new target domain set_as_target +# XEN_DOMCTL_set_cpu_policy # XEN_DOMCTL_set_cpuid set_cpuid # XEN_DOMCTL_gettscinfo From patchwork Wed Sep 11 20:05:00 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Andrew Cooper X-Patchwork-Id: 11141849 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 6403717E6 for ; Wed, 11 Sep 2019 20:07:28 +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 3EE8420838 for ; Wed, 11 Sep 2019 20:07:28 +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="ZonA4OKy" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 3EE8420838 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 1i88rj-00030W-Ri; Wed, 11 Sep 2019 20:05:23 +0000 Received: from us1-rack-iad1.inumbo.com ([172.99.69.81]) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1i88ri-00030J-KR for xen-devel@lists.xenproject.org; Wed, 11 Sep 2019 20:05:22 +0000 X-Inumbo-ID: 7be61c7e-d4cf-11e9-978d-bc764e2007e4 Received: from esa4.hc3370-68.iphmx.com (unknown [216.71.155.144]) by us1-rack-iad1.inumbo.com (Halon) with ESMTPS id 7be61c7e-d4cf-11e9-978d-bc764e2007e4; Wed, 11 Sep 2019 20:05:21 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=citrix.com; s=securemail; t=1568232321; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=5mwy1x2NvpEAJcMZSDwwXuBx23b+MiSxgOml7mKLXH8=; b=ZonA4OKyao3OBNU7aqKvlxaKsK+mlY6mwnmYOhG3kQIcKRGPqmfjmYUk dsFzw9irY9wtl311oFW3eowKIfoZQH2ufQVLZGoAzwP7dHxZZ5uTp6pcm 1xli73fbunqh9OiUlniXw2Gj/S5Ahr8tPi0+E5QbDl3mqQwG0QtTmGYjZ c=; Authentication-Results: esa4.hc3370-68.iphmx.com; dkim=none (message not signed) header.i=none; spf=None smtp.pra=andrew.cooper3@citrix.com; spf=Pass smtp.mailfrom=Andrew.Cooper3@citrix.com; spf=None smtp.helo=postmaster@mail.citrix.com Received-SPF: None (esa4.hc3370-68.iphmx.com: no sender authenticity information available from domain of andrew.cooper3@citrix.com) identity=pra; client-ip=162.221.158.21; receiver=esa4.hc3370-68.iphmx.com; envelope-from="Andrew.Cooper3@citrix.com"; x-sender="andrew.cooper3@citrix.com"; x-conformance=sidf_compatible Received-SPF: Pass (esa4.hc3370-68.iphmx.com: domain of Andrew.Cooper3@citrix.com designates 162.221.158.21 as permitted sender) identity=mailfrom; client-ip=162.221.158.21; receiver=esa4.hc3370-68.iphmx.com; envelope-from="Andrew.Cooper3@citrix.com"; x-sender="Andrew.Cooper3@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 (esa4.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=esa4.hc3370-68.iphmx.com; envelope-from="Andrew.Cooper3@citrix.com"; x-sender="postmaster@mail.citrix.com"; x-conformance=sidf_compatible IronPort-SDR: 9aRAf2ARsQVOzObqupFfxU3QpYt4Vs/I9oSKXX3xWLakzEzIq1AfhtKQmVi2gdYLMT/E5eos2L 6ebiRzc5rMuWKHDM3k09OXXPDqf0G8wouNIieQ/BF0g8mjHTivNEw1JN1LkUSSB6MySgF+f/yi 9qAudeJ2jE25M/musySF6AZ8rCeoEJkPGHf+56QOn0PlUgUFR9RZ5qiBsLcv8Eh13jQRO5OMBG F6nVfM1/f7cu0/AGYfhvAeOEkq90BAEYUeL7HiJika2RaqgoVBzq1NuYvICS/XrdQNWfXJiklp Upk= X-SBRS: 2.7 X-MesageID: 5742443 X-Ironport-Server: esa4.hc3370-68.iphmx.com X-Remote-IP: 162.221.158.21 X-Policy: $RELAYED X-IronPort-AV: E=Sophos;i="5.64,494,1559534400"; d="scan'208";a="5742443" From: Andrew Cooper To: Xen-devel Date: Wed, 11 Sep 2019 21:05:00 +0100 Message-ID: <20190911200504.5693-5-andrew.cooper3@citrix.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20190911200504.5693-1-andrew.cooper3@citrix.com> References: <20190911200504.5693-1-andrew.cooper3@citrix.com> MIME-Version: 1.0 Subject: [Xen-devel] [PATCH 4/8] tools/libxc: Pre-cleanup for xc_cpuid_{set, apply_policy}() 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: Andrew Cooper , Ian Jackson , Wei Liu , Jan Beulich , =?utf-8?q?Roger_Pau_Monn=C3=A9?= Errors-To: xen-devel-bounces@lists.xenproject.org Sender: "Xen-devel" This patch is broken out just to simplify the following two. For xc_cpuid_set(), document how the 'k' works because it is quite subtle. Replace a memset() with weird calculation for a loop of 4 explicit NULL assigments. This mirrors the free()'s in the fail path. For xc_cpuid_apply_policy(), const-ify the featureset pointer. It isn't written to, and was never intended to be mutable. Drop three pieces of trailing whitespace. No functional change. Signed-off-by: Andrew Cooper Reviewed-by: Jan Beulich --- CC: Jan Beulich CC: Wei Liu CC: Roger Pau Monné CC: Ian Jackson --- tools/libxc/include/xenctrl.h | 2 +- tools/libxc/xc_cpuid_x86.c | 21 ++++++++++++++------- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/tools/libxc/include/xenctrl.h b/tools/libxc/include/xenctrl.h index e47778535d..2419a47f22 100644 --- a/tools/libxc/include/xenctrl.h +++ b/tools/libxc/include/xenctrl.h @@ -1800,7 +1800,7 @@ int xc_cpuid_set(xc_interface *xch, char **config_transformed); int xc_cpuid_apply_policy(xc_interface *xch, uint32_t domid, - uint32_t *featureset, + const uint32_t *featureset, unsigned int nr_features); int xc_mca_op(xc_interface *xch, struct xen_mc *mc); int xc_mca_op_inject_v2(xc_interface *xch, unsigned int flags, diff --git a/tools/libxc/xc_cpuid_x86.c b/tools/libxc/xc_cpuid_x86.c index 33b9e9fc85..a2d29a0fae 100644 --- a/tools/libxc/xc_cpuid_x86.c +++ b/tools/libxc/xc_cpuid_x86.c @@ -1,5 +1,5 @@ /****************************************************************************** - * xc_cpuid_x86.c + * xc_cpuid_x86.c * * Compute cpuid of a domain. * @@ -332,7 +332,7 @@ static void cpuid(const unsigned int *input, unsigned int *regs) static int get_cpuid_domain_info(xc_interface *xch, uint32_t domid, struct cpuid_domain_info *info, - uint32_t *featureset, + const uint32_t *featureset, unsigned int nr_features) { struct xen_domctl domctl = {}; @@ -807,8 +807,7 @@ static void sanitise_featureset(struct cpuid_domain_info *info) } int xc_cpuid_apply_policy(xc_interface *xch, uint32_t domid, - uint32_t *featureset, - unsigned int nr_features) + const uint32_t *featureset, unsigned int nr_features) { struct cpuid_domain_info info = {}; unsigned int input[2] = { 0, 0 }, regs[4]; @@ -898,7 +897,7 @@ int xc_cpuid_apply_policy(xc_interface *xch, uint32_t domid, * 'k' -> pass through host value * 's' -> pass through the first time and then keep the same value * across save/restore and migration. - * + * * For 's' and 'x' the configuration is overwritten with the value applied. */ int xc_cpuid_set( @@ -909,7 +908,8 @@ int xc_cpuid_set( unsigned int i, j, regs[4], polregs[4]; struct cpuid_domain_info info = {}; - memset(config_transformed, 0, 4 * sizeof(*config_transformed)); + for ( i = 0; i < 4; ++i ) + config_transformed[i] = NULL; rc = get_cpuid_domain_info(xch, domid, &info, NULL, 0); if ( rc ) @@ -927,7 +927,7 @@ int xc_cpuid_set( regs[i] = polregs[i]; continue; } - + config_transformed[i] = calloc(33, 1); /* 32 bits, NUL terminator. */ if ( config_transformed[i] == NULL ) { @@ -935,6 +935,13 @@ int xc_cpuid_set( goto fail; } + /* + * Notes for following this algorithm: + * + * While it will accept any leaf data, it only makes sense to use on + * feature leaves. regs[] initially contains the host values. This, + * with the fall-through chain is how the 'k' option works. + */ for ( j = 0; j < 32; j++ ) { unsigned char val = !!((regs[i] & (1U << (31 - j)))); From patchwork Wed Sep 11 20:05:01 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Andrew Cooper X-Patchwork-Id: 11141839 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 5DA4A17E6 for ; Wed, 11 Sep 2019 20:07:05 +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 37C802085B for ; Wed, 11 Sep 2019 20:07:05 +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="Fb6x6l7G" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 37C802085B 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 1i88rf-000301-GT; Wed, 11 Sep 2019 20:05:19 +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 1i88re-0002zv-4q for xen-devel@lists.xenproject.org; Wed, 11 Sep 2019 20:05:18 +0000 X-Inumbo-ID: 76dcce3b-d4cf-11e9-83dd-12813bfff9fa Received: from esa2.hc3370-68.iphmx.com (unknown [216.71.145.153]) by us1-amaz-eas2.inumbo.com (Halon) with ESMTPS id 76dcce3b-d4cf-11e9-83dd-12813bfff9fa; Wed, 11 Sep 2019 20:05:13 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=citrix.com; s=securemail; t=1568232314; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=Vf1AG29drMqw2LT/Z66r4aJJqf5+EsSaB0/oRaGhy1U=; b=Fb6x6l7GhTtLYwIetbfFRQlzkbgUyg6bqmtagtEDAUifZ/XM6EbUURgv UiLUDy5iGMPw1rvtvLxPukM15ApHR3IXdeIJyelWrGwdFF6mtvKF7k9WP Ka5Q7Q89WRiCS2PIfZUebHb41Yn1omUlRID0Su2LvPpJvynrG2fhYSrmD M=; Authentication-Results: esa2.hc3370-68.iphmx.com; dkim=none (message not signed) header.i=none; spf=None smtp.pra=andrew.cooper3@citrix.com; spf=Pass smtp.mailfrom=Andrew.Cooper3@citrix.com; spf=None smtp.helo=postmaster@mail.citrix.com Received-SPF: None (esa2.hc3370-68.iphmx.com: no sender authenticity information available from domain of andrew.cooper3@citrix.com) identity=pra; client-ip=162.221.158.21; receiver=esa2.hc3370-68.iphmx.com; envelope-from="Andrew.Cooper3@citrix.com"; x-sender="andrew.cooper3@citrix.com"; x-conformance=sidf_compatible Received-SPF: Pass (esa2.hc3370-68.iphmx.com: domain of Andrew.Cooper3@citrix.com designates 162.221.158.21 as permitted sender) identity=mailfrom; client-ip=162.221.158.21; receiver=esa2.hc3370-68.iphmx.com; envelope-from="Andrew.Cooper3@citrix.com"; x-sender="Andrew.Cooper3@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 (esa2.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=esa2.hc3370-68.iphmx.com; envelope-from="Andrew.Cooper3@citrix.com"; x-sender="postmaster@mail.citrix.com"; x-conformance=sidf_compatible IronPort-SDR: +nKyXPXKqy3lx81FteDEfZSU9DIo1LYIMo+nWZao9CWra4UpLmTBCdgMMtCiWqVUE0P0VfMQ9P Fwr7JQz2ywdM8lDwSJIs/4YM6nh8Cex8eJ8wv+1wZT1xEAMoEQeBM6TKQ9hoRadptEJYGeZtHU exFt891zTg7MDwErmVyJNoiJHeVhCtTOyBM8qZLOsObF+GLaWrN93Y9146dqCQX9sZEwCVU5Ti pzZ/83z1EkFCk1jCJSa1PCGIHrLObPrv9XqCjKtwfGl+a9/baIvSOOFfI+UhMhohuqdy7j19OU 1q4= X-SBRS: 2.7 X-MesageID: 5451849 X-Ironport-Server: esa2.hc3370-68.iphmx.com X-Remote-IP: 162.221.158.21 X-Policy: $RELAYED X-IronPort-AV: E=Sophos;i="5.64,494,1559534400"; d="scan'208";a="5451849" From: Andrew Cooper To: Xen-devel Date: Wed, 11 Sep 2019 21:05:01 +0100 Message-ID: <20190911200504.5693-6-andrew.cooper3@citrix.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20190911200504.5693-1-andrew.cooper3@citrix.com> References: <20190911200504.5693-1-andrew.cooper3@citrix.com> MIME-Version: 1.0 Subject: [Xen-devel] [PATCH 5/8] tools/libxc: Rework xc_cpuid_set() to use {get, set}_cpu_policy() 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: Andrew Cooper , Ian Jackson , Wei Liu , Jan Beulich , =?utf-8?q?Roger_Pau_Monn=C3=A9?= Errors-To: xen-devel-bounces@lists.xenproject.org Sender: "Xen-devel" The purpose of this change is to stop using xc_cpuid_do_domctl(), and to stop basing decisions on a local CPUID instruction. This is not an appropriate way to construct policy information for other domains. Obtain the host and domain-max policies from Xen, and mix the results as before. Provide rather more error logging than before. Signed-off-by: Andrew Cooper Reviewed-by: Jan Beulich --- CC: Jan Beulich CC: Wei Liu CC: Roger Pau Monné CC: Ian Jackson --- tools/libxc/xc_cpuid_x86.c | 95 ++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 84 insertions(+), 11 deletions(-) diff --git a/tools/libxc/xc_cpuid_x86.c b/tools/libxc/xc_cpuid_x86.c index a2d29a0fae..d1a2b61214 100644 --- a/tools/libxc/xc_cpuid_x86.c +++ b/tools/libxc/xc_cpuid_x86.c @@ -905,20 +905,80 @@ int xc_cpuid_set( const char **config, char **config_transformed) { int rc; - unsigned int i, j, regs[4], polregs[4]; - struct cpuid_domain_info info = {}; + unsigned int i, j, regs[4] = {}, polregs[4] = {}; + xc_dominfo_t di; + xen_cpuid_leaf_t *leaves = NULL; + unsigned int nr_leaves, policy_leaves, nr_msrs; + uint32_t err_leaf = -1, err_subleaf = -1, err_msr = -1; for ( i = 0; i < 4; ++i ) config_transformed[i] = NULL; - rc = get_cpuid_domain_info(xch, domid, &info, NULL, 0); + if ( xc_domain_getinfo(xch, domid, 1, &di) != 1 || + di.domid != domid ) + { + ERROR("Failed to obtain d%d info", domid); + rc = -ESRCH; + goto fail; + } + + rc = xc_get_cpu_policy_size(xch, &nr_leaves, &nr_msrs); if ( rc ) - goto out; + { + PERROR("Failed to obtain policy info size"); + rc = -errno; + goto fail; + } - cpuid(input, regs); + rc = -ENOMEM; + if ( (leaves = calloc(nr_leaves, sizeof(*leaves))) == NULL ) + { + ERROR("Unable to allocate memory for %u CPUID leaves", nr_leaves); + goto fail; + } - memcpy(polregs, regs, sizeof(regs)); - xc_cpuid_policy(&info, input, polregs); + /* Get the domain's max policy. */ + nr_msrs = 0; + policy_leaves = nr_leaves; + rc = xc_get_system_cpu_policy(xch, di.hvm ? XEN_SYSCTL_cpu_policy_hvm_max + : XEN_SYSCTL_cpu_policy_pv_max, + &policy_leaves, leaves, &nr_msrs, NULL); + if ( rc ) + { + PERROR("Failed to obtain %s max policy", di.hvm ? "hvm" : "pv"); + rc = -errno; + goto fail; + } + for ( i = 0; i < policy_leaves; ++i ) + if ( leaves[i].leaf == input[0] && leaves[i].subleaf == input[1] ) + { + polregs[0] = leaves[i].a; + polregs[1] = leaves[i].b; + polregs[2] = leaves[i].c; + polregs[3] = leaves[i].d; + break; + } + + /* Get the host policy. */ + nr_msrs = 0; + policy_leaves = nr_leaves; + rc = xc_get_system_cpu_policy(xch, XEN_SYSCTL_cpu_policy_host, + &policy_leaves, leaves, &nr_msrs, NULL); + if ( rc ) + { + PERROR("Failed to obtain host policy"); + rc = -errno; + goto fail; + } + for ( i = 0; i < policy_leaves; ++i ) + if ( leaves[i].leaf == input[0] && leaves[i].subleaf == input[1] ) + { + regs[0] = leaves[i].a; + regs[1] = leaves[i].b; + regs[2] = leaves[i].c; + regs[3] = leaves[i].d; + break; + } for ( i = 0; i < 4; i++ ) { @@ -969,9 +1029,21 @@ int xc_cpuid_set( } } - rc = xc_cpuid_do_domctl(xch, domid, input, regs); - if ( rc == 0 ) - goto out; + /* Feed the transformed leaf back up to Xen. */ + leaves[0] = (xen_cpuid_leaf_t){ input[0], input[1], + regs[0], regs[1], regs[2], regs[3] }; + rc = xc_set_domain_cpu_policy(xch, domid, 1, leaves, 0, NULL, + &err_leaf, &err_subleaf, &err_msr); + if ( rc ) + { + PERROR("Failed to set d%d's policy (err leaf %#x, subleaf %#x, msr %#x)", + domid, err_leaf, err_subleaf, err_msr); + rc = -errno; + goto fail; + } + + /* Success! */ + goto out; fail: for ( i = 0; i < 4; i++ ) @@ -981,6 +1053,7 @@ int xc_cpuid_set( } out: - free_cpuid_domain_info(&info); + free(leaves); + return rc; } From patchwork Wed Sep 11 20:05:02 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Andrew Cooper X-Patchwork-Id: 11141855 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 B79E214E5 for ; Wed, 11 Sep 2019 20:07:38 +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 7B46920838 for ; Wed, 11 Sep 2019 20:07:38 +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="Nm73tg88" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 7B46920838 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 1i88rp-00032W-PL; Wed, 11 Sep 2019 20:05:29 +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 1i88ro-00031l-4w for xen-devel@lists.xenproject.org; Wed, 11 Sep 2019 20:05:28 +0000 X-Inumbo-ID: 77eb7678-d4cf-11e9-83dd-12813bfff9fa Received: from esa1.hc3370-68.iphmx.com (unknown [216.71.145.142]) by us1-amaz-eas2.inumbo.com (Halon) with ESMTPS id 77eb7678-d4cf-11e9-83dd-12813bfff9fa; Wed, 11 Sep 2019 20:05:14 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=citrix.com; s=securemail; t=1568232315; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=GlV4lkCRyDHeXhLWqes45S1ALyFSuCNDXCGmddoW7LU=; b=Nm73tg88JszplMdPIiE5xRgo+BRSv3/ahFt08urFW9StiUX7kCN8zUAx 1c60xTMI7c8/tD+rRkrGftJXUFzk9bU6BroZ5FFFY0yhnhzhIaNkwKY0M i7Ql0aobpxQgOgbfHRrY9Gfwagn6v9Cbc+thM+RsYppmMXXDAjbzTFsQS U=; Authentication-Results: esa1.hc3370-68.iphmx.com; dkim=none (message not signed) header.i=none; spf=None smtp.pra=andrew.cooper3@citrix.com; spf=Pass smtp.mailfrom=Andrew.Cooper3@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 andrew.cooper3@citrix.com) identity=pra; client-ip=162.221.158.21; receiver=esa1.hc3370-68.iphmx.com; envelope-from="Andrew.Cooper3@citrix.com"; x-sender="andrew.cooper3@citrix.com"; x-conformance=sidf_compatible Received-SPF: Pass (esa1.hc3370-68.iphmx.com: domain of Andrew.Cooper3@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="Andrew.Cooper3@citrix.com"; x-sender="Andrew.Cooper3@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="Andrew.Cooper3@citrix.com"; x-sender="postmaster@mail.citrix.com"; x-conformance=sidf_compatible IronPort-SDR: sB2upHIq7COupJ7AdIKNAWIp8qwjNY5AULf5XRGRUDzpU8k5caTFT3/Vw7EaL8QaDWQhoYbQfD 44vuCleTaTRTHFzuOAdbbw5LIWTLHyfbBVOnSiSif0GOOogtWhnXfS8hgVGMH8ksfuzuRM8+0l 8KdtuVB+PTVKOnq5YcLmV/GcjSq6bgCkY6iXRe3a2XkaClo+hEFqMuI/Jmqq8mC6bxUS/+tTZX 9qaGpjSUlMPi+xmj4rsaPLZOZhENiwAngyHT5VpAxQne2+xXwCj9LZdV6NeSa/Dg2N0KfVIqLA Io4= X-SBRS: 2.7 X-MesageID: 5506247 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,494,1559534400"; d="scan'208";a="5506247" From: Andrew Cooper To: Xen-devel Date: Wed, 11 Sep 2019 21:05:02 +0100 Message-ID: <20190911200504.5693-7-andrew.cooper3@citrix.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20190911200504.5693-1-andrew.cooper3@citrix.com> References: <20190911200504.5693-1-andrew.cooper3@citrix.com> MIME-Version: 1.0 Subject: [Xen-devel] [PATCH 6/8] tools/libxc: Rework xc_cpuid_apply_policy() to use {get, set}_cpu_policy() 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: Andrew Cooper , Ian Jackson , Wei Liu , Jan Beulich , =?utf-8?q?Roger_Pau_Monn=C3=A9?= Errors-To: xen-devel-bounces@lists.xenproject.org Sender: "Xen-devel" The purpose of this change is to stop using xc_cpuid_do_domctl(), and to stop basing decisions on a local CPUID instruction. This is not a correct or appropriate way to construct policy information for other domains. The overwhelming majority of this logic is redundant with the policy logic in Xen, but has a habit of becoming stale (e.g. c/s 97e4ebdcd76 resulting in AVX512_BF16 not ever actually being offered to guests). There are a few subtle side effects which need to remain in place. A successful call to xc_cpuid_apply_policy() must result in a call to xc_set_domain_cpu_policy() because that is currently the only way the ITSC/VMX/SVM bits become reflected in the guests CPUID view. Future cleanup will remove this side effect. The topology tweaks are local to libxc. Extend struct cpuid_policy with enough named fields to express the logic, but keep it identical to before. Fixing topology representation is another future area of work. No (expected) change in behaviour. Signed-off-by: Andrew Cooper --- CC: Jan Beulich CC: Wei Liu CC: Roger Pau Monné CC: Ian Jackson The repositioning of xc_cpuid_apply_policy() relative to xc_cpuid_set() is simply to make the diff readable. It is completely illegible otherwise. --- tools/libxc/xc_cpuid_x86.c | 798 ++++++++++------------------------------ xen/include/xen/lib/x86/cpuid.h | 11 +- 2 files changed, 197 insertions(+), 612 deletions(-) diff --git a/tools/libxc/xc_cpuid_x86.c b/tools/libxc/xc_cpuid_x86.c index d1a2b61214..c88acbac9e 100644 --- a/tools/libxc/xc_cpuid_x86.c +++ b/tools/libxc/xc_cpuid_x86.c @@ -34,18 +34,13 @@ enum { #include -#include -#include +#include #define bitmaskof(idx) (1u << ((idx) & 31)) #define featureword_of(idx) ((idx) >> 5) #define clear_feature(idx, dst) ((dst) &= ~bitmaskof(idx)) #define set_feature(idx, dst) ((dst) |= bitmaskof(idx)) -#define DEF_MAX_BASE 0x0000000du -#define DEF_MAX_INTELEXT 0x80000008u -#define DEF_MAX_AMDEXT 0x8000001cu - int xc_get_cpu_levelling_caps(xc_interface *xch, uint32_t *caps) { DECLARE_SYSCTL; @@ -278,609 +273,6 @@ int xc_set_domain_cpu_policy(xc_interface *xch, uint32_t domid, return ret; } -struct cpuid_domain_info -{ - unsigned int vendor; /* X86_VENDOR_* */ - - bool hvm; - uint64_t xfeature_mask; - - /* - * Careful with featureset lengths. - * - * Code in this file requires featureset to have at least - * xc_get_cpu_featureset_size() entries. This is a libxc compiletime - * constant. - * - * The featureset length used by the hypervisor may be different. If the - * hypervisor version is longer, XEN_SYSCTL_get_cpu_featureset will fail - * with -ENOBUFS, and libxc really does need rebuilding. If the - * hypervisor version is shorter, it is safe to zero-extend. - */ - uint32_t *featureset; - unsigned int nr_features; - - /* PV-only information. */ - bool pv64; - - /* HVM-only information. */ - bool pae; - bool nestedhvm; -}; - -static void cpuid(const unsigned int *input, unsigned int *regs) -{ - unsigned int count = (input[1] == XEN_CPUID_INPUT_UNUSED) ? 0 : input[1]; -#ifdef __i386__ - /* Use the stack to avoid reg constraint failures with some gcc flags */ - asm ( - "push %%ebx; push %%edx\n\t" - "cpuid\n\t" - "mov %%ebx,4(%4)\n\t" - "mov %%edx,12(%4)\n\t" - "pop %%edx; pop %%ebx\n\t" - : "=a" (regs[0]), "=c" (regs[2]) - : "0" (input[0]), "1" (count), "S" (regs) - : "memory" ); -#else - asm ( - "cpuid" - : "=a" (regs[0]), "=b" (regs[1]), "=c" (regs[2]), "=d" (regs[3]) - : "0" (input[0]), "2" (count) ); -#endif -} - -static int get_cpuid_domain_info(xc_interface *xch, uint32_t domid, - struct cpuid_domain_info *info, - const uint32_t *featureset, - unsigned int nr_features) -{ - struct xen_domctl domctl = {}; - xc_dominfo_t di; - unsigned int in[2] = { 0, ~0U }, regs[4]; - unsigned int i, host_nr_features = xc_get_cpu_featureset_size(); - int rc; - - cpuid(in, regs); - info->vendor = x86_cpuid_lookup_vendor(regs[1], regs[2], regs[3]); - - if ( xc_domain_getinfo(xch, domid, 1, &di) != 1 || - di.domid != domid ) - return -ESRCH; - - info->hvm = di.hvm; - - info->featureset = calloc(host_nr_features, sizeof(*info->featureset)); - if ( !info->featureset ) - return -ENOMEM; - - info->nr_features = host_nr_features; - - if ( featureset ) - { - /* - * The user supplied featureset may be shorter or longer than - * host_nr_features. Shorter is fine, and we will zero-extend. - * Longer is fine, so long as it only padded with zeros. - */ - unsigned int fslen = min(host_nr_features, nr_features); - - memcpy(info->featureset, featureset, - fslen * sizeof(*info->featureset)); - - /* Check for truncated set bits. */ - for ( i = fslen; i < nr_features; ++i ) - if ( featureset[i] != 0 ) - return -EOPNOTSUPP; - } - else - { - rc = xc_get_cpu_featureset(xch, (info->hvm - ? XEN_SYSCTL_cpu_featureset_hvm - : XEN_SYSCTL_cpu_featureset_pv), - &host_nr_features, info->featureset); - if ( rc ) - return -errno; - } - - /* Get xstate information. */ - domctl.cmd = XEN_DOMCTL_getvcpuextstate; - domctl.domain = domid; - rc = do_domctl(xch, &domctl); - if ( rc ) - return -errno; - - info->xfeature_mask = domctl.u.vcpuextstate.xfeature_mask; - - if ( di.hvm ) - { - uint64_t val; - - rc = xc_hvm_param_get(xch, domid, HVM_PARAM_PAE_ENABLED, &val); - if ( rc ) - return -errno; - - info->pae = !!val; - - rc = xc_hvm_param_get(xch, domid, HVM_PARAM_NESTEDHVM, &val); - if ( rc ) - return -errno; - - info->nestedhvm = !!val; - } - else - { - unsigned int width; - - rc = xc_domain_get_guest_width(xch, domid, &width); - if ( rc ) - return -errno; - - info->pv64 = (width == 8); - } - - return 0; -} - -static void free_cpuid_domain_info(struct cpuid_domain_info *info) -{ - free(info->featureset); -} - -static void amd_xc_cpuid_policy(const struct cpuid_domain_info *info, - const unsigned int *input, unsigned int *regs) -{ - switch ( input[0] ) - { - case 0x00000002: - case 0x00000004: - regs[0] = regs[1] = regs[2] = 0; - break; - - case 0x80000000: - if ( regs[0] > DEF_MAX_AMDEXT ) - regs[0] = DEF_MAX_AMDEXT; - break; - - case 0x80000008: - /* - * ECX[15:12] is ApicIdCoreSize: ECX[7:0] is NumberOfCores (minus one). - * Update to reflect vLAPIC_ID = vCPU_ID * 2. - */ - regs[2] = ((regs[2] + (1u << 12)) & 0xf000u) | - ((regs[2] & 0xffu) << 1) | 1u; - break; - - case 0x8000000a: { - if ( !info->nestedhvm ) - { - regs[0] = regs[1] = regs[2] = regs[3] = 0; - break; - } - -#define SVM_FEATURE_NPT 0x00000001 /* Nested page table support */ -#define SVM_FEATURE_LBRV 0x00000002 /* LBR virtualization support */ -#define SVM_FEATURE_SVML 0x00000004 /* SVM locking MSR support */ -#define SVM_FEATURE_NRIPS 0x00000008 /* Next RIP save on VMEXIT */ -#define SVM_FEATURE_TSCRATEMSR 0x00000010 /* TSC ratio MSR support */ -#define SVM_FEATURE_VMCBCLEAN 0x00000020 /* VMCB clean bits support */ -#define SVM_FEATURE_FLUSHBYASID 0x00000040 /* TLB flush by ASID support */ -#define SVM_FEATURE_DECODEASSISTS 0x00000080 /* Decode assists support */ -#define SVM_FEATURE_PAUSEFILTER 0x00000400 /* Pause intercept filter */ - - /* Pass 1: Only passthrough SVM features which are - * available in hw and which are implemented - */ - regs[3] &= (SVM_FEATURE_NPT | SVM_FEATURE_LBRV | \ - SVM_FEATURE_NRIPS | SVM_FEATURE_PAUSEFILTER | \ - SVM_FEATURE_DECODEASSISTS); - - /* Pass 2: Always enable SVM features which are emulated */ - regs[3] |= SVM_FEATURE_VMCBCLEAN | SVM_FEATURE_TSCRATEMSR; - break; - } - - } -} - -static void intel_xc_cpuid_policy(const struct cpuid_domain_info *info, - const unsigned int *input, unsigned int *regs) -{ - switch ( input[0] ) - { - case 0x00000004: - /* - * EAX[31:26] is Maximum Cores Per Package (minus one). - * Update to reflect vLAPIC_ID = vCPU_ID * 2. - */ - regs[0] = (((regs[0] & 0x7c000000u) << 1) | 0x04000000u | - (regs[0] & 0x3ffu)); - regs[3] &= 0x3ffu; - break; - - case 0x80000000: - if ( regs[0] > DEF_MAX_INTELEXT ) - regs[0] = DEF_MAX_INTELEXT; - break; - - case 0x80000005: - regs[0] = regs[1] = regs[2] = 0; - break; - - case 0x80000008: - /* Mask AMD Number of Cores information. */ - regs[2] = 0; - break; - } -} - -static void xc_cpuid_hvm_policy(const struct cpuid_domain_info *info, - const unsigned int *input, unsigned int *regs) -{ - switch ( input[0] ) - { - case 0x00000000: - if ( regs[0] > DEF_MAX_BASE ) - regs[0] = DEF_MAX_BASE; - break; - - case 0x00000001: - /* - * EBX[23:16] is Maximum Logical Processors Per Package. - * Update to reflect vLAPIC_ID = vCPU_ID * 2. - */ - regs[1] = (regs[1] & 0x0000ffffu) | ((regs[1] & 0x007f0000u) << 1); - - regs[2] = info->featureset[featureword_of(X86_FEATURE_SSE3)]; - regs[3] = (info->featureset[featureword_of(X86_FEATURE_FPU)] | - bitmaskof(X86_FEATURE_HTT)); - break; - - case 0x00000007: /* Intel-defined CPU features */ - if ( input[1] == 0 ) - { - regs[1] = info->featureset[featureword_of(X86_FEATURE_FSGSBASE)]; - regs[2] = info->featureset[featureword_of(X86_FEATURE_PREFETCHWT1)]; - regs[3] = info->featureset[featureword_of(X86_FEATURE_AVX512_4VNNIW)]; - } - else - { - regs[1] = 0; - regs[2] = 0; - regs[3] = 0; - } - regs[0] = 0; - break; - - case 0x0000000d: /* Xen automatically calculates almost everything. */ - if ( input[1] == 1 ) - regs[0] = info->featureset[featureword_of(X86_FEATURE_XSAVEOPT)]; - else - regs[0] = 0; - regs[1] = regs[2] = regs[3] = 0; - break; - - case 0x80000000: - /* Passthrough to cpu vendor specific functions */ - break; - - case 0x80000001: - regs[2] = (info->featureset[featureword_of(X86_FEATURE_LAHF_LM)] & - ~bitmaskof(X86_FEATURE_CMP_LEGACY)); - regs[3] = info->featureset[featureword_of(X86_FEATURE_SYSCALL)]; - break; - - case 0x80000007: - /* - * Keep only TSCInvariant. This may be cleared by the hypervisor - * depending on guest TSC and migration settings. - */ - regs[0] = regs[1] = regs[2] = 0; - regs[3] &= 1u<<8; - break; - - case 0x80000008: - regs[0] &= 0x0000ffffu; - regs[1] = info->featureset[featureword_of(X86_FEATURE_CLZERO)]; - /* regs[2] handled in the per-vendor logic. */ - regs[3] = 0; - break; - - case 0x00000002: /* Intel cache info (dumped by AMD policy) */ - case 0x00000004: /* Intel cache info (dumped by AMD policy) */ - case 0x0000000a: /* Architectural Performance Monitor Features */ - case 0x80000002: /* Processor name string */ - case 0x80000003: /* ... continued */ - case 0x80000004: /* ... continued */ - case 0x80000005: /* AMD L1 cache/TLB info (dumped by Intel policy) */ - case 0x80000006: /* AMD L2/3 cache/TLB info ; Intel L2 cache features */ - case 0x8000000a: /* AMD SVM feature bits */ - case 0x80000019: /* AMD 1G TLB */ - case 0x8000001a: /* AMD perf hints */ - case 0x8000001c: /* AMD lightweight profiling */ - break; - - default: - regs[0] = regs[1] = regs[2] = regs[3] = 0; - break; - } - - if ( info->vendor & (X86_VENDOR_AMD | X86_VENDOR_HYGON) ) - amd_xc_cpuid_policy(info, input, regs); - else - intel_xc_cpuid_policy(info, input, regs); -} - -static void xc_cpuid_pv_policy(const struct cpuid_domain_info *info, - const unsigned int *input, unsigned int *regs) -{ - switch ( input[0] ) - { - case 0x00000000: - if ( regs[0] > DEF_MAX_BASE ) - regs[0] = DEF_MAX_BASE; - break; - - case 0x00000001: - { - /* Host topology exposed to PV guest. Provide host value. */ - bool host_htt = regs[3] & bitmaskof(X86_FEATURE_HTT); - - /* - * Don't pick host's Initial APIC ID which can change from run - * to run. - */ - regs[1] &= 0x00ffffffu; - - regs[2] = info->featureset[featureword_of(X86_FEATURE_SSE3)]; - regs[3] = (info->featureset[featureword_of(X86_FEATURE_FPU)] & - ~bitmaskof(X86_FEATURE_HTT)); - - if ( host_htt ) - regs[3] |= bitmaskof(X86_FEATURE_HTT); - break; - } - - case 0x00000007: - if ( input[1] == 0 ) - { - regs[1] = info->featureset[featureword_of(X86_FEATURE_FSGSBASE)]; - regs[2] = info->featureset[featureword_of(X86_FEATURE_PREFETCHWT1)]; - regs[3] = info->featureset[featureword_of(X86_FEATURE_AVX512_4VNNIW)]; - } - else - { - regs[1] = 0; - regs[2] = 0; - regs[3] = 0; - } - regs[0] = 0; - break; - - case 0x0000000d: /* Xen automatically calculates almost everything. */ - if ( input[1] == 1 ) - regs[0] = info->featureset[featureword_of(X86_FEATURE_XSAVEOPT)]; - else - regs[0] = 0; - regs[1] = regs[2] = regs[3] = 0; - break; - - case 0x80000000: - { - unsigned int max = (info->vendor & (X86_VENDOR_AMD | X86_VENDOR_HYGON)) - ? DEF_MAX_AMDEXT : DEF_MAX_INTELEXT; - - if ( regs[0] > max ) - regs[0] = max; - break; - } - - case 0x80000001: - { - /* Host topology exposed to PV guest. Provide host CMP_LEGACY value. */ - bool host_cmp_legacy = regs[2] & bitmaskof(X86_FEATURE_CMP_LEGACY); - - regs[2] = (info->featureset[featureword_of(X86_FEATURE_LAHF_LM)] & - ~bitmaskof(X86_FEATURE_CMP_LEGACY)); - regs[3] = info->featureset[featureword_of(X86_FEATURE_SYSCALL)]; - - if ( host_cmp_legacy ) - regs[2] |= bitmaskof(X86_FEATURE_CMP_LEGACY); - - break; - } - - case 0x80000008: - regs[0] &= 0x0000ffffu; - regs[1] = info->featureset[featureword_of(X86_FEATURE_CLZERO)]; - regs[2] = regs[3] = 0; - break; - - case 0x00000005: /* MONITOR/MWAIT */ - case 0x0000000b: /* Extended Topology Enumeration */ - case 0x8000000a: /* SVM revision and features */ - case 0x8000001b: /* Instruction Based Sampling */ - case 0x8000001c: /* Light Weight Profiling */ - case 0x8000001e: /* Extended topology reporting */ - regs[0] = regs[1] = regs[2] = regs[3] = 0; - break; - } -} - -static void xc_cpuid_policy(const struct cpuid_domain_info *info, - const unsigned int *input, unsigned int *regs) -{ - /* - * For hypervisor leaves (0x4000XXXX) only 0x4000xx00.EAX[7:0] bits (max - * number of leaves) can be set by user. Hypervisor will enforce this so - * all other bits are don't-care and we can set them to zero. - */ - if ( (input[0] & 0xffff0000) == 0x40000000 ) - { - regs[0] = regs[1] = regs[2] = regs[3] = 0; - return; - } - - if ( info->hvm ) - xc_cpuid_hvm_policy(info, input, regs); - else - xc_cpuid_pv_policy(info, input, regs); -} - -static int xc_cpuid_do_domctl( - xc_interface *xch, uint32_t domid, - const unsigned int *input, const unsigned int *regs) -{ - DECLARE_DOMCTL; - - memset(&domctl, 0, sizeof (domctl)); - domctl.domain = domid; - domctl.cmd = XEN_DOMCTL_set_cpuid; - domctl.u.cpuid.input[0] = input[0]; - domctl.u.cpuid.input[1] = input[1]; - domctl.u.cpuid.eax = regs[0]; - domctl.u.cpuid.ebx = regs[1]; - domctl.u.cpuid.ecx = regs[2]; - domctl.u.cpuid.edx = regs[3]; - - return do_domctl(xch, &domctl); -} - -static void sanitise_featureset(struct cpuid_domain_info *info) -{ - const uint32_t fs_size = xc_get_cpu_featureset_size(); - uint32_t disabled_features[fs_size]; - static const uint32_t deep_features[] = INIT_DEEP_FEATURES; - unsigned int i, b; - - if ( info->hvm ) - { - /* HVM or PVH Guest */ - - if ( !info->pae ) - clear_bit(X86_FEATURE_PAE, info->featureset); - - if ( !info->nestedhvm ) - { - clear_bit(X86_FEATURE_SVM, info->featureset); - clear_bit(X86_FEATURE_VMX, info->featureset); - } - } - else - { - /* PV Guest */ - - if ( !info->pv64 ) - { - clear_bit(X86_FEATURE_LM, info->featureset); - if ( !(info->vendor & (X86_VENDOR_AMD | X86_VENDOR_HYGON)) ) - clear_bit(X86_FEATURE_SYSCALL, info->featureset); - } - - clear_bit(X86_FEATURE_PSE, info->featureset); - clear_bit(X86_FEATURE_PSE36, info->featureset); - clear_bit(X86_FEATURE_PGE, info->featureset); - clear_bit(X86_FEATURE_PAGE1GB, info->featureset); - } - - if ( info->xfeature_mask == 0 ) - clear_bit(X86_FEATURE_XSAVE, info->featureset); - - /* Disable deep dependencies of disabled features. */ - for ( i = 0; i < ARRAY_SIZE(disabled_features); ++i ) - disabled_features[i] = ~info->featureset[i] & deep_features[i]; - - for ( b = 0; b < sizeof(disabled_features) * CHAR_BIT; ++b ) - { - const uint32_t *dfs; - - if ( !test_bit(b, disabled_features) || - !(dfs = x86_cpuid_lookup_deep_deps(b)) ) - continue; - - for ( i = 0; i < ARRAY_SIZE(disabled_features); ++i ) - { - info->featureset[i] &= ~dfs[i]; - disabled_features[i] &= ~dfs[i]; - } - } -} - -int xc_cpuid_apply_policy(xc_interface *xch, uint32_t domid, - const uint32_t *featureset, unsigned int nr_features) -{ - struct cpuid_domain_info info = {}; - unsigned int input[2] = { 0, 0 }, regs[4]; - unsigned int base_max, ext_max; - int rc; - - rc = get_cpuid_domain_info(xch, domid, &info, featureset, nr_features); - if ( rc ) - goto out; - - cpuid(input, regs); - base_max = (regs[0] <= DEF_MAX_BASE) ? regs[0] : DEF_MAX_BASE; - input[0] = 0x80000000; - cpuid(input, regs); - - if ( info.vendor == X86_VENDOR_AMD || info.vendor == X86_VENDOR_HYGON ) - ext_max = (regs[0] <= DEF_MAX_AMDEXT) ? regs[0] : DEF_MAX_AMDEXT; - else - ext_max = (regs[0] <= DEF_MAX_INTELEXT) ? regs[0] : DEF_MAX_INTELEXT; - - sanitise_featureset(&info); - - input[0] = 0; - input[1] = XEN_CPUID_INPUT_UNUSED; - for ( ; ; ) - { - cpuid(input, regs); - xc_cpuid_policy(&info, input, regs); - - if ( regs[0] || regs[1] || regs[2] || regs[3] ) - { - rc = xc_cpuid_do_domctl(xch, domid, input, regs); - if ( rc ) - goto out; - } - - /* Intel cache descriptor leaves. */ - if ( input[0] == 4 ) - { - input[1]++; - /* More to do? Then loop keeping %%eax==0x00000004. */ - if ( (regs[0] & 0x1f) != 0 ) - continue; - } - /* Extended Topology leaves. */ - else if ( input[0] == 0xb ) - { - uint8_t level_type = regs[2] >> 8; - - input[1]++; - if ( level_type >= 1 && level_type <= 2 ) - continue; - } - - input[0]++; - if ( !(input[0] & 0x80000000u) && (input[0] > base_max ) ) - input[0] = 0x80000000u; - - input[1] = XEN_CPUID_INPUT_UNUSED; - if ( (input[0] == 4) || (input[0] == 7) || (input[0] == 0xb) ) - input[1] = 0; - else if ( input[0] == 0xd ) - input[1] = 1; /* Xen automatically calculates almost everything. */ - - if ( (input[0] & 0x80000000u) && (input[0] > ext_max) ) - break; - } - - out: - free_cpuid_domain_info(&info); - return rc; -} - /* * Configure a single input with the informatiom from config. * @@ -1057,3 +449,191 @@ int xc_cpuid_set( return rc; } + +int xc_cpuid_apply_policy(xc_interface *xch, uint32_t domid, + const uint32_t *featureset, unsigned int nr_features) +{ + int rc; + xc_dominfo_t di; + unsigned int i, nr_leaves, nr_msrs; + xen_cpuid_leaf_t *leaves = NULL; + struct cpuid_policy *p = NULL; + uint32_t err_leaf = -1, err_subleaf = -1, err_msr = -1; + + if ( xc_domain_getinfo(xch, domid, 1, &di) != 1 || + di.domid != domid ) + { + ERROR("Failed to obtain d%d info", domid); + rc = -ESRCH; + goto out; + } + + rc = xc_get_cpu_policy_size(xch, &nr_leaves, &nr_msrs); + if ( rc ) + { + PERROR("Failed to obtain policy info size"); + rc = -errno; + goto out; + } + + rc = -ENOMEM; + if ( (leaves = calloc(nr_leaves, sizeof(*leaves))) == NULL || + (p = calloc(1, sizeof(*p))) == NULL ) + goto out; + + nr_msrs = 0; + rc = xc_get_domain_cpu_policy(xch, domid, &nr_leaves, leaves, + &nr_msrs, NULL); + if ( rc ) + { + PERROR("Failed to obtain d%d's policy", domid); + rc = -errno; + goto out; + } + + rc = x86_cpuid_copy_from_buffer(p, leaves, nr_leaves, + &err_leaf, &err_subleaf); + if ( rc ) + { + ERROR("Failed to deserialise CPUID (err leaf %#x, subleaf %#x) (%d = %s)", + err_leaf, err_subleaf, -rc, strerror(-rc)); + goto out; + } + + if ( featureset ) + { + uint32_t disabled_features[FEATURESET_NR_ENTRIES], + feat[FEATURESET_NR_ENTRIES] = {}; + static const uint32_t deep_features[] = INIT_DEEP_FEATURES; + unsigned int i, b; + + /* + * The user supplied featureset may be shorter or longer than + * FEATURESET_NR_ENTRIES. Shorter is fine, and we will zero-extend. + * Longer is fine, so long as it only padded with zeros. + */ + unsigned int user_len = min(FEATURESET_NR_ENTRIES + 0u, nr_features); + + /* Check for truncated set bits. */ + rc = -EOPNOTSUPP; + for ( i = user_len; i < nr_features; ++i ) + if ( featureset[i] != 0 ) + goto out; + + memcpy(feat, featureset, sizeof(*featureset) * user_len); + + /* Disable deep dependencies of disabled features. */ + for ( i = 0; i < ARRAY_SIZE(disabled_features); ++i ) + disabled_features[i] = ~feat[i] & deep_features[i]; + + for ( b = 0; b < sizeof(disabled_features) * CHAR_BIT; ++b ) + { + const uint32_t *dfs; + + if ( !test_bit(b, disabled_features) || + !(dfs = x86_cpuid_lookup_deep_deps(b)) ) + continue; + + for ( i = 0; i < ARRAY_SIZE(disabled_features); ++i ) + { + feat[i] &= ~dfs[i]; + disabled_features[i] &= ~dfs[i]; + } + } + + cpuid_featureset_to_policy(feat, p); + } + + if ( !di.hvm ) + { + uint32_t host_featureset[FEATURESET_NR_ENTRIES]; + uint32_t len = ARRAY_SIZE(host_featureset); + + rc = xc_get_cpu_featureset(xch, XEN_SYSCTL_cpu_featureset_host, + &len, host_featureset); + if ( rc ) + { + /* Tolerate "buffer too small", as we've got the bits we need. */ + if ( errno == ENOBUFS ) + rc = 0; + else + { + PERROR("Failed to obtain host featureset"); + rc = -errno; + goto out; + } + } + + /* + * On hardware without CPUID Faulting, PV guests see real topology. + * As a consequence, they also need to see the host htt/cmp fields. + */ + p->basic.htt = test_bit(X86_FEATURE_HTT, host_featureset); + p->extd.cmp_legacy = test_bit(X86_FEATURE_CMP_LEGACY, host_featureset); + } + else + { + /* + * Topology for HVM guests is entirely controlled by Xen. For now, we + * hardcode APIC_ID = vcpu_id * 2 to give the illusion of no SMT. + */ + p->basic.htt = true; + p->extd.cmp_legacy = false; + + p->basic.lppp *= 2; + + switch ( p->x86_vendor ) + { + case X86_VENDOR_INTEL: + for ( i = 0; (p->cache.subleaf[i].type && + i < ARRAY_SIZE(p->cache.raw)); ++i ) + { + p->cache.subleaf[i].cores_per_package = + (p->cache.subleaf[i].cores_per_package << 1) | 1; + p->cache.subleaf[i].threads_per_cache = 0; + } + break; + + case X86_VENDOR_AMD: + case X86_VENDOR_HYGON: + p->extd.nc = (p->extd.nc << 1) | 1; + p->extd.apic_id_size++; + break; + } + + /* + * These settings are necessary to cause earlier HVM_PARAM_NESTEDHVM / + * XEN_DOMCTL_disable_migrate settings to be reflected correctly in + * CPUID. Xen will discard these bits if configuration hasn't been + * set for the domain. + */ + p->extd.itsc = true; + p->basic.vmx = true; + p->extd.svm = true; + } + + rc = x86_cpuid_copy_to_buffer(p, leaves, &nr_leaves); + if ( rc ) + { + ERROR("Failed to serialise CPUID (%d = %s)", -rc, strerror(-rc)); + goto out; + } + + rc = xc_set_domain_cpu_policy(xch, domid, nr_leaves, leaves, 0, NULL, + &err_leaf, &err_subleaf, &err_msr); + if ( rc ) + { + PERROR("Failed to set d%d's policy (err leaf %#x, subleaf %#x, msr %#x)", + domid, err_leaf, err_subleaf, err_msr); + rc = -errno; + goto out; + } + + rc = 0; + +out: + free(p); + free(leaves); + + return rc; +} diff --git a/xen/include/xen/lib/x86/cpuid.h b/xen/include/xen/lib/x86/cpuid.h index df5946b6b1..6c86c1a0d0 100644 --- a/xen/include/xen/lib/x86/cpuid.h +++ b/xen/include/xen/lib/x86/cpuid.h @@ -154,8 +154,12 @@ struct cpuid_policy union { struct cpuid_leaf raw[CPUID_GUEST_NR_CACHE]; struct cpuid_cache_leaf { - uint32_t type:5, - :27, :32, :32, :32; + uint32_t /* a */ type:5, level:3; + bool self_init:1, fully_assoc:1; + uint32_t :4, threads_per_cache:12, cores_per_package:6; + uint32_t /* b */ line_size:12, partitions:10, ways:10; + uint32_t /* c */ sets; + bool /* d */ wbinvd:1, inclusive:1, complex:1; } subleaf[CPUID_GUEST_NR_CACHE]; } cache; @@ -259,7 +263,8 @@ struct cpuid_policy uint32_t e8b; struct { DECL_BITFIELD(e8b); }; }; - uint32_t /* c */:32, /* d */:32; + uint32_t nc:8, :4, apic_id_size:4, :16; + uint32_t /* d */:32; }; } extd; From patchwork Wed Sep 11 20:05:03 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Andrew Cooper X-Patchwork-Id: 11141843 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 52CA717E6 for ; Wed, 11 Sep 2019 20:07: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 22DD520838 for ; Wed, 11 Sep 2019 20:07: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="d9V7Nu+P" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 22DD520838 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 1i88ru-00034e-Ar; Wed, 11 Sep 2019 20:05:34 +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 1i88rt-000346-5Y for xen-devel@lists.xenproject.org; Wed, 11 Sep 2019 20:05:33 +0000 X-Inumbo-ID: 784cd580-d4cf-11e9-83dd-12813bfff9fa Received: from esa1.hc3370-68.iphmx.com (unknown [216.71.145.142]) by us1-amaz-eas2.inumbo.com (Halon) with ESMTPS id 784cd580-d4cf-11e9-83dd-12813bfff9fa; Wed, 11 Sep 2019 20:05:15 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=citrix.com; s=securemail; t=1568232316; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=GifxMjGTHY9r+VAau+BqTozFP4UmkZ1smS1EjoSb2Gk=; b=d9V7Nu+PqRC5OS7q+sdlsF1x3Tfi7NadfjCP2Gq6axH1xOUMJuk7WsGM FSxF42PBbtYhcp/dKyMYBHECHRXcv6+sJrClcahhK5NidNjx60rk7Oa5t NzadMKAEkktSWwWoNLutgXsFeeU/IbNIcGOEqZsgTN8T4esgdDSKtwoSH Y=; Authentication-Results: esa1.hc3370-68.iphmx.com; dkim=none (message not signed) header.i=none; spf=None smtp.pra=andrew.cooper3@citrix.com; spf=Pass smtp.mailfrom=Andrew.Cooper3@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 andrew.cooper3@citrix.com) identity=pra; client-ip=162.221.158.21; receiver=esa1.hc3370-68.iphmx.com; envelope-from="Andrew.Cooper3@citrix.com"; x-sender="andrew.cooper3@citrix.com"; x-conformance=sidf_compatible Received-SPF: Pass (esa1.hc3370-68.iphmx.com: domain of Andrew.Cooper3@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="Andrew.Cooper3@citrix.com"; x-sender="Andrew.Cooper3@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="Andrew.Cooper3@citrix.com"; x-sender="postmaster@mail.citrix.com"; x-conformance=sidf_compatible IronPort-SDR: QJ3TOWKBR+GY3A4AqH0bXAC9iMRHXNL4CY/sA6REK4lbe+9+XSgoSTMzQI3OPh9WJPCztASYHY zGnJ9fI4ETj2nzHk7Hegtb5pekW7+PZcRYfgfzLSaWutlfKaiMg+1RHakaVJOS0MnPg/8etmr9 oabfvsVI+5bwtsUBbzh5b3FSXyIaxsjBoALRh20RcWWVJ1ACszMF5Dimzc7hrdpqr0Cvy/5H0d CC1dOKA90IFxHfNHb8Nu1BmG9GVObaeOWBgrnQGbcCFtv9MnM2Z6o67LnGvqRm2bm066HXjcnV 5jw= X-SBRS: 2.7 X-MesageID: 5506248 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,494,1559534400"; d="scan'208";a="5506248" From: Andrew Cooper To: Xen-devel Date: Wed, 11 Sep 2019 21:05:03 +0100 Message-ID: <20190911200504.5693-8-andrew.cooper3@citrix.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20190911200504.5693-1-andrew.cooper3@citrix.com> References: <20190911200504.5693-1-andrew.cooper3@citrix.com> MIME-Version: 1.0 Subject: [Xen-devel] [PATCH 7/8] x86/domctl: Drop XEN_DOMCTL_set_cpuid 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: Andrew Cooper , Daniel De Graaf , Wei Liu , Jan Beulich , =?utf-8?q?Roger_Pau_Monn=C3=A9?= Errors-To: xen-devel-bounces@lists.xenproject.org Sender: "Xen-devel" With the final users moved over to using XEN_DOMCTL_set_cpumsr_policy, drop this domctl and associated infrastructure. Rename the preexisting set_cpuid XSM vector to set_cpu_policy, now that it is back to having a single user. Signed-off-by: Andrew Cooper Acked-by: Jan Beulich --- CC: Jan Beulich CC: Wei Liu CC: Roger Pau Monné CC: Daniel De Graaf --- tools/flask/policy/modules/dom0.te | 2 +- tools/flask/policy/modules/xen.if | 2 +- xen/arch/x86/domctl.c | 101 ------------------------------------ xen/include/public/domctl.h | 11 +--- xen/xsm/flask/hooks.c | 3 +- xen/xsm/flask/policy/access_vectors | 3 +- 6 files changed, 5 insertions(+), 117 deletions(-) diff --git a/tools/flask/policy/modules/dom0.te b/tools/flask/policy/modules/dom0.te index 9970f9dc08..272f6a4f75 100644 --- a/tools/flask/policy/modules/dom0.te +++ b/tools/flask/policy/modules/dom0.te @@ -38,7 +38,7 @@ allow dom0_t dom0_t:domain { getpodtarget setpodtarget set_misc_info set_virq_handler }; allow dom0_t dom0_t:domain2 { - set_cpuid gettsc settsc setscheduler set_vnumainfo + set_cpu_policy gettsc settsc setscheduler set_vnumainfo get_vnumainfo psr_cmt_op psr_alloc get_cpu_policy }; allow dom0_t dom0_t:resource { add remove }; diff --git a/tools/flask/policy/modules/xen.if b/tools/flask/policy/modules/xen.if index de5fb331bf..8eb2293a52 100644 --- a/tools/flask/policy/modules/xen.if +++ b/tools/flask/policy/modules/xen.if @@ -50,7 +50,7 @@ define(`create_domain_common', ` getdomaininfo hypercall setvcpucontext getscheduler getvcpuinfo getaddrsize getaffinity setaffinity settime setdomainhandle getvcpucontext set_misc_info }; - allow $1 $2:domain2 { set_cpuid settsc setscheduler setclaim + allow $1 $2:domain2 { set_cpu_policy settsc setscheduler setclaim set_vnumainfo get_vnumainfo cacheflush psr_cmt_op psr_alloc soft_reset resource_map get_cpu_policy }; diff --git a/xen/arch/x86/domctl.c b/xen/arch/x86/domctl.c index 99bc2fb10d..ec50a88156 100644 --- a/xen/arch/x86/domctl.c +++ b/xen/arch/x86/domctl.c @@ -206,94 +206,6 @@ static void domain_cpu_policy_changed(struct domain *d) } } -static int update_domain_cpuid_info(struct domain *d, - const struct xen_domctl_cpuid *ctl) -{ - struct cpuid_policy *p = d->arch.cpuid; - const struct cpuid_leaf leaf = { ctl->eax, ctl->ebx, ctl->ecx, ctl->edx }; - - /* - * Skip update for leaves we don't care about, to avoid the overhead of - * recalculate_cpuid_policy(). - */ - switch ( ctl->input[0] ) - { - case 0x00000000 ... ARRAY_SIZE(p->basic.raw) - 1: - if ( ctl->input[0] == 4 && - ctl->input[1] >= ARRAY_SIZE(p->cache.raw) ) - return 0; - - if ( ctl->input[0] == 7 && - ctl->input[1] >= ARRAY_SIZE(p->feat.raw) ) - return 0; - - if ( ctl->input[0] == 0xb && - ctl->input[1] >= ARRAY_SIZE(p->topo.raw) ) - return 0; - - BUILD_BUG_ON(ARRAY_SIZE(p->xstate.raw) < 2); - if ( ctl->input[0] == XSTATE_CPUID && - ctl->input[1] != 1 ) /* Everything else automatically calculated. */ - return 0; - break; - - case 0x40000000: case 0x40000100: - /* Only care about the max_leaf limit. */ - - case 0x80000000 ... 0x80000000 + ARRAY_SIZE(p->extd.raw) - 1: - break; - - default: - return 0; - } - - /* Insert ctl data into cpuid_policy. */ - switch ( ctl->input[0] ) - { - case 0x00000000 ... ARRAY_SIZE(p->basic.raw) - 1: - switch ( ctl->input[0] ) - { - case 4: - p->cache.raw[ctl->input[1]] = leaf; - break; - - case 7: - p->feat.raw[ctl->input[1]] = leaf; - break; - - case 0xb: - p->topo.raw[ctl->input[1]] = leaf; - break; - - case XSTATE_CPUID: - p->xstate.raw[ctl->input[1]] = leaf; - break; - - default: - p->basic.raw[ctl->input[0]] = leaf; - break; - } - break; - - case 0x40000000: - p->hv_limit = ctl->eax; - break; - - case 0x40000100: - p->hv2_limit = ctl->eax; - break; - - case 0x80000000 ... 0x80000000 + ARRAY_SIZE(p->extd.raw) - 1: - p->extd.raw[ctl->input[0] - 0x80000000] = leaf; - break; - } - - recalculate_cpuid_policy(d); - domain_cpu_policy_changed(d); - - return 0; -} - static int update_domain_cpu_policy(struct domain *d, xen_domctl_cpu_policy_t *xdpc) { @@ -951,19 +863,6 @@ long arch_do_domctl( break; } - case XEN_DOMCTL_set_cpuid: - if ( d == currd ) /* no domain_pause() */ - ret = -EINVAL; - else if ( d->creation_finished ) - ret = -EEXIST; /* No changing once the domain is running. */ - else - { - domain_pause(d); - ret = update_domain_cpuid_info(d, &domctl->u.cpuid); - domain_unpause(d); - } - break; - case XEN_DOMCTL_gettscinfo: if ( d == currd ) /* no domain_pause() */ ret = -EINVAL; diff --git a/xen/include/public/domctl.h b/xen/include/public/domctl.h index 0471d3c680..548b917bdb 100644 --- a/xen/include/public/domctl.h +++ b/xen/include/public/domctl.h @@ -648,14 +648,6 @@ struct xen_domctl_set_target { #if defined(__i386__) || defined(__x86_64__) # define XEN_CPUID_INPUT_UNUSED 0xFFFFFFFF -/* XEN_DOMCTL_set_cpuid */ -struct xen_domctl_cpuid { - uint32_t input[2]; - uint32_t eax; - uint32_t ebx; - uint32_t ecx; - uint32_t edx; -}; /* * XEN_DOMCTL_{get,set}_cpu_policy (x86 specific) @@ -1166,7 +1158,7 @@ struct xen_domctl { #define XEN_DOMCTL_set_target 46 #define XEN_DOMCTL_deassign_device 47 #define XEN_DOMCTL_unbind_pt_irq 48 -#define XEN_DOMCTL_set_cpuid 49 +/* #define XEN_DOMCTL_set_cpuid 49 - Obsolete - use set_cpu_policy */ #define XEN_DOMCTL_get_device_group 50 /* #define XEN_DOMCTL_set_machine_address_size 51 - Obsolete */ /* #define XEN_DOMCTL_get_machine_address_size 52 - Obsolete */ @@ -1243,7 +1235,6 @@ struct xen_domctl { struct xen_domctl_vm_event_op vm_event_op; struct xen_domctl_mem_sharing_op mem_sharing_op; #if defined(__i386__) || defined(__x86_64__) - struct xen_domctl_cpuid cpuid; struct xen_domctl_cpu_policy cpu_policy; struct xen_domctl_vcpuextstate vcpuextstate; struct xen_domctl_vcpu_msrs vcpu_msrs; diff --git a/xen/xsm/flask/hooks.c b/xen/xsm/flask/hooks.c index b23772786a..fd8d23c185 100644 --- a/xen/xsm/flask/hooks.c +++ b/xen/xsm/flask/hooks.c @@ -716,8 +716,7 @@ static int flask_domctl(struct domain *d, int cmd) return current_has_perm(d, SECCLASS_DOMAIN, DOMAIN__SET_VIRQ_HANDLER); case XEN_DOMCTL_set_cpu_policy: - case XEN_DOMCTL_set_cpuid: - return current_has_perm(d, SECCLASS_DOMAIN2, DOMAIN2__SET_CPUID); + return current_has_perm(d, SECCLASS_DOMAIN2, DOMAIN2__SET_CPU_POLICY); case XEN_DOMCTL_gettscinfo: return current_has_perm(d, SECCLASS_DOMAIN2, DOMAIN2__GETTSC); diff --git a/xen/xsm/flask/policy/access_vectors b/xen/xsm/flask/policy/access_vectors index 6f3f9493f8..c055c14c26 100644 --- a/xen/xsm/flask/policy/access_vectors +++ b/xen/xsm/flask/policy/access_vectors @@ -208,8 +208,7 @@ class domain2 # target = the new target domain set_as_target # XEN_DOMCTL_set_cpu_policy -# XEN_DOMCTL_set_cpuid - set_cpuid + set_cpu_policy # XEN_DOMCTL_gettscinfo gettsc # XEN_DOMCTL_settscinfo From patchwork Wed Sep 11 20:05:04 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Andrew Cooper X-Patchwork-Id: 11141851 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 398A617E6 for ; Wed, 11 Sep 2019 20:07:34 +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 1481620838 for ; Wed, 11 Sep 2019 20:07:34 +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="WuX1rwTz" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 1481620838 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 1i88rz-00037x-NQ; Wed, 11 Sep 2019 20:05:39 +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 1i88ry-00036p-5L for xen-devel@lists.xenproject.org; Wed, 11 Sep 2019 20:05:38 +0000 X-Inumbo-ID: 7928fc90-d4cf-11e9-83dd-12813bfff9fa Received: from esa1.hc3370-68.iphmx.com (unknown [216.71.145.142]) by us1-amaz-eas2.inumbo.com (Halon) with ESMTPS id 7928fc90-d4cf-11e9-83dd-12813bfff9fa; Wed, 11 Sep 2019 20:05:16 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=citrix.com; s=securemail; t=1568232317; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=KfxSG6tk+37JqGd8jvH6e0+GTDL4sE5/HpeLBPpTwb0=; b=WuX1rwTzssXv9O2v7azQkJwJ9JE4rhx6HOVUd5UHe43TngzPgo1y5tjv px7tCMSz+fN/iDhjhLUnZLvtcc1hTZZTlI5xo4oURyDN4ZQHJ5VhzTWkD m4p7YGcRfzyLKPWKKXeGLyvZQLk6h+nZbzUUEHCyIT9riBkjSXSG8SD5m 4=; Authentication-Results: esa1.hc3370-68.iphmx.com; dkim=none (message not signed) header.i=none; spf=None smtp.pra=andrew.cooper3@citrix.com; spf=Pass smtp.mailfrom=Andrew.Cooper3@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 andrew.cooper3@citrix.com) identity=pra; client-ip=162.221.158.21; receiver=esa1.hc3370-68.iphmx.com; envelope-from="Andrew.Cooper3@citrix.com"; x-sender="andrew.cooper3@citrix.com"; x-conformance=sidf_compatible Received-SPF: Pass (esa1.hc3370-68.iphmx.com: domain of Andrew.Cooper3@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="Andrew.Cooper3@citrix.com"; x-sender="Andrew.Cooper3@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="Andrew.Cooper3@citrix.com"; x-sender="postmaster@mail.citrix.com"; x-conformance=sidf_compatible IronPort-SDR: SjzUhlq534F1vTly/5WySxx/tew3DnAeD2PyBNLhkCbwEx//twfzXMGUUPk98kZhseDlKIDE7y Bc1eh3OdmpWVDDTAXnzCdj4a6uwqk6aEhuioPKHVu1P1AfYyh+Itn9PE0qNcR557RvWvBx8q++ lhcQhK9XvyDdYBxrk3cRKQ4JGEabBjKDwb59LfCWI9zPRP5uyhzHyyBQmqBQq0hPnnYnCxz6EC hI0PG0/C667zF+TM501gak+LO1Bgch6q/x83YhzINafz3XGCEmkrmJeQHdT9rBHhlYIg3FKK0W bfo= X-SBRS: 2.7 X-MesageID: 5506249 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,494,1559534400"; d="scan'208";a="5506249" From: Andrew Cooper To: Xen-devel Date: Wed, 11 Sep 2019 21:05:04 +0100 Message-ID: <20190911200504.5693-9-andrew.cooper3@citrix.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20190911200504.5693-1-andrew.cooper3@citrix.com> References: <20190911200504.5693-1-andrew.cooper3@citrix.com> MIME-Version: 1.0 Subject: [Xen-devel] [PATCH 8/8] x86/cpuid: Enable CPUID Faulting for the control domain 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: Andrew Cooper , Wei Liu , Jan Beulich , =?utf-8?q?Roger_Pau_Monn=C3=A9?= Errors-To: xen-devel-bounces@lists.xenproject.org Sender: "Xen-devel" The domain builder no longer uses CPUID instructions for policy decisions. Signed-off-by: Andrew Cooper --- CC: Jan Beulich CC: Wei Liu CC: Roger Pau Monné --- xen/arch/x86/cpu/common.c | 19 ++----------------- 1 file changed, 2 insertions(+), 17 deletions(-) diff --git a/xen/arch/x86/cpu/common.c b/xen/arch/x86/cpu/common.c index 8de4a44c1a..2e883835b8 100644 --- a/xen/arch/x86/cpu/common.c +++ b/xen/arch/x86/cpu/common.c @@ -168,23 +168,8 @@ void ctxt_switch_levelling(const struct vcpu *next) */ if (nextd && is_idle_domain(nextd)) return; - /* - * We *should* be enabling faulting for the control domain. - * - * Unfortunately, the domain builder (having only ever been a - * PV guest) expects to be able to see host cpuid state in a - * native CPUID instruction, to correctly build a CPUID policy - * for HVM guests (notably the xstate leaves). - * - * This logic is fundimentally broken for HVM toolstack - * domains, and faulting causes PV guests to behave like HVM - * guests from their point of view. - * - * Future development plans will move responsibility for - * generating the maximum full cpuid policy into Xen, at which - * this problem will disappear. - */ - set_cpuid_faulting(nextd && !is_control_domain(nextd) && + + set_cpuid_faulting(nextd && (is_pv_domain(nextd) || next->arch.msrs-> misc_features_enables.cpuid_faulting));