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__ */