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