mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-12 13:55:32 +00:00
![Kees Cook](/assets/img/avatar_default.png)
Intel CPUs have an additional MSR bit to indicate if the BIOS was configured to disable the NX cpu feature. This bit was traditionally used for operating systems that did not understand how to handle the NX bit. Since Linux understands this, this BIOS flag should be ignored by default. In a review[1] of reported hardware being used by Ubuntu bug reporters, almost 10% of systems had an incorrectly configured BIOS, leaving their systems unable to use the NX features of their CPU. This change will clear the MSR_IA32_MISC_ENABLE_XD_DISABLE bit so that NX cannot be inappropriately controlled by the BIOS on Intel CPUs. If, under very strange hardware configurations, NX actually needs to be disabled, "noexec=off" can be used to restore the prior behavior. [1] http://www.outflux.net/blog/archives/2010/02/18/data-mining-for-nx-bit/ Signed-off-by: Kees Cook <kees.cook@canonical.com> LKML-Reference: <1289414154-7829-3-git-send-email-kees.cook@canonical.com> Acked-by: Pekka Enberg <penberg@kernel.org> Acked-by: Alan Cox <alan@lxorguk.ukuu.org.uk> Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
138 lines
3.6 KiB
ArmAsm
138 lines
3.6 KiB
ArmAsm
/*
|
|
*
|
|
* verify_cpu.S - Code for cpu long mode and SSE verification. This
|
|
* code has been borrowed from boot/setup.S and was introduced by
|
|
* Andi Kleen.
|
|
*
|
|
* Copyright (c) 2007 Andi Kleen (ak@suse.de)
|
|
* Copyright (c) 2007 Eric Biederman (ebiederm@xmission.com)
|
|
* Copyright (c) 2007 Vivek Goyal (vgoyal@in.ibm.com)
|
|
* Copyright (c) 2010 Kees Cook (kees.cook@canonical.com)
|
|
*
|
|
* This source code is licensed under the GNU General Public License,
|
|
* Version 2. See the file COPYING for more details.
|
|
*
|
|
* This is a common code for verification whether CPU supports
|
|
* long mode and SSE or not. It is not called directly instead this
|
|
* file is included at various places and compiled in that context.
|
|
* This file is expected to run in 32bit code. Currently:
|
|
*
|
|
* arch/x86_64/boot/compressed/head_64.S: Boot cpu verification
|
|
* arch/x86_64/kernel/trampoline_64.S: secondary processor verfication
|
|
*
|
|
* verify_cpu, returns the status of longmode and SSE in register %eax.
|
|
* 0: Success 1: Failure
|
|
*
|
|
* On Intel, the XD_DISABLE flag will be cleared as a side-effect.
|
|
*
|
|
* The caller needs to check for the error code and take the action
|
|
* appropriately. Either display a message or halt.
|
|
*/
|
|
|
|
#include <asm/cpufeature.h>
|
|
#include <asm/msr-index.h>
|
|
|
|
verify_cpu:
|
|
pushfl # Save caller passed flags
|
|
pushl $0 # Kill any dangerous flags
|
|
popfl
|
|
|
|
pushfl # standard way to check for cpuid
|
|
popl %eax
|
|
movl %eax,%ebx
|
|
xorl $0x200000,%eax
|
|
pushl %eax
|
|
popfl
|
|
pushfl
|
|
popl %eax
|
|
cmpl %eax,%ebx
|
|
jz verify_cpu_no_longmode # cpu has no cpuid
|
|
|
|
movl $0x0,%eax # See if cpuid 1 is implemented
|
|
cpuid
|
|
cmpl $0x1,%eax
|
|
jb verify_cpu_no_longmode # no cpuid 1
|
|
|
|
xor %di,%di
|
|
cmpl $0x68747541,%ebx # AuthenticAMD
|
|
jnz verify_cpu_noamd
|
|
cmpl $0x69746e65,%edx
|
|
jnz verify_cpu_noamd
|
|
cmpl $0x444d4163,%ecx
|
|
jnz verify_cpu_noamd
|
|
mov $1,%di # cpu is from AMD
|
|
jmp verify_cpu_check
|
|
|
|
verify_cpu_noamd:
|
|
cmpl $0x756e6547,%ebx # GenuineIntel?
|
|
jnz verify_cpu_check
|
|
cmpl $0x49656e69,%edx
|
|
jnz verify_cpu_check
|
|
cmpl $0x6c65746e,%ecx
|
|
jnz verify_cpu_check
|
|
|
|
# only call IA32_MISC_ENABLE when:
|
|
# family > 6 || (family == 6 && model >= 0xd)
|
|
movl $0x1, %eax # check CPU family and model
|
|
cpuid
|
|
movl %eax, %ecx
|
|
|
|
andl $0x0ff00f00, %eax # mask family and extended family
|
|
shrl $8, %eax
|
|
cmpl $6, %eax
|
|
ja verify_cpu_clear_xd # family > 6, ok
|
|
jb verify_cpu_check # family < 6, skip
|
|
|
|
andl $0x000f00f0, %ecx # mask model and extended model
|
|
shrl $4, %ecx
|
|
cmpl $0xd, %ecx
|
|
jb verify_cpu_check # family == 6, model < 0xd, skip
|
|
|
|
verify_cpu_clear_xd:
|
|
movl $MSR_IA32_MISC_ENABLE, %ecx
|
|
rdmsr
|
|
btrl $2, %edx # clear MSR_IA32_MISC_ENABLE_XD_DISABLE
|
|
jnc verify_cpu_check # only write MSR if bit was changed
|
|
wrmsr
|
|
|
|
verify_cpu_check:
|
|
movl $0x1,%eax # Does the cpu have what it takes
|
|
cpuid
|
|
andl $REQUIRED_MASK0,%edx
|
|
xorl $REQUIRED_MASK0,%edx
|
|
jnz verify_cpu_no_longmode
|
|
|
|
movl $0x80000000,%eax # See if extended cpuid is implemented
|
|
cpuid
|
|
cmpl $0x80000001,%eax
|
|
jb verify_cpu_no_longmode # no extended cpuid
|
|
|
|
movl $0x80000001,%eax # Does the cpu have what it takes
|
|
cpuid
|
|
andl $REQUIRED_MASK1,%edx
|
|
xorl $REQUIRED_MASK1,%edx
|
|
jnz verify_cpu_no_longmode
|
|
|
|
verify_cpu_sse_test:
|
|
movl $1,%eax
|
|
cpuid
|
|
andl $SSE_MASK,%edx
|
|
cmpl $SSE_MASK,%edx
|
|
je verify_cpu_sse_ok
|
|
test %di,%di
|
|
jz verify_cpu_no_longmode # only try to force SSE on AMD
|
|
movl $MSR_K7_HWCR,%ecx
|
|
rdmsr
|
|
btr $15,%eax # enable SSE
|
|
wrmsr
|
|
xor %di,%di # don't loop
|
|
jmp verify_cpu_sse_test # try again
|
|
|
|
verify_cpu_no_longmode:
|
|
popfl # Restore caller passed flags
|
|
movl $1,%eax
|
|
ret
|
|
verify_cpu_sse_ok:
|
|
popfl # Restore caller passed flags
|
|
xorl %eax, %eax
|
|
ret
|