Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 53778
b: refs/heads/master
c: a4831e0
h: refs/heads/master
v: v3
  • Loading branch information
Vivek Goyal authored and Andi Kleen committed May 2, 2007
1 parent a893857 commit a5bd7d3
Show file tree
Hide file tree
Showing 6 changed files with 153 additions and 124 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 8035d3ea78c2a61a9738c7857742370e0aa74d5c
refs/heads/master: a4831e08b7f3ed51623c9eb25e8c945b76b3eda3
19 changes: 18 additions & 1 deletion trunk/arch/x86_64/boot/compressed/head.S
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,15 @@ startup_32:
1: popl %ebp
subl $1b, %ebp

/* setup a stack and make sure cpu supports long mode. */
movl $user_stack_end, %eax
addl %ebp, %eax
movl %eax, %esp

call verify_cpu
testl %eax, %eax
jnz no_longmode

/* Compute the delta between where we were compiled to run at
* and where the code will actually run at.
*/
Expand Down Expand Up @@ -159,13 +168,21 @@ startup_32:
/* Jump from 32bit compatibility mode into 64bit mode. */
lret

no_longmode:
/* This isn't an x86-64 CPU so hang */
1:
hlt
jmp 1b

#include "../../kernel/verify_cpu.S"

/* Be careful here startup_64 needs to be at a predictable
* address so I can export it in an ELF header. Bootloaders
* should look at the ELF header to find this address, as
* it may change in the future.
*/
.code64
.org 0x100
.org 0x200
ENTRY(startup_64)
/* We come here either from startup_32 or directly from a
* 64bit bootloader. If we come here from a bootloader we depend on
Expand Down
65 changes: 6 additions & 59 deletions trunk/arch/x86_64/boot/setup.S
Original file line number Diff line number Diff line change
Expand Up @@ -299,64 +299,10 @@ loader_ok:
movw %cs,%ax
movw %ax,%ds

/* minimum CPUID flags for x86-64 */
/* see http://www.x86-64.org/lists/discuss/msg02971.html */
#define SSE_MASK ((1<<25)|(1<<26))
#define REQUIRED_MASK1 ((1<<0)|(1<<3)|(1<<4)|(1<<5)|(1<<6)|(1<<8)|\
(1<<13)|(1<<15)|(1<<24))
#define REQUIRED_MASK2 (1<<29)

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 no_longmode /* cpu has no cpuid */
movl $0x0,%eax
cpuid
cmpl $0x1,%eax
jb no_longmode /* no cpuid 1 */
xor %di,%di
cmpl $0x68747541,%ebx /* AuthenticAMD */
jnz noamd
cmpl $0x69746e65,%edx
jnz noamd
cmpl $0x444d4163,%ecx
jnz noamd
mov $1,%di /* cpu is from AMD */
noamd:
movl $0x1,%eax
cpuid
andl $REQUIRED_MASK1,%edx
xorl $REQUIRED_MASK1,%edx
jnz no_longmode
movl $0x80000000,%eax
cpuid
cmpl $0x80000001,%eax
jb no_longmode /* no extended cpuid */
movl $0x80000001,%eax
cpuid
andl $REQUIRED_MASK2,%edx
xorl $REQUIRED_MASK2,%edx
jnz no_longmode
sse_test:
movl $1,%eax
cpuid
andl $SSE_MASK,%edx
cmpl $SSE_MASK,%edx
je sse_ok
test %di,%di
jz no_longmode /* only try to force SSE on AMD */
movl $0xc0010015,%ecx /* HWCR */
rdmsr
btr $15,%eax /* enable SSE */
wrmsr
xor %di,%di /* don't loop */
jmp sse_test /* try again */
call verify_cpu
testl %eax,%eax
jz sse_ok

no_longmode:
call beep
lea long_mode_panic,%si
Expand All @@ -366,7 +312,8 @@ no_longmode_loop:
long_mode_panic:
.string "Your CPU does not support long mode. Use a 32bit distribution."
.byte 0


#include "../kernel/verify_cpu.S"
sse_ok:
popw %ds

Expand Down
30 changes: 15 additions & 15 deletions trunk/arch/x86_64/kernel/acpi/wakeup.S
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,11 @@ wakeup_code:
cmpl $0x12345678, %eax
jne bogus_real_magic

call verify_cpu # Verify the cpu supports long
# mode
testl %eax, %eax
jnz no_longmode

testl $1, video_flags - wakeup_code
jz 1f
lcall $0xc000,$3
Expand Down Expand Up @@ -92,18 +97,6 @@ wakeup_32:
# Running in this code, but at low address; paging is not yet turned on.
movb $0xa5, %al ; outb %al, $0x80

/* Check if extended functions are implemented */
movl $0x80000000, %eax
cpuid
cmpl $0x80000000, %eax
jbe bogus_cpu
wbinvd
mov $0x80000001, %eax
cpuid
btl $29, %edx
jnc bogus_cpu
movl %edx,%edi

movl $__KERNEL_DS, %eax
movl %eax, %ds

Expand All @@ -123,6 +116,11 @@ wakeup_32:
leal (wakeup_level4_pgt - wakeup_code)(%esi), %eax
movl %eax, %cr3

/* Check if nx is implemented */
movl $0x80000001, %eax
cpuid
movl %edx,%edi

/* Enable Long Mode */
xorl %eax, %eax
btsl $_EFER_LME, %eax
Expand Down Expand Up @@ -244,10 +242,12 @@ bogus_64_magic:
movb $0xb3,%al ; outb %al,$0x80
jmp bogus_64_magic

bogus_cpu:
movb $0xbc,%al ; outb %al,$0x80
jmp bogus_cpu
.code16
no_longmode:
movb $0xbc,%al ; outb %al,$0x80
jmp no_longmode

#include "../verify_cpu.S"

/* This code uses an extended set of video mode numbers. These include:
* Aliases for standard modes
Expand Down
51 changes: 3 additions & 48 deletions trunk/arch/x86_64/kernel/trampoline.S
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ r_base = .
movw $(trampoline_stack_end - r_base), %sp

call verify_cpu # Verify the cpu supports long mode
testl %eax, %eax # Check for return code
jnz no_longmode

mov %cs, %ax
movzx %ax, %esi # Find the 32bit trampoline location
Expand Down Expand Up @@ -121,57 +123,10 @@ startup_64:
jmp *%rax

.code16
verify_cpu:
pushl $0 # Kill any dangerous flags
popfl

/* minimum CPUID flags for x86-64 */
/* see http://www.x86-64.org/lists/discuss/msg02971.html */
#define REQUIRED_MASK1 ((1<<0)|(1<<3)|(1<<4)|(1<<5)|(1<<6)|(1<<8)|\
(1<<13)|(1<<15)|(1<<24)|(1<<25)|(1<<26))
#define REQUIRED_MASK2 (1<<29)

pushfl # check for cpuid
popl %eax
movl %eax, %ebx
xorl $0x200000,%eax
pushl %eax
popfl
pushfl
popl %eax
pushl %ebx
popfl
cmpl %eax, %ebx
jz no_longmode

xorl %eax, %eax # See if cpuid 1 is implemented
cpuid
cmpl $0x1, %eax
jb no_longmode

movl $0x01, %eax # Does the cpu have what it takes?
cpuid
andl $REQUIRED_MASK1, %edx
xorl $REQUIRED_MASK1, %edx
jnz no_longmode

movl $0x80000000, %eax # See if extended cpuid is implemented
cpuid
cmpl $0x80000001, %eax
jb no_longmode

movl $0x80000001, %eax # Does the cpu have what it takes?
cpuid
andl $REQUIRED_MASK2, %edx
xorl $REQUIRED_MASK2, %edx
jnz no_longmode

ret # The cpu supports long mode

no_longmode:
hlt
jmp no_longmode

#include "verify_cpu.S"

# Careful these need to be in the same 64K segment as the above;
tidt:
Expand Down
110 changes: 110 additions & 0 deletions trunk/arch/x86_64/kernel/verify_cpu.S
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
/*
*
* 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)
*
* 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.
* Following are the current usage.
*
* This file is included by both 16bit and 32bit code.
*
* arch/x86_64/boot/setup.S : Boot cpu verification (16bit)
* arch/x86_64/boot/compressed/head.S: Boot cpu verification (32bit)
* arch/x86_64/kernel/trampoline.S: secondary processor verfication (16bit)
* arch/x86_64/kernel/acpi/wakeup.S:Verfication at resume (16bit)
*
* verify_cpu, returns the status of cpu check in register %eax.
* 0: Success 1: Failure
*
* The caller needs to check for the error code and take the action
* appropriately. Either display a message or halt.
*/

verify_cpu:

pushfl # Save caller passed flags
pushl $0 # Kill any dangerous flags
popfl

/* minimum CPUID flags for x86-64 */
/* see http://www.x86-64.org/lists/discuss/msg02971.html */
#define SSE_MASK ((1<<25)|(1<<26))
#define REQUIRED_MASK1 ((1<<0)|(1<<3)|(1<<4)|(1<<5)|(1<<6)|(1<<8)|\
(1<<13)|(1<<15)|(1<<24))
#define REQUIRED_MASK2 (1<<29)
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

verify_cpu_noamd:
movl $0x1,%eax # Does the cpu have what it takes
cpuid
andl $REQUIRED_MASK1,%edx
xorl $REQUIRED_MASK1,%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_MASK2,%edx
xorl $REQUIRED_MASK2,%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 $0xc0010015,%ecx # HWCR
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

0 comments on commit a5bd7d3

Please sign in to comment.