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; }