Blame view
arch/x86/kernel/verify_cpu.S
3.63 KB
a4831e08b [PATCH] x86-64: M... |
1 2 3 4 5 6 7 8 9 |
/* * * 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) |
ae84739c2 x86, cpu: Clear X... |
10 |
* Copyright (c) 2010 Kees Cook (kees.cook@canonical.com) |
a4831e08b [PATCH] x86-64: M... |
11 12 13 14 15 16 17 |
* * 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. |
ae84739c2 x86, cpu: Clear X... |
18 |
* This file is expected to run in 32bit code. Currently: |
a4831e08b [PATCH] x86-64: M... |
19 |
* |
79250af2d x86: Fix included... |
20 |
* arch/x86/boot/compressed/head_64.S: Boot cpu verification |
0d2eb44f6 x86: Fix common m... |
21 |
* arch/x86/kernel/trampoline_64.S: secondary processor verification |
79250af2d x86: Fix included... |
22 |
* arch/x86/kernel/head_32.S: processor startup |
a4831e08b [PATCH] x86-64: M... |
23 |
* |
ae84739c2 x86, cpu: Clear X... |
24 |
* verify_cpu, returns the status of longmode and SSE in register %eax. |
a4831e08b [PATCH] x86-64: M... |
25 26 |
* 0: Success 1: Failure * |
ae84739c2 x86, cpu: Clear X... |
27 28 |
* On Intel, the XD_DISABLE flag will be cleared as a side-effect. * |
a4831e08b [PATCH] x86-64: M... |
29 30 31 |
* The caller needs to check for the error code and take the action * appropriately. Either display a message or halt. */ |
72b1b1d01 [PATCH] x86-64: U... |
32 |
#include <asm/cpufeature.h> |
cfaa71ee9 x86: Use symbolic... |
33 |
#include <asm/msr-index.h> |
a4831e08b [PATCH] x86-64: M... |
34 |
|
72b1b1d01 [PATCH] x86-64: U... |
35 |
verify_cpu: |
a4831e08b [PATCH] x86-64: M... |
36 37 38 |
pushfl # Save caller passed flags pushl $0 # Kill any dangerous flags popfl |
a4831e08b [PATCH] x86-64: M... |
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
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 |
ae84739c2 x86, cpu: Clear X... |
63 |
jmp verify_cpu_check |
a4831e08b [PATCH] x86-64: M... |
64 65 |
verify_cpu_noamd: |
ae84739c2 x86, cpu: Clear X... |
66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 |
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: |
a4831e08b [PATCH] x86-64: M... |
98 99 |
movl $0x1,%eax # Does the cpu have what it takes cpuid |
ec481536b Unify the CPU fea... |
100 101 |
andl $REQUIRED_MASK0,%edx xorl $REQUIRED_MASK0,%edx |
a4831e08b [PATCH] x86-64: M... |
102 103 104 105 106 107 108 109 110 |
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 |
ec481536b Unify the CPU fea... |
111 112 |
andl $REQUIRED_MASK1,%edx xorl $REQUIRED_MASK1,%edx |
a4831e08b [PATCH] x86-64: M... |
113 114 115 116 117 118 119 120 121 122 |
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 |
cfaa71ee9 x86: Use symbolic... |
123 |
movl $MSR_K7_HWCR,%ecx |
a4831e08b [PATCH] x86-64: M... |
124 125 126 127 128 129 130 131 132 133 134 135 136 137 |
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 |