aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric W. Biederman <ebiederm@xmission.com>2005-10-30 17:59:41 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2005-10-30 20:37:13 -0500
commitf2b36db692b7ff6972320ad9839ae656a3b0ee3e (patch)
tree110387d2557a156d6b9453ea0c45d392b47796c2
parent29b70081f7cb094513d5189e82d3478b50777a28 (diff)
[PATCH] i386: move apic init in init_IRQs
All kinds of ugliness exists because we don't initialize the apics during init_IRQs. - We calibrate jiffies in non apic mode even when we are using apics. - We have to have special code to initialize the apics when non-smp. - The legacy i8259 must exist and be setup correctly, even when we won't use it past initialization. - The kexec on panic code must restore the state of the io_apics. - init/main.c needs a special case for !smp smp_init on x86 In addition to pure code movement I needed a couple of non-obvious changes: - Move setup_boot_APIC_clock into APIC_late_time_init for simplicity. - Use cpu_khz to generate a better approximation of loops_per_jiffies so I can verify the timer interrupt is working. - Call setup_apic_nmi_watchdog again after cpu_khz is initialized on the boot cpu. Signed-off-by: Eric W. Biederman <ebiederm@xmission.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--arch/i386/kernel/apic.c81
-rw-r--r--arch/i386/kernel/i8259.c4
-rw-r--r--arch/i386/kernel/io_apic.c6
-rw-r--r--arch/i386/kernel/smpboot.c68
-rw-r--r--arch/i386/kernel/time.c12
-rw-r--r--include/asm-i386/apic.h3
-rw-r--r--include/asm-i386/hw_irq.h1
-rw-r--r--include/asm-i386/mach-default/smpboot_hooks.h15
-rw-r--r--include/asm-i386/mach-visws/smpboot_hooks.h7
-rw-r--r--init/main.c11
10 files changed, 103 insertions, 105 deletions
diff --git a/arch/i386/kernel/apic.c b/arch/i386/kernel/apic.c
index 5546ddebec33..8d81b7bf7ad2 100644
--- a/arch/i386/kernel/apic.c
+++ b/arch/i386/kernel/apic.c
@@ -803,6 +803,7 @@ no_apic:
803 803
804void __init init_apic_mappings(void) 804void __init init_apic_mappings(void)
805{ 805{
806 unsigned int orig_apicid;
806 unsigned long apic_phys; 807 unsigned long apic_phys;
807 808
808 /* 809 /*
@@ -824,8 +825,11 @@ void __init init_apic_mappings(void)
824 * Fetch the APIC ID of the BSP in case we have a 825 * Fetch the APIC ID of the BSP in case we have a
825 * default configuration (or the MP table is broken). 826 * default configuration (or the MP table is broken).
826 */ 827 */
827 if (boot_cpu_physical_apicid == -1U) 828 orig_apicid = boot_cpu_physical_apicid;
828 boot_cpu_physical_apicid = GET_APIC_ID(apic_read(APIC_ID)); 829 boot_cpu_physical_apicid = GET_APIC_ID(apic_read(APIC_ID));
830 if ((orig_apicid != -1U) && (orig_apicid != boot_cpu_physical_apicid))
831 printk(KERN_WARNING "Boot APIC ID in local APIC unexpected (%d vs %d)",
832 orig_apicid, boot_cpu_physical_apicid);
829 833
830#ifdef CONFIG_X86_IO_APIC 834#ifdef CONFIG_X86_IO_APIC
831 { 835 {
@@ -1046,9 +1050,11 @@ static unsigned int calibration_result;
1046 1050
1047void __init setup_boot_APIC_clock(void) 1051void __init setup_boot_APIC_clock(void)
1048{ 1052{
1053 unsigned long flags;
1049 apic_printk(APIC_VERBOSE, "Using local APIC timer interrupts.\n"); 1054 apic_printk(APIC_VERBOSE, "Using local APIC timer interrupts.\n");
1050 using_apic_timer = 1; 1055 using_apic_timer = 1;
1051 1056
1057 local_irq_save(flags);
1052 local_irq_disable(); 1058 local_irq_disable();
1053 1059
1054 calibration_result = calibrate_APIC_clock(); 1060 calibration_result = calibrate_APIC_clock();
@@ -1057,7 +1063,7 @@ void __init setup_boot_APIC_clock(void)
1057 */ 1063 */
1058 setup_APIC_timer(calibration_result); 1064 setup_APIC_timer(calibration_result);
1059 1065
1060 local_irq_enable(); 1066 local_irq_restore(flags);
1061} 1067}
1062 1068
1063void __devinit setup_secondary_APIC_clock(void) 1069void __devinit setup_secondary_APIC_clock(void)
@@ -1254,40 +1260,81 @@ fastcall void smp_error_interrupt(struct pt_regs *regs)
1254} 1260}
1255 1261
1256/* 1262/*
1257 * This initializes the IO-APIC and APIC hardware if this is 1263 * This initializes the IO-APIC and APIC hardware.
1258 * a UP kernel.
1259 */ 1264 */
1260int __init APIC_init_uniprocessor (void) 1265int __init APIC_init(void)
1261{ 1266{
1262 if (enable_local_apic < 0) 1267 if (enable_local_apic < 0) {
1263 clear_bit(X86_FEATURE_APIC, boot_cpu_data.x86_capability); 1268 printk(KERN_INFO "APIC disabled\n");
1269 return -1;
1270 }
1264 1271
1265 if (!smp_found_config && !cpu_has_apic) 1272 /* See if we have a SMP configuration or have forced enabled
1273 * the local apic.
1274 */
1275 if (!smp_found_config && !acpi_lapic && !cpu_has_apic) {
1276 enable_local_apic = -1;
1266 return -1; 1277 return -1;
1278 }
1267 1279
1268 /* 1280 /*
1269 * Complain if the BIOS pretends there is one. 1281 * Complain if the BIOS pretends there is an apic.
1282 * Then get out because we don't have an a local apic.
1270 */ 1283 */
1271 if (!cpu_has_apic && APIC_INTEGRATED(apic_version[boot_cpu_physical_apicid])) { 1284 if (!cpu_has_apic && APIC_INTEGRATED(apic_version[boot_cpu_physical_apicid])) {
1272 printk(KERN_ERR "BIOS bug, local APIC #%d not detected!...\n", 1285 printk(KERN_ERR "BIOS bug, local APIC #%d not detected!...\n",
1273 boot_cpu_physical_apicid); 1286 boot_cpu_physical_apicid);
1287 printk(KERN_ERR "... forcing use of dummy APIC emulation. (tell your hw vendor)\n");
1288 enable_local_apic = -1;
1274 return -1; 1289 return -1;
1275 } 1290 }
1276 1291
1277 verify_local_APIC(); 1292 verify_local_APIC();
1278 1293
1294 /*
1295 * Should not be necessary because the MP table should list the boot
1296 * CPU too, but we do it for the sake of robustness anyway.
1297 * Makes no sense to do this check in clustered apic mode, so skip it
1298 */
1299 if (!check_phys_apicid_present(boot_cpu_physical_apicid)) {
1300 printk("weird, boot CPU (#%d) not listed by the BIOS.\n",
1301 boot_cpu_physical_apicid);
1302 physid_set(hard_smp_processor_id(), phys_cpu_present_map);
1303 }
1304
1305 /*
1306 * Switch from PIC to APIC mode.
1307 */
1279 connect_bsp_APIC(); 1308 connect_bsp_APIC();
1309 setup_local_APIC();
1280 1310
1281 phys_cpu_present_map = physid_mask_of_physid(boot_cpu_physical_apicid); 1311#ifdef CONFIG_X86_IO_APIC
1312 /*
1313 * Now start the IO-APICs
1314 */
1315 if (smp_found_config && !skip_ioapic_setup && nr_ioapics)
1316 setup_IO_APIC();
1317#endif
1318 return 0;
1319}
1282 1320
1283 setup_local_APIC(); 1321void __init APIC_late_time_init(void)
1322{
1323 /* Improve our loops per jiffy estimate */
1324 loops_per_jiffy = ((1000 + HZ - 1)/HZ)*cpu_khz;
1325 boot_cpu_data.loops_per_jiffy = loops_per_jiffy;
1326 cpu_data[0].loops_per_jiffy = loops_per_jiffy;
1327
1328 /* setup_apic_nmi_watchdog doesn't work properly before cpu_khz is
1329 * initialized. So redo it here to ensure the boot cpu is setup
1330 * properly.
1331 */
1332 if (nmi_watchdog == NMI_LOCAL_APIC)
1333 setup_apic_nmi_watchdog();
1284 1334
1285#ifdef CONFIG_X86_IO_APIC 1335#ifdef CONFIG_X86_IO_APIC
1286 if (smp_found_config) 1336 if (smp_found_config && !skip_ioapic_setup && nr_ioapics)
1287 if (!skip_ioapic_setup && nr_ioapics) 1337 IO_APIC_late_time_init();
1288 setup_IO_APIC();
1289#endif 1338#endif
1290 setup_boot_APIC_clock(); 1339 setup_boot_APIC_clock();
1291
1292 return 0;
1293} 1340}
diff --git a/arch/i386/kernel/i8259.c b/arch/i386/kernel/i8259.c
index 323ef8ab3244..d86f24909284 100644
--- a/arch/i386/kernel/i8259.c
+++ b/arch/i386/kernel/i8259.c
@@ -435,4 +435,8 @@ void __init init_IRQ(void)
435 setup_irq(FPU_IRQ, &fpu_irq); 435 setup_irq(FPU_IRQ, &fpu_irq);
436 436
437 irq_ctx_init(smp_processor_id()); 437 irq_ctx_init(smp_processor_id());
438
439#ifdef CONFIG_X86_LOCAL_APIC
440 APIC_init();
441#endif
438} 442}
diff --git a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c
index cc5d7ac5b2e7..5a77c52b20a9 100644
--- a/arch/i386/kernel/io_apic.c
+++ b/arch/i386/kernel/io_apic.c
@@ -2387,11 +2387,15 @@ void __init setup_IO_APIC(void)
2387 sync_Arb_IDs(); 2387 sync_Arb_IDs();
2388 setup_IO_APIC_irqs(); 2388 setup_IO_APIC_irqs();
2389 init_IO_APIC_traps(); 2389 init_IO_APIC_traps();
2390 check_timer();
2391 if (!acpi_ioapic) 2390 if (!acpi_ioapic)
2392 print_IO_APIC(); 2391 print_IO_APIC();
2393} 2392}
2394 2393
2394void __init IO_APIC_late_time_init(void)
2395{
2396 check_timer();
2397}
2398
2395/* 2399/*
2396 * Called after all the initialization is done. If we didnt find any 2400 * Called after all the initialization is done. If we didnt find any
2397 * APIC bugs then we can allow the modify fast path 2401 * APIC bugs then we can allow the modify fast path
diff --git a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c
index 01b618e73ecd..5a2bbe0c4fff 100644
--- a/arch/i386/kernel/smpboot.c
+++ b/arch/i386/kernel/smpboot.c
@@ -1078,6 +1078,16 @@ void *xquad_portio;
1078EXPORT_SYMBOL(xquad_portio); 1078EXPORT_SYMBOL(xquad_portio);
1079#endif 1079#endif
1080 1080
1081/*
1082 * Fall back to non SMP mode after errors.
1083 *
1084 */
1085static __init void disable_smp(void)
1086{
1087 cpu_set(0, cpu_sibling_map[0]);
1088 cpu_set(0, cpu_core_map[0]);
1089}
1090
1081static void __init smp_boot_cpus(unsigned int max_cpus) 1091static void __init smp_boot_cpus(unsigned int max_cpus)
1082{ 1092{
1083 int apicid, cpu, bit, kicked; 1093 int apicid, cpu, bit, kicked;
@@ -1090,7 +1100,6 @@ static void __init smp_boot_cpus(unsigned int max_cpus)
1090 printk("CPU%d: ", 0); 1100 printk("CPU%d: ", 0);
1091 print_cpu_info(&cpu_data[0]); 1101 print_cpu_info(&cpu_data[0]);
1092 1102
1093 boot_cpu_physical_apicid = GET_APIC_ID(apic_read(APIC_ID));
1094 boot_cpu_logical_apicid = logical_smp_processor_id(); 1103 boot_cpu_logical_apicid = logical_smp_processor_id();
1095 x86_cpu_to_apicid[0] = boot_cpu_physical_apicid; 1104 x86_cpu_to_apicid[0] = boot_cpu_physical_apicid;
1096 1105
@@ -1102,68 +1111,27 @@ static void __init smp_boot_cpus(unsigned int max_cpus)
1102 cpus_clear(cpu_core_map[0]); 1111 cpus_clear(cpu_core_map[0]);
1103 cpu_set(0, cpu_core_map[0]); 1112 cpu_set(0, cpu_core_map[0]);
1104 1113
1114 map_cpu_to_logical_apicid();
1115
1105 /* 1116 /*
1106 * If we couldn't find an SMP configuration at boot time, 1117 * If we couldn't find an SMP configuration at boot time,
1107 * get out of here now! 1118 * get out of here now!
1108 */ 1119 */
1109 if (!smp_found_config && !acpi_lapic) { 1120 if (!smp_found_config && !acpi_lapic) {
1110 printk(KERN_NOTICE "SMP motherboard not detected.\n"); 1121 printk(KERN_NOTICE "SMP motherboard not detected.\n");
1111 smpboot_clear_io_apic_irqs(); 1122 disable_smp();
1112 phys_cpu_present_map = physid_mask_of_physid(0);
1113 if (APIC_init_uniprocessor())
1114 printk(KERN_NOTICE "Local APIC not detected."
1115 " Using dummy APIC emulation.\n");
1116 map_cpu_to_logical_apicid();
1117 cpu_set(0, cpu_sibling_map[0]);
1118 cpu_set(0, cpu_core_map[0]);
1119 return;
1120 }
1121
1122 /*
1123 * Should not be necessary because the MP table should list the boot
1124 * CPU too, but we do it for the sake of robustness anyway.
1125 * Makes no sense to do this check in clustered apic mode, so skip it
1126 */
1127 if (!check_phys_apicid_present(boot_cpu_physical_apicid)) {
1128 printk("weird, boot CPU (#%d) not listed by the BIOS.\n",
1129 boot_cpu_physical_apicid);
1130 physid_set(hard_smp_processor_id(), phys_cpu_present_map);
1131 }
1132
1133 /*
1134 * If we couldn't find a local APIC, then get out of here now!
1135 */
1136 if (APIC_INTEGRATED(apic_version[boot_cpu_physical_apicid]) && !cpu_has_apic) {
1137 printk(KERN_ERR "BIOS bug, local APIC #%d not detected!...\n",
1138 boot_cpu_physical_apicid);
1139 printk(KERN_ERR "... forcing use of dummy APIC emulation. (tell your hw vendor)\n");
1140 smpboot_clear_io_apic_irqs();
1141 phys_cpu_present_map = physid_mask_of_physid(0);
1142 cpu_set(0, cpu_sibling_map[0]);
1143 cpu_set(0, cpu_core_map[0]);
1144 return; 1123 return;
1145 } 1124 }
1146 1125
1147 verify_local_APIC();
1148
1149 /* 1126 /*
1150 * If SMP should be disabled, then really disable it! 1127 * If SMP should be disabled, then really disable it!
1151 */ 1128 */
1152 if (!max_cpus) { 1129 if (!max_cpus || (enable_local_apic < 0)) {
1153 smp_found_config = 0; 1130 printk(KERN_INFO "SMP mode deactivated.\n");
1154 printk(KERN_INFO "SMP mode deactivated, forcing use of dummy APIC emulation.\n"); 1131 disable_smp();
1155 smpboot_clear_io_apic_irqs();
1156 phys_cpu_present_map = physid_mask_of_physid(0);
1157 cpu_set(0, cpu_sibling_map[0]);
1158 cpu_set(0, cpu_core_map[0]);
1159 return; 1132 return;
1160 } 1133 }
1161 1134
1162 connect_bsp_APIC();
1163 setup_local_APIC();
1164 map_cpu_to_logical_apicid();
1165
1166
1167 setup_portio_remap(); 1135 setup_portio_remap();
1168 1136
1169 /* 1137 /*
@@ -1244,10 +1212,6 @@ static void __init smp_boot_cpus(unsigned int max_cpus)
1244 cpu_set(0, cpu_sibling_map[0]); 1212 cpu_set(0, cpu_sibling_map[0]);
1245 cpu_set(0, cpu_core_map[0]); 1213 cpu_set(0, cpu_core_map[0]);
1246 1214
1247 smpboot_setup_io_apic();
1248
1249 setup_boot_APIC_clock();
1250
1251 /* 1215 /*
1252 * Synchronize the TSC with the AP 1216 * Synchronize the TSC with the AP
1253 */ 1217 */
diff --git a/arch/i386/kernel/time.c b/arch/i386/kernel/time.c
index 2883a4d4f01f..46c35ec9137d 100644
--- a/arch/i386/kernel/time.c
+++ b/arch/i386/kernel/time.c
@@ -444,8 +444,8 @@ static int time_init_device(void)
444 444
445device_initcall(time_init_device); 445device_initcall(time_init_device);
446 446
447#ifdef CONFIG_HPET_TIMER
448extern void (*late_time_init)(void); 447extern void (*late_time_init)(void);
448#ifdef CONFIG_HPET_TIMER
449/* Duplicate of time_init() below, with hpet_enable part added */ 449/* Duplicate of time_init() below, with hpet_enable part added */
450static void __init hpet_time_init(void) 450static void __init hpet_time_init(void)
451{ 451{
@@ -462,6 +462,11 @@ static void __init hpet_time_init(void)
462 printk(KERN_INFO "Using %s for high-res timesource\n",cur_timer->name); 462 printk(KERN_INFO "Using %s for high-res timesource\n",cur_timer->name);
463 463
464 time_init_hook(); 464 time_init_hook();
465
466#ifdef CONFIG_X86_LOCAL_APIC
467 if (enable_local_apic >= 0)
468 APIC_late_time_init();
469#endif
465} 470}
466#endif 471#endif
467 472
@@ -486,4 +491,9 @@ void __init time_init(void)
486 printk(KERN_INFO "Using %s for high-res timesource\n",cur_timer->name); 491 printk(KERN_INFO "Using %s for high-res timesource\n",cur_timer->name);
487 492
488 time_init_hook(); 493 time_init_hook();
494
495#ifdef CONFIG_X86_LOCAL_APIC
496 if (enable_local_apic >= 0)
497 late_time_init = APIC_late_time_init;
498#endif
489} 499}
diff --git a/include/asm-i386/apic.h b/include/asm-i386/apic.h
index 8c454aa58ac6..a515e2aed829 100644
--- a/include/asm-i386/apic.h
+++ b/include/asm-i386/apic.h
@@ -118,7 +118,8 @@ extern void release_lapic_nmi(void);
118extern void disable_timer_nmi_watchdog(void); 118extern void disable_timer_nmi_watchdog(void);
119extern void enable_timer_nmi_watchdog(void); 119extern void enable_timer_nmi_watchdog(void);
120extern void nmi_watchdog_tick (struct pt_regs * regs); 120extern void nmi_watchdog_tick (struct pt_regs * regs);
121extern int APIC_init_uniprocessor (void); 121extern int APIC_init(void);
122extern void APIC_late_time_init(void);
122extern void disable_APIC_timer(void); 123extern void disable_APIC_timer(void);
123extern void enable_APIC_timer(void); 124extern void enable_APIC_timer(void);
124 125
diff --git a/include/asm-i386/hw_irq.h b/include/asm-i386/hw_irq.h
index 622815bf3243..9139b89497a1 100644
--- a/include/asm-i386/hw_irq.h
+++ b/include/asm-i386/hw_irq.h
@@ -55,6 +55,7 @@ void init_8259A(int aeoi);
55void FASTCALL(send_IPI_self(int vector)); 55void FASTCALL(send_IPI_self(int vector));
56void init_VISWS_APIC_irqs(void); 56void init_VISWS_APIC_irqs(void);
57void setup_IO_APIC(void); 57void setup_IO_APIC(void);
58void IO_APIC_late_time_init(void);
58void disable_IO_APIC(void); 59void disable_IO_APIC(void);
59void print_IO_APIC(void); 60void print_IO_APIC(void);
60int IO_APIC_get_PCI_irq_vector(int bus, int slot, int fn); 61int IO_APIC_get_PCI_irq_vector(int bus, int slot, int fn);
diff --git a/include/asm-i386/mach-default/smpboot_hooks.h b/include/asm-i386/mach-default/smpboot_hooks.h
index 7f45f6311059..d7c70c144f9f 100644
--- a/include/asm-i386/mach-default/smpboot_hooks.h
+++ b/include/asm-i386/mach-default/smpboot_hooks.h
@@ -1,11 +1,6 @@
1/* two abstractions specific to kernel/smpboot.c, mainly to cater to visws 1/* two abstractions specific to kernel/smpboot.c, mainly to cater to visws
2 * which needs to alter them. */ 2 * which needs to alter them. */
3 3
4static inline void smpboot_clear_io_apic_irqs(void)
5{
6 io_apic_irqs = 0;
7}
8
9static inline void smpboot_setup_warm_reset_vector(unsigned long start_eip) 4static inline void smpboot_setup_warm_reset_vector(unsigned long start_eip)
10{ 5{
11 CMOS_WRITE(0xa, 0xf); 6 CMOS_WRITE(0xa, 0xf);
@@ -32,13 +27,3 @@ static inline void smpboot_restore_warm_reset_vector(void)
32 27
33 *((volatile long *) phys_to_virt(0x467)) = 0; 28 *((volatile long *) phys_to_virt(0x467)) = 0;
34} 29}
35
36static inline void smpboot_setup_io_apic(void)
37{
38 /*
39 * Here we can be sure that there is an IO-APIC in the system. Let's
40 * go and set it up:
41 */
42 if (!skip_ioapic_setup && nr_ioapics)
43 setup_IO_APIC();
44}
diff --git a/include/asm-i386/mach-visws/smpboot_hooks.h b/include/asm-i386/mach-visws/smpboot_hooks.h
index d926471fa359..14d8e0375f7a 100644
--- a/include/asm-i386/mach-visws/smpboot_hooks.h
+++ b/include/asm-i386/mach-visws/smpboot_hooks.h
@@ -11,14 +11,7 @@ static inline void smpboot_setup_warm_reset_vector(unsigned long start_eip)
11 11
12/* for visws do nothing for any of these */ 12/* for visws do nothing for any of these */
13 13
14static inline void smpboot_clear_io_apic_irqs(void)
15{
16}
17
18static inline void smpboot_restore_warm_reset_vector(void) 14static inline void smpboot_restore_warm_reset_vector(void)
19{ 15{
20} 16}
21 17
22static inline void smpboot_setup_io_apic(void)
23{
24}
diff --git a/init/main.c b/init/main.c
index f142d4035341..4075d97e94b1 100644
--- a/init/main.c
+++ b/init/main.c
@@ -64,10 +64,6 @@
64#endif 64#endif
65#endif 65#endif
66 66
67#ifdef CONFIG_X86_LOCAL_APIC
68#include <asm/smp.h>
69#endif
70
71/* 67/*
72 * Versions of gcc older than that listed below may actually compile 68 * Versions of gcc older than that listed below may actually compile
73 * and link okay, but the end product can have subtle run time bugs. 69 * and link okay, but the end product can have subtle run time bugs.
@@ -314,14 +310,7 @@ extern void setup_arch(char **);
314 310
315#ifndef CONFIG_SMP 311#ifndef CONFIG_SMP
316 312
317#ifdef CONFIG_X86_LOCAL_APIC
318static void __init smp_init(void)
319{
320 APIC_init_uniprocessor();
321}
322#else
323#define smp_init() do { } while (0) 313#define smp_init() do { } while (0)
324#endif
325 314
326static inline void setup_per_cpu_areas(void) { } 315static inline void setup_per_cpu_areas(void) { }
327static inline void smp_prepare_cpus(unsigned int maxcpus) { } 316static inline void smp_prepare_cpus(unsigned int maxcpus) { }