From: Alejandro Vallejo <alejandro.vallejo@cloud.com>
To: Xen-devel <xen-devel@lists.xenproject.org>
Cc: "Alejandro Vallejo" <alejandro.vallejo@cloud.com>,
"Jan Beulich" <jbeulich@suse.com>,
"Andrew Cooper" <andrew.cooper3@citrix.com>,
"Roger Pau Monné" <roger.pau@citrix.com>, "Wei Liu" <wl@xen.org>
Subject: [PATCH 2/3] x86: Add support for CpuidUserDis
Date: Fri, 5 May 2023 18:57:04 +0100 [thread overview]
Message-ID: <20230505175705.18098-3-alejandro.vallejo@cloud.com> (raw)
In-Reply-To: <20230505175705.18098-1-alejandro.vallejo@cloud.com>
Includes a refactor to move vendor-specific probes to vendor-specific
files. Furthermore, because CpuIdUserDis is reported in Cpuid itself,
the extended leaf containing that bit must be retrieved before calling
c_early_init()
Signed-off-by: Alejandro Vallejo <alejandro.vallejo@cloud.com>
---
xen/arch/x86/cpu/amd.c | 29 ++++++++++++++++++-
xen/arch/x86/cpu/common.c | 51 ++++++++++++++++++----------------
xen/arch/x86/cpu/intel.c | 11 +++++++-
xen/arch/x86/include/asm/amd.h | 1 +
4 files changed, 66 insertions(+), 26 deletions(-)
diff --git a/xen/arch/x86/cpu/amd.c b/xen/arch/x86/cpu/amd.c
index caafe44740..9269015edd 100644
--- a/xen/arch/x86/cpu/amd.c
+++ b/xen/arch/x86/cpu/amd.c
@@ -271,8 +271,20 @@ static void __init noinline amd_init_levelling(void)
{
const struct cpuidmask *m = NULL;
- if (probe_cpuid_faulting())
+ /*
+ * If there's support for CpuidUserDis or CPUID faulting then
+ * we can skip levelling because CPUID accesses are trapped anyway.
+ *
+ * CPUID faulting is an Intel feature analogous to CpuidUserDis, so
+ * that can only be present when Xen is itself virtualized (because
+ * it can be emulated)
+ */
+ if ((cpu_has_hypervisor && probe_cpuid_faulting()) ||
+ boot_cpu_has(X86_FEATURE_CPUID_USER_DIS)) {
+ expected_levelling_cap |= LCAP_faulting;
+ levelling_caps |= LCAP_faulting;
return;
+ }
probe_masking_msrs();
@@ -363,6 +375,21 @@ static void __init noinline amd_init_levelling(void)
ctxt_switch_masking = amd_ctxt_switch_masking;
}
+void amd_set_cpuid_user_dis(bool enable)
+{
+ const uint64_t msr_addr = MSR_K8_HWCR;
+ const uint64_t bit = K8_HWCR_CPUID_USER_DIS;
+ uint64_t val;
+
+ rdmsrl(msr_addr, val);
+
+ if (!!(val & bit) == enable)
+ return;
+
+ val ^= bit;
+ wrmsrl(msr_addr, val);
+}
+
/*
* Check for the presence of an AMD erratum. Arguments are defined in amd.h
* for each known erratum. Return 1 if erratum is found.
diff --git a/xen/arch/x86/cpu/common.c b/xen/arch/x86/cpu/common.c
index edc4db1335..9bbb385db4 100644
--- a/xen/arch/x86/cpu/common.c
+++ b/xen/arch/x86/cpu/common.c
@@ -4,6 +4,7 @@
#include <xen/param.h>
#include <xen/smp.h>
+#include <asm/amd.h>
#include <asm/cpu-policy.h>
#include <asm/current.h>
#include <asm/debugreg.h>
@@ -131,17 +132,6 @@ bool __init probe_cpuid_faulting(void)
uint64_t val;
int rc;
- /*
- * Don't bother looking for CPUID faulting if we aren't virtualised on
- * AMD or Hygon hardware - it won't be present. Likewise for Fam0F
- * Intel hardware.
- */
- if (((boot_cpu_data.x86_vendor & (X86_VENDOR_AMD | X86_VENDOR_HYGON)) ||
- ((boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) &&
- boot_cpu_data.x86 == 0xf)) &&
- !cpu_has_hypervisor)
- return false;
-
if ((rc = rdmsr_safe(MSR_INTEL_PLATFORM_INFO, val)) == 0)
raw_cpu_policy.platform_info.cpuid_faulting =
val & MSR_PLATFORM_INFO_CPUID_FAULTING;
@@ -155,8 +145,6 @@ bool __init probe_cpuid_faulting(void)
return false;
}
- expected_levelling_cap |= LCAP_faulting;
- levelling_caps |= LCAP_faulting;
setup_force_cpu_cap(X86_FEATURE_CPUID_FAULTING);
return true;
@@ -179,8 +167,10 @@ static void set_cpuid_faulting(bool enable)
void ctxt_switch_levelling(const struct vcpu *next)
{
const struct domain *nextd = next ? next->domain : NULL;
+ bool enable_cpuid_faulting;
- if (cpu_has_cpuid_faulting) {
+ if (cpu_has_cpuid_faulting ||
+ boot_cpu_has(X86_FEATURE_CPUID_USER_DIS)) {
/*
* No need to alter the faulting setting if we are switching
* to idle; it won't affect any code running in idle context.
@@ -201,12 +191,18 @@ void ctxt_switch_levelling(const struct vcpu *next)
* an interim escape hatch in the form of
* `dom0=no-cpuid-faulting` to restore the older behaviour.
*/
- set_cpuid_faulting(nextd && (opt_dom0_cpuid_faulting ||
- !is_control_domain(nextd) ||
- !is_pv_domain(nextd)) &&
- (is_pv_domain(nextd) ||
- next->arch.msrs->
- misc_features_enables.cpuid_faulting));
+ enable_cpuid_faulting = nextd && (opt_dom0_cpuid_faulting ||
+ !is_control_domain(nextd) ||
+ !is_pv_domain(nextd)) &&
+ (is_pv_domain(nextd) ||
+ next->arch.msrs->
+ misc_features_enables.cpuid_faulting);
+
+ if (cpu_has_cpuid_faulting)
+ set_cpuid_faulting(enable_cpuid_faulting);
+ else
+ amd_set_cpuid_user_dis(enable_cpuid_faulting);
+
return;
}
@@ -415,6 +411,17 @@ static void generic_identify(struct cpuinfo_x86 *c)
c->apicid = phys_pkg_id((ebx >> 24) & 0xFF, 0);
c->phys_proc_id = c->apicid;
+ eax = cpuid_eax(0x80000000);
+ if ((eax >> 16) == 0x8000)
+ c->extended_cpuid_level = eax;
+
+ /*
+ * These AMD-defined flags are out of place, but we need
+ * them early for the CPUID faulting probe code
+ */
+ if (c->extended_cpuid_level >= 0x80000021)
+ c->x86_capability[FEATURESET_e21a] = cpuid_eax(0x80000021);
+
if (this_cpu->c_early_init)
this_cpu->c_early_init(c);
@@ -431,10 +438,6 @@ static void generic_identify(struct cpuinfo_x86 *c)
(cpuid_ecx(CPUID_PM_LEAF) & CPUID6_ECX_APERFMPERF_CAPABILITY) )
__set_bit(X86_FEATURE_APERFMPERF, c->x86_capability);
- eax = cpuid_eax(0x80000000);
- if ((eax >> 16) == 0x8000)
- c->extended_cpuid_level = eax;
-
/* AMD-defined flags: level 0x80000001 */
if (c->extended_cpuid_level >= 0x80000001)
cpuid(0x80000001, &tmp, &tmp,
diff --git a/xen/arch/x86/cpu/intel.c b/xen/arch/x86/cpu/intel.c
index 71fc1a1e18..7e5c657758 100644
--- a/xen/arch/x86/cpu/intel.c
+++ b/xen/arch/x86/cpu/intel.c
@@ -226,8 +226,17 @@ static void cf_check intel_ctxt_switch_masking(const struct vcpu *next)
*/
static void __init noinline intel_init_levelling(void)
{
- if (probe_cpuid_faulting())
+ /* Intel Fam0f is old enough that probing for CPUID faulting support
+ * introduces spurious #GP(0) when the appropriate MSRs are read,
+ * so skip it altogether. In the case where Xen is virtualized these
+ * MSRs may be emulated though, so we allow it in that case.
+ */
+ if ((cpu_has_hypervisor || boot_cpu_data.x86 !=0xf) &&
+ probe_cpuid_faulting()) {
+ expected_levelling_cap |= LCAP_faulting;
+ levelling_caps |= LCAP_faulting;
return;
+ }
probe_masking_msrs();
diff --git a/xen/arch/x86/include/asm/amd.h b/xen/arch/x86/include/asm/amd.h
index a975d3de26..09ee52dc1c 100644
--- a/xen/arch/x86/include/asm/amd.h
+++ b/xen/arch/x86/include/asm/amd.h
@@ -155,5 +155,6 @@ extern bool amd_legacy_ssbd;
extern bool amd_virt_spec_ctrl;
bool amd_setup_legacy_ssbd(void);
void amd_set_legacy_ssbd(bool enable);
+void amd_set_cpuid_user_dis(bool enable);
#endif /* __AMD_H__ */
--
2.34.1
next prev parent reply other threads:[~2023-05-05 17:57 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-05-05 17:57 [PATCH 0/3] Add CpuidUserDis support Alejandro Vallejo
2023-05-05 17:57 ` [PATCH 1/3] x86: Add AMD's CpuidUserDis bit definitions Alejandro Vallejo
2023-05-05 17:57 ` Alejandro Vallejo [this message]
2023-05-08 9:17 ` [PATCH 2/3] x86: Add support for CpuidUserDis Jan Beulich
2023-05-05 17:57 ` [PATCH 3/3] x86: Use CpuidUserDis if an AMD HVM guest toggles CPUID faulting Alejandro Vallejo
2023-05-08 13:18 ` Jan Beulich
2023-05-09 10:05 ` Andrew Cooper
2023-05-09 14:41 ` Jan Beulich
2023-05-09 14:57 ` Alejandro Vallejo
2023-05-10 8:15 ` Jan Beulich
2023-05-10 10:52 ` Alejandro Vallejo
2023-05-10 13:17 ` Jan Beulich
2023-05-08 9:06 ` [PATCH 0/3] Add CpuidUserDis support Jan Beulich
2023-05-10 11:28 ` Alejandro Vallejo
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20230505175705.18098-3-alejandro.vallejo@cloud.com \
--to=alejandro.vallejo@cloud.com \
--cc=andrew.cooper3@citrix.com \
--cc=jbeulich@suse.com \
--cc=roger.pau@citrix.com \
--cc=wl@xen.org \
--cc=xen-devel@lists.xenproject.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.