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/smpboot.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/smpboot.c')
-rw-r--r-- | arch/i386/kernel/smpboot.c | 68 |
1 files changed, 16 insertions, 52 deletions
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; | |||
1078 | EXPORT_SYMBOL(xquad_portio); | 1078 | EXPORT_SYMBOL(xquad_portio); |
1079 | #endif | 1079 | #endif |
1080 | 1080 | ||
1081 | /* | ||
1082 | * Fall back to non SMP mode after errors. | ||
1083 | * | ||
1084 | */ | ||
1085 | static __init void disable_smp(void) | ||
1086 | { | ||
1087 | cpu_set(0, cpu_sibling_map[0]); | ||
1088 | cpu_set(0, cpu_core_map[0]); | ||
1089 | } | ||
1090 | |||
1081 | static void __init smp_boot_cpus(unsigned int max_cpus) | 1091 | static 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 | */ |