Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


Merge branch 'devel'
[palacios.git] / kitten / arch / x86_64 / kernel / verify_cpu.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 <arch/cpufeature.h>
34
35 verify_cpu:
36         pushfl                          # Save caller passed flags
37         pushl   $0                      # Kill any dangerous flags
38         popfl
39
40         /* minimum CPUID flags for x86-64 as defined by AMD */
41 #define M(x) (1<<(x))
42 #define M2(a,b) M(a)|M(b)
43 #define M4(a,b,c,d) M(a)|M(b)|M(c)|M(d)
44
45 #define SSE_MASK \
46         (M2(X86_FEATURE_XMM,X86_FEATURE_XMM2))
47 #define REQUIRED_MASK1 \
48         (M4(X86_FEATURE_FPU,X86_FEATURE_PSE,X86_FEATURE_TSC,X86_FEATURE_MSR)|\
49          M4(X86_FEATURE_PAE,X86_FEATURE_CX8,X86_FEATURE_PGE,X86_FEATURE_CMOV)|\
50          M(X86_FEATURE_FXSR))
51 #define REQUIRED_MASK2 \
52         (M(X86_FEATURE_LM - 32))
53
54         pushfl                          # standard way to check for cpuid
55         popl    %eax
56         movl    %eax,%ebx
57         xorl    $0x200000,%eax
58         pushl   %eax
59         popfl
60         pushfl
61         popl    %eax
62         cmpl    %eax,%ebx
63         jz      verify_cpu_no_longmode  # cpu has no cpuid
64
65         movl    $0x0,%eax               # See if cpuid 1 is implemented
66         cpuid
67         cmpl    $0x1,%eax
68         jb      verify_cpu_no_longmode  # no cpuid 1
69
70         xor     %di,%di
71         cmpl    $0x68747541,%ebx        # AuthenticAMD
72         jnz     verify_cpu_noamd
73         cmpl    $0x69746e65,%edx
74         jnz     verify_cpu_noamd
75         cmpl    $0x444d4163,%ecx
76         jnz     verify_cpu_noamd
77         mov     $1,%di                  # cpu is from AMD
78
79 verify_cpu_noamd:
80         movl    $0x1,%eax               # Does the cpu have what it takes
81         cpuid
82         andl    $REQUIRED_MASK1,%edx
83         xorl    $REQUIRED_MASK1,%edx
84         jnz     verify_cpu_no_longmode
85
86         movl    $0x80000000,%eax        # See if extended cpuid is implemented
87         cpuid
88         cmpl    $0x80000001,%eax
89         jb      verify_cpu_no_longmode  # no extended cpuid
90
91         movl    $0x80000001,%eax        # Does the cpu have what it takes
92         cpuid
93         andl    $REQUIRED_MASK2,%edx
94         xorl    $REQUIRED_MASK2,%edx
95         jnz     verify_cpu_no_longmode
96
97 verify_cpu_sse_test:
98         movl    $1,%eax
99         cpuid
100         andl    $SSE_MASK,%edx
101         cmpl    $SSE_MASK,%edx
102         je      verify_cpu_sse_ok
103         test    %di,%di
104         jz      verify_cpu_no_longmode  # only try to force SSE on AMD
105         movl    $0xc0010015,%ecx        # HWCR
106         rdmsr
107         btr     $15,%eax                # enable SSE
108         wrmsr
109         xor     %di,%di                 # don't loop
110         jmp     verify_cpu_sse_test     # try again
111
112 verify_cpu_no_longmode:
113         popfl                           # Restore caller passed flags
114         movl $1,%eax
115         ret
116 verify_cpu_sse_ok:
117         popfl                           # Restore caller passed flags
118         xorl %eax, %eax
119         ret