diff options
Diffstat (limited to 'arch/x86/kernel/setup_64.c')
-rw-r--r-- | arch/x86/kernel/setup_64.c | 224 |
1 files changed, 88 insertions, 136 deletions
diff --git a/arch/x86/kernel/setup_64.c b/arch/x86/kernel/setup_64.c index f4f7ecfb898c..674ef3510cdf 100644 --- a/arch/x86/kernel/setup_64.c +++ b/arch/x86/kernel/setup_64.c | |||
@@ -58,7 +58,6 @@ | |||
58 | #include <asm/mmu_context.h> | 58 | #include <asm/mmu_context.h> |
59 | #include <asm/proto.h> | 59 | #include <asm/proto.h> |
60 | #include <asm/setup.h> | 60 | #include <asm/setup.h> |
61 | #include <asm/mach_apic.h> | ||
62 | #include <asm/numa.h> | 61 | #include <asm/numa.h> |
63 | #include <asm/sections.h> | 62 | #include <asm/sections.h> |
64 | #include <asm/dmi.h> | 63 | #include <asm/dmi.h> |
@@ -66,7 +65,9 @@ | |||
66 | #include <asm/mce.h> | 65 | #include <asm/mce.h> |
67 | #include <asm/ds.h> | 66 | #include <asm/ds.h> |
68 | #include <asm/topology.h> | 67 | #include <asm/topology.h> |
68 | #include <asm/trampoline.h> | ||
69 | 69 | ||
70 | #include <mach_apic.h> | ||
70 | #ifdef CONFIG_PARAVIRT | 71 | #ifdef CONFIG_PARAVIRT |
71 | #include <asm/paravirt.h> | 72 | #include <asm/paravirt.h> |
72 | #else | 73 | #else |
@@ -248,6 +249,7 @@ static void __init reserve_crashkernel(void) | |||
248 | (unsigned long)(total_mem >> 20)); | 249 | (unsigned long)(total_mem >> 20)); |
249 | crashk_res.start = crash_base; | 250 | crashk_res.start = crash_base; |
250 | crashk_res.end = crash_base + crash_size - 1; | 251 | crashk_res.end = crash_base + crash_size - 1; |
252 | insert_resource(&iomem_resource, &crashk_res); | ||
251 | } | 253 | } |
252 | } | 254 | } |
253 | #else | 255 | #else |
@@ -322,6 +324,11 @@ void __init setup_arch(char **cmdline_p) | |||
322 | 324 | ||
323 | finish_e820_parsing(); | 325 | finish_e820_parsing(); |
324 | 326 | ||
327 | /* after parse_early_param, so could debug it */ | ||
328 | insert_resource(&iomem_resource, &code_resource); | ||
329 | insert_resource(&iomem_resource, &data_resource); | ||
330 | insert_resource(&iomem_resource, &bss_resource); | ||
331 | |||
325 | early_gart_iommu_check(); | 332 | early_gart_iommu_check(); |
326 | 333 | ||
327 | e820_register_active_regions(0, 0, -1UL); | 334 | e820_register_active_regions(0, 0, -1UL); |
@@ -341,10 +348,12 @@ void __init setup_arch(char **cmdline_p) | |||
341 | 348 | ||
342 | check_efer(); | 349 | check_efer(); |
343 | 350 | ||
344 | init_memory_mapping(0, (end_pfn_map << PAGE_SHIFT)); | 351 | max_pfn_mapped = init_memory_mapping(0, (max_pfn_mapped << PAGE_SHIFT)); |
345 | if (efi_enabled) | 352 | if (efi_enabled) |
346 | efi_init(); | 353 | efi_init(); |
347 | 354 | ||
355 | vsmp_init(); | ||
356 | |||
348 | dmi_scan_machine(); | 357 | dmi_scan_machine(); |
349 | 358 | ||
350 | io_delay_init(); | 359 | io_delay_init(); |
@@ -450,7 +459,7 @@ void __init setup_arch(char **cmdline_p) | |||
450 | /* | 459 | /* |
451 | * We trust e820 completely. No explicit ROM probing in memory. | 460 | * We trust e820 completely. No explicit ROM probing in memory. |
452 | */ | 461 | */ |
453 | e820_reserve_resources(&code_resource, &data_resource, &bss_resource); | 462 | e820_reserve_resources(); |
454 | e820_mark_nosave_regions(); | 463 | e820_mark_nosave_regions(); |
455 | 464 | ||
456 | /* request I/O space for devices used on all i[345]86 PCs */ | 465 | /* request I/O space for devices used on all i[345]86 PCs */ |
@@ -552,9 +561,9 @@ static void __cpuinit amd_detect_cmp(struct cpuinfo_x86 *c) | |||
552 | bits = c->x86_coreid_bits; | 561 | bits = c->x86_coreid_bits; |
553 | 562 | ||
554 | /* Low order bits define the core id (index of core in socket) */ | 563 | /* Low order bits define the core id (index of core in socket) */ |
555 | c->cpu_core_id = c->phys_proc_id & ((1 << bits)-1); | 564 | c->cpu_core_id = c->initial_apicid & ((1 << bits)-1); |
556 | /* Convert the APIC ID into the socket ID */ | 565 | /* Convert the initial APIC ID into the socket ID */ |
557 | c->phys_proc_id = phys_pkg_id(bits); | 566 | c->phys_proc_id = c->initial_apicid >> bits; |
558 | 567 | ||
559 | #ifdef CONFIG_NUMA | 568 | #ifdef CONFIG_NUMA |
560 | node = c->phys_proc_id; | 569 | node = c->phys_proc_id; |
@@ -571,7 +580,7 @@ static void __cpuinit amd_detect_cmp(struct cpuinfo_x86 *c) | |||
571 | If that doesn't result in a usable node fall back to the | 580 | If that doesn't result in a usable node fall back to the |
572 | path for the previous case. */ | 581 | path for the previous case. */ |
573 | 582 | ||
574 | int ht_nodeid = apicid - (cpu_data(0).phys_proc_id << bits); | 583 | int ht_nodeid = c->initial_apicid; |
575 | 584 | ||
576 | if (ht_nodeid >= 0 && | 585 | if (ht_nodeid >= 0 && |
577 | apicid_to_node[ht_nodeid] != NUMA_NO_NODE) | 586 | apicid_to_node[ht_nodeid] != NUMA_NO_NODE) |
@@ -677,7 +686,7 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c) | |||
677 | 686 | ||
678 | /* Bit 31 in normal CPUID used for nonstandard 3DNow ID; | 687 | /* Bit 31 in normal CPUID used for nonstandard 3DNow ID; |
679 | 3DNow is IDd by bit 31 in extended CPUID (1*32+31) anyway */ | 688 | 3DNow is IDd by bit 31 in extended CPUID (1*32+31) anyway */ |
680 | clear_bit(0*32+31, (unsigned long *)&c->x86_capability); | 689 | clear_cpu_cap(c, 0*32+31); |
681 | 690 | ||
682 | /* On C+ stepping K8 rep microcode works well for copy/memset */ | 691 | /* On C+ stepping K8 rep microcode works well for copy/memset */ |
683 | level = cpuid_eax(1); | 692 | level = cpuid_eax(1); |
@@ -721,6 +730,19 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c) | |||
721 | 730 | ||
722 | if (amd_apic_timer_broken()) | 731 | if (amd_apic_timer_broken()) |
723 | disable_apic_timer = 1; | 732 | disable_apic_timer = 1; |
733 | |||
734 | if (c == &boot_cpu_data && c->x86 >= 0xf && c->x86 <= 0x11) { | ||
735 | unsigned long long tseg; | ||
736 | |||
737 | /* | ||
738 | * Split up direct mapping around the TSEG SMM area. | ||
739 | * Don't do it for gbpages because there seems very little | ||
740 | * benefit in doing so. | ||
741 | */ | ||
742 | if (!rdmsrl_safe(MSR_K8_TSEG_ADDR, &tseg) && | ||
743 | (tseg >> PMD_SHIFT) < (max_pfn_mapped >> (PMD_SHIFT-PAGE_SHIFT))) | ||
744 | set_memory_4k((unsigned long)__va(tseg), 1); | ||
745 | } | ||
724 | } | 746 | } |
725 | 747 | ||
726 | void __cpuinit detect_ht(struct cpuinfo_x86 *c) | 748 | void __cpuinit detect_ht(struct cpuinfo_x86 *c) |
@@ -813,7 +835,7 @@ static void __cpuinit early_init_intel(struct cpuinfo_x86 *c) | |||
813 | { | 835 | { |
814 | if ((c->x86 == 0xf && c->x86_model >= 0x03) || | 836 | if ((c->x86 == 0xf && c->x86_model >= 0x03) || |
815 | (c->x86 == 0x6 && c->x86_model >= 0x0e)) | 837 | (c->x86 == 0x6 && c->x86_model >= 0x0e)) |
816 | set_bit(X86_FEATURE_CONSTANT_TSC, &c->x86_capability); | 838 | set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC); |
817 | } | 839 | } |
818 | 840 | ||
819 | static void __cpuinit init_intel(struct cpuinfo_x86 *c) | 841 | static void __cpuinit init_intel(struct cpuinfo_x86 *c) |
@@ -856,9 +878,6 @@ static void __cpuinit init_intel(struct cpuinfo_x86 *c) | |||
856 | 878 | ||
857 | if (c->x86 == 15) | 879 | if (c->x86 == 15) |
858 | c->x86_cache_alignment = c->x86_clflush_size * 2; | 880 | c->x86_cache_alignment = c->x86_clflush_size * 2; |
859 | if ((c->x86 == 0xf && c->x86_model >= 0x03) || | ||
860 | (c->x86 == 0x6 && c->x86_model >= 0x0e)) | ||
861 | set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC); | ||
862 | if (c->x86 == 6) | 881 | if (c->x86 == 6) |
863 | set_cpu_cap(c, X86_FEATURE_REP_GOOD); | 882 | set_cpu_cap(c, X86_FEATURE_REP_GOOD); |
864 | set_cpu_cap(c, X86_FEATURE_LFENCE_RDTSC); | 883 | set_cpu_cap(c, X86_FEATURE_LFENCE_RDTSC); |
@@ -867,6 +886,32 @@ static void __cpuinit init_intel(struct cpuinfo_x86 *c) | |||
867 | srat_detect_node(); | 886 | srat_detect_node(); |
868 | } | 887 | } |
869 | 888 | ||
889 | static void __cpuinit early_init_centaur(struct cpuinfo_x86 *c) | ||
890 | { | ||
891 | if (c->x86 == 0x6 && c->x86_model >= 0xf) | ||
892 | set_bit(X86_FEATURE_CONSTANT_TSC, &c->x86_capability); | ||
893 | } | ||
894 | |||
895 | static void __cpuinit init_centaur(struct cpuinfo_x86 *c) | ||
896 | { | ||
897 | /* Cache sizes */ | ||
898 | unsigned n; | ||
899 | |||
900 | n = c->extended_cpuid_level; | ||
901 | if (n >= 0x80000008) { | ||
902 | unsigned eax = cpuid_eax(0x80000008); | ||
903 | c->x86_virt_bits = (eax >> 8) & 0xff; | ||
904 | c->x86_phys_bits = eax & 0xff; | ||
905 | } | ||
906 | |||
907 | if (c->x86 == 0x6 && c->x86_model >= 0xf) { | ||
908 | c->x86_cache_alignment = c->x86_clflush_size * 2; | ||
909 | set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC); | ||
910 | set_cpu_cap(c, X86_FEATURE_REP_GOOD); | ||
911 | } | ||
912 | set_cpu_cap(c, X86_FEATURE_LFENCE_RDTSC); | ||
913 | } | ||
914 | |||
870 | static void __cpuinit get_cpu_vendor(struct cpuinfo_x86 *c) | 915 | static void __cpuinit get_cpu_vendor(struct cpuinfo_x86 *c) |
871 | { | 916 | { |
872 | char *v = c->x86_vendor_id; | 917 | char *v = c->x86_vendor_id; |
@@ -875,6 +920,8 @@ static void __cpuinit get_cpu_vendor(struct cpuinfo_x86 *c) | |||
875 | c->x86_vendor = X86_VENDOR_AMD; | 920 | c->x86_vendor = X86_VENDOR_AMD; |
876 | else if (!strcmp(v, "GenuineIntel")) | 921 | else if (!strcmp(v, "GenuineIntel")) |
877 | c->x86_vendor = X86_VENDOR_INTEL; | 922 | c->x86_vendor = X86_VENDOR_INTEL; |
923 | else if (!strcmp(v, "CentaurHauls")) | ||
924 | c->x86_vendor = X86_VENDOR_CENTAUR; | ||
878 | else | 925 | else |
879 | c->x86_vendor = X86_VENDOR_UNKNOWN; | 926 | c->x86_vendor = X86_VENDOR_UNKNOWN; |
880 | } | 927 | } |
@@ -922,15 +969,16 @@ static void __cpuinit early_identify_cpu(struct cpuinfo_x86 *c) | |||
922 | c->x86 += (tfms >> 20) & 0xff; | 969 | c->x86 += (tfms >> 20) & 0xff; |
923 | if (c->x86 >= 0x6) | 970 | if (c->x86 >= 0x6) |
924 | c->x86_model += ((tfms >> 16) & 0xF) << 4; | 971 | c->x86_model += ((tfms >> 16) & 0xF) << 4; |
925 | if (c->x86_capability[0] & (1<<19)) | 972 | if (test_cpu_cap(c, X86_FEATURE_CLFLSH)) |
926 | c->x86_clflush_size = ((misc >> 8) & 0xff) * 8; | 973 | c->x86_clflush_size = ((misc >> 8) & 0xff) * 8; |
927 | } else { | 974 | } else { |
928 | /* Have CPUID level 0 only - unheard of */ | 975 | /* Have CPUID level 0 only - unheard of */ |
929 | c->x86 = 4; | 976 | c->x86 = 4; |
930 | } | 977 | } |
931 | 978 | ||
979 | c->initial_apicid = (cpuid_ebx(1) >> 24) & 0xff; | ||
932 | #ifdef CONFIG_SMP | 980 | #ifdef CONFIG_SMP |
933 | c->phys_proc_id = (cpuid_ebx(1) >> 24) & 0xff; | 981 | c->phys_proc_id = c->initial_apicid; |
934 | #endif | 982 | #endif |
935 | /* AMD-defined flags: level 0x80000001 */ | 983 | /* AMD-defined flags: level 0x80000001 */ |
936 | xlvl = cpuid_eax(0x80000000); | 984 | xlvl = cpuid_eax(0x80000000); |
@@ -956,12 +1004,22 @@ static void __cpuinit early_identify_cpu(struct cpuinfo_x86 *c) | |||
956 | if (c->extended_cpuid_level >= 0x80000007) | 1004 | if (c->extended_cpuid_level >= 0x80000007) |
957 | c->x86_power = cpuid_edx(0x80000007); | 1005 | c->x86_power = cpuid_edx(0x80000007); |
958 | 1006 | ||
1007 | |||
1008 | clear_cpu_cap(c, X86_FEATURE_PAT); | ||
1009 | |||
959 | switch (c->x86_vendor) { | 1010 | switch (c->x86_vendor) { |
960 | case X86_VENDOR_AMD: | 1011 | case X86_VENDOR_AMD: |
961 | early_init_amd(c); | 1012 | early_init_amd(c); |
1013 | if (c->x86 >= 0xf && c->x86 <= 0x11) | ||
1014 | set_cpu_cap(c, X86_FEATURE_PAT); | ||
962 | break; | 1015 | break; |
963 | case X86_VENDOR_INTEL: | 1016 | case X86_VENDOR_INTEL: |
964 | early_init_intel(c); | 1017 | early_init_intel(c); |
1018 | if (c->x86 == 0xF || (c->x86 == 6 && c->x86_model >= 15)) | ||
1019 | set_cpu_cap(c, X86_FEATURE_PAT); | ||
1020 | break; | ||
1021 | case X86_VENDOR_CENTAUR: | ||
1022 | early_init_centaur(c); | ||
965 | break; | 1023 | break; |
966 | } | 1024 | } |
967 | 1025 | ||
@@ -999,6 +1057,10 @@ void __cpuinit identify_cpu(struct cpuinfo_x86 *c) | |||
999 | init_intel(c); | 1057 | init_intel(c); |
1000 | break; | 1058 | break; |
1001 | 1059 | ||
1060 | case X86_VENDOR_CENTAUR: | ||
1061 | init_centaur(c); | ||
1062 | break; | ||
1063 | |||
1002 | case X86_VENDOR_UNKNOWN: | 1064 | case X86_VENDOR_UNKNOWN: |
1003 | default: | 1065 | default: |
1004 | display_cacheinfo(c); | 1066 | display_cacheinfo(c); |
@@ -1028,14 +1090,24 @@ void __cpuinit identify_cpu(struct cpuinfo_x86 *c) | |||
1028 | #endif | 1090 | #endif |
1029 | select_idle_routine(c); | 1091 | select_idle_routine(c); |
1030 | 1092 | ||
1031 | if (c != &boot_cpu_data) | ||
1032 | mtrr_ap_init(); | ||
1033 | #ifdef CONFIG_NUMA | 1093 | #ifdef CONFIG_NUMA |
1034 | numa_add_cpu(smp_processor_id()); | 1094 | numa_add_cpu(smp_processor_id()); |
1035 | #endif | 1095 | #endif |
1036 | 1096 | ||
1037 | } | 1097 | } |
1038 | 1098 | ||
1099 | void __cpuinit identify_boot_cpu(void) | ||
1100 | { | ||
1101 | identify_cpu(&boot_cpu_data); | ||
1102 | } | ||
1103 | |||
1104 | void __cpuinit identify_secondary_cpu(struct cpuinfo_x86 *c) | ||
1105 | { | ||
1106 | BUG_ON(c == &boot_cpu_data); | ||
1107 | identify_cpu(c); | ||
1108 | mtrr_ap_init(); | ||
1109 | } | ||
1110 | |||
1039 | static __init int setup_noclflush(char *arg) | 1111 | static __init int setup_noclflush(char *arg) |
1040 | { | 1112 | { |
1041 | setup_clear_cpu_cap(X86_FEATURE_CLFLSH); | 1113 | setup_clear_cpu_cap(X86_FEATURE_CLFLSH); |
@@ -1064,123 +1136,3 @@ static __init int setup_disablecpuid(char *arg) | |||
1064 | return 1; | 1136 | return 1; |
1065 | } | 1137 | } |
1066 | __setup("clearcpuid=", setup_disablecpuid); | 1138 | __setup("clearcpuid=", setup_disablecpuid); |
1067 | |||
1068 | /* | ||
1069 | * Get CPU information for use by the procfs. | ||
1070 | */ | ||
1071 | |||
1072 | static int show_cpuinfo(struct seq_file *m, void *v) | ||
1073 | { | ||
1074 | struct cpuinfo_x86 *c = v; | ||
1075 | int cpu = 0, i; | ||
1076 | |||
1077 | #ifdef CONFIG_SMP | ||
1078 | cpu = c->cpu_index; | ||
1079 | #endif | ||
1080 | |||
1081 | seq_printf(m, "processor\t: %u\n" | ||
1082 | "vendor_id\t: %s\n" | ||
1083 | "cpu family\t: %d\n" | ||
1084 | "model\t\t: %d\n" | ||
1085 | "model name\t: %s\n", | ||
1086 | (unsigned)cpu, | ||
1087 | c->x86_vendor_id[0] ? c->x86_vendor_id : "unknown", | ||
1088 | c->x86, | ||
1089 | (int)c->x86_model, | ||
1090 | c->x86_model_id[0] ? c->x86_model_id : "unknown"); | ||
1091 | |||
1092 | if (c->x86_mask || c->cpuid_level >= 0) | ||
1093 | seq_printf(m, "stepping\t: %d\n", c->x86_mask); | ||
1094 | else | ||
1095 | seq_printf(m, "stepping\t: unknown\n"); | ||
1096 | |||
1097 | if (cpu_has(c, X86_FEATURE_TSC)) { | ||
1098 | unsigned int freq = cpufreq_quick_get((unsigned)cpu); | ||
1099 | |||
1100 | if (!freq) | ||
1101 | freq = cpu_khz; | ||
1102 | seq_printf(m, "cpu MHz\t\t: %u.%03u\n", | ||
1103 | freq / 1000, (freq % 1000)); | ||
1104 | } | ||
1105 | |||
1106 | /* Cache size */ | ||
1107 | if (c->x86_cache_size >= 0) | ||
1108 | seq_printf(m, "cache size\t: %d KB\n", c->x86_cache_size); | ||
1109 | |||
1110 | #ifdef CONFIG_SMP | ||
1111 | if (smp_num_siblings * c->x86_max_cores > 1) { | ||
1112 | seq_printf(m, "physical id\t: %d\n", c->phys_proc_id); | ||
1113 | seq_printf(m, "siblings\t: %d\n", | ||
1114 | cpus_weight(per_cpu(cpu_core_map, cpu))); | ||
1115 | seq_printf(m, "core id\t\t: %d\n", c->cpu_core_id); | ||
1116 | seq_printf(m, "cpu cores\t: %d\n", c->booted_cores); | ||
1117 | } | ||
1118 | #endif | ||
1119 | |||
1120 | seq_printf(m, | ||
1121 | "fpu\t\t: yes\n" | ||
1122 | "fpu_exception\t: yes\n" | ||
1123 | "cpuid level\t: %d\n" | ||
1124 | "wp\t\t: yes\n" | ||
1125 | "flags\t\t:", | ||
1126 | c->cpuid_level); | ||
1127 | |||
1128 | for (i = 0; i < 32*NCAPINTS; i++) | ||
1129 | if (cpu_has(c, i) && x86_cap_flags[i] != NULL) | ||
1130 | seq_printf(m, " %s", x86_cap_flags[i]); | ||
1131 | |||
1132 | seq_printf(m, "\nbogomips\t: %lu.%02lu\n", | ||
1133 | c->loops_per_jiffy/(500000/HZ), | ||
1134 | (c->loops_per_jiffy/(5000/HZ)) % 100); | ||
1135 | |||
1136 | if (c->x86_tlbsize > 0) | ||
1137 | seq_printf(m, "TLB size\t: %d 4K pages\n", c->x86_tlbsize); | ||
1138 | seq_printf(m, "clflush size\t: %d\n", c->x86_clflush_size); | ||
1139 | seq_printf(m, "cache_alignment\t: %d\n", c->x86_cache_alignment); | ||
1140 | |||
1141 | seq_printf(m, "address sizes\t: %u bits physical, %u bits virtual\n", | ||
1142 | c->x86_phys_bits, c->x86_virt_bits); | ||
1143 | |||
1144 | seq_printf(m, "power management:"); | ||
1145 | for (i = 0; i < 32; i++) { | ||
1146 | if (c->x86_power & (1 << i)) { | ||
1147 | if (i < ARRAY_SIZE(x86_power_flags) && | ||
1148 | x86_power_flags[i]) | ||
1149 | seq_printf(m, "%s%s", | ||
1150 | x86_power_flags[i][0]?" ":"", | ||
1151 | x86_power_flags[i]); | ||
1152 | else | ||
1153 | seq_printf(m, " [%d]", i); | ||
1154 | } | ||
1155 | } | ||
1156 | |||
1157 | seq_printf(m, "\n\n"); | ||
1158 | |||
1159 | return 0; | ||
1160 | } | ||
1161 | |||
1162 | static void *c_start(struct seq_file *m, loff_t *pos) | ||
1163 | { | ||
1164 | if (*pos == 0) /* just in case, cpu 0 is not the first */ | ||
1165 | *pos = first_cpu(cpu_online_map); | ||
1166 | if ((*pos) < NR_CPUS && cpu_online(*pos)) | ||
1167 | return &cpu_data(*pos); | ||
1168 | return NULL; | ||
1169 | } | ||
1170 | |||
1171 | static void *c_next(struct seq_file *m, void *v, loff_t *pos) | ||
1172 | { | ||
1173 | *pos = next_cpu(*pos, cpu_online_map); | ||
1174 | return c_start(m, pos); | ||
1175 | } | ||
1176 | |||
1177 | static void c_stop(struct seq_file *m, void *v) | ||
1178 | { | ||
1179 | } | ||
1180 | |||
1181 | const struct seq_operations cpuinfo_op = { | ||
1182 | .start = c_start, | ||
1183 | .next = c_next, | ||
1184 | .stop = c_stop, | ||
1185 | .show = show_cpuinfo, | ||
1186 | }; | ||