Skip to content

Commit 04633df

Browse files
suryasaimadhuKAGA-KOKO
authored andcommitted
x86/cpu: Call verify_cpu() after having entered long mode too
When we get loaded by a 64-bit bootloader, kernel entry point is startup_64 in head_64.S. We don't trust any and all bootloaders because some will fiddle with CPU configuration so we go ahead and massage each CPU into sanity again. For example, some dell BIOSes have this XD disable feature which set IA32_MISC_ENABLE[34] and disable NX. This might be some dumb workaround for other OSes but Linux sure doesn't need it. A similar thing is present in the Surface 3 firmware - see https://bugzilla.kernel.org/show_bug.cgi?id=106051 - which sets this bit only on the BSP: # rdmsr -a 0x1a0 400850089 850089 850089 850089 I know, right?! There's not even an off switch in there. So fix all those cases by sanitizing the 64-bit entry point too. For that, make verify_cpu() callable in 64-bit mode also. Requested-and-debugged-by: "H. Peter Anvin" <hpa@zytor.com> Reported-and-tested-by: Bastien Nocera <bugzilla@hadess.net> Signed-off-by: Borislav Petkov <bp@suse.de> Cc: Matt Fleming <matt@codeblueprint.co.uk> Cc: Peter Zijlstra <peterz@infradead.org> Cc: stable@vger.kernel.org Link: http://lkml.kernel.org/r/1446739076-21303-1-git-send-email-bp@alien8.de Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
1 parent 68accac commit 04633df

File tree

2 files changed

+15
-5
lines changed

2 files changed

+15
-5
lines changed

arch/x86/kernel/head_64.S

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,9 @@ startup_64:
6565
* tables and then reload them.
6666
*/
6767

68+
/* Sanitize CPU configuration */
69+
call verify_cpu
70+
6871
/*
6972
* Compute the delta between the address I am compiled to run at and the
7073
* address I am actually running at.
@@ -174,6 +177,9 @@ ENTRY(secondary_startup_64)
174177
* after the boot processor executes this code.
175178
*/
176179

180+
/* Sanitize CPU configuration */
181+
call verify_cpu
182+
177183
movq $(init_level4_pgt - __START_KERNEL_map), %rax
178184
1:
179185

@@ -288,6 +294,8 @@ ENTRY(secondary_startup_64)
288294
pushq %rax # target address in negative space
289295
lretq
290296

297+
#include "verify_cpu.S"
298+
291299
#ifdef CONFIG_HOTPLUG_CPU
292300
/*
293301
* Boot CPU0 entry point. It's called from play_dead(). Everything has been set

arch/x86/kernel/verify_cpu.S

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,11 @@
3434
#include <asm/msr-index.h>
3535

3636
verify_cpu:
37-
pushfl # Save caller passed flags
38-
pushl $0 # Kill any dangerous flags
39-
popfl
37+
pushf # Save caller passed flags
38+
push $0 # Kill any dangerous flags
39+
popf
4040

41+
#ifndef __x86_64__
4142
pushfl # standard way to check for cpuid
4243
popl %eax
4344
movl %eax,%ebx
@@ -48,6 +49,7 @@ verify_cpu:
4849
popl %eax
4950
cmpl %eax,%ebx
5051
jz verify_cpu_no_longmode # cpu has no cpuid
52+
#endif
5153

5254
movl $0x0,%eax # See if cpuid 1 is implemented
5355
cpuid
@@ -130,10 +132,10 @@ verify_cpu_sse_test:
130132
jmp verify_cpu_sse_test # try again
131133

132134
verify_cpu_no_longmode:
133-
popfl # Restore caller passed flags
135+
popf # Restore caller passed flags
134136
movl $1,%eax
135137
ret
136138
verify_cpu_sse_ok:
137-
popfl # Restore caller passed flags
139+
popf # Restore caller passed flags
138140
xorl %eax, %eax
139141
ret

0 commit comments

Comments
 (0)