[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[xen master] x86/boot: Clear XD_DISABLE from the early boot path



commit fc3090a47b21bfe746ef3bd2cbc5d0cdaa797686
Author:     Alejandro Vallejo <alejandro.vallejo@xxxxxxxxx>
AuthorDate: Thu Jun 29 13:17:12 2023 +0100
Commit:     Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
CommitDate: Fri Jun 30 14:18:28 2023 +0100

    x86/boot: Clear XD_DISABLE from the early boot path
    
    Intel CPUs have a bit in MSR_IA32_MISC_ENABLE that may prevent the NX bit
    from being advertised. Clear it unconditionally if we can't find the NX
    feature right away on boot.
    
    The conditions for the MSR being read on early boot are (in this order):
    
    * Long Mode is supported
    * NX isn't advertised
    * The vendor is Intel
    
    The order of checks has been chosen carefully so a virtualized Xen on a
    hypervisor that doesn't emulate that MSR (but supports NX) doesn't triple
    fault trying to access the non-existing MSR.
    
    With that done, we can remove the XD_DISABLE checks in the intel-specific
    init path (as they are already done in early assembly). Keep a printk to
    highlight the fact that NX was forcefully enabled.
    
    Signed-off-by: Alejandro Vallejo <alejandro.vallejo@xxxxxxxxx>
    Reviewed-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
---
 xen/arch/x86/boot/head.S               | 49 +++++++++++++++++++++++++++++-----
 xen/arch/x86/cpu/intel.c               | 15 ++++-------
 xen/arch/x86/include/asm/msr-index.h   |  2 +-
 xen/arch/x86/include/asm/x86-vendors.h | 30 ++++++++++-----------
 4 files changed, 64 insertions(+), 32 deletions(-)

diff --git a/xen/arch/x86/boot/head.S b/xen/arch/x86/boot/head.S
index 9fbd602ea5..6685d3e504 100644
--- a/xen/arch/x86/boot/head.S
+++ b/xen/arch/x86/boot/head.S
@@ -652,16 +652,53 @@ trampoline_setup:
         cpuid
 1:      mov     %edx, CPUINFO_FEATURE_OFFSET(X86_FEATURE_LM) + 
sym_esi(boot_cpu_data)
 
-        /* Check for NX. Adjust EFER setting if available. */
-        bt      $cpufeat_bit(X86_FEATURE_NX), %edx
-        jnc     1f
-        orb     $EFER_NXE >> 8, 1 + sym_esi(trampoline_efer)
-1:
-
         /* Check for availability of long mode. */
         bt      $cpufeat_bit(X86_FEATURE_LM),%edx
         jnc     .Lbad_cpu
 
+        /* Check for NX */
+        bt      $cpufeat_bit(X86_FEATURE_NX), %edx
+        jc     .Lgot_nx
+
+        /*
+         * NX appears to be unsupported, but it might be hidden.
+         *
+         * The feature is part of the AMD64 spec, but the very first Intel
+         * 64bit CPUs lacked the feature, and thereafter there was a
+         * firmware knob to disable the feature. Undo the disable if
+         * possible.
+         *
+         * All 64bit Intel CPUs support this MSR. If virtualised, expect
+         * the hypervisor to either emulate the MSR or give us NX.
+         */
+        xor     %eax, %eax
+        cpuid
+        cmp     $X86_VENDOR_INTEL_EBX, %ebx
+        jnz     .Lno_nx
+        cmp     $X86_VENDOR_INTEL_EDX, %edx
+        jnz     .Lno_nx
+        cmp     $X86_VENDOR_INTEL_ECX, %ecx
+        jnz     .Lno_nx
+
+        /* Clear the XD_DISABLE bit */
+        mov     $MSR_IA32_MISC_ENABLE, %ecx
+        rdmsr
+        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
+        cpuid
+        bt      $cpufeat_bit(X86_FEATURE_NX), %edx
+        jnc     .Lno_nx
+
+.Lgot_nx:
+        /* Adjust EFER given that NX is present */
+        orb     $EFER_NXE >> 8, 1 + sym_esi(trampoline_efer)
+.Lno_nx:
+
         /* Stash TSC to calculate a good approximation of time-since-boot */
         rdtsc
         mov     %eax,     sym_esi(boot_tsc_stamp)
diff --git a/xen/arch/x86/cpu/intel.c b/xen/arch/x86/cpu/intel.c
index 168cd58f36..36018aa8fe 100644
--- a/xen/arch/x86/cpu/intel.c
+++ b/xen/arch/x86/cpu/intel.c
@@ -304,24 +304,19 @@ static void cf_check early_init_intel(struct cpuinfo_x86 
*c)
        if (c->x86 == 15 && c->x86_cache_alignment == 64)
                c->x86_cache_alignment = 128;
 
+       if (c == &boot_cpu_data &&
+            bootsym(trampoline_misc_enable_off) & 
MSR_IA32_MISC_ENABLE_XD_DISABLE)
+               printk(KERN_INFO "re-enabled NX (Execute Disable) 
protection\n");
+
        /* Unmask CPUID levels and NX if masked: */
        rdmsrl(MSR_IA32_MISC_ENABLE, misc_enable);
 
-       disable = misc_enable & (MSR_IA32_MISC_ENABLE_LIMIT_CPUID |
-                                MSR_IA32_MISC_ENABLE_XD_DISABLE);
+       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;
-               bootsym(trampoline_efer) |= EFER_NXE;
-       }
-
-       if (disable & MSR_IA32_MISC_ENABLE_LIMIT_CPUID)
                printk(KERN_INFO "revised cpuid level: %d\n",
                       cpuid_eax(0));
-       if (disable & MSR_IA32_MISC_ENABLE_XD_DISABLE) {
-               write_efer(read_efer() | EFER_NXE);
-               printk(KERN_INFO
-                      "re-enabled NX (Execute Disable) protection\n");
        }
 
        /* CPUID workaround for Intel 0F33/0F34 CPU */
diff --git a/xen/arch/x86/include/asm/msr-index.h 
b/xen/arch/x86/include/asm/msr-index.h
index 2749e433d2..4f861c0bb4 100644
--- a/xen/arch/x86/include/asm/msr-index.h
+++ b/xen/arch/x86/include/asm/msr-index.h
@@ -502,7 +502,7 @@
 #define MSR_IA32_MISC_ENABLE_MONITOR_ENABLE (1<<18)
 #define MSR_IA32_MISC_ENABLE_LIMIT_CPUID  (1<<22)
 #define MSR_IA32_MISC_ENABLE_XTPR_DISABLE (1<<23)
-#define MSR_IA32_MISC_ENABLE_XD_DISABLE        (1ULL << 34)
+#define MSR_IA32_MISC_ENABLE_XD_DISABLE   (_AC(1, ULL) << 34)
 
 #define MSR_IA32_TSC_DEADLINE          0x000006E0
 #define MSR_IA32_ENERGY_PERF_BIAS      0x000001b0
diff --git a/xen/arch/x86/include/asm/x86-vendors.h 
b/xen/arch/x86/include/asm/x86-vendors.h
index 0a37024cbd..d51c516909 100644
--- a/xen/arch/x86/include/asm/x86-vendors.h
+++ b/xen/arch/x86/include/asm/x86-vendors.h
@@ -12,28 +12,28 @@
 #define X86_VENDOR_UNKNOWN 0
 
 #define X86_VENDOR_INTEL (1 << 0)
-#define X86_VENDOR_INTEL_EBX 0x756e6547U /* "GenuineIntel" */
-#define X86_VENDOR_INTEL_ECX 0x6c65746eU
-#define X86_VENDOR_INTEL_EDX 0x49656e69U
+#define X86_VENDOR_INTEL_EBX _AC(0x756e6547, U) /* "GenuineIntel" */
+#define X86_VENDOR_INTEL_ECX _AC(0x6c65746e, U)
+#define X86_VENDOR_INTEL_EDX _AC(0x49656e69, U)
 
 #define X86_VENDOR_AMD (1 << 1)
-#define X86_VENDOR_AMD_EBX 0x68747541U /* "AuthenticAMD" */
-#define X86_VENDOR_AMD_ECX 0x444d4163U
-#define X86_VENDOR_AMD_EDX 0x69746e65U
+#define X86_VENDOR_AMD_EBX _AC(0x68747541, U) /* "AuthenticAMD" */
+#define X86_VENDOR_AMD_ECX _AC(0x444d4163, U)
+#define X86_VENDOR_AMD_EDX _AC(0x69746e65, U)
 
 #define X86_VENDOR_CENTAUR (1 << 2)
-#define X86_VENDOR_CENTAUR_EBX 0x746e6543U /* "CentaurHauls" */
-#define X86_VENDOR_CENTAUR_ECX 0x736c7561U
-#define X86_VENDOR_CENTAUR_EDX 0x48727561U
+#define X86_VENDOR_CENTAUR_EBX _AC(0x746e6543, U) /* "CentaurHauls" */
+#define X86_VENDOR_CENTAUR_ECX _AC(0x736c7561, U)
+#define X86_VENDOR_CENTAUR_EDX _AC(0x48727561, U)
 
 #define X86_VENDOR_SHANGHAI (1 << 3)
-#define X86_VENDOR_SHANGHAI_EBX 0x68532020U /* "  Shanghai  " */
-#define X86_VENDOR_SHANGHAI_ECX 0x20206961U
-#define X86_VENDOR_SHANGHAI_EDX 0x68676e61U
+#define X86_VENDOR_SHANGHAI_EBX _AC(0x68532020, U) /* "  Shanghai  " */
+#define X86_VENDOR_SHANGHAI_ECX _AC(0x20206961, U)
+#define X86_VENDOR_SHANGHAI_EDX _AC(0x68676e61, U)
 
 #define X86_VENDOR_HYGON (1 << 4)
-#define X86_VENDOR_HYGON_EBX 0x6f677948U /* "HygonGenuine" */
-#define X86_VENDOR_HYGON_ECX 0x656e6975U
-#define X86_VENDOR_HYGON_EDX 0x6e65476eU
+#define X86_VENDOR_HYGON_EBX _AC(0x6f677948, U) /* "HygonGenuine" */
+#define X86_VENDOR_HYGON_ECX _AC(0x656e6975, U)
+#define X86_VENDOR_HYGON_EDX _AC(0x6e65476e, U)
 
 #endif /* __XEN_X86_VENDORS_H__ */
--
generated by git-patchbot for /home/xen/git/xen.git#master



 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.