0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031 #include <asm/cpufeatures.h>
0032 #include <asm/msr-index.h>
0033
0034 SYM_FUNC_START_LOCAL(verify_cpu)
0035 pushf # Save caller passed flags
0036 push $0 # Kill any dangerous flags
0037 popf
0038
0039 #ifndef __x86_64__
0040 pushfl # standard way to check for cpuid
0041 popl %eax
0042 movl %eax,%ebx
0043 xorl $0x200000,%eax
0044 pushl %eax
0045 popfl
0046 pushfl
0047 popl %eax
0048 cmpl %eax,%ebx
0049 jz .Lverify_cpu_no_longmode # cpu has no cpuid
0050 #endif
0051
0052 movl $0x0,%eax # See if cpuid 1 is implemented
0053 cpuid
0054 cmpl $0x1,%eax
0055 jb .Lverify_cpu_no_longmode # no cpuid 1
0056
0057 xor %di,%di
0058 cmpl $0x68747541,%ebx # AuthenticAMD
0059 jnz .Lverify_cpu_noamd
0060 cmpl $0x69746e65,%edx
0061 jnz .Lverify_cpu_noamd
0062 cmpl $0x444d4163,%ecx
0063 jnz .Lverify_cpu_noamd
0064 mov $1,%di # cpu is from AMD
0065 jmp .Lverify_cpu_check
0066
0067 .Lverify_cpu_noamd:
0068 cmpl $0x756e6547,%ebx # GenuineIntel?
0069 jnz .Lverify_cpu_check
0070 cmpl $0x49656e69,%edx
0071 jnz .Lverify_cpu_check
0072 cmpl $0x6c65746e,%ecx
0073 jnz .Lverify_cpu_check
0074
0075 # only call IA32_MISC_ENABLE when:
0076 # family > 6 || (family == 6 && model >= 0xd)
0077 movl $0x1, %eax # check CPU family and model
0078 cpuid
0079 movl %eax, %ecx
0080
0081 andl $0x0ff00f00, %eax # mask family and extended family
0082 shrl $8, %eax
0083 cmpl $6, %eax
0084 ja .Lverify_cpu_clear_xd # family > 6, ok
0085 jb .Lverify_cpu_check # family < 6, skip
0086
0087 andl $0x000f00f0, %ecx # mask model and extended model
0088 shrl $4, %ecx
0089 cmpl $0xd, %ecx
0090 jb .Lverify_cpu_check # family == 6, model < 0xd, skip
0091
0092 .Lverify_cpu_clear_xd:
0093 movl $MSR_IA32_MISC_ENABLE, %ecx
0094 rdmsr
0095 btrl $2, %edx # clear MSR_IA32_MISC_ENABLE_XD_DISABLE
0096 jnc .Lverify_cpu_check # only write MSR if bit was changed
0097 wrmsr
0098
0099 .Lverify_cpu_check:
0100 movl $0x1,%eax # Does the cpu have what it takes
0101 cpuid
0102 andl $REQUIRED_MASK0,%edx
0103 xorl $REQUIRED_MASK0,%edx
0104 jnz .Lverify_cpu_no_longmode
0105
0106 movl $0x80000000,%eax # See if extended cpuid is implemented
0107 cpuid
0108 cmpl $0x80000001,%eax
0109 jb .Lverify_cpu_no_longmode # no extended cpuid
0110
0111 movl $0x80000001,%eax # Does the cpu have what it takes
0112 cpuid
0113 andl $REQUIRED_MASK1,%edx
0114 xorl $REQUIRED_MASK1,%edx
0115 jnz .Lverify_cpu_no_longmode
0116
0117 .Lverify_cpu_sse_test:
0118 movl $1,%eax
0119 cpuid
0120 andl $SSE_MASK,%edx
0121 cmpl $SSE_MASK,%edx
0122 je .Lverify_cpu_sse_ok
0123 test %di,%di
0124 jz .Lverify_cpu_no_longmode # only try to force SSE on AMD
0125 movl $MSR_K7_HWCR,%ecx
0126 rdmsr
0127 btr $15,%eax # enable SSE
0128 wrmsr
0129 xor %di,%di # don't loop
0130 jmp .Lverify_cpu_sse_test # try again
0131
0132 .Lverify_cpu_no_longmode:
0133 popf # Restore caller passed flags
0134 movl $1,%eax
0135 RET
0136 .Lverify_cpu_sse_ok:
0137 popf # Restore caller passed flags
0138 xorl %eax, %eax
0139 RET
0140 SYM_FUNC_END(verify_cpu)