Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-2.6
[linux-2.6] / arch / x86 / kernel / verify_cpu_64.S
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
33 #include <asm/cpufeature.h>
34
35 verify_cpu:
36         pushfl                          # Save caller passed flags
37         pushl   $0                      # Kill any dangerous flags
38         popfl
39
40         pushfl                          # standard way to check for cpuid
41         popl    %eax
42         movl    %eax,%ebx
43         xorl    $0x200000,%eax
44         pushl   %eax
45         popfl
46         pushfl
47         popl    %eax
48         cmpl    %eax,%ebx
49         jz      verify_cpu_no_longmode  # cpu has no cpuid
50
51         movl    $0x0,%eax               # See if cpuid 1 is implemented
52         cpuid
53         cmpl    $0x1,%eax
54         jb      verify_cpu_no_longmode  # no cpuid 1
55
56         xor     %di,%di
57         cmpl    $0x68747541,%ebx        # AuthenticAMD
58         jnz     verify_cpu_noamd
59         cmpl    $0x69746e65,%edx
60         jnz     verify_cpu_noamd
61         cmpl    $0x444d4163,%ecx
62         jnz     verify_cpu_noamd
63         mov     $1,%di                  # cpu is from AMD
64
65 verify_cpu_noamd:
66         movl    $0x1,%eax               # Does the cpu have what it takes
67         cpuid
68         andl    $REQUIRED_MASK0,%edx
69         xorl    $REQUIRED_MASK0,%edx
70         jnz     verify_cpu_no_longmode
71
72         movl    $0x80000000,%eax        # See if extended cpuid is implemented
73         cpuid
74         cmpl    $0x80000001,%eax
75         jb      verify_cpu_no_longmode  # no extended cpuid
76
77         movl    $0x80000001,%eax        # Does the cpu have what it takes
78         cpuid
79         andl    $REQUIRED_MASK1,%edx
80         xorl    $REQUIRED_MASK1,%edx
81         jnz     verify_cpu_no_longmode
82
83 verify_cpu_sse_test:
84         movl    $1,%eax
85         cpuid
86         andl    $SSE_MASK,%edx
87         cmpl    $SSE_MASK,%edx
88         je      verify_cpu_sse_ok
89         test    %di,%di
90         jz      verify_cpu_no_longmode  # only try to force SSE on AMD
91         movl    $0xc0010015,%ecx        # HWCR
92         rdmsr
93         btr     $15,%eax                # enable SSE
94         wrmsr
95         xor     %di,%di                 # don't loop
96         jmp     verify_cpu_sse_test     # try again
97
98 verify_cpu_no_longmode:
99         popfl                           # Restore caller passed flags
100         movl $1,%eax
101         ret
102 verify_cpu_sse_ok:
103         popfl                           # Restore caller passed flags
104         xorl %eax, %eax
105         ret