diff options
Diffstat (limited to 'arch/x86_64/boot')
-rw-r--r-- | arch/x86_64/boot/compressed/head.S | 19 | ||||
-rw-r--r-- | arch/x86_64/boot/setup.S | 65 |
2 files changed, 24 insertions, 60 deletions
diff --git a/arch/x86_64/boot/compressed/head.S b/arch/x86_64/boot/compressed/head.S index c353a9266ea4..f9d5692a0106 100644 --- a/arch/x86_64/boot/compressed/head.S +++ b/arch/x86_64/boot/compressed/head.S | |||
@@ -54,6 +54,15 @@ startup_32: | |||
54 | 1: popl %ebp | 54 | 1: popl %ebp |
55 | subl $1b, %ebp | 55 | subl $1b, %ebp |
56 | 56 | ||
57 | /* setup a stack and make sure cpu supports long mode. */ | ||
58 | movl $user_stack_end, %eax | ||
59 | addl %ebp, %eax | ||
60 | movl %eax, %esp | ||
61 | |||
62 | call verify_cpu | ||
63 | testl %eax, %eax | ||
64 | jnz no_longmode | ||
65 | |||
57 | /* Compute the delta between where we were compiled to run at | 66 | /* Compute the delta between where we were compiled to run at |
58 | * and where the code will actually run at. | 67 | * and where the code will actually run at. |
59 | */ | 68 | */ |
@@ -159,13 +168,21 @@ startup_32: | |||
159 | /* Jump from 32bit compatibility mode into 64bit mode. */ | 168 | /* Jump from 32bit compatibility mode into 64bit mode. */ |
160 | lret | 169 | lret |
161 | 170 | ||
171 | no_longmode: | ||
172 | /* This isn't an x86-64 CPU so hang */ | ||
173 | 1: | ||
174 | hlt | ||
175 | jmp 1b | ||
176 | |||
177 | #include "../../kernel/verify_cpu.S" | ||
178 | |||
162 | /* Be careful here startup_64 needs to be at a predictable | 179 | /* Be careful here startup_64 needs to be at a predictable |
163 | * address so I can export it in an ELF header. Bootloaders | 180 | * address so I can export it in an ELF header. Bootloaders |
164 | * should look at the ELF header to find this address, as | 181 | * should look at the ELF header to find this address, as |
165 | * it may change in the future. | 182 | * it may change in the future. |
166 | */ | 183 | */ |
167 | .code64 | 184 | .code64 |
168 | .org 0x100 | 185 | .org 0x200 |
169 | ENTRY(startup_64) | 186 | ENTRY(startup_64) |
170 | /* We come here either from startup_32 or directly from a | 187 | /* We come here either from startup_32 or directly from a |
171 | * 64bit bootloader. If we come here from a bootloader we depend on | 188 | * 64bit bootloader. If we come here from a bootloader we depend on |
diff --git a/arch/x86_64/boot/setup.S b/arch/x86_64/boot/setup.S index deb3573c7aec..816d04faa2be 100644 --- a/arch/x86_64/boot/setup.S +++ b/arch/x86_64/boot/setup.S | |||
@@ -299,64 +299,10 @@ loader_ok: | |||
299 | movw %cs,%ax | 299 | movw %cs,%ax |
300 | movw %ax,%ds | 300 | movw %ax,%ds |
301 | 301 | ||
302 | /* minimum CPUID flags for x86-64 */ | 302 | call verify_cpu |
303 | /* see http://www.x86-64.org/lists/discuss/msg02971.html */ | 303 | testl %eax,%eax |
304 | #define SSE_MASK ((1<<25)|(1<<26)) | 304 | jz sse_ok |
305 | #define REQUIRED_MASK1 ((1<<0)|(1<<3)|(1<<4)|(1<<5)|(1<<6)|(1<<8)|\ | 305 | |
306 | (1<<13)|(1<<15)|(1<<24)) | ||
307 | #define REQUIRED_MASK2 (1<<29) | ||
308 | |||
309 | pushfl /* standard way to check for cpuid */ | ||
310 | popl %eax | ||
311 | movl %eax,%ebx | ||
312 | xorl $0x200000,%eax | ||
313 | pushl %eax | ||
314 | popfl | ||
315 | pushfl | ||
316 | popl %eax | ||
317 | cmpl %eax,%ebx | ||
318 | jz no_longmode /* cpu has no cpuid */ | ||
319 | movl $0x0,%eax | ||
320 | cpuid | ||
321 | cmpl $0x1,%eax | ||
322 | jb no_longmode /* no cpuid 1 */ | ||
323 | xor %di,%di | ||
324 | cmpl $0x68747541,%ebx /* AuthenticAMD */ | ||
325 | jnz noamd | ||
326 | cmpl $0x69746e65,%edx | ||
327 | jnz noamd | ||
328 | cmpl $0x444d4163,%ecx | ||
329 | jnz noamd | ||
330 | mov $1,%di /* cpu is from AMD */ | ||
331 | noamd: | ||
332 | movl $0x1,%eax | ||
333 | cpuid | ||
334 | andl $REQUIRED_MASK1,%edx | ||
335 | xorl $REQUIRED_MASK1,%edx | ||
336 | jnz no_longmode | ||
337 | movl $0x80000000,%eax | ||
338 | cpuid | ||
339 | cmpl $0x80000001,%eax | ||
340 | jb no_longmode /* no extended cpuid */ | ||
341 | movl $0x80000001,%eax | ||
342 | cpuid | ||
343 | andl $REQUIRED_MASK2,%edx | ||
344 | xorl $REQUIRED_MASK2,%edx | ||
345 | jnz no_longmode | ||
346 | sse_test: | ||
347 | movl $1,%eax | ||
348 | cpuid | ||
349 | andl $SSE_MASK,%edx | ||
350 | cmpl $SSE_MASK,%edx | ||
351 | je sse_ok | ||
352 | test %di,%di | ||
353 | jz no_longmode /* only try to force SSE on AMD */ | ||
354 | movl $0xc0010015,%ecx /* HWCR */ | ||
355 | rdmsr | ||
356 | btr $15,%eax /* enable SSE */ | ||
357 | wrmsr | ||
358 | xor %di,%di /* don't loop */ | ||
359 | jmp sse_test /* try again */ | ||
360 | no_longmode: | 306 | no_longmode: |
361 | call beep | 307 | call beep |
362 | lea long_mode_panic,%si | 308 | lea long_mode_panic,%si |
@@ -366,7 +312,8 @@ no_longmode_loop: | |||
366 | long_mode_panic: | 312 | long_mode_panic: |
367 | .string "Your CPU does not support long mode. Use a 32bit distribution." | 313 | .string "Your CPU does not support long mode. Use a 32bit distribution." |
368 | .byte 0 | 314 | .byte 0 |
369 | 315 | ||
316 | #include "../kernel/verify_cpu.S" | ||
370 | sse_ok: | 317 | sse_ok: |
371 | popw %ds | 318 | popw %ds |
372 | 319 | ||