|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [PATCH] xen: Move NX handling to a dedicated place
Currently the CONFIG_REQUIRE_NX prevents booting XEN, if NX is disabled
in the BIOS. AMD doesn't have a software-accessible MSR to re-enable it,
so there is nothing we can do. The system is going to die anyway. But on
Intel NX might just be hidden via IA32_MISC_ENABLE.XD_DISABLE. But the
function to re-enable it is called after the check + panic in
efi_arch_cpu. So, this patch removes the early check and moves the
entire NX handling into a dedicated place.
Signed-off-by: Julian Vetter <julian.vetter@xxxxxxxxxx>
---
xen/arch/x86/boot/head.S | 56 --------------------------------
xen/arch/x86/boot/trampoline.S | 5 ++-
xen/arch/x86/cpu/intel.c | 4 ---
xen/arch/x86/efi/efi-boot.h | 12 -------
xen/arch/x86/include/asm/setup.h | 2 ++
xen/arch/x86/setup.c | 46 ++++++++++++++++++++++++++
6 files changed, 50 insertions(+), 75 deletions(-)
diff --git a/xen/arch/x86/boot/head.S b/xen/arch/x86/boot/head.S
index 77bb7a9e21..7fb7fb1351 100644
--- a/xen/arch/x86/boot/head.S
+++ b/xen/arch/x86/boot/head.S
@@ -133,7 +133,6 @@ multiboot2_header:
.Lbad_ldr_nbs: .asciz "ERR: Bootloader shutdown EFI x64 boot services!"
.Lbad_efi_msg: .asciz "ERR: EFI IA-32 platforms are not supported!"
.Lbag_alg_msg: .asciz "ERR: Xen must be loaded at a 2Mb boundary!"
-.Lno_nx_msg: .asciz "ERR: Not an NX-capable CPU!"
.section .init.data, "aw", @progbits
.subsection 1 /* Put data here after the page tables (in x86_64.S). */
@@ -165,11 +164,6 @@ early_error: /* Here to improve the disassembly. */
.Lnot_aligned:
mov $sym_offs(.Lbag_alg_msg), %ecx
jmp .Lget_vtb
-#ifdef CONFIG_REQUIRE_NX
-.Lno_nx:
- mov $sym_offs(.Lno_nx_msg), %ecx
- jmp .Lget_vtb
-#endif
.Lmb2_no_bs:
/*
* Ditto. Additionally, here there is a chance that Xen was started
@@ -547,56 +541,6 @@ trampoline_setup:
bt $cpufeat_bit(X86_FEATURE_LM),%edx
jnc .Lbad_cpu
- /*
- * Check for NX
- * - If Xen was compiled requiring it simply assert it's
- * supported. The trampoline already has the right constant.
- * - Otherwise, update the trampoline EFER mask accordingly.
- */
- 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:
-#ifndef CONFIG_REQUIRE_NX
- /* Adjust EFER given that NX is present */
- orb $EFER_NXE >> 8, 1 + sym_esi(trampoline_efer)
-.Lno_nx:
-#endif
-
/* 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/boot/trampoline.S b/xen/arch/x86/boot/trampoline.S
index a92e399fbe..8e8d50cbdf 100644
--- a/xen/arch/x86/boot/trampoline.S
+++ b/xen/arch/x86/boot/trampoline.S
@@ -144,10 +144,9 @@ gdt_48:
GLOBAL(trampoline_misc_enable_off)
.quad 0
-/* EFER OR-mask for boot paths. SCE conditional on PV support, NX added when
available. */
+/* EFER OR-mask for boot paths. SCE conditional on PV support. */
GLOBAL(trampoline_efer)
- .long EFER_LME | (EFER_SCE * IS_ENABLED(CONFIG_PV)) | \
- (EFER_NXE * IS_ENABLED(CONFIG_REQUIRE_NX))
+ .long EFER_LME | (EFER_SCE * IS_ENABLED(CONFIG_PV))
GLOBAL(trampoline_xen_phys_start)
.long 0
diff --git a/xen/arch/x86/cpu/intel.c b/xen/arch/x86/cpu/intel.c
index b76797cb9a..e8cf51e853 100644
--- a/xen/arch/x86/cpu/intel.c
+++ b/xen/arch/x86/cpu/intel.c
@@ -351,10 +351,6 @@ 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");
-
intel_unlock_cpuid_leaves(c);
/* CPUID workaround for Intel 0F33/0F34 CPU */
diff --git a/xen/arch/x86/efi/efi-boot.h b/xen/arch/x86/efi/efi-boot.h
index 0194720003..8dfd549f12 100644
--- a/xen/arch/x86/efi/efi-boot.h
+++ b/xen/arch/x86/efi/efi-boot.h
@@ -748,18 +748,6 @@ static void __init efi_arch_cpu(void)
if ( (eax >> 16) == 0x8000 && eax > 0x80000000U )
{
caps[FEATURESET_e1d] = cpuid_edx(0x80000001U);
-
- /*
- * This check purposefully doesn't use cpu_has_nx because
- * cpu_has_nx bypasses the boot_cpu_data read if Xen was compiled
- * with CONFIG_REQUIRE_NX
- */
- if ( IS_ENABLED(CONFIG_REQUIRE_NX) &&
- !boot_cpu_has(X86_FEATURE_NX) )
- blexit(L"This build of Xen requires NX support");
-
- if ( cpu_has_nx )
- trampoline_efer |= EFER_NXE;
}
}
diff --git a/xen/arch/x86/include/asm/setup.h b/xen/arch/x86/include/asm/setup.h
index b01e83a8ed..16f53725ca 100644
--- a/xen/arch/x86/include/asm/setup.h
+++ b/xen/arch/x86/include/asm/setup.h
@@ -70,4 +70,6 @@ extern bool opt_dom0_msr_relaxed;
#define max_init_domid (0)
+void nx_init(void);
+
#endif
diff --git a/xen/arch/x86/setup.c b/xen/arch/x86/setup.c
index 27c63d1d97..608720b717 100644
--- a/xen/arch/x86/setup.c
+++ b/xen/arch/x86/setup.c
@@ -1119,6 +1119,50 @@ static struct domain *__init create_dom0(struct
boot_info *bi)
return d;
}
+void __init nx_init(void)
+{
+ uint64_t misc_enable;
+ uint32_t eax, ebx, ecx, edx;
+
+ if ( !boot_cpu_has(X86_FEATURE_NX) )
+ {
+ /* Intel: try to unhide NX by clearing XD_DISABLE */
+ cpuid(0, &eax, &ebx, &ecx, &edx);
+ if ( ebx == X86_VENDOR_INTEL_EBX &&
+ ecx == X86_VENDOR_INTEL_ECX &&
+ edx == X86_VENDOR_INTEL_EDX )
+ {
+ rdmsrl(MSR_IA32_MISC_ENABLE, misc_enable);
+ if ( misc_enable & MSR_IA32_MISC_ENABLE_XD_DISABLE )
+ {
+ misc_enable &= ~MSR_IA32_MISC_ENABLE_XD_DISABLE;
+ wrmsrl(MSR_IA32_MISC_ENABLE, misc_enable);
+
+ /* Re-read CPUID after having cleared XD_DISABLE */
+ boot_cpu_data.x86_capability[FEATURESET_e1d] =
cpuid_edx(0x80000001U);
+
+ /* Adjust misc_enable_off for secondary startup and wakeup
code */
+ bootsym(trampoline_misc_enable_off) |=
MSR_IA32_MISC_ENABLE_XD_DISABLE;
+ printk(KERN_INFO "re-enabled NX (Execute Disable)
protection\n");
+ }
+ }
+ /* AMD: nothing we can do - NX must be enabled in BIOS */
+ }
+
+ /* Enable EFER.NXE only if NX is available */
+ if ( boot_cpu_has(X86_FEATURE_NX) )
+ {
+ if ( !(read_efer() & EFER_NXE) )
+ write_efer(read_efer() | EFER_NXE);
+
+ /* Adjust trampoline_efer for secondary startup and wakeup code */
+ bootsym(trampoline_efer) |= EFER_NXE;
+ }
+
+ if ( IS_ENABLED(CONFIG_REQUIRE_NX) && !boot_cpu_has(X86_FEATURE_NX) )
+ panic("This build of Xen requires NX support\n");
+}
+
/* How much of the directmap is prebuilt at compile time. */
#define PREBUILT_MAP_LIMIT (1 << L2_PAGETABLE_SHIFT)
@@ -1159,6 +1203,8 @@ void asmlinkage __init noreturn __start_xen(void)
rdmsrl(MSR_EFER, this_cpu(efer));
asm volatile ( "mov %%cr4,%0" : "=r" (info->cr4) );
+ nx_init();
+
/* Enable NMIs. Our loader (e.g. Tboot) may have left them disabled. */
enable_nmis();
--
2.51.0
--
Julian Vetter | Vates Hypervisor & Kernel Developer
XCP-ng & Xen Orchestra - Vates solutions
web: https://vates.tech
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |