diff options
Diffstat (limited to 'arch/x86/kernel/smpboot.c')
-rw-r--r-- | arch/x86/kernel/smpboot.c | 113 |
1 files changed, 67 insertions, 46 deletions
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index 6d7022c683e3..febc6aabc72e 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c | |||
@@ -73,7 +73,6 @@ | |||
73 | #include <asm/setup.h> | 73 | #include <asm/setup.h> |
74 | #include <asm/uv/uv.h> | 74 | #include <asm/uv/uv.h> |
75 | #include <linux/mc146818rtc.h> | 75 | #include <linux/mc146818rtc.h> |
76 | #include <asm/smpboot_hooks.h> | ||
77 | #include <asm/i8259.h> | 76 | #include <asm/i8259.h> |
78 | #include <asm/realmode.h> | 77 | #include <asm/realmode.h> |
79 | #include <asm/misc.h> | 78 | #include <asm/misc.h> |
@@ -104,6 +103,43 @@ EXPORT_PER_CPU_SYMBOL(cpu_info); | |||
104 | 103 | ||
105 | atomic_t init_deasserted; | 104 | atomic_t init_deasserted; |
106 | 105 | ||
106 | static inline void smpboot_setup_warm_reset_vector(unsigned long start_eip) | ||
107 | { | ||
108 | unsigned long flags; | ||
109 | |||
110 | spin_lock_irqsave(&rtc_lock, flags); | ||
111 | CMOS_WRITE(0xa, 0xf); | ||
112 | spin_unlock_irqrestore(&rtc_lock, flags); | ||
113 | local_flush_tlb(); | ||
114 | pr_debug("1.\n"); | ||
115 | *((volatile unsigned short *)phys_to_virt(TRAMPOLINE_PHYS_HIGH)) = | ||
116 | start_eip >> 4; | ||
117 | pr_debug("2.\n"); | ||
118 | *((volatile unsigned short *)phys_to_virt(TRAMPOLINE_PHYS_LOW)) = | ||
119 | start_eip & 0xf; | ||
120 | pr_debug("3.\n"); | ||
121 | } | ||
122 | |||
123 | static inline void smpboot_restore_warm_reset_vector(void) | ||
124 | { | ||
125 | unsigned long flags; | ||
126 | |||
127 | /* | ||
128 | * Install writable page 0 entry to set BIOS data area. | ||
129 | */ | ||
130 | local_flush_tlb(); | ||
131 | |||
132 | /* | ||
133 | * Paranoid: Set warm reset code and vector here back | ||
134 | * to default values. | ||
135 | */ | ||
136 | spin_lock_irqsave(&rtc_lock, flags); | ||
137 | CMOS_WRITE(0, 0xf); | ||
138 | spin_unlock_irqrestore(&rtc_lock, flags); | ||
139 | |||
140 | *((volatile u32 *)phys_to_virt(TRAMPOLINE_PHYS_LOW)) = 0; | ||
141 | } | ||
142 | |||
107 | /* | 143 | /* |
108 | * Report back to the Boot Processor during boot time or to the caller processor | 144 | * Report back to the Boot Processor during boot time or to the caller processor |
109 | * during CPU online. | 145 | * during CPU online. |
@@ -136,8 +172,7 @@ static void smp_callin(void) | |||
136 | * CPU, first the APIC. (this is probably redundant on most | 172 | * CPU, first the APIC. (this is probably redundant on most |
137 | * boards) | 173 | * boards) |
138 | */ | 174 | */ |
139 | setup_local_APIC(); | 175 | apic_ap_setup(); |
140 | end_local_APIC_setup(); | ||
141 | 176 | ||
142 | /* | 177 | /* |
143 | * Need to setup vector mappings before we enable interrupts. | 178 | * Need to setup vector mappings before we enable interrupts. |
@@ -955,9 +990,12 @@ void arch_disable_smp_support(void) | |||
955 | */ | 990 | */ |
956 | static __init void disable_smp(void) | 991 | static __init void disable_smp(void) |
957 | { | 992 | { |
993 | pr_info("SMP disabled\n"); | ||
994 | |||
995 | disable_ioapic_support(); | ||
996 | |||
958 | init_cpu_present(cpumask_of(0)); | 997 | init_cpu_present(cpumask_of(0)); |
959 | init_cpu_possible(cpumask_of(0)); | 998 | init_cpu_possible(cpumask_of(0)); |
960 | smpboot_clear_io_apic_irqs(); | ||
961 | 999 | ||
962 | if (smp_found_config) | 1000 | if (smp_found_config) |
963 | physid_set_mask_of_physid(boot_cpu_physical_apicid, &phys_cpu_present_map); | 1001 | physid_set_mask_of_physid(boot_cpu_physical_apicid, &phys_cpu_present_map); |
@@ -967,6 +1005,13 @@ static __init void disable_smp(void) | |||
967 | cpumask_set_cpu(0, cpu_core_mask(0)); | 1005 | cpumask_set_cpu(0, cpu_core_mask(0)); |
968 | } | 1006 | } |
969 | 1007 | ||
1008 | enum { | ||
1009 | SMP_OK, | ||
1010 | SMP_NO_CONFIG, | ||
1011 | SMP_NO_APIC, | ||
1012 | SMP_FORCE_UP, | ||
1013 | }; | ||
1014 | |||
970 | /* | 1015 | /* |
971 | * Various sanity checks. | 1016 | * Various sanity checks. |
972 | */ | 1017 | */ |
@@ -1014,10 +1059,7 @@ static int __init smp_sanity_check(unsigned max_cpus) | |||
1014 | if (!smp_found_config && !acpi_lapic) { | 1059 | if (!smp_found_config && !acpi_lapic) { |
1015 | preempt_enable(); | 1060 | preempt_enable(); |
1016 | pr_notice("SMP motherboard not detected\n"); | 1061 | pr_notice("SMP motherboard not detected\n"); |
1017 | disable_smp(); | 1062 | return SMP_NO_CONFIG; |
1018 | if (APIC_init_uniprocessor()) | ||
1019 | pr_notice("Local APIC not detected. Using dummy APIC emulation.\n"); | ||
1020 | return -1; | ||
1021 | } | 1063 | } |
1022 | 1064 | ||
1023 | /* | 1065 | /* |
@@ -1041,9 +1083,7 @@ static int __init smp_sanity_check(unsigned max_cpus) | |||
1041 | boot_cpu_physical_apicid); | 1083 | boot_cpu_physical_apicid); |
1042 | pr_err("... forcing use of dummy APIC emulation (tell your hw vendor)\n"); | 1084 | pr_err("... forcing use of dummy APIC emulation (tell your hw vendor)\n"); |
1043 | } | 1085 | } |
1044 | smpboot_clear_io_apic(); | 1086 | return SMP_NO_APIC; |
1045 | disable_ioapic_support(); | ||
1046 | return -1; | ||
1047 | } | 1087 | } |
1048 | 1088 | ||
1049 | verify_local_APIC(); | 1089 | verify_local_APIC(); |
@@ -1053,15 +1093,10 @@ static int __init smp_sanity_check(unsigned max_cpus) | |||
1053 | */ | 1093 | */ |
1054 | if (!max_cpus) { | 1094 | if (!max_cpus) { |
1055 | pr_info("SMP mode deactivated\n"); | 1095 | pr_info("SMP mode deactivated\n"); |
1056 | smpboot_clear_io_apic(); | 1096 | return SMP_FORCE_UP; |
1057 | |||
1058 | connect_bsp_APIC(); | ||
1059 | setup_local_APIC(); | ||
1060 | bsp_end_local_APIC_setup(); | ||
1061 | return -1; | ||
1062 | } | 1097 | } |
1063 | 1098 | ||
1064 | return 0; | 1099 | return SMP_OK; |
1065 | } | 1100 | } |
1066 | 1101 | ||
1067 | static void __init smp_cpu_index_default(void) | 1102 | static void __init smp_cpu_index_default(void) |
@@ -1101,10 +1136,21 @@ void __init native_smp_prepare_cpus(unsigned int max_cpus) | |||
1101 | } | 1136 | } |
1102 | set_cpu_sibling_map(0); | 1137 | set_cpu_sibling_map(0); |
1103 | 1138 | ||
1104 | if (smp_sanity_check(max_cpus) < 0) { | 1139 | switch (smp_sanity_check(max_cpus)) { |
1105 | pr_info("SMP disabled\n"); | 1140 | case SMP_NO_CONFIG: |
1106 | disable_smp(); | 1141 | disable_smp(); |
1142 | if (APIC_init_uniprocessor()) | ||
1143 | pr_notice("Local APIC not detected. Using dummy APIC emulation.\n"); | ||
1107 | return; | 1144 | return; |
1145 | case SMP_NO_APIC: | ||
1146 | disable_smp(); | ||
1147 | return; | ||
1148 | case SMP_FORCE_UP: | ||
1149 | disable_smp(); | ||
1150 | apic_bsp_setup(false); | ||
1151 | return; | ||
1152 | case SMP_OK: | ||
1153 | break; | ||
1108 | } | 1154 | } |
1109 | 1155 | ||
1110 | default_setup_apic_routing(); | 1156 | default_setup_apic_routing(); |
@@ -1115,33 +1161,10 @@ void __init native_smp_prepare_cpus(unsigned int max_cpus) | |||
1115 | /* Or can we switch back to PIC here? */ | 1161 | /* Or can we switch back to PIC here? */ |
1116 | } | 1162 | } |
1117 | 1163 | ||
1118 | connect_bsp_APIC(); | 1164 | cpu0_logical_apicid = apic_bsp_setup(false); |
1119 | |||
1120 | /* | ||
1121 | * Switch from PIC to APIC mode. | ||
1122 | */ | ||
1123 | setup_local_APIC(); | ||
1124 | |||
1125 | if (x2apic_mode) | ||
1126 | cpu0_logical_apicid = apic_read(APIC_LDR); | ||
1127 | else | ||
1128 | cpu0_logical_apicid = GET_APIC_LOGICAL_ID(apic_read(APIC_LDR)); | ||
1129 | |||
1130 | /* | ||
1131 | * Enable IO APIC before setting up error vector | ||
1132 | */ | ||
1133 | if (!skip_ioapic_setup && nr_ioapics) | ||
1134 | enable_IO_APIC(); | ||
1135 | |||
1136 | bsp_end_local_APIC_setup(); | ||
1137 | smpboot_setup_io_apic(); | ||
1138 | /* | ||
1139 | * Set up local APIC timer on boot CPU. | ||
1140 | */ | ||
1141 | 1165 | ||
1142 | pr_info("CPU%d: ", 0); | 1166 | pr_info("CPU%d: ", 0); |
1143 | print_cpu_info(&cpu_data(0)); | 1167 | print_cpu_info(&cpu_data(0)); |
1144 | x86_init.timers.setup_percpu_clockev(); | ||
1145 | 1168 | ||
1146 | if (is_uv_system()) | 1169 | if (is_uv_system()) |
1147 | uv_system_init(); | 1170 | uv_system_init(); |
@@ -1177,9 +1200,7 @@ void __init native_smp_cpus_done(unsigned int max_cpus) | |||
1177 | 1200 | ||
1178 | nmi_selftest(); | 1201 | nmi_selftest(); |
1179 | impress_friends(); | 1202 | impress_friends(); |
1180 | #ifdef CONFIG_X86_IO_APIC | ||
1181 | setup_ioapic_dest(); | 1203 | setup_ioapic_dest(); |
1182 | #endif | ||
1183 | mtrr_aps_init(); | 1204 | mtrr_aps_init(); |
1184 | } | 1205 | } |
1185 | 1206 | ||