Commit 3682517d authored by Borislav Petkov's avatar Borislav Petkov Committed by Zefan Li

x86/cpu: Call verify_cpu() after having entered long mode too

commit 04633df0 upstream.

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: default avatar"H. Peter Anvin" <hpa@zytor.com>
Reported-and-tested-by: default avatarBastien Nocera <bugzilla@hadess.net>
Signed-off-by: default avatarBorislav Petkov <bp@suse.de>
Cc: Matt Fleming <matt@codeblueprint.co.uk>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/1446739076-21303-1-git-send-email-bp@alien8.deSigned-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
[lizf: Backported to 3.4: adjust context]
Signed-off-by: default avatarZefan Li <lizefan@huawei.com>
parent 51257521
...@@ -45,6 +45,9 @@ L3_START_KERNEL = pud_index(__START_KERNEL_map) ...@@ -45,6 +45,9 @@ L3_START_KERNEL = pud_index(__START_KERNEL_map)
.globl startup_64 .globl startup_64
startup_64: startup_64:
/* Sanitize CPU configuration */
call verify_cpu
/* /*
* At this point the CPU runs in 64bit mode CS.L = 1 CS.D = 1, * At this point the CPU runs in 64bit mode CS.L = 1 CS.D = 1,
* and someone has loaded an identity mapped page table * and someone has loaded an identity mapped page table
...@@ -160,6 +163,9 @@ ENTRY(secondary_startup_64) ...@@ -160,6 +163,9 @@ ENTRY(secondary_startup_64)
* after the boot processor executes this code. * after the boot processor executes this code.
*/ */
/* Sanitize CPU configuration */
call verify_cpu
/* Enable PAE mode and PGE */ /* Enable PAE mode and PGE */
movl $(X86_CR4_PAE | X86_CR4_PGE), %eax movl $(X86_CR4_PAE | X86_CR4_PGE), %eax
movq %rax, %cr4 movq %rax, %cr4
...@@ -253,6 +259,8 @@ ENTRY(secondary_startup_64) ...@@ -253,6 +259,8 @@ ENTRY(secondary_startup_64)
pushq %rax # target address in negative space pushq %rax # target address in negative space
lretq lretq
#include "verify_cpu.S"
/* SMP bootup changes these two */ /* SMP bootup changes these two */
__REFDATA __REFDATA
.align 8 .align 8
......
...@@ -34,10 +34,11 @@ ...@@ -34,10 +34,11 @@
#include <asm/msr-index.h> #include <asm/msr-index.h>
verify_cpu: verify_cpu:
pushfl # Save caller passed flags pushf # Save caller passed flags
pushl $0 # Kill any dangerous flags push $0 # Kill any dangerous flags
popfl popf
#ifndef __x86_64__
pushfl # standard way to check for cpuid pushfl # standard way to check for cpuid
popl %eax popl %eax
movl %eax,%ebx movl %eax,%ebx
...@@ -48,6 +49,7 @@ verify_cpu: ...@@ -48,6 +49,7 @@ verify_cpu:
popl %eax popl %eax
cmpl %eax,%ebx cmpl %eax,%ebx
jz verify_cpu_no_longmode # cpu has no cpuid jz verify_cpu_no_longmode # cpu has no cpuid
#endif
movl $0x0,%eax # See if cpuid 1 is implemented movl $0x0,%eax # See if cpuid 1 is implemented
cpuid cpuid
...@@ -130,10 +132,10 @@ verify_cpu_sse_test: ...@@ -130,10 +132,10 @@ verify_cpu_sse_test:
jmp verify_cpu_sse_test # try again jmp verify_cpu_sse_test # try again
verify_cpu_no_longmode: verify_cpu_no_longmode:
popfl # Restore caller passed flags popf # Restore caller passed flags
movl $1,%eax movl $1,%eax
ret ret
verify_cpu_sse_ok: verify_cpu_sse_ok:
popfl # Restore caller passed flags popf # Restore caller passed flags
xorl %eax, %eax xorl %eax, %eax
ret ret
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment