diff options
author | Glauber de Oliveira Costa <gcosta@redhat.com> | 2008-03-19 13:26:11 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-04-17 11:41:04 -0400 |
commit | 8aef135c73436fa46fdb4dc8aba49d5539dee72d (patch) | |
tree | d733efeff177fc41ccf110dfb1d805b81518f8ef /arch/x86/kernel/smpboot.c | |
parent | 9f3734f631267d2f36008833b62670ca342ac000 (diff) |
x86: merge native_smp_prepare_cpus
With the previous changes, code for native_smp_prepare_cpus()
in i386 and x86_64 now look very similar. merge them into
smpboot.c. Minor differences are inside ifdef
Signed-off-by: Glauber Costa <gcosta@redhat.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch/x86/kernel/smpboot.c')
-rw-r--r-- | arch/x86/kernel/smpboot.c | 170 |
1 files changed, 170 insertions, 0 deletions
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index 26118b4a1c38..45119d39f31e 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c | |||
@@ -7,6 +7,7 @@ | |||
7 | #include <linux/err.h> | 7 | #include <linux/err.h> |
8 | #include <linux/nmi.h> | 8 | #include <linux/nmi.h> |
9 | 9 | ||
10 | #include <asm/acpi.h> | ||
10 | #include <asm/desc.h> | 11 | #include <asm/desc.h> |
11 | #include <asm/nmi.h> | 12 | #include <asm/nmi.h> |
12 | #include <asm/irq.h> | 13 | #include <asm/irq.h> |
@@ -75,6 +76,8 @@ EXPORT_PER_CPU_SYMBOL(cpu_info); | |||
75 | 76 | ||
76 | static atomic_t init_deasserted; | 77 | static atomic_t init_deasserted; |
77 | 78 | ||
79 | static int boot_cpu_logical_apicid; | ||
80 | |||
78 | /* ready for x86_64, no harm for x86, since it will overwrite after alloc */ | 81 | /* ready for x86_64, no harm for x86, since it will overwrite after alloc */ |
79 | unsigned char *trampoline_base = __va(SMP_TRAMPOLINE_BASE); | 82 | unsigned char *trampoline_base = __va(SMP_TRAMPOLINE_BASE); |
80 | 83 | ||
@@ -1002,6 +1005,173 @@ int __cpuinit native_cpu_up(unsigned int cpu) | |||
1002 | } | 1005 | } |
1003 | 1006 | ||
1004 | /* | 1007 | /* |
1008 | * Fall back to non SMP mode after errors. | ||
1009 | * | ||
1010 | * RED-PEN audit/test this more. I bet there is more state messed up here. | ||
1011 | */ | ||
1012 | static __init void disable_smp(void) | ||
1013 | { | ||
1014 | cpu_present_map = cpumask_of_cpu(0); | ||
1015 | cpu_possible_map = cpumask_of_cpu(0); | ||
1016 | #ifdef CONFIG_X86_32 | ||
1017 | smpboot_clear_io_apic_irqs(); | ||
1018 | #endif | ||
1019 | if (smp_found_config) | ||
1020 | phys_cpu_present_map = | ||
1021 | physid_mask_of_physid(boot_cpu_physical_apicid); | ||
1022 | else | ||
1023 | phys_cpu_present_map = physid_mask_of_physid(0); | ||
1024 | map_cpu_to_logical_apicid(); | ||
1025 | cpu_set(0, per_cpu(cpu_sibling_map, 0)); | ||
1026 | cpu_set(0, per_cpu(cpu_core_map, 0)); | ||
1027 | } | ||
1028 | |||
1029 | /* | ||
1030 | * Various sanity checks. | ||
1031 | */ | ||
1032 | static int __init smp_sanity_check(unsigned max_cpus) | ||
1033 | { | ||
1034 | if (!physid_isset(hard_smp_processor_id(), phys_cpu_present_map)) { | ||
1035 | printk(KERN_WARNING "weird, boot CPU (#%d) not listed" | ||
1036 | "by the BIOS.\n", hard_smp_processor_id()); | ||
1037 | physid_set(hard_smp_processor_id(), phys_cpu_present_map); | ||
1038 | } | ||
1039 | |||
1040 | /* | ||
1041 | * If we couldn't find an SMP configuration at boot time, | ||
1042 | * get out of here now! | ||
1043 | */ | ||
1044 | if (!smp_found_config && !acpi_lapic) { | ||
1045 | printk(KERN_NOTICE "SMP motherboard not detected.\n"); | ||
1046 | disable_smp(); | ||
1047 | if (APIC_init_uniprocessor()) | ||
1048 | printk(KERN_NOTICE "Local APIC not detected." | ||
1049 | " Using dummy APIC emulation.\n"); | ||
1050 | return -1; | ||
1051 | } | ||
1052 | |||
1053 | /* | ||
1054 | * Should not be necessary because the MP table should list the boot | ||
1055 | * CPU too, but we do it for the sake of robustness anyway. | ||
1056 | */ | ||
1057 | if (!check_phys_apicid_present(boot_cpu_physical_apicid)) { | ||
1058 | printk(KERN_NOTICE | ||
1059 | "weird, boot CPU (#%d) not listed by the BIOS.\n", | ||
1060 | boot_cpu_physical_apicid); | ||
1061 | physid_set(hard_smp_processor_id(), phys_cpu_present_map); | ||
1062 | } | ||
1063 | |||
1064 | /* | ||
1065 | * If we couldn't find a local APIC, then get out of here now! | ||
1066 | */ | ||
1067 | if (APIC_INTEGRATED(apic_version[boot_cpu_physical_apicid]) && | ||
1068 | !cpu_has_apic) { | ||
1069 | printk(KERN_ERR "BIOS bug, local APIC #%d not detected!...\n", | ||
1070 | boot_cpu_physical_apicid); | ||
1071 | printk(KERN_ERR "... forcing use of dummy APIC emulation." | ||
1072 | "(tell your hw vendor)\n"); | ||
1073 | smpboot_clear_io_apic(); | ||
1074 | return -1; | ||
1075 | } | ||
1076 | |||
1077 | verify_local_APIC(); | ||
1078 | |||
1079 | /* | ||
1080 | * If SMP should be disabled, then really disable it! | ||
1081 | */ | ||
1082 | if (!max_cpus) { | ||
1083 | printk(KERN_INFO "SMP mode deactivated," | ||
1084 | "forcing use of dummy APIC emulation.\n"); | ||
1085 | smpboot_clear_io_apic(); | ||
1086 | #ifdef CONFIG_X86_32 | ||
1087 | if (nmi_watchdog == NMI_LOCAL_APIC) { | ||
1088 | printk(KERN_INFO "activating minimal APIC for" | ||
1089 | "NMI watchdog use.\n"); | ||
1090 | connect_bsp_APIC(); | ||
1091 | setup_local_APIC(); | ||
1092 | end_local_APIC_setup(); | ||
1093 | } | ||
1094 | #endif | ||
1095 | return -1; | ||
1096 | } | ||
1097 | |||
1098 | return 0; | ||
1099 | } | ||
1100 | |||
1101 | static void __init smp_cpu_index_default(void) | ||
1102 | { | ||
1103 | int i; | ||
1104 | struct cpuinfo_x86 *c; | ||
1105 | |||
1106 | for_each_cpu_mask(i, cpu_possible_map) { | ||
1107 | c = &cpu_data(i); | ||
1108 | /* mark all to hotplug */ | ||
1109 | c->cpu_index = NR_CPUS; | ||
1110 | } | ||
1111 | } | ||
1112 | |||
1113 | /* | ||
1114 | * Prepare for SMP bootup. The MP table or ACPI has been read | ||
1115 | * earlier. Just do some sanity checking here and enable APIC mode. | ||
1116 | */ | ||
1117 | void __init native_smp_prepare_cpus(unsigned int max_cpus) | ||
1118 | { | ||
1119 | nmi_watchdog_default(); | ||
1120 | smp_cpu_index_default(); | ||
1121 | current_cpu_data = boot_cpu_data; | ||
1122 | cpu_callin_map = cpumask_of_cpu(0); | ||
1123 | mb(); | ||
1124 | /* | ||
1125 | * Setup boot CPU information | ||
1126 | */ | ||
1127 | smp_store_cpu_info(0); /* Final full version of the data */ | ||
1128 | boot_cpu_logical_apicid = logical_smp_processor_id(); | ||
1129 | current_thread_info()->cpu = 0; /* needed? */ | ||
1130 | set_cpu_sibling_map(0); | ||
1131 | |||
1132 | if (smp_sanity_check(max_cpus) < 0) { | ||
1133 | printk(KERN_INFO "SMP disabled\n"); | ||
1134 | disable_smp(); | ||
1135 | return; | ||
1136 | } | ||
1137 | |||
1138 | if (GET_APIC_ID(apic_read(APIC_ID)) != boot_cpu_physical_apicid) { | ||
1139 | panic("Boot APIC ID in local APIC unexpected (%d vs %d)", | ||
1140 | GET_APIC_ID(apic_read(APIC_ID)), boot_cpu_physical_apicid); | ||
1141 | /* Or can we switch back to PIC here? */ | ||
1142 | } | ||
1143 | |||
1144 | #ifdef CONFIG_X86_32 | ||
1145 | connect_bsp_APIC(); | ||
1146 | #endif | ||
1147 | /* | ||
1148 | * Switch from PIC to APIC mode. | ||
1149 | */ | ||
1150 | setup_local_APIC(); | ||
1151 | |||
1152 | #ifdef CONFIG_X86_64 | ||
1153 | /* | ||
1154 | * Enable IO APIC before setting up error vector | ||
1155 | */ | ||
1156 | if (!skip_ioapic_setup && nr_ioapics) | ||
1157 | enable_IO_APIC(); | ||
1158 | #endif | ||
1159 | end_local_APIC_setup(); | ||
1160 | |||
1161 | map_cpu_to_logical_apicid(); | ||
1162 | |||
1163 | setup_portio_remap(); | ||
1164 | |||
1165 | smpboot_setup_io_apic(); | ||
1166 | /* | ||
1167 | * Set up local APIC timer on boot CPU. | ||
1168 | */ | ||
1169 | |||
1170 | printk(KERN_INFO "CPU%d: ", 0); | ||
1171 | print_cpu_info(&cpu_data(0)); | ||
1172 | setup_boot_clock(); | ||
1173 | } | ||
1174 | /* | ||
1005 | * Early setup to make printk work. | 1175 | * Early setup to make printk work. |
1006 | */ | 1176 | */ |
1007 | void __init native_smp_prepare_boot_cpu(void) | 1177 | void __init native_smp_prepare_boot_cpu(void) |