I noticed Linux 4.4 doing this universally now, and I think it's a good
idea to override such anti-security BIOS settings (we certainly have no
compatibility problem due to NX being enabled).
Secondary changes:
- no need to check supported extended CPUID level for leaves
80000000
and
80000001 (required on x86-64)
- no need to update c->cpuid_level in early_init_intel() (done anyway
in generic_identify())
- alignment of trampoline data items
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
lmsw %ax # CR0.PE = 1 (enter protected mode)
ljmpl $BOOT_CS32,$bootsym_rel(trampoline_protmode_entry,6)
+ .balign 8
+ .word 0
idt_48: .word 0, 0, 0 # base = limit = 0
+ .word 0
gdt_48: .word 6*8-1
.long bootsym_rel(trampoline_gdt,4)
+
trampoline_gdt:
/* 0x0000: unused */
.quad 0x0000000000000000
.long trampoline_gdt + BOOT_PSEUDORM_DS + 2 - .
.popsection
+GLOBAL(trampoline_misc_enable_off)
+ .quad 0
+
GLOBAL(cpuid_ext_features)
.long 0
add bootsym_rel(trampoline_xen_phys_start,4,%eax)
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
+ mov $MSR_IA32_MISC_ENABLE,%ecx
+ rdmsr
+ not %esi
+ not %edi
+ and %esi,%eax
+ and %edi,%edx
+ wrmsr
+1:
+
/* Set up EFER (Extended Feature Enable Register). */
mov bootsym_rel(cpuid_ext_features,4,%edi)
movl $MSR_EFER,%ecx
/* AMD-defined flags: level 0x80000001 */
c->extended_cpuid_level = cpuid_eax(0x80000000);
- if ( (c->extended_cpuid_level & 0xffff0000) == 0x80000000 ) {
- if ( c->extended_cpuid_level >= 0x80000001 )
- cpuid(0x80000001, &tmp, &tmp,
- &c->x86_capability[cpufeat_word(X86_FEATURE_LAHF_LM)],
- &c->x86_capability[cpufeat_word(X86_FEATURE_SYSCALL)]);
-
- if ( c->extended_cpuid_level >= 0x80000004 )
- get_model_name(c); /* Default name */
- }
+ cpuid(0x80000001, &tmp, &tmp,
+ &c->x86_capability[cpufeat_word(X86_FEATURE_LAHF_LM)],
+ &c->x86_capability[cpufeat_word(X86_FEATURE_SYSCALL)]);
+ if (c == &boot_cpu_data)
+ bootsym(cpuid_ext_features) =
+ c->x86_capability[cpufeat_word(X86_FEATURE_NX)];
+
+ if (c->extended_cpuid_level >= 0x80000004)
+ get_model_name(c); /* Default name */
/* Intel-defined flags: level 0x00000007 */
if ( c->cpuid_level >= 0x00000007 )
if (c->x86 == 15 && c->x86_cache_alignment == 64)
c->x86_cache_alignment = 128;
- /* Unmask CPUID levels if masked: */
+ /* Unmask CPUID levels and NX if masked: */
if (c->x86 > 6 || (c->x86 == 6 && c->x86_model >= 0xd)) {
- u64 misc_enable;
+ u64 misc_enable, disable;
rdmsrl(MSR_IA32_MISC_ENABLE, misc_enable);
- if (misc_enable & MSR_IA32_MISC_ENABLE_LIMIT_CPUID) {
- misc_enable &= ~MSR_IA32_MISC_ENABLE_LIMIT_CPUID;
- wrmsrl(MSR_IA32_MISC_ENABLE, misc_enable);
- c->cpuid_level = cpuid_eax(0);
- if (opt_cpu_info || c == &boot_cpu_data)
- printk(KERN_INFO "revised cpuid level: %d\n",
- c->cpuid_level);
+ disable = misc_enable & (MSR_IA32_MISC_ENABLE_LIMIT_CPUID |
+ MSR_IA32_MISC_ENABLE_XD_DISABLE);
+ if (disable) {
+ wrmsrl(MSR_IA32_MISC_ENABLE, misc_enable & ~disable);
+ bootsym(trampoline_misc_enable_off) |= disable;
+ }
+
+ 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_NX);
+ printk(KERN_INFO
+ "re-enabled NX (Execute Disable) protection\n");
}
}
#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_TSC_DEADLINE 0x000006E0
#define MSR_IA32_ENERGY_PERF_BIAS 0x000001b0
extern u64 host_pat;
extern bool_t opt_cpu_info;
extern u32 cpuid_ext_features;
+extern u64 trampoline_misc_enable_off;
/* Maximum width of physical addresses supported by the hardware */
extern unsigned int paddr_bits;