mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 02:01:24 +01:00
x86: Add support for CpuidUserDis
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> Reviewed-by: Jan Beulich <jbeulich@suse.com>
This commit is contained in:
1 parent
1240932a8d
commit
c8e4bbb5b8
3 files changed
+49
-13
No files matched your search
+21
-2
@@ -277,9 +277,14 @@ static void __init noinline amd_init_levelling(void)
|
||||
*
|
||||
* 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)
|
||||
* it can be emulated).
|
||||
*
|
||||
* Note that probing for the Intel feature _first_ isn't a mistake,
|
||||
* but a means to ensure MSR_INTEL_PLATFORM_INFO is read and added
|
||||
* to the raw CPU policy if present.
|
||||
*/
|
||||
if (cpu_has_hypervisor && probe_cpuid_faulting()) {
|
||||
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;
|
||||
@@ -374,6 +379,20 @@ 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 bit = K8_HWCR_CPUID_USER_DIS;
|
||||
uint64_t val;
|
||||
|
||||
rdmsrl(MSR_K8_HWCR, val);
|
||||
|
||||
if (!!(val & bit) == enable)
|
||||
return;
|
||||
|
||||
val ^= bit;
|
||||
wrmsrl(MSR_K8_HWCR, 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.
|
||||
|
||||
+27
-11
@@ -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>
|
||||
@@ -166,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.
|
||||
@@ -188,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;
|
||||
}
|
||||
|
||||
@@ -402,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);
|
||||
|
||||
@@ -418,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,
|
||||
|
||||
@@ -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__ */
|
||||