From nobody Tue Feb 10 01:32:53 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) client-ip=192.237.175.120; envelope-from=xen-devel-bounces@lists.xenproject.org; helo=lists.xenproject.org; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass(p=reject dis=none) header.from=citrix.com ARC-Seal: i=1; a=rsa-sha256; t=1680602371; cv=none; d=zohomail.com; s=zohoarc; b=jxz9MvAuPLg7h/Npa2Ca5JsxfUXQa74u1yvxD0uIyCmkqgb9FFWnCDlDAtV0if41q+HxPeD10pms69IcZZCSaad/lm87ZYNaPsJ5DK4Mef3LNdkLLp8xKMGpoRADnpppldSpIx3x8Gbq6oXzI7tUBuNz0Uiom7c+bDNxCD5mXBU= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1680602371; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=h2PNUbManLroqpvULURuqEBdscRic+9RDc5G1ajVsBY=; b=hmGHWdL7H/xXkWTi3LqUuxJrv2psiZcBDcvjGkt6XSlsSEsk/4HcmX19Ez8ZwhmBSqXSu8HkupEEKNu84pyHRM/HVtB9U6Km8JPEQ6Avetv3VABvGTolBxec+CXPOwJFF2q75mqNhdcRG84Yk3N4KCgJjHl41SlhRLtCV7Cehwo= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass header.from= (p=reject dis=none) Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 1680602371528627.0574667496224; Tue, 4 Apr 2023 02:59:31 -0700 (PDT) Received: from list by lists.xenproject.org with outflank-mailman.517745.803559 (Exim 4.92) (envelope-from ) id 1pjdRK-00037Y-Hw; Tue, 04 Apr 2023 09:58:58 +0000 Received: by outflank-mailman (output) from mailman id 517745.803559; Tue, 04 Apr 2023 09:58:58 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1pjdRK-00037R-Eu; Tue, 04 Apr 2023 09:58:58 +0000 Received: by outflank-mailman (input) for mailman id 517745; Tue, 04 Apr 2023 09:58:56 +0000 Received: from se1-gles-sth1-in.inumbo.com ([159.253.27.254] helo=se1-gles-sth1.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1pjdMR-0005bo-Qm for xen-devel@lists.xenproject.org; Tue, 04 Apr 2023 09:53:56 +0000 Received: from esa1.hc3370-68.iphmx.com (esa1.hc3370-68.iphmx.com [216.71.145.142]) by se1-gles-sth1.inumbo.com (Halon) with ESMTPS id 9a1b42c3-d2ce-11ed-85db-49a42c6b2330; Tue, 04 Apr 2023 11:53:52 +0200 (CEST) X-Outflank-Mailman: Message body and most headers restored to incoming version X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" X-Inumbo-ID: 9a1b42c3-d2ce-11ed-85db-49a42c6b2330 DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=citrix.com; s=securemail; t=1680602032; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=+gBx+55wWG2Xc8HbkdAE6jzV3hAbtN970XBfRirIXxI=; b=UCF0+KPNPzktodWBff3mT/1jmkk0sEMy6VSSA8VMX2UUtV0oh57Ss0sO KG3xCyeBEas0u6P0n3/FCXgn8oW4wVG0ROtacZybgn0SYnw3z55kgUjvf WxQVDTpi5uYQadEGOEFBSGMI/yiKW+c9mk18QQDhmYNv1PcmoK1OCiEky k=; Authentication-Results: esa1.hc3370-68.iphmx.com; dkim=none (message not signed) header.i=none X-SBRS: 4.0 X-MesageID: 104656675 X-Ironport-Server: esa1.hc3370-68.iphmx.com X-Remote-IP: 162.221.156.123 X-Policy: $RELAYED IronPort-Data: A9a23:uS3LlKIe1D1PhJBLFE+RrpUlxSXFcZb7ZxGr2PjKsXjdYENS0mMCm 2sYXW+OOvnfZ2TxcoxyaYTjpE5XusPdyoc2QAtlqX01Q3x08seUXt7xwmUcnc+xBpaaEB84t ZV2hv3odp1coqr0/0/1WlTZhSAgk/rOHvykU7Ss1hlZHWdMUD0mhQ9oh9k3i4tphcnRKw6Ws Jb5rta31GWNglaYCUpJrfPTwP9TlK6q4mhA4gRiPakjUGL2zBH5MrpOfcldEFOgKmVkNrbSb /rOyri/4lTY838FYj9yuu+mGqGiaue60Tmm0hK6aYD76vRxjnVaPpIAHOgdcS9qZwChxLid/ jnvWauYEm/FNoWU8AgUvoIx/ytWZcWq85efSZSzXFD6I+QrvBIAzt03ZHzaM7H09c56AFhr5 P4KDQwqVSyYmfDm5aiSUu9z05FLwMnDZOvzu1llxDDdS/0nXYrCU+PB4towMDUY354UW6yEP oxANGQpNU6bC/FMEg5/5JYWteGknHTgNRZfr0qYv/Ef6GnP1g1hlrPqNbI5f/TTHZkLwxjG+ T+uE2LRBwBGbYOGkQS+ryijj8nQsAb8UbkwG+jtnhJtqALKnTFCYPEMbnOrrP/8hkOgVtZ3L 00P5jFovaU07FasTNT2Q1u/unHsljw2VsdUEuY6wBqQ0aeS6AGcbkAbShZRZdpgs9U5LQHGz XfQwYmvX2Y29uTIFzTErOz8QS6O1TY9IG47QD4GXy45xOLfu58h3jfVZ85lD/vg5jHqIg0c0 wxmvQBn2eVL0JFVjfrilbzUq2ny/8aUF2bZ8i2SBzv4tV0hOeZJcqTysTDmAeB8wJF1p7Vrl FwNgICg4e8HFvlhfwTdEbxWTNlFCxtoWQAwYGKD/LF7rVxBA1b5IehtDMhWfS+FyPosdz7ze 1P0sghM/pJVN3bCRfYpM9rsV5p7l/O6S4SNuhXogj1mO8AZSeN61Hs2OR74M57FyyDAbp3Ty b/EKJ3xXB72+IxszSasRvd17ILHMhsWnDuJLbiilkTP7FZrTCLNIVvzGAfUP79RAWLtiFm9z uuzwOPRlEoDCrSiPXCHmWPRRHhTRUUG6VnNg5Q/Xoa+zsBOQgnN19e5LWsdRrFY IronPort-HdrOrdr: A9a23:xxqf5a2COqozSHZlDIYQaQqjBHYkLtp133Aq2lEZdPU0SKGlfq GV7ZEmPHrP4gr5N0tOpTntAse9qBDnhPxICOsqXYtKNTOO0AeVxelZhrcKqAeQeBEWmNQ96U 9hGZIOcuEZDzJB/LvHCN/TKadd/DGFmprY+ts31x1WPGVXgzkL1XYANu6ceHcGIzVuNN4CO7 e3wNFInDakcWR/VLXBOpFUN9KzweEijfjdEGc7OyI= X-IronPort-AV: E=Sophos;i="5.98,317,1673931600"; d="scan'208";a="104656675" From: Andrew Cooper To: Xen-devel CC: Andrew Cooper , Jan Beulich , =?UTF-8?q?Roger=20Pau=20Monn=C3=A9?= , Wei Liu Subject: [PATCH v2 11/15] x86/boot: Merge CPUID policy initialisation logic into cpu-policy.c Date: Tue, 4 Apr 2023 10:52:18 +0100 Message-ID: <20230404095222.1373721-12-andrew.cooper3@citrix.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20230404095222.1373721-1-andrew.cooper3@citrix.com> References: <20230404095222.1373721-1-andrew.cooper3@citrix.com> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-ZohoMail-DKIM: pass (identity @citrix.com) X-ZM-MESSAGEID: 1680602373769100001 Switch to the newer cpu_policy nomenclature. Do some easy cleanup of includes. No practical change. Signed-off-by: Andrew Cooper Acked-by: Jan Beulich --- CC: Jan Beulich CC: Roger Pau Monn=C3=A9 CC: Wei Liu v2: * New --- xen/arch/x86/cpu-policy.c | 752 ++++++++++++++++++++++++ xen/arch/x86/cpuid.c | 817 +------------------------- xen/arch/x86/hvm/hvm.c | 1 - xen/arch/x86/include/asm/cpu-policy.h | 6 + xen/arch/x86/include/asm/cpuid.h | 11 +- xen/arch/x86/pv/domain.c | 1 + xen/arch/x86/setup.c | 2 - 7 files changed, 764 insertions(+), 826 deletions(-) diff --git a/xen/arch/x86/cpu-policy.c b/xen/arch/x86/cpu-policy.c index f6a2317ed7bd..83186e940ca7 100644 --- a/xen/arch/x86/cpu-policy.c +++ b/xen/arch/x86/cpu-policy.c @@ -1,13 +1,19 @@ /* SPDX-License-Identifier: GPL-2.0-or-later */ #include #include +#include #include =20 #include =20 +#include #include +#include +#include #include +#include #include +#include =20 struct cpu_policy __ro_after_init raw_cpu_policy; struct cpu_policy __ro_after_init host_cpu_policy; @@ -20,10 +26,332 @@ struct cpu_policy __ro_after_init hvm_max_cpu_policy; struct cpu_policy __ro_after_init hvm_def_cpu_policy; #endif =20 +const uint32_t known_features[] =3D INIT_KNOWN_FEATURES; + +static const uint32_t __initconst pv_max_featuremask[] =3D INIT_PV_MAX_FEA= TURES; +static const uint32_t hvm_shadow_max_featuremask[] =3D INIT_HVM_SHADOW_MAX= _FEATURES; +static const uint32_t __initconst hvm_hap_max_featuremask[] =3D + INIT_HVM_HAP_MAX_FEATURES; +static const uint32_t __initconst pv_def_featuremask[] =3D INIT_PV_DEF_FEA= TURES; +static const uint32_t __initconst hvm_shadow_def_featuremask[] =3D + INIT_HVM_SHADOW_DEF_FEATURES; +static const uint32_t __initconst hvm_hap_def_featuremask[] =3D + INIT_HVM_HAP_DEF_FEATURES; +static const uint32_t deep_features[] =3D INIT_DEEP_FEATURES; + +static const struct feature_name { + const char *name; + unsigned int bit; +} feature_names[] __initconstrel =3D INIT_FEATURE_NAMES; + +/* + * Parse a list of cpuid feature names -> bool, calling the callback for a= ny + * matches found. + * + * always_inline, because this is init code only and we really don't want a + * function pointer call in the middle of the loop. + */ +static int __init always_inline parse_cpuid( + const char *s, void (*callback)(unsigned int feat, bool val)) +{ + const char *ss; + int val, rc =3D 0; + + do { + const struct feature_name *lhs, *rhs, *mid =3D NULL /* GCC... */; + const char *feat; + + ss =3D strchr(s, ','); + if ( !ss ) + ss =3D strchr(s, '\0'); + + /* Skip the 'no-' prefix for name comparisons. */ + feat =3D s; + if ( strncmp(s, "no-", 3) =3D=3D 0 ) + feat +=3D 3; + + /* (Re)initalise lhs and rhs for binary search. */ + lhs =3D feature_names; + rhs =3D feature_names + ARRAY_SIZE(feature_names); + + while ( lhs < rhs ) + { + int res; + + mid =3D lhs + (rhs - lhs) / 2; + res =3D cmdline_strcmp(feat, mid->name); + + if ( res < 0 ) + { + rhs =3D mid; + continue; + } + if ( res > 0 ) + { + lhs =3D mid + 1; + continue; + } + + if ( (val =3D parse_boolean(mid->name, s, ss)) >=3D 0 ) + { + callback(mid->bit, val); + mid =3D NULL; + } + + break; + } + + /* + * Mid being NULL means that the name and boolean were successfully + * identified. Everything else is an error. + */ + if ( mid ) + rc =3D -EINVAL; + + s =3D ss + 1; + } while ( *ss ); + + return rc; +} + +static void __init cf_check _parse_xen_cpuid(unsigned int feat, bool val) +{ + if ( !val ) + setup_clear_cpu_cap(feat); + else if ( feat =3D=3D X86_FEATURE_RDRAND && + (cpuid_ecx(1) & cpufeat_mask(X86_FEATURE_RDRAND)) ) + setup_force_cpu_cap(X86_FEATURE_RDRAND); +} + +static int __init cf_check parse_xen_cpuid(const char *s) +{ + return parse_cpuid(s, _parse_xen_cpuid); +} +custom_param("cpuid", parse_xen_cpuid); + +static bool __initdata dom0_cpuid_cmdline; +static uint32_t __initdata dom0_enable_feat[FSCAPINTS]; +static uint32_t __initdata dom0_disable_feat[FSCAPINTS]; + +static void __init cf_check _parse_dom0_cpuid(unsigned int feat, bool val) +{ + __set_bit (feat, val ? dom0_enable_feat : dom0_disable_feat); + __clear_bit(feat, val ? dom0_disable_feat : dom0_enable_feat ); +} + +static int __init cf_check parse_dom0_cpuid(const char *s) +{ + dom0_cpuid_cmdline =3D true; + + return parse_cpuid(s, _parse_dom0_cpuid); +} +custom_param("dom0-cpuid", parse_dom0_cpuid); + +#define EMPTY_LEAF ((struct cpuid_leaf){}) +static void zero_leaves(struct cpuid_leaf *l, + unsigned int first, unsigned int last) +{ + memset(&l[first], 0, sizeof(*l) * (last - first + 1)); +} + +static void sanitise_featureset(uint32_t *fs) +{ + /* for_each_set_bit() uses unsigned longs. Extend with zeroes. */ + uint32_t disabled_features[ + ROUNDUP(FSCAPINTS, sizeof(unsigned long)/sizeof(uint32_t))] =3D {}; + unsigned int i; + + for ( i =3D 0; i < FSCAPINTS; ++i ) + { + /* Clamp to known mask. */ + fs[i] &=3D known_features[i]; + + /* + * Identify which features with deep dependencies have been + * disabled. + */ + disabled_features[i] =3D ~fs[i] & deep_features[i]; + } + + for_each_set_bit(i, (void *)disabled_features, + sizeof(disabled_features) * 8) + { + const uint32_t *dfs =3D x86_cpuid_lookup_deep_deps(i); + unsigned int j; + + ASSERT(dfs); /* deep_features[] should guarentee this. */ + + for ( j =3D 0; j < FSCAPINTS; ++j ) + { + fs[j] &=3D ~dfs[j]; + disabled_features[j] &=3D ~dfs[j]; + } + } +} + +static void recalculate_xstate(struct cpu_policy *p) +{ + uint64_t xstates =3D XSTATE_FP_SSE; + uint32_t xstate_size =3D XSTATE_AREA_MIN_SIZE; + unsigned int i, Da1 =3D p->xstate.Da1; + + /* + * The Da1 leaf is the only piece of information preserved in the comm= on + * case. Everything else is derived from other feature state. + */ + memset(&p->xstate, 0, sizeof(p->xstate)); + + if ( !p->basic.xsave ) + return; + + if ( p->basic.avx ) + { + xstates |=3D X86_XCR0_YMM; + xstate_size =3D max(xstate_size, + xstate_offsets[X86_XCR0_YMM_POS] + + xstate_sizes[X86_XCR0_YMM_POS]); + } + + if ( p->feat.mpx ) + { + xstates |=3D X86_XCR0_BNDREGS | X86_XCR0_BNDCSR; + xstate_size =3D max(xstate_size, + xstate_offsets[X86_XCR0_BNDCSR_POS] + + xstate_sizes[X86_XCR0_BNDCSR_POS]); + } + + if ( p->feat.avx512f ) + { + xstates |=3D X86_XCR0_OPMASK | X86_XCR0_ZMM | X86_XCR0_HI_ZMM; + xstate_size =3D max(xstate_size, + xstate_offsets[X86_XCR0_HI_ZMM_POS] + + xstate_sizes[X86_XCR0_HI_ZMM_POS]); + } + + if ( p->feat.pku ) + { + xstates |=3D X86_XCR0_PKRU; + xstate_size =3D max(xstate_size, + xstate_offsets[X86_XCR0_PKRU_POS] + + xstate_sizes[X86_XCR0_PKRU_POS]); + } + + p->xstate.max_size =3D xstate_size; + p->xstate.xcr0_low =3D xstates & ~XSTATE_XSAVES_ONLY; + p->xstate.xcr0_high =3D (xstates & ~XSTATE_XSAVES_ONLY) >> 32; + + p->xstate.Da1 =3D Da1; + if ( p->xstate.xsaves ) + { + p->xstate.xss_low =3D xstates & XSTATE_XSAVES_ONLY; + p->xstate.xss_high =3D (xstates & XSTATE_XSAVES_ONLY) >> 32; + } + else + xstates &=3D ~XSTATE_XSAVES_ONLY; + + for ( i =3D 2; i < min(63ul, ARRAY_SIZE(p->xstate.comp)); ++i ) + { + uint64_t curr_xstate =3D 1ul << i; + + if ( !(xstates & curr_xstate) ) + continue; + + p->xstate.comp[i].size =3D xstate_sizes[i]; + p->xstate.comp[i].offset =3D xstate_offsets[i]; + p->xstate.comp[i].xss =3D curr_xstate & XSTATE_XSAVES_ONLY; + p->xstate.comp[i].align =3D curr_xstate & xstate_align; + } +} + +/* + * Misc adjustments to the policy. Mostly clobbering reserved fields and + * duplicating shared fields. Intentionally hidden fields are annotated. + */ +static void recalculate_misc(struct cpu_policy *p) +{ + p->basic.raw_fms &=3D 0x0fff0fff; /* Clobber Processor Type on Intel. = */ + p->basic.apic_id =3D 0; /* Dynamic. */ + + p->basic.raw[0x5] =3D EMPTY_LEAF; /* MONITOR not exposed to guests. */ + p->basic.raw[0x6] =3D EMPTY_LEAF; /* Therm/Power not exposed to guests= . */ + + p->basic.raw[0x8] =3D EMPTY_LEAF; + + /* TODO: Rework topology logic. */ + memset(p->topo.raw, 0, sizeof(p->topo.raw)); + + p->basic.raw[0xc] =3D EMPTY_LEAF; + + p->extd.e1d &=3D ~CPUID_COMMON_1D_FEATURES; + + /* Most of Power/RAS hidden from guests. */ + p->extd.raw[0x7].a =3D p->extd.raw[0x7].b =3D p->extd.raw[0x7].c =3D 0; + + p->extd.raw[0x8].d =3D 0; + + switch ( p->x86_vendor ) + { + case X86_VENDOR_INTEL: + p->basic.l2_nr_queries =3D 1; /* Fixed to 1 query. */ + p->basic.raw[0x3] =3D EMPTY_LEAF; /* PSN - always hidden. */ + p->basic.raw[0x9] =3D EMPTY_LEAF; /* DCA - always hidden. */ + + p->extd.vendor_ebx =3D 0; + p->extd.vendor_ecx =3D 0; + p->extd.vendor_edx =3D 0; + + p->extd.raw[0x1].a =3D p->extd.raw[0x1].b =3D 0; + + p->extd.raw[0x5] =3D EMPTY_LEAF; + p->extd.raw[0x6].a =3D p->extd.raw[0x6].b =3D p->extd.raw[0x6].d = =3D 0; + + p->extd.raw[0x8].a &=3D 0x0000ffff; + p->extd.raw[0x8].c =3D 0; + break; + + case X86_VENDOR_AMD: + case X86_VENDOR_HYGON: + zero_leaves(p->basic.raw, 0x2, 0x3); + memset(p->cache.raw, 0, sizeof(p->cache.raw)); + zero_leaves(p->basic.raw, 0x9, 0xa); + + p->extd.vendor_ebx =3D p->basic.vendor_ebx; + p->extd.vendor_ecx =3D p->basic.vendor_ecx; + p->extd.vendor_edx =3D p->basic.vendor_edx; + + p->extd.raw_fms =3D p->basic.raw_fms; + p->extd.raw[0x1].b &=3D 0xff00ffff; + p->extd.e1d |=3D p->basic._1d & CPUID_COMMON_1D_FEATURES; + + p->extd.raw[0x8].a &=3D 0x0000ffff; /* GuestMaxPhysAddr hidden. */ + p->extd.raw[0x8].c &=3D 0x0003f0ff; + + p->extd.raw[0x9] =3D EMPTY_LEAF; + + zero_leaves(p->extd.raw, 0xb, 0x18); + + /* 0x19 - TLB details. Pass through. */ + /* 0x1a - Perf hints. Pass through. */ + + p->extd.raw[0x1b] =3D EMPTY_LEAF; /* IBS - not supported. */ + p->extd.raw[0x1c] =3D EMPTY_LEAF; /* LWP - not supported. */ + p->extd.raw[0x1d] =3D EMPTY_LEAF; /* TopoExt Cache */ + p->extd.raw[0x1e] =3D EMPTY_LEAF; /* TopoExt APIC ID/Core/Node */ + p->extd.raw[0x1f] =3D EMPTY_LEAF; /* SEV */ + p->extd.raw[0x20] =3D EMPTY_LEAF; /* Platform QoS */ + break; + } +} + static void __init calculate_raw_policy(void) { struct cpu_policy *p =3D &raw_cpu_policy; =20 + x86_cpuid_policy_fill_native(p); + + /* Nothing good will come from Xen and libx86 disagreeing on vendor. */ + ASSERT(p->x86_vendor =3D=3D boot_cpu_data.x86_vendor); + /* 0x000000ce MSR_INTEL_PLATFORM_INFO */ /* Was already added by probe_cpuid_faulting() */ =20 @@ -34,9 +362,50 @@ static void __init calculate_raw_policy(void) static void __init calculate_host_policy(void) { struct cpu_policy *p =3D &host_cpu_policy; + unsigned int max_extd_leaf; =20 *p =3D raw_cpu_policy; =20 + p->basic.max_leaf =3D + min_t(uint32_t, p->basic.max_leaf, ARRAY_SIZE(p->basic.raw) - 1); + p->feat.max_subleaf =3D + min_t(uint32_t, p->feat.max_subleaf, ARRAY_SIZE(p->feat.raw) - 1); + + max_extd_leaf =3D p->extd.max_leaf; + + /* + * For AMD/Hygon hardware before Zen3, we unilaterally modify LFENCE t= o be + * dispatch serialising for Spectre mitigations. Extend max_extd_leaf + * beyond what hardware supports, to include the feature leaf containi= ng + * this information. + */ + if ( cpu_has_lfence_dispatch ) + max_extd_leaf =3D max(max_extd_leaf, 0x80000021); + + p->extd.max_leaf =3D 0x80000000 | min_t(uint32_t, max_extd_leaf & 0xff= ff, + ARRAY_SIZE(p->extd.raw) - 1); + + x86_cpu_featureset_to_policy(boot_cpu_data.x86_capability, p); + recalculate_xstate(p); + recalculate_misc(p); + + /* When vPMU is disabled, drop it from the host policy. */ + if ( vpmu_mode =3D=3D XENPMU_MODE_OFF ) + p->basic.raw[0xa] =3D EMPTY_LEAF; + + if ( p->extd.svm ) + { + /* Clamp to implemented features which require hardware support. */ + p->extd.raw[0xa].d &=3D ((1u << SVM_FEATURE_NPT) | + (1u << SVM_FEATURE_LBRV) | + (1u << SVM_FEATURE_NRIPS) | + (1u << SVM_FEATURE_PAUSEFILTER) | + (1u << SVM_FEATURE_DECODEASSISTS)); + /* Enable features which are always emulated. */ + p->extd.raw[0xa].d |=3D ((1u << SVM_FEATURE_VMCBCLEAN) | + (1u << SVM_FEATURE_TSCRATEMSR)); + } + /* 0x000000ce MSR_INTEL_PLATFORM_INFO */ /* probe_cpuid_faulting() sanity checks presence of MISC_FEATURES_ENAB= LES */ p->platform_info.cpuid_faulting =3D cpu_has_cpuid_faulting; @@ -51,11 +420,88 @@ static void __init calculate_host_policy(void) ARCH_CAPS_PBRSB_NO); } =20 +static void __init guest_common_default_feature_adjustments(uint32_t *fs) +{ + /* + * IvyBridge client parts suffer from leakage of RDRAND data due to SR= BDS + * (XSA-320 / CVE-2020-0543), and won't be receiving microcode to + * compensate. + * + * Mitigate by hiding RDRAND from guests by default, unless explicitly + * overridden on the Xen command line (cpuid=3Drdrand). Irrespective = of the + * default setting, guests can use RDRAND if explicitly enabled + * (cpuid=3D"host,rdrand=3D1") in the VM's config file, and VMs which = were + * previously using RDRAND can migrate in. + */ + if ( boot_cpu_data.x86_vendor =3D=3D X86_VENDOR_INTEL && + boot_cpu_data.x86 =3D=3D 6 && boot_cpu_data.x86_model =3D=3D 0x3a= && + cpu_has_rdrand && !is_forced_cpu_cap(X86_FEATURE_RDRAND) ) + __clear_bit(X86_FEATURE_RDRAND, fs); + + /* + * On certain hardware, speculative or errata workarounds can result in + * TSX being placed in "force-abort" mode, where it doesn't actually + * function as expected, but is technically compatible with the ISA. + * + * Do not advertise RTM to guests by default if it won't actually work. + */ + if ( rtm_disabled ) + __clear_bit(X86_FEATURE_RTM, fs); +} + +static void __init guest_common_feature_adjustments(uint32_t *fs) +{ + /* Unconditionally claim to be able to set the hypervisor bit. */ + __set_bit(X86_FEATURE_HYPERVISOR, fs); + + /* + * If IBRS is offered to the guest, unconditionally offer STIBP. It i= s a + * nop on non-HT hardware, and has this behaviour to make heterogeneous + * setups easier to manage. + */ + if ( test_bit(X86_FEATURE_IBRSB, fs) ) + __set_bit(X86_FEATURE_STIBP, fs); + if ( test_bit(X86_FEATURE_IBRS, fs) ) + __set_bit(X86_FEATURE_AMD_STIBP, fs); + + /* + * On hardware which supports IBRS/IBPB, we can offer IBPB independent= ly + * of IBRS by using the AMD feature bit. An administrator may wish for + * performance reasons to offer IBPB without IBRS. + */ + if ( host_cpu_policy.feat.ibrsb ) + __set_bit(X86_FEATURE_IBPB, fs); +} + static void __init calculate_pv_max_policy(void) { struct cpu_policy *p =3D &pv_max_cpu_policy; + uint32_t fs[FSCAPINTS]; + unsigned int i; =20 *p =3D host_cpu_policy; + x86_cpu_policy_to_featureset(p, fs); + + for ( i =3D 0; i < ARRAY_SIZE(fs); ++i ) + fs[i] &=3D pv_max_featuremask[i]; + + /* + * If Xen isn't virtualising MSR_SPEC_CTRL for PV guests (functional + * availability, or admin choice), hide the feature. + */ + if ( !boot_cpu_has(X86_FEATURE_SC_MSR_PV) ) + { + __clear_bit(X86_FEATURE_IBRSB, fs); + __clear_bit(X86_FEATURE_IBRS, fs); + } + + guest_common_feature_adjustments(fs); + + sanitise_featureset(fs); + x86_cpu_featureset_to_policy(fs, p); + recalculate_xstate(p); + + p->extd.raw[0xa] =3D EMPTY_LEAF; /* No SVM for PV guests. */ =20 p->arch_caps.raw =3D 0; /* Not supported yet. */ } @@ -63,15 +509,112 @@ static void __init calculate_pv_max_policy(void) static void __init calculate_pv_def_policy(void) { struct cpu_policy *p =3D &pv_def_cpu_policy; + uint32_t fs[FSCAPINTS]; + unsigned int i; =20 *p =3D pv_max_cpu_policy; + x86_cpu_policy_to_featureset(p, fs); + + for ( i =3D 0; i < ARRAY_SIZE(fs); ++i ) + fs[i] &=3D pv_def_featuremask[i]; + + guest_common_feature_adjustments(fs); + guest_common_default_feature_adjustments(fs); + + sanitise_featureset(fs); + x86_cpu_featureset_to_policy(fs, p); + recalculate_xstate(p); } =20 static void __init calculate_hvm_max_policy(void) { struct cpu_policy *p =3D &hvm_max_cpu_policy; + uint32_t fs[FSCAPINTS]; + unsigned int i; + const uint32_t *mask; =20 *p =3D host_cpu_policy; + x86_cpu_policy_to_featureset(p, fs); + + mask =3D hvm_hap_supported() ? + hvm_hap_max_featuremask : hvm_shadow_max_featuremask; + + for ( i =3D 0; i < ARRAY_SIZE(fs); ++i ) + fs[i] &=3D mask[i]; + + /* + * Xen can provide an (x2)APIC emulation to HVM guests even if the hos= t's + * (x2)APIC isn't enabled. + */ + __set_bit(X86_FEATURE_APIC, fs); + __set_bit(X86_FEATURE_X2APIC, fs); + + /* + * We don't support EFER.LMSLE at all. AMD has dropped the feature fr= om + * hardware and allocated a CPUID bit to indicate its absence. + */ + __set_bit(X86_FEATURE_NO_LMSL, fs); + + /* + * On AMD, PV guests are entirely unable to use SYSENTER as Xen runs in + * long mode (and init_amd() has cleared it out of host capabilities),= but + * HVM guests are able if running in protected mode. + */ + if ( (boot_cpu_data.x86_vendor & (X86_VENDOR_AMD | X86_VENDOR_HYGON)) = && + raw_cpu_policy.basic.sep ) + __set_bit(X86_FEATURE_SEP, fs); + + /* + * VIRT_SSBD is exposed in the default policy as a result of + * amd_virt_spec_ctrl being set, it also needs exposing in the max pol= icy. + */ + if ( amd_virt_spec_ctrl ) + __set_bit(X86_FEATURE_VIRT_SSBD, fs); + + /* + * If Xen isn't virtualising MSR_SPEC_CTRL for HVM guests (functional + * availability, or admin choice), hide the feature. + */ + if ( !boot_cpu_has(X86_FEATURE_SC_MSR_HVM) ) + { + __clear_bit(X86_FEATURE_IBRSB, fs); + __clear_bit(X86_FEATURE_IBRS, fs); + } + else if ( boot_cpu_has(X86_FEATURE_AMD_SSBD) ) + /* + * If SPEC_CTRL.SSBD is available VIRT_SPEC_CTRL.SSBD can be expos= ed + * and implemented using the former. Expose in the max policy only= as + * the preference is for guests to use SPEC_CTRL.SSBD if available. + */ + __set_bit(X86_FEATURE_VIRT_SSBD, fs); + + /* + * With VT-x, some features are only supported by Xen if dedicated + * hardware support is also available. + */ + if ( cpu_has_vmx ) + { + if ( !cpu_has_vmx_mpx ) + __clear_bit(X86_FEATURE_MPX, fs); + + if ( !cpu_has_vmx_xsaves ) + __clear_bit(X86_FEATURE_XSAVES, fs); + } + + /* + * Xen doesn't use PKS, so the guest support for it has opted to not u= se + * the VMCS load/save controls for efficiency reasons. This depends on + * the exact vmentry/exit behaviour, so don't expose PKS in other + * situations until someone has cross-checked the behaviour for safety. + */ + if ( !cpu_has_vmx ) + __clear_bit(X86_FEATURE_PKS, fs); + + guest_common_feature_adjustments(fs); + + sanitise_featureset(fs); + x86_cpu_featureset_to_policy(fs, p); + recalculate_xstate(p); =20 /* It's always possible to emulate CPUID faulting for HVM guests */ p->platform_info.cpuid_faulting =3D true; @@ -82,8 +625,32 @@ static void __init calculate_hvm_max_policy(void) static void __init calculate_hvm_def_policy(void) { struct cpu_policy *p =3D &hvm_def_cpu_policy; + uint32_t fs[FSCAPINTS]; + unsigned int i; + const uint32_t *mask; =20 *p =3D hvm_max_cpu_policy; + x86_cpu_policy_to_featureset(p, fs); + + mask =3D hvm_hap_supported() ? + hvm_hap_def_featuremask : hvm_shadow_def_featuremask; + + for ( i =3D 0; i < ARRAY_SIZE(fs); ++i ) + fs[i] &=3D mask[i]; + + guest_common_feature_adjustments(fs); + guest_common_default_feature_adjustments(fs); + + /* + * Only expose VIRT_SSBD if AMD_SSBD is not available, and thus + * amd_virt_spec_ctrl is set. + */ + if ( amd_virt_spec_ctrl ) + __set_bit(X86_FEATURE_VIRT_SSBD, fs); + + sanitise_featureset(fs); + x86_cpu_featureset_to_policy(fs, p); + recalculate_xstate(p); } =20 void __init init_guest_cpu_policies(void) @@ -149,3 +716,188 @@ int init_domain_cpu_policy(struct domain *d) =20 return 0; } + +void recalculate_cpuid_policy(struct domain *d) +{ + struct cpu_policy *p =3D d->arch.cpuid; + const struct cpu_policy *max =3D is_pv_domain(d) + ? (IS_ENABLED(CONFIG_PV) ? &pv_max_cpu_policy : NULL) + : (IS_ENABLED(CONFIG_HVM) ? &hvm_max_cpu_policy : NULL); + uint32_t fs[FSCAPINTS], max_fs[FSCAPINTS]; + unsigned int i; + + if ( !max ) + { + ASSERT_UNREACHABLE(); + return; + } + + p->x86_vendor =3D x86_cpuid_lookup_vendor( + p->basic.vendor_ebx, p->basic.vendor_ecx, p->basic.vendor_edx); + + p->basic.max_leaf =3D min(p->basic.max_leaf, max->basic.max_leaf); + p->feat.max_subleaf =3D min(p->feat.max_subleaf, max->feat.max_subleaf= ); + p->extd.max_leaf =3D 0x80000000 | min(p->extd.max_leaf & 0xffff, + ((p->x86_vendor & (X86_VENDOR_A= MD | + X86_VENDOR_H= YGON)) + ? CPUID_GUEST_NR_EXTD_AMD + : CPUID_GUEST_NR_EXTD_INTEL) -= 1); + + x86_cpu_policy_to_featureset(p, fs); + x86_cpu_policy_to_featureset(max, max_fs); + + if ( is_hvm_domain(d) ) + { + /* + * HVM domains using Shadow paging have further restrictions on th= eir + * available paging features. + */ + if ( !hap_enabled(d) ) + { + for ( i =3D 0; i < ARRAY_SIZE(max_fs); i++ ) + max_fs[i] &=3D hvm_shadow_max_featuremask[i]; + } + + /* Hide nested-virt if it hasn't been explicitly configured. */ + if ( !nestedhvm_enabled(d) ) + { + __clear_bit(X86_FEATURE_VMX, max_fs); + __clear_bit(X86_FEATURE_SVM, max_fs); + } + } + + /* + * Allow the toolstack to set HTT, X2APIC and CMP_LEGACY. These bits + * affect how to interpret topology information in other cpuid leaves. + */ + __set_bit(X86_FEATURE_HTT, max_fs); + __set_bit(X86_FEATURE_X2APIC, max_fs); + __set_bit(X86_FEATURE_CMP_LEGACY, max_fs); + + /* + * 32bit PV domains can't use any Long Mode features, and cannot use + * SYSCALL on non-AMD hardware. + */ + if ( is_pv_32bit_domain(d) ) + { + __clear_bit(X86_FEATURE_LM, max_fs); + if ( !(boot_cpu_data.x86_vendor & (X86_VENDOR_AMD | X86_VENDOR_HYG= ON)) ) + __clear_bit(X86_FEATURE_SYSCALL, max_fs); + } + + /* Clamp the toolstacks choices to reality. */ + for ( i =3D 0; i < ARRAY_SIZE(fs); i++ ) + fs[i] &=3D max_fs[i]; + + if ( p->basic.max_leaf < XSTATE_CPUID ) + __clear_bit(X86_FEATURE_XSAVE, fs); + + sanitise_featureset(fs); + + /* Fold host's FDP_EXCP_ONLY and NO_FPU_SEL into guest's view. */ + fs[FEATURESET_7b0] &=3D ~(cpufeat_mask(X86_FEATURE_FDP_EXCP_ONLY) | + cpufeat_mask(X86_FEATURE_NO_FPU_SEL)); + fs[FEATURESET_7b0] |=3D (host_cpu_policy.feat._7b0 & + (cpufeat_mask(X86_FEATURE_FDP_EXCP_ONLY) | + cpufeat_mask(X86_FEATURE_NO_FPU_SEL))); + + x86_cpu_featureset_to_policy(fs, p); + + /* Pass host cacheline size through to guests. */ + p->basic.clflush_size =3D max->basic.clflush_size; + + p->extd.maxphysaddr =3D min(p->extd.maxphysaddr, max->extd.maxphysaddr= ); + p->extd.maxphysaddr =3D min_t(uint8_t, p->extd.maxphysaddr, + paging_max_paddr_bits(d)); + p->extd.maxphysaddr =3D max_t(uint8_t, p->extd.maxphysaddr, + (p->basic.pae || p->basic.pse36) ? 36 : 32= ); + + p->extd.maxlinaddr =3D p->extd.lm ? 48 : 32; + + recalculate_xstate(p); + recalculate_misc(p); + + for ( i =3D 0; i < ARRAY_SIZE(p->cache.raw); ++i ) + { + if ( p->cache.subleaf[i].type >=3D 1 && + p->cache.subleaf[i].type <=3D 3 ) + { + /* Subleaf has a valid cache type. Zero reserved fields. */ + p->cache.raw[i].a &=3D 0xffffc3ffu; + p->cache.raw[i].d &=3D 0x00000007u; + } + else + { + /* Subleaf is not valid. Zero the rest of the union. */ + zero_leaves(p->cache.raw, i, ARRAY_SIZE(p->cache.raw) - 1); + break; + } + } + + if ( vpmu_mode =3D=3D XENPMU_MODE_OFF || + ((vpmu_mode & XENPMU_MODE_ALL) && !is_hardware_domain(d)) ) + p->basic.raw[0xa] =3D EMPTY_LEAF; + + if ( !p->extd.svm ) + p->extd.raw[0xa] =3D EMPTY_LEAF; + + if ( !p->extd.page1gb ) + p->extd.raw[0x19] =3D EMPTY_LEAF; +} + +void __init init_dom0_cpuid_policy(struct domain *d) +{ + struct cpu_policy *p =3D d->arch.cpuid; + + /* dom0 can't migrate. Give it ITSC if available. */ + if ( cpu_has_itsc ) + p->extd.itsc =3D true; + + /* + * Expose the "hardware speculation behaviour" bits of ARCH_CAPS to do= m0, + * so dom0 can turn off workarounds as appropriate. Temporary, until = the + * domain policy logic gains a better understanding of MSRs. + */ + if ( cpu_has_arch_caps ) + p->feat.arch_caps =3D true; + + /* Apply dom0-cpuid=3D command line settings, if provided. */ + if ( dom0_cpuid_cmdline ) + { + uint32_t fs[FSCAPINTS]; + unsigned int i; + + x86_cpu_policy_to_featureset(p, fs); + + for ( i =3D 0; i < ARRAY_SIZE(fs); ++i ) + { + fs[i] |=3D dom0_enable_feat [i]; + fs[i] &=3D ~dom0_disable_feat[i]; + } + + x86_cpu_featureset_to_policy(fs, p); + + recalculate_cpuid_policy(d); + } +} + +static void __init __maybe_unused build_assertions(void) +{ + BUILD_BUG_ON(ARRAY_SIZE(known_features) !=3D FSCAPINTS); + BUILD_BUG_ON(ARRAY_SIZE(pv_max_featuremask) !=3D FSCAPINTS); + BUILD_BUG_ON(ARRAY_SIZE(hvm_shadow_max_featuremask) !=3D FSCAPINTS); + BUILD_BUG_ON(ARRAY_SIZE(hvm_hap_max_featuremask) !=3D FSCAPINTS); + BUILD_BUG_ON(ARRAY_SIZE(deep_features) !=3D FSCAPINTS); + + /* Find some more clever allocation scheme if this trips. */ + BUILD_BUG_ON(sizeof(struct cpu_policy) > PAGE_SIZE); + + BUILD_BUG_ON(sizeof(raw_cpu_policy.basic) !=3D + sizeof(raw_cpu_policy.basic.raw)); + BUILD_BUG_ON(sizeof(raw_cpu_policy.feat) !=3D + sizeof(raw_cpu_policy.feat.raw)); + BUILD_BUG_ON(sizeof(raw_cpu_policy.xstate) !=3D + sizeof(raw_cpu_policy.xstate.raw)); + BUILD_BUG_ON(sizeof(raw_cpu_policy.extd) !=3D + sizeof(raw_cpu_policy.extd.raw)); +} diff --git a/xen/arch/x86/cpuid.c b/xen/arch/x86/cpuid.c index 5eb5f1893516..3f20c342fde8 100644 --- a/xen/arch/x86/cpuid.c +++ b/xen/arch/x86/cpuid.c @@ -1,638 +1,14 @@ -#include -#include -#include #include -#include -#include +#include + +#include + #include #include -#include -#include -#include #include -#include -#include -#include #include =20 -const uint32_t known_features[] =3D INIT_KNOWN_FEATURES; - -static const uint32_t __initconst pv_max_featuremask[] =3D INIT_PV_MAX_FEA= TURES; -static const uint32_t hvm_shadow_max_featuremask[] =3D INIT_HVM_SHADOW_MAX= _FEATURES; -static const uint32_t __initconst hvm_hap_max_featuremask[] =3D - INIT_HVM_HAP_MAX_FEATURES; -static const uint32_t __initconst pv_def_featuremask[] =3D INIT_PV_DEF_FEA= TURES; -static const uint32_t __initconst hvm_shadow_def_featuremask[] =3D - INIT_HVM_SHADOW_DEF_FEATURES; -static const uint32_t __initconst hvm_hap_def_featuremask[] =3D - INIT_HVM_HAP_DEF_FEATURES; -static const uint32_t deep_features[] =3D INIT_DEEP_FEATURES; - -static const struct feature_name { - const char *name; - unsigned int bit; -} feature_names[] __initconstrel =3D INIT_FEATURE_NAMES; - -/* - * Parse a list of cpuid feature names -> bool, calling the callback for a= ny - * matches found. - * - * always_inline, because this is init code only and we really don't want a - * function pointer call in the middle of the loop. - */ -static int __init always_inline parse_cpuid( - const char *s, void (*callback)(unsigned int feat, bool val)) -{ - const char *ss; - int val, rc =3D 0; - - do { - const struct feature_name *lhs, *rhs, *mid =3D NULL /* GCC... */; - const char *feat; - - ss =3D strchr(s, ','); - if ( !ss ) - ss =3D strchr(s, '\0'); - - /* Skip the 'no-' prefix for name comparisons. */ - feat =3D s; - if ( strncmp(s, "no-", 3) =3D=3D 0 ) - feat +=3D 3; - - /* (Re)initalise lhs and rhs for binary search. */ - lhs =3D feature_names; - rhs =3D feature_names + ARRAY_SIZE(feature_names); - - while ( lhs < rhs ) - { - int res; - - mid =3D lhs + (rhs - lhs) / 2; - res =3D cmdline_strcmp(feat, mid->name); - - if ( res < 0 ) - { - rhs =3D mid; - continue; - } - if ( res > 0 ) - { - lhs =3D mid + 1; - continue; - } - - if ( (val =3D parse_boolean(mid->name, s, ss)) >=3D 0 ) - { - callback(mid->bit, val); - mid =3D NULL; - } - - break; - } - - /* - * Mid being NULL means that the name and boolean were successfully - * identified. Everything else is an error. - */ - if ( mid ) - rc =3D -EINVAL; - - s =3D ss + 1; - } while ( *ss ); - - return rc; -} - -static void __init cf_check _parse_xen_cpuid(unsigned int feat, bool val) -{ - if ( !val ) - setup_clear_cpu_cap(feat); - else if ( feat =3D=3D X86_FEATURE_RDRAND && - (cpuid_ecx(1) & cpufeat_mask(X86_FEATURE_RDRAND)) ) - setup_force_cpu_cap(X86_FEATURE_RDRAND); -} - -static int __init cf_check parse_xen_cpuid(const char *s) -{ - return parse_cpuid(s, _parse_xen_cpuid); -} -custom_param("cpuid", parse_xen_cpuid); - -static bool __initdata dom0_cpuid_cmdline; -static uint32_t __initdata dom0_enable_feat[FSCAPINTS]; -static uint32_t __initdata dom0_disable_feat[FSCAPINTS]; - -static void __init cf_check _parse_dom0_cpuid(unsigned int feat, bool val) -{ - __set_bit (feat, val ? dom0_enable_feat : dom0_disable_feat); - __clear_bit(feat, val ? dom0_disable_feat : dom0_enable_feat ); -} - -static int __init cf_check parse_dom0_cpuid(const char *s) -{ - dom0_cpuid_cmdline =3D true; - - return parse_cpuid(s, _parse_dom0_cpuid); -} -custom_param("dom0-cpuid", parse_dom0_cpuid); - #define EMPTY_LEAF ((struct cpuid_leaf){}) -static void zero_leaves(struct cpuid_leaf *l, - unsigned int first, unsigned int last) -{ - memset(&l[first], 0, sizeof(*l) * (last - first + 1)); -} - -static void sanitise_featureset(uint32_t *fs) -{ - /* for_each_set_bit() uses unsigned longs. Extend with zeroes. */ - uint32_t disabled_features[ - ROUNDUP(FSCAPINTS, sizeof(unsigned long)/sizeof(uint32_t))] =3D {}; - unsigned int i; - - for ( i =3D 0; i < FSCAPINTS; ++i ) - { - /* Clamp to known mask. */ - fs[i] &=3D known_features[i]; - - /* - * Identify which features with deep dependencies have been - * disabled. - */ - disabled_features[i] =3D ~fs[i] & deep_features[i]; - } - - for_each_set_bit(i, (void *)disabled_features, - sizeof(disabled_features) * 8) - { - const uint32_t *dfs =3D x86_cpuid_lookup_deep_deps(i); - unsigned int j; - - ASSERT(dfs); /* deep_features[] should guarentee this. */ - - for ( j =3D 0; j < FSCAPINTS; ++j ) - { - fs[j] &=3D ~dfs[j]; - disabled_features[j] &=3D ~dfs[j]; - } - } -} - -static void recalculate_xstate(struct cpuid_policy *p) -{ - uint64_t xstates =3D XSTATE_FP_SSE; - uint32_t xstate_size =3D XSTATE_AREA_MIN_SIZE; - unsigned int i, Da1 =3D p->xstate.Da1; - - /* - * The Da1 leaf is the only piece of information preserved in the comm= on - * case. Everything else is derived from other feature state. - */ - memset(&p->xstate, 0, sizeof(p->xstate)); - - if ( !p->basic.xsave ) - return; - - if ( p->basic.avx ) - { - xstates |=3D X86_XCR0_YMM; - xstate_size =3D max(xstate_size, - xstate_offsets[X86_XCR0_YMM_POS] + - xstate_sizes[X86_XCR0_YMM_POS]); - } - - if ( p->feat.mpx ) - { - xstates |=3D X86_XCR0_BNDREGS | X86_XCR0_BNDCSR; - xstate_size =3D max(xstate_size, - xstate_offsets[X86_XCR0_BNDCSR_POS] + - xstate_sizes[X86_XCR0_BNDCSR_POS]); - } - - if ( p->feat.avx512f ) - { - xstates |=3D X86_XCR0_OPMASK | X86_XCR0_ZMM | X86_XCR0_HI_ZMM; - xstate_size =3D max(xstate_size, - xstate_offsets[X86_XCR0_HI_ZMM_POS] + - xstate_sizes[X86_XCR0_HI_ZMM_POS]); - } - - if ( p->feat.pku ) - { - xstates |=3D X86_XCR0_PKRU; - xstate_size =3D max(xstate_size, - xstate_offsets[X86_XCR0_PKRU_POS] + - xstate_sizes[X86_XCR0_PKRU_POS]); - } - - p->xstate.max_size =3D xstate_size; - p->xstate.xcr0_low =3D xstates & ~XSTATE_XSAVES_ONLY; - p->xstate.xcr0_high =3D (xstates & ~XSTATE_XSAVES_ONLY) >> 32; - - p->xstate.Da1 =3D Da1; - if ( p->xstate.xsaves ) - { - p->xstate.xss_low =3D xstates & XSTATE_XSAVES_ONLY; - p->xstate.xss_high =3D (xstates & XSTATE_XSAVES_ONLY) >> 32; - } - else - xstates &=3D ~XSTATE_XSAVES_ONLY; - - for ( i =3D 2; i < min(63ul, ARRAY_SIZE(p->xstate.comp)); ++i ) - { - uint64_t curr_xstate =3D 1ul << i; - - if ( !(xstates & curr_xstate) ) - continue; - - p->xstate.comp[i].size =3D xstate_sizes[i]; - p->xstate.comp[i].offset =3D xstate_offsets[i]; - p->xstate.comp[i].xss =3D curr_xstate & XSTATE_XSAVES_ONLY; - p->xstate.comp[i].align =3D curr_xstate & xstate_align; - } -} - -/* - * Misc adjustments to the policy. Mostly clobbering reserved fields and - * duplicating shared fields. Intentionally hidden fields are annotated. - */ -static void recalculate_misc(struct cpuid_policy *p) -{ - p->basic.raw_fms &=3D 0x0fff0fff; /* Clobber Processor Type on Intel. = */ - p->basic.apic_id =3D 0; /* Dynamic. */ - - p->basic.raw[0x5] =3D EMPTY_LEAF; /* MONITOR not exposed to guests. */ - p->basic.raw[0x6] =3D EMPTY_LEAF; /* Therm/Power not exposed to guests= . */ - - p->basic.raw[0x8] =3D EMPTY_LEAF; - - /* TODO: Rework topology logic. */ - memset(p->topo.raw, 0, sizeof(p->topo.raw)); - - p->basic.raw[0xc] =3D EMPTY_LEAF; - - p->extd.e1d &=3D ~CPUID_COMMON_1D_FEATURES; - - /* Most of Power/RAS hidden from guests. */ - p->extd.raw[0x7].a =3D p->extd.raw[0x7].b =3D p->extd.raw[0x7].c =3D 0; - - p->extd.raw[0x8].d =3D 0; - - switch ( p->x86_vendor ) - { - case X86_VENDOR_INTEL: - p->basic.l2_nr_queries =3D 1; /* Fixed to 1 query. */ - p->basic.raw[0x3] =3D EMPTY_LEAF; /* PSN - always hidden. */ - p->basic.raw[0x9] =3D EMPTY_LEAF; /* DCA - always hidden. */ - - p->extd.vendor_ebx =3D 0; - p->extd.vendor_ecx =3D 0; - p->extd.vendor_edx =3D 0; - - p->extd.raw[0x1].a =3D p->extd.raw[0x1].b =3D 0; - - p->extd.raw[0x5] =3D EMPTY_LEAF; - p->extd.raw[0x6].a =3D p->extd.raw[0x6].b =3D p->extd.raw[0x6].d = =3D 0; - - p->extd.raw[0x8].a &=3D 0x0000ffff; - p->extd.raw[0x8].c =3D 0; - break; - - case X86_VENDOR_AMD: - case X86_VENDOR_HYGON: - zero_leaves(p->basic.raw, 0x2, 0x3); - memset(p->cache.raw, 0, sizeof(p->cache.raw)); - zero_leaves(p->basic.raw, 0x9, 0xa); - - p->extd.vendor_ebx =3D p->basic.vendor_ebx; - p->extd.vendor_ecx =3D p->basic.vendor_ecx; - p->extd.vendor_edx =3D p->basic.vendor_edx; - - p->extd.raw_fms =3D p->basic.raw_fms; - p->extd.raw[0x1].b &=3D 0xff00ffff; - p->extd.e1d |=3D p->basic._1d & CPUID_COMMON_1D_FEATURES; - - p->extd.raw[0x8].a &=3D 0x0000ffff; /* GuestMaxPhysAddr hidden. */ - p->extd.raw[0x8].c &=3D 0x0003f0ff; - - p->extd.raw[0x9] =3D EMPTY_LEAF; - - zero_leaves(p->extd.raw, 0xb, 0x18); - - /* 0x19 - TLB details. Pass through. */ - /* 0x1a - Perf hints. Pass through. */ - - p->extd.raw[0x1b] =3D EMPTY_LEAF; /* IBS - not supported. */ - p->extd.raw[0x1c] =3D EMPTY_LEAF; /* LWP - not supported. */ - p->extd.raw[0x1d] =3D EMPTY_LEAF; /* TopoExt Cache */ - p->extd.raw[0x1e] =3D EMPTY_LEAF; /* TopoExt APIC ID/Core/Node */ - p->extd.raw[0x1f] =3D EMPTY_LEAF; /* SEV */ - p->extd.raw[0x20] =3D EMPTY_LEAF; /* Platform QoS */ - break; - } -} - -static void __init calculate_raw_policy(void) -{ - struct cpuid_policy *p =3D &raw_cpu_policy; - - x86_cpuid_policy_fill_native(p); - - /* Nothing good will come from Xen and libx86 disagreeing on vendor. */ - ASSERT(p->x86_vendor =3D=3D boot_cpu_data.x86_vendor); -} - -static void __init calculate_host_policy(void) -{ - struct cpuid_policy *p =3D &host_cpu_policy; - unsigned int max_extd_leaf; - - *p =3D raw_cpu_policy; - - p->basic.max_leaf =3D - min_t(uint32_t, p->basic.max_leaf, ARRAY_SIZE(p->basic.raw) - 1); - p->feat.max_subleaf =3D - min_t(uint32_t, p->feat.max_subleaf, ARRAY_SIZE(p->feat.raw) - 1); - - max_extd_leaf =3D p->extd.max_leaf; - - /* - * For AMD/Hygon hardware before Zen3, we unilaterally modify LFENCE t= o be - * dispatch serialising for Spectre mitigations. Extend max_extd_leaf - * beyond what hardware supports, to include the feature leaf containi= ng - * this information. - */ - if ( cpu_has_lfence_dispatch ) - max_extd_leaf =3D max(max_extd_leaf, 0x80000021); - - p->extd.max_leaf =3D 0x80000000 | min_t(uint32_t, max_extd_leaf & 0xff= ff, - ARRAY_SIZE(p->extd.raw) - 1); - - x86_cpu_featureset_to_policy(boot_cpu_data.x86_capability, p); - recalculate_xstate(p); - recalculate_misc(p); - - /* When vPMU is disabled, drop it from the host policy. */ - if ( vpmu_mode =3D=3D XENPMU_MODE_OFF ) - p->basic.raw[0xa] =3D EMPTY_LEAF; - - if ( p->extd.svm ) - { - /* Clamp to implemented features which require hardware support. */ - p->extd.raw[0xa].d &=3D ((1u << SVM_FEATURE_NPT) | - (1u << SVM_FEATURE_LBRV) | - (1u << SVM_FEATURE_NRIPS) | - (1u << SVM_FEATURE_PAUSEFILTER) | - (1u << SVM_FEATURE_DECODEASSISTS)); - /* Enable features which are always emulated. */ - p->extd.raw[0xa].d |=3D ((1u << SVM_FEATURE_VMCBCLEAN) | - (1u << SVM_FEATURE_TSCRATEMSR)); - } -} - -static void __init guest_common_default_feature_adjustments(uint32_t *fs) -{ - /* - * IvyBridge client parts suffer from leakage of RDRAND data due to SR= BDS - * (XSA-320 / CVE-2020-0543), and won't be receiving microcode to - * compensate. - * - * Mitigate by hiding RDRAND from guests by default, unless explicitly - * overridden on the Xen command line (cpuid=3Drdrand). Irrespective = of the - * default setting, guests can use RDRAND if explicitly enabled - * (cpuid=3D"host,rdrand=3D1") in the VM's config file, and VMs which = were - * previously using RDRAND can migrate in. - */ - if ( boot_cpu_data.x86_vendor =3D=3D X86_VENDOR_INTEL && - boot_cpu_data.x86 =3D=3D 6 && boot_cpu_data.x86_model =3D=3D 0x3a= && - cpu_has_rdrand && !is_forced_cpu_cap(X86_FEATURE_RDRAND) ) - __clear_bit(X86_FEATURE_RDRAND, fs); - - /* - * On certain hardware, speculative or errata workarounds can result in - * TSX being placed in "force-abort" mode, where it doesn't actually - * function as expected, but is technically compatible with the ISA. - * - * Do not advertise RTM to guests by default if it won't actually work. - */ - if ( rtm_disabled ) - __clear_bit(X86_FEATURE_RTM, fs); -} - -static void __init guest_common_feature_adjustments(uint32_t *fs) -{ - /* Unconditionally claim to be able to set the hypervisor bit. */ - __set_bit(X86_FEATURE_HYPERVISOR, fs); - - /* - * If IBRS is offered to the guest, unconditionally offer STIBP. It i= s a - * nop on non-HT hardware, and has this behaviour to make heterogeneous - * setups easier to manage. - */ - if ( test_bit(X86_FEATURE_IBRSB, fs) ) - __set_bit(X86_FEATURE_STIBP, fs); - if ( test_bit(X86_FEATURE_IBRS, fs) ) - __set_bit(X86_FEATURE_AMD_STIBP, fs); - - /* - * On hardware which supports IBRS/IBPB, we can offer IBPB independent= ly - * of IBRS by using the AMD feature bit. An administrator may wish for - * performance reasons to offer IBPB without IBRS. - */ - if ( host_cpu_policy.feat.ibrsb ) - __set_bit(X86_FEATURE_IBPB, fs); -} - -static void __init calculate_pv_max_policy(void) -{ - struct cpuid_policy *p =3D &pv_max_cpu_policy; - uint32_t pv_featureset[FSCAPINTS]; - unsigned int i; - - *p =3D host_cpu_policy; - x86_cpu_policy_to_featureset(p, pv_featureset); - - for ( i =3D 0; i < ARRAY_SIZE(pv_featureset); ++i ) - pv_featureset[i] &=3D pv_max_featuremask[i]; - - /* - * If Xen isn't virtualising MSR_SPEC_CTRL for PV guests (functional - * availability, or admin choice), hide the feature. - */ - if ( !boot_cpu_has(X86_FEATURE_SC_MSR_PV) ) - { - __clear_bit(X86_FEATURE_IBRSB, pv_featureset); - __clear_bit(X86_FEATURE_IBRS, pv_featureset); - } - - guest_common_feature_adjustments(pv_featureset); - - sanitise_featureset(pv_featureset); - x86_cpu_featureset_to_policy(pv_featureset, p); - recalculate_xstate(p); - - p->extd.raw[0xa] =3D EMPTY_LEAF; /* No SVM for PV guests. */ -} - -static void __init calculate_pv_def_policy(void) -{ - struct cpuid_policy *p =3D &pv_def_cpu_policy; - uint32_t pv_featureset[FSCAPINTS]; - unsigned int i; - - *p =3D pv_max_cpu_policy; - x86_cpu_policy_to_featureset(p, pv_featureset); - - for ( i =3D 0; i < ARRAY_SIZE(pv_featureset); ++i ) - pv_featureset[i] &=3D pv_def_featuremask[i]; - - guest_common_feature_adjustments(pv_featureset); - guest_common_default_feature_adjustments(pv_featureset); - - sanitise_featureset(pv_featureset); - x86_cpu_featureset_to_policy(pv_featureset, p); - recalculate_xstate(p); -} - -static void __init calculate_hvm_max_policy(void) -{ - struct cpuid_policy *p =3D &hvm_max_cpu_policy; - uint32_t hvm_featureset[FSCAPINTS]; - unsigned int i; - const uint32_t *hvm_featuremask; - - *p =3D host_cpu_policy; - x86_cpu_policy_to_featureset(p, hvm_featureset); - - hvm_featuremask =3D hvm_hap_supported() ? - hvm_hap_max_featuremask : hvm_shadow_max_featuremask; - - for ( i =3D 0; i < ARRAY_SIZE(hvm_featureset); ++i ) - hvm_featureset[i] &=3D hvm_featuremask[i]; - - /* - * Xen can provide an (x2)APIC emulation to HVM guests even if the hos= t's - * (x2)APIC isn't enabled. - */ - __set_bit(X86_FEATURE_APIC, hvm_featureset); - __set_bit(X86_FEATURE_X2APIC, hvm_featureset); - - /* - * We don't support EFER.LMSLE at all. AMD has dropped the feature fr= om - * hardware and allocated a CPUID bit to indicate its absence. - */ - __set_bit(X86_FEATURE_NO_LMSL, hvm_featureset); - - /* - * On AMD, PV guests are entirely unable to use SYSENTER as Xen runs in - * long mode (and init_amd() has cleared it out of host capabilities),= but - * HVM guests are able if running in protected mode. - */ - if ( (boot_cpu_data.x86_vendor & (X86_VENDOR_AMD | X86_VENDOR_HYGON)) = && - raw_cpu_policy.basic.sep ) - __set_bit(X86_FEATURE_SEP, hvm_featureset); - - /* - * VIRT_SSBD is exposed in the default policy as a result of - * amd_virt_spec_ctrl being set, it also needs exposing in the max pol= icy. - */ - if ( amd_virt_spec_ctrl ) - __set_bit(X86_FEATURE_VIRT_SSBD, hvm_featureset); - - /* - * If Xen isn't virtualising MSR_SPEC_CTRL for HVM guests (functional - * availability, or admin choice), hide the feature. - */ - if ( !boot_cpu_has(X86_FEATURE_SC_MSR_HVM) ) - { - __clear_bit(X86_FEATURE_IBRSB, hvm_featureset); - __clear_bit(X86_FEATURE_IBRS, hvm_featureset); - } - else if ( boot_cpu_has(X86_FEATURE_AMD_SSBD) ) - /* - * If SPEC_CTRL.SSBD is available VIRT_SPEC_CTRL.SSBD can be expos= ed - * and implemented using the former. Expose in the max policy only= as - * the preference is for guests to use SPEC_CTRL.SSBD if available. - */ - __set_bit(X86_FEATURE_VIRT_SSBD, hvm_featureset); - - /* - * With VT-x, some features are only supported by Xen if dedicated - * hardware support is also available. - */ - if ( cpu_has_vmx ) - { - if ( !cpu_has_vmx_mpx ) - __clear_bit(X86_FEATURE_MPX, hvm_featureset); - - if ( !cpu_has_vmx_xsaves ) - __clear_bit(X86_FEATURE_XSAVES, hvm_featureset); - } - - /* - * Xen doesn't use PKS, so the guest support for it has opted to not u= se - * the VMCS load/save controls for efficiency reasons. This depends on - * the exact vmentry/exit behaviour, so don't expose PKS in other - * situations until someone has cross-checked the behaviour for safety. - */ - if ( !cpu_has_vmx ) - __clear_bit(X86_FEATURE_PKS, hvm_featureset); - - guest_common_feature_adjustments(hvm_featureset); - - sanitise_featureset(hvm_featureset); - x86_cpu_featureset_to_policy(hvm_featureset, p); - recalculate_xstate(p); -} - -static void __init calculate_hvm_def_policy(void) -{ - struct cpuid_policy *p =3D &hvm_def_cpu_policy; - uint32_t hvm_featureset[FSCAPINTS]; - unsigned int i; - const uint32_t *hvm_featuremask; - - *p =3D hvm_max_cpu_policy; - x86_cpu_policy_to_featureset(p, hvm_featureset); - - hvm_featuremask =3D hvm_hap_supported() ? - hvm_hap_def_featuremask : hvm_shadow_def_featuremask; - - for ( i =3D 0; i < ARRAY_SIZE(hvm_featureset); ++i ) - hvm_featureset[i] &=3D hvm_featuremask[i]; - - guest_common_feature_adjustments(hvm_featureset); - guest_common_default_feature_adjustments(hvm_featureset); - - /* - * Only expose VIRT_SSBD if AMD_SSBD is not available, and thus - * amd_virt_spec_ctrl is set. - */ - if ( amd_virt_spec_ctrl ) - __set_bit(X86_FEATURE_VIRT_SSBD, hvm_featureset); - - sanitise_featureset(hvm_featureset); - x86_cpu_featureset_to_policy(hvm_featureset, p); - recalculate_xstate(p); -} - -void __init init_guest_cpuid(void) -{ - calculate_raw_policy(); - calculate_host_policy(); - - if ( IS_ENABLED(CONFIG_PV) ) - { - calculate_pv_max_policy(); - calculate_pv_def_policy(); - } - - if ( hvm_enabled ) - { - calculate_hvm_max_policy(); - calculate_hvm_def_policy(); - } -} =20 bool recheck_cpu_features(unsigned int cpu) { @@ -656,170 +32,6 @@ bool recheck_cpu_features(unsigned int cpu) return okay; } =20 -void recalculate_cpuid_policy(struct domain *d) -{ - struct cpuid_policy *p =3D d->arch.cpuid; - const struct cpuid_policy *max =3D is_pv_domain(d) - ? (IS_ENABLED(CONFIG_PV) ? &pv_max_cpu_policy : NULL) - : (IS_ENABLED(CONFIG_HVM) ? &hvm_max_cpu_policy : NULL); - uint32_t fs[FSCAPINTS], max_fs[FSCAPINTS]; - unsigned int i; - - if ( !max ) - { - ASSERT_UNREACHABLE(); - return; - } - - p->x86_vendor =3D x86_cpuid_lookup_vendor( - p->basic.vendor_ebx, p->basic.vendor_ecx, p->basic.vendor_edx); - - p->basic.max_leaf =3D min(p->basic.max_leaf, max->basic.max_leaf); - p->feat.max_subleaf =3D min(p->feat.max_subleaf, max->feat.max_subleaf= ); - p->extd.max_leaf =3D 0x80000000 | min(p->extd.max_leaf & 0xffff, - ((p->x86_vendor & (X86_VENDOR_A= MD | - X86_VENDOR_H= YGON)) - ? CPUID_GUEST_NR_EXTD_AMD - : CPUID_GUEST_NR_EXTD_INTEL) -= 1); - - x86_cpu_policy_to_featureset(p, fs); - x86_cpu_policy_to_featureset(max, max_fs); - - if ( is_hvm_domain(d) ) - { - /* - * HVM domains using Shadow paging have further restrictions on th= eir - * available paging features. - */ - if ( !hap_enabled(d) ) - { - for ( i =3D 0; i < ARRAY_SIZE(max_fs); i++ ) - max_fs[i] &=3D hvm_shadow_max_featuremask[i]; - } - - /* Hide nested-virt if it hasn't been explicitly configured. */ - if ( !nestedhvm_enabled(d) ) - { - __clear_bit(X86_FEATURE_VMX, max_fs); - __clear_bit(X86_FEATURE_SVM, max_fs); - } - } - - /* - * Allow the toolstack to set HTT, X2APIC and CMP_LEGACY. These bits - * affect how to interpret topology information in other cpuid leaves. - */ - __set_bit(X86_FEATURE_HTT, max_fs); - __set_bit(X86_FEATURE_X2APIC, max_fs); - __set_bit(X86_FEATURE_CMP_LEGACY, max_fs); - - /* - * 32bit PV domains can't use any Long Mode features, and cannot use - * SYSCALL on non-AMD hardware. - */ - if ( is_pv_32bit_domain(d) ) - { - __clear_bit(X86_FEATURE_LM, max_fs); - if ( !(boot_cpu_data.x86_vendor & (X86_VENDOR_AMD | X86_VENDOR_HYG= ON)) ) - __clear_bit(X86_FEATURE_SYSCALL, max_fs); - } - - /* Clamp the toolstacks choices to reality. */ - for ( i =3D 0; i < ARRAY_SIZE(fs); i++ ) - fs[i] &=3D max_fs[i]; - - if ( p->basic.max_leaf < XSTATE_CPUID ) - __clear_bit(X86_FEATURE_XSAVE, fs); - - sanitise_featureset(fs); - - /* Fold host's FDP_EXCP_ONLY and NO_FPU_SEL into guest's view. */ - fs[FEATURESET_7b0] &=3D ~(cpufeat_mask(X86_FEATURE_FDP_EXCP_ONLY) | - cpufeat_mask(X86_FEATURE_NO_FPU_SEL)); - fs[FEATURESET_7b0] |=3D (host_cpu_policy.feat._7b0 & - (cpufeat_mask(X86_FEATURE_FDP_EXCP_ONLY) | - cpufeat_mask(X86_FEATURE_NO_FPU_SEL))); - - x86_cpu_featureset_to_policy(fs, p); - - /* Pass host cacheline size through to guests. */ - p->basic.clflush_size =3D max->basic.clflush_size; - - p->extd.maxphysaddr =3D min(p->extd.maxphysaddr, max->extd.maxphysaddr= ); - p->extd.maxphysaddr =3D min_t(uint8_t, p->extd.maxphysaddr, - paging_max_paddr_bits(d)); - p->extd.maxphysaddr =3D max_t(uint8_t, p->extd.maxphysaddr, - (p->basic.pae || p->basic.pse36) ? 36 : 32= ); - - p->extd.maxlinaddr =3D p->extd.lm ? 48 : 32; - - recalculate_xstate(p); - recalculate_misc(p); - - for ( i =3D 0; i < ARRAY_SIZE(p->cache.raw); ++i ) - { - if ( p->cache.subleaf[i].type >=3D 1 && - p->cache.subleaf[i].type <=3D 3 ) - { - /* Subleaf has a valid cache type. Zero reserved fields. */ - p->cache.raw[i].a &=3D 0xffffc3ffu; - p->cache.raw[i].d &=3D 0x00000007u; - } - else - { - /* Subleaf is not valid. Zero the rest of the union. */ - zero_leaves(p->cache.raw, i, ARRAY_SIZE(p->cache.raw) - 1); - break; - } - } - - if ( vpmu_mode =3D=3D XENPMU_MODE_OFF || - ((vpmu_mode & XENPMU_MODE_ALL) && !is_hardware_domain(d)) ) - p->basic.raw[0xa] =3D EMPTY_LEAF; - - if ( !p->extd.svm ) - p->extd.raw[0xa] =3D EMPTY_LEAF; - - if ( !p->extd.page1gb ) - p->extd.raw[0x19] =3D EMPTY_LEAF; -} - -void __init init_dom0_cpuid_policy(struct domain *d) -{ - struct cpuid_policy *p =3D d->arch.cpuid; - - /* dom0 can't migrate. Give it ITSC if available. */ - if ( cpu_has_itsc ) - p->extd.itsc =3D true; - - /* - * Expose the "hardware speculation behaviour" bits of ARCH_CAPS to do= m0, - * so dom0 can turn off workarounds as appropriate. Temporary, until = the - * domain policy logic gains a better understanding of MSRs. - */ - if ( cpu_has_arch_caps ) - p->feat.arch_caps =3D true; - - /* Apply dom0-cpuid=3D command line settings, if provided. */ - if ( dom0_cpuid_cmdline ) - { - uint32_t fs[FSCAPINTS]; - unsigned int i; - - x86_cpu_policy_to_featureset(p, fs); - - for ( i =3D 0; i < ARRAY_SIZE(fs); ++i ) - { - fs[i] |=3D dom0_enable_feat [i]; - fs[i] &=3D ~dom0_disable_feat[i]; - } - - x86_cpu_featureset_to_policy(fs, p); - - recalculate_cpuid_policy(d); - } -} - void guest_cpuid(const struct vcpu *v, uint32_t leaf, uint32_t subleaf, struct cpuid_leaf *res) { @@ -1190,27 +402,6 @@ void guest_cpuid(const struct vcpu *v, uint32_t leaf, } } =20 -static void __init __maybe_unused build_assertions(void) -{ - BUILD_BUG_ON(ARRAY_SIZE(known_features) !=3D FSCAPINTS); - BUILD_BUG_ON(ARRAY_SIZE(pv_max_featuremask) !=3D FSCAPINTS); - BUILD_BUG_ON(ARRAY_SIZE(hvm_shadow_max_featuremask) !=3D FSCAPINTS); - BUILD_BUG_ON(ARRAY_SIZE(hvm_hap_max_featuremask) !=3D FSCAPINTS); - BUILD_BUG_ON(ARRAY_SIZE(deep_features) !=3D FSCAPINTS); - - /* Find some more clever allocation scheme if this trips. */ - BUILD_BUG_ON(sizeof(struct cpuid_policy) > PAGE_SIZE); - - BUILD_BUG_ON(sizeof(raw_cpu_policy.basic) !=3D - sizeof(raw_cpu_policy.basic.raw)); - BUILD_BUG_ON(sizeof(raw_cpu_policy.feat) !=3D - sizeof(raw_cpu_policy.feat.raw)); - BUILD_BUG_ON(sizeof(raw_cpu_policy.xstate) !=3D - sizeof(raw_cpu_policy.xstate.raw)); - BUILD_BUG_ON(sizeof(raw_cpu_policy.extd) !=3D - sizeof(raw_cpu_policy.extd.raw)); -} - /* * Local variables: * mode: C diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c index d326fa1c0136..675c523d9909 100644 --- a/xen/arch/x86/hvm/hvm.c +++ b/xen/arch/x86/hvm/hvm.c @@ -77,7 +77,6 @@ #include #include #include -#include =20 #include =20 diff --git a/xen/arch/x86/include/asm/cpu-policy.h b/xen/arch/x86/include/a= sm/cpu-policy.h index 13e2a1f86d13..b361537a602b 100644 --- a/xen/arch/x86/include/asm/cpu-policy.h +++ b/xen/arch/x86/include/asm/cpu-policy.h @@ -18,4 +18,10 @@ void init_guest_cpu_policies(void); /* Allocate and initialise a CPU policy suitable for the domain. */ int init_domain_cpu_policy(struct domain *d); =20 +/* Apply dom0-specific tweaks to the CPUID policy. */ +void init_dom0_cpuid_policy(struct domain *d); + +/* Clamp the CPUID policy to reality. */ +void recalculate_cpuid_policy(struct domain *d); + #endif /* X86_CPU_POLICY_H */ diff --git a/xen/arch/x86/include/asm/cpuid.h b/xen/arch/x86/include/asm/cp= uid.h index 7f81b998ce01..b32ba0bbfe5c 100644 --- a/xen/arch/x86/include/asm/cpuid.h +++ b/xen/arch/x86/include/asm/cpuid.h @@ -8,14 +8,10 @@ #include #include =20 -#include - #include =20 extern const uint32_t known_features[FSCAPINTS]; =20 -void init_guest_cpuid(void); - /* * Expected levelling capabilities (given cpuid vendor/family information), * and levelling capabilities actually available (given MSR probing). @@ -49,13 +45,8 @@ extern struct cpuidmasks cpuidmask_defaults; /* Check that all previously present features are still available. */ bool recheck_cpu_features(unsigned int cpu); =20 -/* Apply dom0-specific tweaks to the CPUID policy. */ -void init_dom0_cpuid_policy(struct domain *d); - -/* Clamp the CPUID policy to reality. */ -void recalculate_cpuid_policy(struct domain *d); - struct vcpu; +struct cpuid_leaf; void guest_cpuid(const struct vcpu *v, uint32_t leaf, uint32_t subleaf, struct cpuid_leaf *res); =20 diff --git a/xen/arch/x86/pv/domain.c b/xen/arch/x86/pv/domain.c index f94f28c8e271..95492715d8ad 100644 --- a/xen/arch/x86/pv/domain.c +++ b/xen/arch/x86/pv/domain.c @@ -10,6 +10,7 @@ #include #include =20 +#include #include #include #include diff --git a/xen/arch/x86/setup.c b/xen/arch/x86/setup.c index 51a19b9019eb..08ade715a3ce 100644 --- a/xen/arch/x86/setup.c +++ b/xen/arch/x86/setup.c @@ -51,7 +51,6 @@ #include #include #include -#include #include #include #include @@ -1991,7 +1990,6 @@ void __init noreturn __start_xen(unsigned long mbi_p) if ( !tboot_protect_mem_regions() ) panic("Could not protect TXT memory regions\n"); =20 - init_guest_cpuid(); init_guest_cpu_policies(); =20 if ( xen_cpuidle ) --=20 2.30.2