aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86_64/kernel/verify_cpu.S
diff options
context:
space:
mode:
authorVivek Goyal <vgoyal@in.ibm.com>2007-05-02 13:27:08 -0400
committerAndi Kleen <andi@basil.nowhere.org>2007-05-02 13:27:08 -0400
commita4831e08b7f3ed51623c9eb25e8c945b76b3eda3 (patch)
treecc38c9df02560fba778dfbff5f389e4ac3b720b9 /arch/x86_64/kernel/verify_cpu.S
parent8035d3ea78c2a61a9738c7857742370e0aa74d5c (diff)
[PATCH] x86-64: Move cpu verification code to common file
o This patch moves the code to verify long mode and SSE to a common file. This code is now shared by trampoline.S, wakeup.S, boot/setup.S and boot/compressed/head.S o So far we used to do very limited check in trampoline.S, wakeup.S and in 32bit entry point. Now all the entry paths are forced to do the exhaustive check, including SSE because verify_cpu is shared. o I am keeping this patch as last in the x86 relocatable series because previous patches have got quite some amount of testing done and don't want to distrub that. So that if there is problem introduced by this patch, at least it can be easily isolated. Signed-off-by: Eric W. Biederman <ebiederm@xmission.com> Signed-off-by: Vivek Goyal <vgoyal@in.ibm.com> Signed-off-by: Andi Kleen <ak@suse.de>
Diffstat (limited to 'arch/x86_64/kernel/verify_cpu.S')
-rw-r--r--arch/x86_64/kernel/verify_cpu.S110
1 files changed, 110 insertions, 0 deletions
diff --git a/arch/x86_64/kernel/verify_cpu.S b/arch/x86_64/kernel/verify_cpu.S
new file mode 100644
index 000000000000..72edabd2ef9a
--- /dev/null
+++ b/arch/x86_64/kernel/verify_cpu.S
@@ -0,0 +1,110 @@
1/*
2 *
3 * verify_cpu.S - Code for cpu long mode and SSE verification. This
4 * code has been borrowed from boot/setup.S and was introduced by
5 * Andi Kleen.
6 *
7 * Copyright (c) 2007 Andi Kleen (ak@suse.de)
8 * Copyright (c) 2007 Eric Biederman (ebiederm@xmission.com)
9 * Copyright (c) 2007 Vivek Goyal (vgoyal@in.ibm.com)
10 *
11 * This source code is licensed under the GNU General Public License,
12 * Version 2. See the file COPYING for more details.
13 *
14 * This is a common code for verification whether CPU supports
15 * long mode and SSE or not. It is not called directly instead this
16 * file is included at various places and compiled in that context.
17 * Following are the current usage.
18 *
19 * This file is included by both 16bit and 32bit code.
20 *
21 * arch/x86_64/boot/setup.S : Boot cpu verification (16bit)
22 * arch/x86_64/boot/compressed/head.S: Boot cpu verification (32bit)
23 * arch/x86_64/kernel/trampoline.S: secondary processor verfication (16bit)
24 * arch/x86_64/kernel/acpi/wakeup.S:Verfication at resume (16bit)
25 *
26 * verify_cpu, returns the status of cpu check in register %eax.
27 * 0: Success 1: Failure
28 *
29 * The caller needs to check for the error code and take the action
30 * appropriately. Either display a message or halt.
31 */
32
33verify_cpu:
34
35 pushfl # Save caller passed flags
36 pushl $0 # Kill any dangerous flags
37 popfl
38
39 /* minimum CPUID flags for x86-64 */
40 /* see http://www.x86-64.org/lists/discuss/msg02971.html */
41#define SSE_MASK ((1<<25)|(1<<26))
42#define REQUIRED_MASK1 ((1<<0)|(1<<3)|(1<<4)|(1<<5)|(1<<6)|(1<<8)|\
43 (1<<13)|(1<<15)|(1<<24))
44#define REQUIRED_MASK2 (1<<29)
45 pushfl # standard way to check for cpuid
46 popl %eax
47 movl %eax,%ebx
48 xorl $0x200000,%eax
49 pushl %eax
50 popfl
51 pushfl
52 popl %eax
53 cmpl %eax,%ebx
54 jz verify_cpu_no_longmode # cpu has no cpuid
55
56 movl $0x0,%eax # See if cpuid 1 is implemented
57 cpuid
58 cmpl $0x1,%eax
59 jb verify_cpu_no_longmode # no cpuid 1
60
61 xor %di,%di
62 cmpl $0x68747541,%ebx # AuthenticAMD
63 jnz verify_cpu_noamd
64 cmpl $0x69746e65,%edx
65 jnz verify_cpu_noamd
66 cmpl $0x444d4163,%ecx
67 jnz verify_cpu_noamd
68 mov $1,%di # cpu is from AMD
69
70verify_cpu_noamd:
71 movl $0x1,%eax # Does the cpu have what it takes
72 cpuid
73 andl $REQUIRED_MASK1,%edx
74 xorl $REQUIRED_MASK1,%edx
75 jnz verify_cpu_no_longmode
76
77 movl $0x80000000,%eax # See if extended cpuid is implemented
78 cpuid
79 cmpl $0x80000001,%eax
80 jb verify_cpu_no_longmode # no extended cpuid
81
82 movl $0x80000001,%eax # Does the cpu have what it takes
83 cpuid
84 andl $REQUIRED_MASK2,%edx
85 xorl $REQUIRED_MASK2,%edx
86 jnz verify_cpu_no_longmode
87
88verify_cpu_sse_test:
89 movl $1,%eax
90 cpuid
91 andl $SSE_MASK,%edx
92 cmpl $SSE_MASK,%edx
93 je verify_cpu_sse_ok
94 test %di,%di
95 jz verify_cpu_no_longmode # only try to force SSE on AMD
96 movl $0xc0010015,%ecx # HWCR
97 rdmsr
98 btr $15,%eax # enable SSE
99 wrmsr
100 xor %di,%di # don't loop
101 jmp verify_cpu_sse_test # try again
102
103verify_cpu_no_longmode:
104 popfl # Restore caller passed flags
105 movl $1,%eax
106 ret
107verify_cpu_sse_ok:
108 popfl # Restore caller passed flags
109 xorl %eax, %eax
110 ret