diff options
Diffstat (limited to 'arch/x86/kernel/cpu/common.c')
-rw-r--r-- | arch/x86/kernel/cpu/common.c | 45 |
1 files changed, 43 insertions, 2 deletions
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 80ab20d4fa39..c63ec65f484c 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <asm/mtrr.h> | 13 | #include <asm/mtrr.h> |
14 | #include <asm/mce.h> | 14 | #include <asm/mce.h> |
15 | #include <asm/pat.h> | 15 | #include <asm/pat.h> |
16 | #include <asm/asm.h> | ||
16 | #ifdef CONFIG_X86_LOCAL_APIC | 17 | #ifdef CONFIG_X86_LOCAL_APIC |
17 | #include <asm/mpspec.h> | 18 | #include <asm/mpspec.h> |
18 | #include <asm/apic.h> | 19 | #include <asm/apic.h> |
@@ -341,6 +342,35 @@ static void __init early_cpu_detect(void) | |||
341 | early_get_cap(c); | 342 | early_get_cap(c); |
342 | } | 343 | } |
343 | 344 | ||
345 | /* | ||
346 | * The NOPL instruction is supposed to exist on all CPUs with | ||
347 | * family >= 6, unfortunately, that's not true in practice because | ||
348 | * of early VIA chips and (more importantly) broken virtualizers that | ||
349 | * are not easy to detect. Hence, probe for it based on first | ||
350 | * principles. | ||
351 | */ | ||
352 | static void __cpuinit detect_nopl(struct cpuinfo_x86 *c) | ||
353 | { | ||
354 | const u32 nopl_signature = 0x888c53b1; /* Random number */ | ||
355 | u32 has_nopl = nopl_signature; | ||
356 | |||
357 | clear_cpu_cap(c, X86_FEATURE_NOPL); | ||
358 | if (c->x86 >= 6) { | ||
359 | asm volatile("\n" | ||
360 | "1: .byte 0x0f,0x1f,0xc0\n" /* nopl %eax */ | ||
361 | "2:\n" | ||
362 | " .section .fixup,\"ax\"\n" | ||
363 | "3: xor %0,%0\n" | ||
364 | " jmp 2b\n" | ||
365 | " .previous\n" | ||
366 | _ASM_EXTABLE(1b,3b) | ||
367 | : "+a" (has_nopl)); | ||
368 | |||
369 | if (has_nopl == nopl_signature) | ||
370 | set_cpu_cap(c, X86_FEATURE_NOPL); | ||
371 | } | ||
372 | } | ||
373 | |||
344 | static void __cpuinit generic_identify(struct cpuinfo_x86 *c) | 374 | static void __cpuinit generic_identify(struct cpuinfo_x86 *c) |
345 | { | 375 | { |
346 | u32 tfms, xlvl; | 376 | u32 tfms, xlvl; |
@@ -395,8 +425,8 @@ static void __cpuinit generic_identify(struct cpuinfo_x86 *c) | |||
395 | } | 425 | } |
396 | 426 | ||
397 | init_scattered_cpuid_features(c); | 427 | init_scattered_cpuid_features(c); |
428 | detect_nopl(c); | ||
398 | } | 429 | } |
399 | |||
400 | } | 430 | } |
401 | 431 | ||
402 | static void __cpuinit squash_the_stupid_serial_number(struct cpuinfo_x86 *c) | 432 | static void __cpuinit squash_the_stupid_serial_number(struct cpuinfo_x86 *c) |
@@ -709,9 +739,20 @@ void __cpuinit cpu_init(void) | |||
709 | /* | 739 | /* |
710 | * Force FPU initialization: | 740 | * Force FPU initialization: |
711 | */ | 741 | */ |
712 | current_thread_info()->status = 0; | 742 | if (cpu_has_xsave) |
743 | current_thread_info()->status = TS_XSAVE; | ||
744 | else | ||
745 | current_thread_info()->status = 0; | ||
713 | clear_used_math(); | 746 | clear_used_math(); |
714 | mxcsr_feature_mask_init(); | 747 | mxcsr_feature_mask_init(); |
748 | |||
749 | /* | ||
750 | * Boot processor to setup the FP and extended state context info. | ||
751 | */ | ||
752 | if (!smp_processor_id()) | ||
753 | init_thread_xstate(); | ||
754 | |||
755 | xsave_init(); | ||
715 | } | 756 | } |
716 | 757 | ||
717 | #ifdef CONFIG_HOTPLUG_CPU | 758 | #ifdef CONFIG_HOTPLUG_CPU |