|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [PATCH 09/16] x86/intel: Always check MSR_MISC_ENABLE on all CPUs
Currently, the BSP only leaves instructions for the APs to adjust
MSR_MISC_ENABLE if the BSP is found to need adjustments. Particularly if
XD_DISABLE is needed on an AP but not the BSP, the system will triple fault
with no information provided to the user.
Rework the BSP and trampoline logic to always read MISC_ENABLE, and clear
CPUID_LIMIT and XD_DISABLE if either are set.
Repurpose intel_unlock_cpuid_leaves() to be intel_check_misc_enable() and make
it static in common.c. Replace trampoline_misc_enable_off with the smaller
trampoline_check_misc_enable.
Signed-off-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
---
CC: Jan Beulich <JBeulich@xxxxxxxx>
CC: Roger Pau Monné <roger.pau@xxxxxxxxxx>
CC: Julian Vetter <julian.vetter@xxxxxxxxxx>
CC: Teddy Astie <teddy.astie@xxxxxxxxxx>
This temporarily removes the printk() noting the reactivation of XD because
the earlier BSP code has already done it, but that logic is about to be
removed.
---
xen/arch/x86/boot/head.S | 1 -
xen/arch/x86/boot/trampoline.S | 29 ++++++++++--------
xen/arch/x86/boot/wakeup.S | 27 ++++++++++-------
xen/arch/x86/cpu/common.c | 43 ++++++++++++++++++++++++++-
xen/arch/x86/cpu/cpu.h | 2 --
xen/arch/x86/cpu/intel.c | 19 ------------
xen/arch/x86/include/asm/trampoline.h | 7 +++--
7 files changed, 79 insertions(+), 49 deletions(-)
diff --git a/xen/arch/x86/boot/head.S b/xen/arch/x86/boot/head.S
index 77bb7a9e2191..4022f8639478 100644
--- a/xen/arch/x86/boot/head.S
+++ b/xen/arch/x86/boot/head.S
@@ -582,7 +582,6 @@ trampoline_setup:
btr $2, %edx
jnc .Lno_nx
wrmsr
- orb $MSR_IA32_MISC_ENABLE_XD_DISABLE >> 32, 4 +
sym_esi(trampoline_misc_enable_off)
/* Check again for NX */
mov $0x80000001, %eax
diff --git a/xen/arch/x86/boot/trampoline.S b/xen/arch/x86/boot/trampoline.S
index a92e399fbe0e..2b4552096fd7 100644
--- a/xen/arch/x86/boot/trampoline.S
+++ b/xen/arch/x86/boot/trampoline.S
@@ -77,17 +77,22 @@ trampoline_protmode_entry:
mov %eax,%cr3
/* Adjust IA32_MISC_ENABLE if needed (for NX enabling below). */
- mov bootsym_rel(trampoline_misc_enable_off,4,%esi)
- mov bootsym_rel(trampoline_misc_enable_off+4,4,%edi)
- mov %esi,%eax
- or %edi,%eax
- jz 1f
+ cmpb $1, bootsym_rel(trampoline_check_misc_enable, 5)
+ jne 1f
+
mov $MSR_IA32_MISC_ENABLE,%ecx
rdmsr
- not %esi
- not %edi
- and %esi,%eax
- and %edi,%edx
+
+ xor %edi, %edi
+ btr $22 /* ilog2(MSR_IA32_MISC_ENABLE_LIMIT_CPUID) */, %eax
+ adc %edi, %edi
+
+ btr $34 /* ilog2(MSR_IA32_MISC_ENABLE_XD_DISABLE) */ - 32, %edx
+ adc %edi, %edi
+
+ /* No bits need clearing? Nothing to do */
+ jz 1f
+
wrmsr
1:
/* Set up PAT before enabling paging. */
@@ -141,9 +146,6 @@ gdt_48:
.long trampoline_gdt + BOOT_PSEUDORM_DS + 2 - .
.popsection
-GLOBAL(trampoline_misc_enable_off)
- .quad 0
-
/* EFER OR-mask for boot paths. SCE conditional on PV support, NX added when
available. */
GLOBAL(trampoline_efer)
.long EFER_LME | (EFER_SCE * IS_ENABLED(CONFIG_PV)) | \
@@ -155,6 +157,9 @@ GLOBAL(trampoline_xen_phys_start)
GLOBAL(trampoline_cpu_started)
.byte 0
+GLOBAL(trampoline_check_misc_enable)
+ .byte 0
+
LABEL(trampoline_perm_end, 0)
/* From here on early boot only. */
diff --git a/xen/arch/x86/boot/wakeup.S b/xen/arch/x86/boot/wakeup.S
index 654e97005ff4..aced8153bafa 100644
--- a/xen/arch/x86/boot/wakeup.S
+++ b/xen/arch/x86/boot/wakeup.S
@@ -126,18 +126,23 @@ wakeup_32:
add bootsym_rel(trampoline_xen_phys_start,4,%eax)
mov %eax,%cr3
- /* Reapply IA32_MISC_ENABLE modifications from early_init_intel(). */
- mov bootsym_rel(trampoline_misc_enable_off, 4, %esi)
- mov bootsym_rel(trampoline_misc_enable_off + 4, 4, %edi)
- mov %esi, %eax
- or %edi, %eax
- jz 1f
- mov $MSR_IA32_MISC_ENABLE, %ecx
+ /* Adjust IA32_MISC_ENABLE if needed (for NX enabling below). */
+ cmpb $1, bootsym_rel(trampoline_check_misc_enable, 5)
+ jne 1f
+
+ mov $MSR_IA32_MISC_ENABLE,%ecx
rdmsr
- not %esi
- not %edi
- and %esi, %eax
- and %edi, %edx
+
+ xor %edi, %edi
+ btr $22 /* ilog2(MSR_IA32_MISC_ENABLE_LIMIT_CPUID) */, %eax
+ adc %edi, %edi
+
+ btr $34 /* ilog2(MSR_IA32_MISC_ENABLE_XD_DISABLE) */ - 32, %edx
+ adc %edi, %edi
+
+ /* No bits need clearing? Nothing to do */
+ jz 1f
+
wrmsr
1:
/* Set up PAT before enabling paging. */
diff --git a/xen/arch/x86/cpu/common.c b/xen/arch/x86/cpu/common.c
index d70f9cf87dc8..0249bb4bf2dc 100644
--- a/xen/arch/x86/cpu/common.c
+++ b/xen/arch/x86/cpu/common.c
@@ -19,6 +19,7 @@
#include <asm/random.h>
#include <asm/setup.h>
#include <asm/shstk.h>
+#include <asm/trampoline.h>
#include <asm/xstate.h>
#include <public/sysctl.h>
@@ -307,6 +308,46 @@ static inline u32 phys_pkg_id(u32 cpuid_apic, int
index_msb)
return _phys_pkg_id(get_apic_id(), index_msb);
}
+/*
+ * Disable restrictions in MSR_MISC_ENABLE. These are often available as
+ * firmware settings for backwards compatibility. Called prior to cpuid_level
+ * being acted upon, as it may need unlimiting.
+ */
+static void __init intel_check_misc_enable(struct cpuinfo_x86 *c)
+{
+ uint64_t misc_enable, disable = (MSR_IA32_MISC_ENABLE_LIMIT_CPUID |
+ MSR_IA32_MISC_ENABLE_XD_DISABLE);
+
+ /* Instruct the trampoline to perform the same check too. */
+ bootsym(trampoline_check_misc_enable) = true;
+
+ misc_enable = rdmsr(MSR_IA32_MISC_ENABLE);
+
+ if ( (misc_enable & disable) == 0 )
+ return; /* Nothing to do */
+
+ wrmsr(MSR_IA32_MISC_ENABLE, misc_enable & ~disable);
+
+ /*
+ * When the P4 Nocona introduced the Structured Cache information, it was
+ * discovered that WinNT crashed on encountering a CPUID Leaf 4. Intel
+ * worked around this by introducing an ability to limit the maximum
+ * reported leaf to 2 (PSN, leaf 3 had already been removed by this time).
+ */
+ if ( misc_enable & MSR_IA32_MISC_ENABLE_LIMIT_CPUID )
+ {
+ c->cpuid_level = cpuid_eax(0);
+ printk(XENLOG_INFO "revised cpuid level: %u\n", c->cpuid_level);
+ }
+
+ /*
+ * When Intel added XD support originally, it was recommended to be off by
+ * default because of stability problems in WinXP SP2.
+ */
+ if ( misc_enable & MSR_IA32_MISC_ENABLE_XD_DISABLE )
+ printk(XENLOG_INFO "re-enabled NX (Execute Disable) protection\n");
+}
+
/* Do minimum CPU detection early.
Fields really needed: vendor, cpuid_level, family, model, mask, cache
alignment.
The others are not touched to avoid unwanted side effects.
@@ -327,7 +368,7 @@ void __init early_cpu_init(bool verbose)
c->x86_vendor = x86_cpuid_lookup_vendor(ebx, ecx, edx);
switch (c->x86_vendor) {
- case X86_VENDOR_INTEL: intel_unlock_cpuid_leaves(c);
+ case X86_VENDOR_INTEL: intel_check_misc_enable(c);
actual_cpu = intel_cpu_dev; break;
case X86_VENDOR_AMD: actual_cpu = amd_cpu_dev; break;
case X86_VENDOR_CENTAUR: actual_cpu = centaur_cpu_dev; break;
diff --git a/xen/arch/x86/cpu/cpu.h b/xen/arch/x86/cpu/cpu.h
index 0fc6370edb13..d2d37d1d5eec 100644
--- a/xen/arch/x86/cpu/cpu.h
+++ b/xen/arch/x86/cpu/cpu.h
@@ -27,6 +27,4 @@ void amd_init_ssbd(const struct cpuinfo_x86 *c);
void amd_init_spectral_chicken(void);
void detect_zen2_null_seg_behaviour(void);
-void intel_unlock_cpuid_leaves(struct cpuinfo_x86 *c);
-
#endif /* X86_CPU_H */
diff --git a/xen/arch/x86/cpu/intel.c b/xen/arch/x86/cpu/intel.c
index 2aeeb2f5bf55..b1dd06d92f60 100644
--- a/xen/arch/x86/cpu/intel.c
+++ b/xen/arch/x86/cpu/intel.c
@@ -309,22 +309,6 @@ static void __init intel_init_levelling(void)
ctxt_switch_masking = intel_ctxt_switch_masking;
}
-/* Unmask CPUID levels if masked. */
-void __init intel_unlock_cpuid_leaves(struct cpuinfo_x86 *c)
-{
- uint64_t misc_enable, disable;
-
- rdmsrl(MSR_IA32_MISC_ENABLE, misc_enable);
-
- disable = misc_enable & MSR_IA32_MISC_ENABLE_LIMIT_CPUID;
- if (disable) {
- wrmsrl(MSR_IA32_MISC_ENABLE, misc_enable & ~disable);
- bootsym(trampoline_misc_enable_off) |= disable;
- c->cpuid_level = cpuid_eax(0);
- printk(KERN_INFO "revised cpuid level: %u\n", c->cpuid_level);
- }
-}
-
/*
* Errata BA80, AAK120, AAM108, AAO67, BD59, AAY54: Rapid Core C3/C6 Transition
* May Cause Unpredictable System Behavior
@@ -392,9 +376,6 @@ static void __init probe_mwait_errata(void)
static void __init cf_check early_init_intel(void)
{
- if ( bootsym(trampoline_misc_enable_off) & MSR_IA32_MISC_ENABLE_XD_DISABLE
)
- printk(KERN_INFO "re-enabled NX (Execute Disable) protection\n");
-
check_memory_type_self_snoop_errata();
/*
diff --git a/xen/arch/x86/include/asm/trampoline.h
b/xen/arch/x86/include/asm/trampoline.h
index deed2679d9d5..893bbe54f325 100644
--- a/xen/arch/x86/include/asm/trampoline.h
+++ b/xen/arch/x86/include/asm/trampoline.h
@@ -153,10 +153,11 @@ extern uint8_t trampoline_cpu_started;
extern uint32_t trampoline_efer;
/*
- * When nonzero, clear the specified bits in MSR_MISC_ENABLE. This is
- * necessary to clobber XD_DISABLE before trying to set MSR_EFER.NXE.
+ * Instruction from the BSP to APs that MSR_MISC_ENABLE is available and
+ * should be checked to remove limitations. This is necessary to clobber
+ * XD_DISABLE before trying to set MSR_EFER.NXE.
*/
-extern uint64_t trampoline_misc_enable_off;
+extern bool trampoline_check_misc_enable;
/* Quirks about video mode-setting on S3 resume. */
extern uint8_t video_flags;
--
2.39.5
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |