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