diff options
author | Eric W. Biederman <ebiederm@xmission.com> | 2005-10-30 17:59:41 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2005-10-30 20:37:13 -0500 |
commit | f2b36db692b7ff6972320ad9839ae656a3b0ee3e (patch) | |
tree | 110387d2557a156d6b9453ea0c45d392b47796c2 /arch/i386/kernel/apic.c | |
parent | 29b70081f7cb094513d5189e82d3478b50777a28 (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>
Diffstat (limited to 'arch/i386/kernel/apic.c')
-rw-r--r-- | arch/i386/kernel/apic.c | 81 |
1 files changed, 64 insertions, 17 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 | ||
804 | void __init init_apic_mappings(void) | 804 | void __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 | ||
1047 | void __init setup_boot_APIC_clock(void) | 1051 | void __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 | ||
1063 | void __devinit setup_secondary_APIC_clock(void) | 1069 | void __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 | */ |
1260 | int __init APIC_init_uniprocessor (void) | 1265 | int __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(); | 1321 | void __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 | } |