diff options
Diffstat (limited to 'arch/x86/kernel/cpu/common.c')
-rw-r--r-- | arch/x86/kernel/cpu/common.c | 66 |
1 files changed, 39 insertions, 27 deletions
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index f2f9ac7da25c..22a073d7fbff 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c | |||
@@ -254,6 +254,25 @@ static inline void squash_the_stupid_serial_number(struct cpuinfo_x86 *c) | |||
254 | } | 254 | } |
255 | #endif | 255 | #endif |
256 | 256 | ||
257 | static int disable_smep __cpuinitdata; | ||
258 | static __init int setup_disable_smep(char *arg) | ||
259 | { | ||
260 | disable_smep = 1; | ||
261 | return 1; | ||
262 | } | ||
263 | __setup("nosmep", setup_disable_smep); | ||
264 | |||
265 | static __cpuinit void setup_smep(struct cpuinfo_x86 *c) | ||
266 | { | ||
267 | if (cpu_has(c, X86_FEATURE_SMEP)) { | ||
268 | if (unlikely(disable_smep)) { | ||
269 | setup_clear_cpu_cap(X86_FEATURE_SMEP); | ||
270 | clear_in_cr4(X86_CR4_SMEP); | ||
271 | } else | ||
272 | set_in_cr4(X86_CR4_SMEP); | ||
273 | } | ||
274 | } | ||
275 | |||
257 | /* | 276 | /* |
258 | * Some CPU features depend on higher CPUID levels, which may not always | 277 | * Some CPU features depend on higher CPUID levels, which may not always |
259 | * be available due to CPUID level capping or broken virtualization | 278 | * be available due to CPUID level capping or broken virtualization |
@@ -458,13 +477,6 @@ void __cpuinit detect_ht(struct cpuinfo_x86 *c) | |||
458 | if (smp_num_siblings <= 1) | 477 | if (smp_num_siblings <= 1) |
459 | goto out; | 478 | goto out; |
460 | 479 | ||
461 | if (smp_num_siblings > nr_cpu_ids) { | ||
462 | pr_warning("CPU: Unsupported number of siblings %d", | ||
463 | smp_num_siblings); | ||
464 | smp_num_siblings = 1; | ||
465 | return; | ||
466 | } | ||
467 | |||
468 | index_msb = get_count_order(smp_num_siblings); | 480 | index_msb = get_count_order(smp_num_siblings); |
469 | c->phys_proc_id = apic->phys_pkg_id(c->initial_apicid, index_msb); | 481 | c->phys_proc_id = apic->phys_pkg_id(c->initial_apicid, index_msb); |
470 | 482 | ||
@@ -565,8 +577,7 @@ void __cpuinit get_cpu_cap(struct cpuinfo_x86 *c) | |||
565 | 577 | ||
566 | cpuid_count(0x00000007, 0, &eax, &ebx, &ecx, &edx); | 578 | cpuid_count(0x00000007, 0, &eax, &ebx, &ecx, &edx); |
567 | 579 | ||
568 | if (eax > 0) | 580 | c->x86_capability[9] = ebx; |
569 | c->x86_capability[9] = ebx; | ||
570 | } | 581 | } |
571 | 582 | ||
572 | /* AMD-defined flags: level 0x80000001 */ | 583 | /* AMD-defined flags: level 0x80000001 */ |
@@ -665,9 +676,11 @@ static void __init early_identify_cpu(struct cpuinfo_x86 *c) | |||
665 | this_cpu->c_early_init(c); | 676 | this_cpu->c_early_init(c); |
666 | 677 | ||
667 | #ifdef CONFIG_SMP | 678 | #ifdef CONFIG_SMP |
668 | c->cpu_index = boot_cpu_id; | 679 | c->cpu_index = 0; |
669 | #endif | 680 | #endif |
670 | filter_cpuid_features(c, false); | 681 | filter_cpuid_features(c, false); |
682 | |||
683 | setup_smep(c); | ||
671 | } | 684 | } |
672 | 685 | ||
673 | void __init early_cpu_init(void) | 686 | void __init early_cpu_init(void) |
@@ -675,7 +688,7 @@ void __init early_cpu_init(void) | |||
675 | const struct cpu_dev *const *cdev; | 688 | const struct cpu_dev *const *cdev; |
676 | int count = 0; | 689 | int count = 0; |
677 | 690 | ||
678 | #ifdef PROCESSOR_SELECT | 691 | #ifdef CONFIG_PROCESSOR_SELECT |
679 | printk(KERN_INFO "KERNEL supported cpus:\n"); | 692 | printk(KERN_INFO "KERNEL supported cpus:\n"); |
680 | #endif | 693 | #endif |
681 | 694 | ||
@@ -687,7 +700,7 @@ void __init early_cpu_init(void) | |||
687 | cpu_devs[count] = cpudev; | 700 | cpu_devs[count] = cpudev; |
688 | count++; | 701 | count++; |
689 | 702 | ||
690 | #ifdef PROCESSOR_SELECT | 703 | #ifdef CONFIG_PROCESSOR_SELECT |
691 | { | 704 | { |
692 | unsigned int j; | 705 | unsigned int j; |
693 | 706 | ||
@@ -704,16 +717,21 @@ void __init early_cpu_init(void) | |||
704 | } | 717 | } |
705 | 718 | ||
706 | /* | 719 | /* |
707 | * The NOPL instruction is supposed to exist on all CPUs with | 720 | * The NOPL instruction is supposed to exist on all CPUs of family >= 6; |
708 | * family >= 6; unfortunately, that's not true in practice because | 721 | * unfortunately, that's not true in practice because of early VIA |
709 | * of early VIA chips and (more importantly) broken virtualizers that | 722 | * chips and (more importantly) broken virtualizers that are not easy |
710 | * are not easy to detect. In the latter case it doesn't even *fail* | 723 | * to detect. In the latter case it doesn't even *fail* reliably, so |
711 | * reliably, so probing for it doesn't even work. Disable it completely | 724 | * probing for it doesn't even work. Disable it completely on 32-bit |
712 | * unless we can find a reliable way to detect all the broken cases. | 725 | * unless we can find a reliable way to detect all the broken cases. |
726 | * Enable it explicitly on 64-bit for non-constant inputs of cpu_has(). | ||
713 | */ | 727 | */ |
714 | static void __cpuinit detect_nopl(struct cpuinfo_x86 *c) | 728 | static void __cpuinit detect_nopl(struct cpuinfo_x86 *c) |
715 | { | 729 | { |
730 | #ifdef CONFIG_X86_32 | ||
716 | clear_cpu_cap(c, X86_FEATURE_NOPL); | 731 | clear_cpu_cap(c, X86_FEATURE_NOPL); |
732 | #else | ||
733 | set_cpu_cap(c, X86_FEATURE_NOPL); | ||
734 | #endif | ||
717 | } | 735 | } |
718 | 736 | ||
719 | static void __cpuinit generic_identify(struct cpuinfo_x86 *c) | 737 | static void __cpuinit generic_identify(struct cpuinfo_x86 *c) |
@@ -748,6 +766,8 @@ static void __cpuinit generic_identify(struct cpuinfo_x86 *c) | |||
748 | #endif | 766 | #endif |
749 | } | 767 | } |
750 | 768 | ||
769 | setup_smep(c); | ||
770 | |||
751 | get_model_name(c); /* Default name */ | 771 | get_model_name(c); /* Default name */ |
752 | 772 | ||
753 | detect_nopl(c); | 773 | detect_nopl(c); |
@@ -864,7 +884,7 @@ static void __cpuinit identify_cpu(struct cpuinfo_x86 *c) | |||
864 | 884 | ||
865 | select_idle_routine(c); | 885 | select_idle_routine(c); |
866 | 886 | ||
867 | #if defined(CONFIG_NUMA) && defined(CONFIG_X86_64) | 887 | #ifdef CONFIG_NUMA |
868 | numa_add_cpu(smp_processor_id()); | 888 | numa_add_cpu(smp_processor_id()); |
869 | #endif | 889 | #endif |
870 | } | 890 | } |
@@ -882,14 +902,13 @@ static void vgetcpu_set_mode(void) | |||
882 | void __init identify_boot_cpu(void) | 902 | void __init identify_boot_cpu(void) |
883 | { | 903 | { |
884 | identify_cpu(&boot_cpu_data); | 904 | identify_cpu(&boot_cpu_data); |
885 | init_c1e_mask(); | 905 | init_amd_e400_c1e_mask(); |
886 | #ifdef CONFIG_X86_32 | 906 | #ifdef CONFIG_X86_32 |
887 | sysenter_setup(); | 907 | sysenter_setup(); |
888 | enable_sep_cpu(); | 908 | enable_sep_cpu(); |
889 | #else | 909 | #else |
890 | vgetcpu_set_mode(); | 910 | vgetcpu_set_mode(); |
891 | #endif | 911 | #endif |
892 | init_hw_perf_events(); | ||
893 | } | 912 | } |
894 | 913 | ||
895 | void __cpuinit identify_secondary_cpu(struct cpuinfo_x86 *c) | 914 | void __cpuinit identify_secondary_cpu(struct cpuinfo_x86 *c) |
@@ -1264,13 +1283,6 @@ void __cpuinit cpu_init(void) | |||
1264 | clear_all_debug_regs(); | 1283 | clear_all_debug_regs(); |
1265 | dbg_restore_debug_regs(); | 1284 | dbg_restore_debug_regs(); |
1266 | 1285 | ||
1267 | /* | ||
1268 | * Force FPU initialization: | ||
1269 | */ | ||
1270 | current_thread_info()->status = 0; | ||
1271 | clear_used_math(); | ||
1272 | mxcsr_feature_mask_init(); | ||
1273 | |||
1274 | fpu_init(); | 1286 | fpu_init(); |
1275 | xsave_init(); | 1287 | xsave_init(); |
1276 | } | 1288 | } |