diff options
author | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
---|---|---|
committer | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
commit | c71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch) | |
tree | ecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /arch/x86/kernel/apic/apic.c | |
parent | ea53c912f8a86a8567697115b6a0d8152beee5c8 (diff) | |
parent | 6a00f206debf8a5c8899055726ad127dbeeed098 (diff) |
Merge branch 'mpi-master' into wip-k-fmlpwip-k-fmlp
Conflicts:
litmus/sched_cedf.c
Diffstat (limited to 'arch/x86/kernel/apic/apic.c')
-rw-r--r-- | arch/x86/kernel/apic/apic.c | 554 |
1 files changed, 296 insertions, 258 deletions
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index e3b534cda49a..b9338b8cf420 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c | |||
@@ -24,14 +24,13 @@ | |||
24 | #include <linux/ftrace.h> | 24 | #include <linux/ftrace.h> |
25 | #include <linux/ioport.h> | 25 | #include <linux/ioport.h> |
26 | #include <linux/module.h> | 26 | #include <linux/module.h> |
27 | #include <linux/sysdev.h> | 27 | #include <linux/syscore_ops.h> |
28 | #include <linux/delay.h> | 28 | #include <linux/delay.h> |
29 | #include <linux/timex.h> | 29 | #include <linux/timex.h> |
30 | #include <linux/dmar.h> | 30 | #include <linux/dmar.h> |
31 | #include <linux/init.h> | 31 | #include <linux/init.h> |
32 | #include <linux/cpu.h> | 32 | #include <linux/cpu.h> |
33 | #include <linux/dmi.h> | 33 | #include <linux/dmi.h> |
34 | #include <linux/nmi.h> | ||
35 | #include <linux/smp.h> | 34 | #include <linux/smp.h> |
36 | #include <linux/mm.h> | 35 | #include <linux/mm.h> |
37 | 36 | ||
@@ -44,14 +43,15 @@ | |||
44 | #include <asm/i8259.h> | 43 | #include <asm/i8259.h> |
45 | #include <asm/proto.h> | 44 | #include <asm/proto.h> |
46 | #include <asm/apic.h> | 45 | #include <asm/apic.h> |
46 | #include <asm/io_apic.h> | ||
47 | #include <asm/desc.h> | 47 | #include <asm/desc.h> |
48 | #include <asm/hpet.h> | 48 | #include <asm/hpet.h> |
49 | #include <asm/idle.h> | 49 | #include <asm/idle.h> |
50 | #include <asm/mtrr.h> | 50 | #include <asm/mtrr.h> |
51 | #include <asm/smp.h> | 51 | #include <asm/smp.h> |
52 | #include <asm/mce.h> | 52 | #include <asm/mce.h> |
53 | #include <asm/kvm_para.h> | ||
54 | #include <asm/tsc.h> | 53 | #include <asm/tsc.h> |
54 | #include <asm/hypervisor.h> | ||
55 | 55 | ||
56 | unsigned int num_processors; | 56 | unsigned int num_processors; |
57 | 57 | ||
@@ -79,12 +79,21 @@ EXPORT_EARLY_PER_CPU_SYMBOL(x86_cpu_to_apicid); | |||
79 | EXPORT_EARLY_PER_CPU_SYMBOL(x86_bios_cpu_apicid); | 79 | EXPORT_EARLY_PER_CPU_SYMBOL(x86_bios_cpu_apicid); |
80 | 80 | ||
81 | #ifdef CONFIG_X86_32 | 81 | #ifdef CONFIG_X86_32 |
82 | |||
83 | /* | ||
84 | * On x86_32, the mapping between cpu and logical apicid may vary | ||
85 | * depending on apic in use. The following early percpu variable is | ||
86 | * used for the mapping. This is where the behaviors of x86_64 and 32 | ||
87 | * actually diverge. Let's keep it ugly for now. | ||
88 | */ | ||
89 | DEFINE_EARLY_PER_CPU(int, x86_cpu_to_logical_apicid, BAD_APICID); | ||
90 | |||
82 | /* | 91 | /* |
83 | * Knob to control our willingness to enable the local APIC. | 92 | * Knob to control our willingness to enable the local APIC. |
84 | * | 93 | * |
85 | * +1=force-enable | 94 | * +1=force-enable |
86 | */ | 95 | */ |
87 | static int force_enable_local_apic; | 96 | static int force_enable_local_apic __initdata; |
88 | /* | 97 | /* |
89 | * APIC command line parameters | 98 | * APIC command line parameters |
90 | */ | 99 | */ |
@@ -154,7 +163,7 @@ early_param("nox2apic", setup_nox2apic); | |||
154 | unsigned long mp_lapic_addr; | 163 | unsigned long mp_lapic_addr; |
155 | int disable_apic; | 164 | int disable_apic; |
156 | /* Disable local APIC timer from the kernel commandline or via dmi quirk */ | 165 | /* Disable local APIC timer from the kernel commandline or via dmi quirk */ |
157 | static int disable_apic_timer __cpuinitdata; | 166 | static int disable_apic_timer __initdata; |
158 | /* Local APIC timer works in C2 */ | 167 | /* Local APIC timer works in C2 */ |
159 | int local_apic_timer_c2_ok; | 168 | int local_apic_timer_c2_ok; |
160 | EXPORT_SYMBOL_GPL(local_apic_timer_c2_ok); | 169 | EXPORT_SYMBOL_GPL(local_apic_timer_c2_ok); |
@@ -178,29 +187,8 @@ static struct resource lapic_resource = { | |||
178 | 187 | ||
179 | static unsigned int calibration_result; | 188 | static unsigned int calibration_result; |
180 | 189 | ||
181 | static int lapic_next_event(unsigned long delta, | ||
182 | struct clock_event_device *evt); | ||
183 | static void lapic_timer_setup(enum clock_event_mode mode, | ||
184 | struct clock_event_device *evt); | ||
185 | static void lapic_timer_broadcast(const struct cpumask *mask); | ||
186 | static void apic_pm_activate(void); | 190 | static void apic_pm_activate(void); |
187 | 191 | ||
188 | /* | ||
189 | * The local apic timer can be used for any function which is CPU local. | ||
190 | */ | ||
191 | static struct clock_event_device lapic_clockevent = { | ||
192 | .name = "lapic", | ||
193 | .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT | ||
194 | | CLOCK_EVT_FEAT_C3STOP | CLOCK_EVT_FEAT_DUMMY, | ||
195 | .shift = 32, | ||
196 | .set_mode = lapic_timer_setup, | ||
197 | .set_next_event = lapic_next_event, | ||
198 | .broadcast = lapic_timer_broadcast, | ||
199 | .rating = 100, | ||
200 | .irq = -1, | ||
201 | }; | ||
202 | static DEFINE_PER_CPU(struct clock_event_device, lapic_events); | ||
203 | |||
204 | static unsigned long apic_phys; | 192 | static unsigned long apic_phys; |
205 | 193 | ||
206 | /* | 194 | /* |
@@ -239,7 +227,7 @@ static int modern_apic(void) | |||
239 | * right after this call apic become NOOP driven | 227 | * right after this call apic become NOOP driven |
240 | * so apic->write/read doesn't do anything | 228 | * so apic->write/read doesn't do anything |
241 | */ | 229 | */ |
242 | void apic_disable(void) | 230 | static void __init apic_disable(void) |
243 | { | 231 | { |
244 | pr_info("APIC: switched to apic NOOP\n"); | 232 | pr_info("APIC: switched to apic NOOP\n"); |
245 | apic = &apic_noop; | 233 | apic = &apic_noop; |
@@ -283,23 +271,6 @@ u64 native_apic_icr_read(void) | |||
283 | return icr1 | ((u64)icr2 << 32); | 271 | return icr1 | ((u64)icr2 << 32); |
284 | } | 272 | } |
285 | 273 | ||
286 | /** | ||
287 | * enable_NMI_through_LVT0 - enable NMI through local vector table 0 | ||
288 | */ | ||
289 | void __cpuinit enable_NMI_through_LVT0(void) | ||
290 | { | ||
291 | unsigned int v; | ||
292 | |||
293 | /* unmask and set to NMI */ | ||
294 | v = APIC_DM_NMI; | ||
295 | |||
296 | /* Level triggered for 82489DX (32bit mode) */ | ||
297 | if (!lapic_is_integrated()) | ||
298 | v |= APIC_LVT_LEVEL_TRIGGER; | ||
299 | |||
300 | apic_write(APIC_LVT0, v); | ||
301 | } | ||
302 | |||
303 | #ifdef CONFIG_X86_32 | 274 | #ifdef CONFIG_X86_32 |
304 | /** | 275 | /** |
305 | * get_physical_broadcast - Get number of physical broadcast IDs | 276 | * get_physical_broadcast - Get number of physical broadcast IDs |
@@ -370,38 +341,89 @@ static void __setup_APIC_LVTT(unsigned int clocks, int oneshot, int irqen) | |||
370 | } | 341 | } |
371 | 342 | ||
372 | /* | 343 | /* |
373 | * Setup extended LVT, AMD specific (K8, family 10h) | 344 | * Setup extended LVT, AMD specific |
374 | * | 345 | * |
375 | * Vector mappings are hard coded. On K8 only offset 0 (APIC500) and | 346 | * Software should use the LVT offsets the BIOS provides. The offsets |
376 | * MCE interrupts are supported. Thus MCE offset must be set to 0. | 347 | * are determined by the subsystems using it like those for MCE |
348 | * threshold or IBS. On K8 only offset 0 (APIC500) and MCE interrupts | ||
349 | * are supported. Beginning with family 10h at least 4 offsets are | ||
350 | * available. | ||
377 | * | 351 | * |
378 | * If mask=1, the LVT entry does not generate interrupts while mask=0 | 352 | * Since the offsets must be consistent for all cores, we keep track |
379 | * enables the vector. See also the BKDGs. | 353 | * of the LVT offsets in software and reserve the offset for the same |
354 | * vector also to be used on other cores. An offset is freed by | ||
355 | * setting the entry to APIC_EILVT_MASKED. | ||
356 | * | ||
357 | * If the BIOS is right, there should be no conflicts. Otherwise a | ||
358 | * "[Firmware Bug]: ..." error message is generated. However, if | ||
359 | * software does not properly determines the offsets, it is not | ||
360 | * necessarily a BIOS bug. | ||
380 | */ | 361 | */ |
381 | 362 | ||
382 | #define APIC_EILVT_LVTOFF_MCE 0 | 363 | static atomic_t eilvt_offsets[APIC_EILVT_NR_MAX]; |
383 | #define APIC_EILVT_LVTOFF_IBS 1 | ||
384 | 364 | ||
385 | static void setup_APIC_eilvt(u8 lvt_off, u8 vector, u8 msg_type, u8 mask) | 365 | static inline int eilvt_entry_is_changeable(unsigned int old, unsigned int new) |
386 | { | 366 | { |
387 | unsigned long reg = (lvt_off << 4) + APIC_EILVTn(0); | 367 | return (old & APIC_EILVT_MASKED) |
388 | unsigned int v = (mask << 16) | (msg_type << 8) | vector; | 368 | || (new == APIC_EILVT_MASKED) |
389 | 369 | || ((new & ~APIC_EILVT_MASKED) == old); | |
390 | apic_write(reg, v); | ||
391 | } | 370 | } |
392 | 371 | ||
393 | u8 setup_APIC_eilvt_mce(u8 vector, u8 msg_type, u8 mask) | 372 | static unsigned int reserve_eilvt_offset(int offset, unsigned int new) |
394 | { | 373 | { |
395 | setup_APIC_eilvt(APIC_EILVT_LVTOFF_MCE, vector, msg_type, mask); | 374 | unsigned int rsvd; /* 0: uninitialized */ |
396 | return APIC_EILVT_LVTOFF_MCE; | 375 | |
376 | if (offset >= APIC_EILVT_NR_MAX) | ||
377 | return ~0; | ||
378 | |||
379 | rsvd = atomic_read(&eilvt_offsets[offset]) & ~APIC_EILVT_MASKED; | ||
380 | do { | ||
381 | if (rsvd && | ||
382 | !eilvt_entry_is_changeable(rsvd, new)) | ||
383 | /* may not change if vectors are different */ | ||
384 | return rsvd; | ||
385 | rsvd = atomic_cmpxchg(&eilvt_offsets[offset], rsvd, new); | ||
386 | } while (rsvd != new); | ||
387 | |||
388 | return new; | ||
397 | } | 389 | } |
398 | 390 | ||
399 | u8 setup_APIC_eilvt_ibs(u8 vector, u8 msg_type, u8 mask) | 391 | /* |
392 | * If mask=1, the LVT entry does not generate interrupts while mask=0 | ||
393 | * enables the vector. See also the BKDGs. Must be called with | ||
394 | * preemption disabled. | ||
395 | */ | ||
396 | |||
397 | int setup_APIC_eilvt(u8 offset, u8 vector, u8 msg_type, u8 mask) | ||
400 | { | 398 | { |
401 | setup_APIC_eilvt(APIC_EILVT_LVTOFF_IBS, vector, msg_type, mask); | 399 | unsigned long reg = APIC_EILVTn(offset); |
402 | return APIC_EILVT_LVTOFF_IBS; | 400 | unsigned int new, old, reserved; |
401 | |||
402 | new = (mask << 16) | (msg_type << 8) | vector; | ||
403 | old = apic_read(reg); | ||
404 | reserved = reserve_eilvt_offset(offset, new); | ||
405 | |||
406 | if (reserved != new) { | ||
407 | pr_err(FW_BUG "cpu %d, try to use APIC%lX (LVT offset %d) for " | ||
408 | "vector 0x%x, but the register is already in use for " | ||
409 | "vector 0x%x on another cpu\n", | ||
410 | smp_processor_id(), reg, offset, new, reserved); | ||
411 | return -EINVAL; | ||
412 | } | ||
413 | |||
414 | if (!eilvt_entry_is_changeable(old, new)) { | ||
415 | pr_err(FW_BUG "cpu %d, try to use APIC%lX (LVT offset %d) for " | ||
416 | "vector 0x%x, but the register is already in use for " | ||
417 | "vector 0x%x on this cpu\n", | ||
418 | smp_processor_id(), reg, offset, new, old); | ||
419 | return -EBUSY; | ||
420 | } | ||
421 | |||
422 | apic_write(reg, new); | ||
423 | |||
424 | return 0; | ||
403 | } | 425 | } |
404 | EXPORT_SYMBOL_GPL(setup_APIC_eilvt_ibs); | 426 | EXPORT_SYMBOL_GPL(setup_APIC_eilvt); |
405 | 427 | ||
406 | /* | 428 | /* |
407 | * Program the next event, relative to now | 429 | * Program the next event, relative to now |
@@ -459,6 +481,23 @@ static void lapic_timer_broadcast(const struct cpumask *mask) | |||
459 | #endif | 481 | #endif |
460 | } | 482 | } |
461 | 483 | ||
484 | |||
485 | /* | ||
486 | * The local apic timer can be used for any function which is CPU local. | ||
487 | */ | ||
488 | static struct clock_event_device lapic_clockevent = { | ||
489 | .name = "lapic", | ||
490 | .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT | ||
491 | | CLOCK_EVT_FEAT_C3STOP | CLOCK_EVT_FEAT_DUMMY, | ||
492 | .shift = 32, | ||
493 | .set_mode = lapic_timer_setup, | ||
494 | .set_next_event = lapic_next_event, | ||
495 | .broadcast = lapic_timer_broadcast, | ||
496 | .rating = 100, | ||
497 | .irq = -1, | ||
498 | }; | ||
499 | static DEFINE_PER_CPU(struct clock_event_device, lapic_events); | ||
500 | |||
462 | /* | 501 | /* |
463 | * Setup the local APIC timer for this CPU. Copy the initialized values | 502 | * Setup the local APIC timer for this CPU. Copy the initialized values |
464 | * of the boot CPU and register the clock event in the framework. | 503 | * of the boot CPU and register the clock event in the framework. |
@@ -467,7 +506,7 @@ static void __cpuinit setup_APIC_timer(void) | |||
467 | { | 506 | { |
468 | struct clock_event_device *levt = &__get_cpu_var(lapic_events); | 507 | struct clock_event_device *levt = &__get_cpu_var(lapic_events); |
469 | 508 | ||
470 | if (cpu_has(¤t_cpu_data, X86_FEATURE_ARAT)) { | 509 | if (this_cpu_has(X86_FEATURE_ARAT)) { |
471 | lapic_clockevent.features &= ~CLOCK_EVT_FEAT_C3STOP; | 510 | lapic_clockevent.features &= ~CLOCK_EVT_FEAT_C3STOP; |
472 | /* Make LAPIC timer preferrable over percpu HPET */ | 511 | /* Make LAPIC timer preferrable over percpu HPET */ |
473 | lapic_clockevent.rating = 150; | 512 | lapic_clockevent.rating = 150; |
@@ -635,7 +674,7 @@ static int __init calibrate_APIC_clock(void) | |||
635 | lapic_clockevent.mult = div_sc(delta, TICK_NSEC * LAPIC_CAL_LOOPS, | 674 | lapic_clockevent.mult = div_sc(delta, TICK_NSEC * LAPIC_CAL_LOOPS, |
636 | lapic_clockevent.shift); | 675 | lapic_clockevent.shift); |
637 | lapic_clockevent.max_delta_ns = | 676 | lapic_clockevent.max_delta_ns = |
638 | clockevent_delta2ns(0x7FFFFF, &lapic_clockevent); | 677 | clockevent_delta2ns(0x7FFFFFFF, &lapic_clockevent); |
639 | lapic_clockevent.min_delta_ns = | 678 | lapic_clockevent.min_delta_ns = |
640 | clockevent_delta2ns(0xF, &lapic_clockevent); | 679 | clockevent_delta2ns(0xF, &lapic_clockevent); |
641 | 680 | ||
@@ -750,11 +789,7 @@ void __init setup_boot_APIC_clock(void) | |||
750 | * PIT/HPET going. Otherwise register lapic as a dummy | 789 | * PIT/HPET going. Otherwise register lapic as a dummy |
751 | * device. | 790 | * device. |
752 | */ | 791 | */ |
753 | if (nmi_watchdog != NMI_IO_APIC) | 792 | lapic_clockevent.features &= ~CLOCK_EVT_FEAT_DUMMY; |
754 | lapic_clockevent.features &= ~CLOCK_EVT_FEAT_DUMMY; | ||
755 | else | ||
756 | pr_warning("APIC timer registered as dummy," | ||
757 | " due to nmi_watchdog=%d!\n", nmi_watchdog); | ||
758 | 793 | ||
759 | /* Setup the lapic or request the broadcast */ | 794 | /* Setup the lapic or request the broadcast */ |
760 | setup_APIC_timer(); | 795 | setup_APIC_timer(); |
@@ -1146,12 +1181,15 @@ static void __cpuinit lapic_setup_esr(void) | |||
1146 | oldvalue, value); | 1181 | oldvalue, value); |
1147 | } | 1182 | } |
1148 | 1183 | ||
1149 | |||
1150 | /** | 1184 | /** |
1151 | * setup_local_APIC - setup the local APIC | 1185 | * setup_local_APIC - setup the local APIC |
1186 | * | ||
1187 | * Used to setup local APIC while initializing BSP or bringin up APs. | ||
1188 | * Always called with preemption disabled. | ||
1152 | */ | 1189 | */ |
1153 | void __cpuinit setup_local_APIC(void) | 1190 | void __cpuinit setup_local_APIC(void) |
1154 | { | 1191 | { |
1192 | int cpu = smp_processor_id(); | ||
1155 | unsigned int value, queued; | 1193 | unsigned int value, queued; |
1156 | int i, j, acked = 0; | 1194 | int i, j, acked = 0; |
1157 | unsigned long long tsc = 0, ntsc; | 1195 | unsigned long long tsc = 0, ntsc; |
@@ -1161,7 +1199,7 @@ void __cpuinit setup_local_APIC(void) | |||
1161 | rdtscll(tsc); | 1199 | rdtscll(tsc); |
1162 | 1200 | ||
1163 | if (disable_apic) { | 1201 | if (disable_apic) { |
1164 | arch_disable_smp_support(); | 1202 | disable_ioapic_support(); |
1165 | return; | 1203 | return; |
1166 | } | 1204 | } |
1167 | 1205 | ||
@@ -1176,8 +1214,6 @@ void __cpuinit setup_local_APIC(void) | |||
1176 | #endif | 1214 | #endif |
1177 | perf_events_lapic_init(); | 1215 | perf_events_lapic_init(); |
1178 | 1216 | ||
1179 | preempt_disable(); | ||
1180 | |||
1181 | /* | 1217 | /* |
1182 | * Double-check whether this APIC is really registered. | 1218 | * Double-check whether this APIC is really registered. |
1183 | * This is meaningless in clustered apic mode, so we skip it. | 1219 | * This is meaningless in clustered apic mode, so we skip it. |
@@ -1191,6 +1227,30 @@ void __cpuinit setup_local_APIC(void) | |||
1191 | */ | 1227 | */ |
1192 | apic->init_apic_ldr(); | 1228 | apic->init_apic_ldr(); |
1193 | 1229 | ||
1230 | #ifdef CONFIG_X86_32 | ||
1231 | /* | ||
1232 | * APIC LDR is initialized. If logical_apicid mapping was | ||
1233 | * initialized during get_smp_config(), make sure it matches the | ||
1234 | * actual value. | ||
1235 | */ | ||
1236 | i = early_per_cpu(x86_cpu_to_logical_apicid, cpu); | ||
1237 | WARN_ON(i != BAD_APICID && i != logical_smp_processor_id()); | ||
1238 | /* always use the value from LDR */ | ||
1239 | early_per_cpu(x86_cpu_to_logical_apicid, cpu) = | ||
1240 | logical_smp_processor_id(); | ||
1241 | |||
1242 | /* | ||
1243 | * Some NUMA implementations (NUMAQ) don't initialize apicid to | ||
1244 | * node mapping during NUMA init. Now that logical apicid is | ||
1245 | * guaranteed to be known, give it another chance. This is already | ||
1246 | * a bit too late - percpu allocation has already happened without | ||
1247 | * proper NUMA affinity. | ||
1248 | */ | ||
1249 | if (apic->x86_32_numa_cpu_node) | ||
1250 | set_apicid_to_node(early_per_cpu(x86_cpu_to_apicid, cpu), | ||
1251 | apic->x86_32_numa_cpu_node(cpu)); | ||
1252 | #endif | ||
1253 | |||
1194 | /* | 1254 | /* |
1195 | * Set Task Priority to 'accept all'. We never change this | 1255 | * Set Task Priority to 'accept all'. We never change this |
1196 | * later on. | 1256 | * later on. |
@@ -1293,21 +1353,19 @@ void __cpuinit setup_local_APIC(void) | |||
1293 | * TODO: set up through-local-APIC from through-I/O-APIC? --macro | 1353 | * TODO: set up through-local-APIC from through-I/O-APIC? --macro |
1294 | */ | 1354 | */ |
1295 | value = apic_read(APIC_LVT0) & APIC_LVT_MASKED; | 1355 | value = apic_read(APIC_LVT0) & APIC_LVT_MASKED; |
1296 | if (!smp_processor_id() && (pic_mode || !value)) { | 1356 | if (!cpu && (pic_mode || !value)) { |
1297 | value = APIC_DM_EXTINT; | 1357 | value = APIC_DM_EXTINT; |
1298 | apic_printk(APIC_VERBOSE, "enabled ExtINT on CPU#%d\n", | 1358 | apic_printk(APIC_VERBOSE, "enabled ExtINT on CPU#%d\n", cpu); |
1299 | smp_processor_id()); | ||
1300 | } else { | 1359 | } else { |
1301 | value = APIC_DM_EXTINT | APIC_LVT_MASKED; | 1360 | value = APIC_DM_EXTINT | APIC_LVT_MASKED; |
1302 | apic_printk(APIC_VERBOSE, "masked ExtINT on CPU#%d\n", | 1361 | apic_printk(APIC_VERBOSE, "masked ExtINT on CPU#%d\n", cpu); |
1303 | smp_processor_id()); | ||
1304 | } | 1362 | } |
1305 | apic_write(APIC_LVT0, value); | 1363 | apic_write(APIC_LVT0, value); |
1306 | 1364 | ||
1307 | /* | 1365 | /* |
1308 | * only the BP should see the LINT1 NMI signal, obviously. | 1366 | * only the BP should see the LINT1 NMI signal, obviously. |
1309 | */ | 1367 | */ |
1310 | if (!smp_processor_id()) | 1368 | if (!cpu) |
1311 | value = APIC_DM_NMI; | 1369 | value = APIC_DM_NMI; |
1312 | else | 1370 | else |
1313 | value = APIC_DM_NMI | APIC_LVT_MASKED; | 1371 | value = APIC_DM_NMI | APIC_LVT_MASKED; |
@@ -1315,11 +1373,9 @@ void __cpuinit setup_local_APIC(void) | |||
1315 | value |= APIC_LVT_LEVEL_TRIGGER; | 1373 | value |= APIC_LVT_LEVEL_TRIGGER; |
1316 | apic_write(APIC_LVT1, value); | 1374 | apic_write(APIC_LVT1, value); |
1317 | 1375 | ||
1318 | preempt_enable(); | ||
1319 | |||
1320 | #ifdef CONFIG_X86_MCE_INTEL | 1376 | #ifdef CONFIG_X86_MCE_INTEL |
1321 | /* Recheck CMCI information after local APIC is up on CPU #0 */ | 1377 | /* Recheck CMCI information after local APIC is up on CPU #0 */ |
1322 | if (smp_processor_id() == 0) | 1378 | if (!cpu) |
1323 | cmci_recheck(); | 1379 | cmci_recheck(); |
1324 | #endif | 1380 | #endif |
1325 | } | 1381 | } |
@@ -1338,10 +1394,22 @@ void __cpuinit end_local_APIC_setup(void) | |||
1338 | } | 1394 | } |
1339 | #endif | 1395 | #endif |
1340 | 1396 | ||
1341 | setup_apic_nmi_watchdog(NULL); | ||
1342 | apic_pm_activate(); | 1397 | apic_pm_activate(); |
1343 | } | 1398 | } |
1344 | 1399 | ||
1400 | void __init bsp_end_local_APIC_setup(void) | ||
1401 | { | ||
1402 | end_local_APIC_setup(); | ||
1403 | |||
1404 | /* | ||
1405 | * Now that local APIC setup is completed for BP, configure the fault | ||
1406 | * handling for interrupt remapping. | ||
1407 | */ | ||
1408 | if (intr_remapping_enabled) | ||
1409 | enable_drhd_fault_handling(); | ||
1410 | |||
1411 | } | ||
1412 | |||
1345 | #ifdef CONFIG_X86_X2APIC | 1413 | #ifdef CONFIG_X86_X2APIC |
1346 | void check_x2apic(void) | 1414 | void check_x2apic(void) |
1347 | { | 1415 | { |
@@ -1394,7 +1462,6 @@ int __init enable_IR(void) | |||
1394 | void __init enable_IR_x2apic(void) | 1462 | void __init enable_IR_x2apic(void) |
1395 | { | 1463 | { |
1396 | unsigned long flags; | 1464 | unsigned long flags; |
1397 | struct IO_APIC_route_entry **ioapic_entries = NULL; | ||
1398 | int ret, x2apic_enabled = 0; | 1465 | int ret, x2apic_enabled = 0; |
1399 | int dmar_table_init_ret; | 1466 | int dmar_table_init_ret; |
1400 | 1467 | ||
@@ -1402,13 +1469,7 @@ void __init enable_IR_x2apic(void) | |||
1402 | if (dmar_table_init_ret && !x2apic_supported()) | 1469 | if (dmar_table_init_ret && !x2apic_supported()) |
1403 | return; | 1470 | return; |
1404 | 1471 | ||
1405 | ioapic_entries = alloc_ioapic_entries(); | 1472 | ret = save_ioapic_entries(); |
1406 | if (!ioapic_entries) { | ||
1407 | pr_err("Allocate ioapic_entries failed\n"); | ||
1408 | goto out; | ||
1409 | } | ||
1410 | |||
1411 | ret = save_IO_APIC_setup(ioapic_entries); | ||
1412 | if (ret) { | 1473 | if (ret) { |
1413 | pr_info("Saving IO-APIC state failed: %d\n", ret); | 1474 | pr_info("Saving IO-APIC state failed: %d\n", ret); |
1414 | goto out; | 1475 | goto out; |
@@ -1416,7 +1477,7 @@ void __init enable_IR_x2apic(void) | |||
1416 | 1477 | ||
1417 | local_irq_save(flags); | 1478 | local_irq_save(flags); |
1418 | legacy_pic->mask_all(); | 1479 | legacy_pic->mask_all(); |
1419 | mask_IO_APIC_setup(ioapic_entries); | 1480 | mask_ioapic_entries(); |
1420 | 1481 | ||
1421 | if (dmar_table_init_ret) | 1482 | if (dmar_table_init_ret) |
1422 | ret = 0; | 1483 | ret = 0; |
@@ -1427,7 +1488,8 @@ void __init enable_IR_x2apic(void) | |||
1427 | /* IR is required if there is APIC ID > 255 even when running | 1488 | /* IR is required if there is APIC ID > 255 even when running |
1428 | * under KVM | 1489 | * under KVM |
1429 | */ | 1490 | */ |
1430 | if (max_physical_apicid > 255 || !kvm_para_available()) | 1491 | if (max_physical_apicid > 255 || |
1492 | !hypervisor_x2apic_available()) | ||
1431 | goto nox2apic; | 1493 | goto nox2apic; |
1432 | /* | 1494 | /* |
1433 | * without IR all CPUs can be addressed by IOAPIC/MSI | 1495 | * without IR all CPUs can be addressed by IOAPIC/MSI |
@@ -1446,14 +1508,11 @@ void __init enable_IR_x2apic(void) | |||
1446 | 1508 | ||
1447 | nox2apic: | 1509 | nox2apic: |
1448 | if (!ret) /* IR enabling failed */ | 1510 | if (!ret) /* IR enabling failed */ |
1449 | restore_IO_APIC_setup(ioapic_entries); | 1511 | restore_ioapic_entries(); |
1450 | legacy_pic->restore_mask(); | 1512 | legacy_pic->restore_mask(); |
1451 | local_irq_restore(flags); | 1513 | local_irq_restore(flags); |
1452 | 1514 | ||
1453 | out: | 1515 | out: |
1454 | if (ioapic_entries) | ||
1455 | free_ioapic_entries(ioapic_entries); | ||
1456 | |||
1457 | if (x2apic_enabled) | 1516 | if (x2apic_enabled) |
1458 | return; | 1517 | return; |
1459 | 1518 | ||
@@ -1481,13 +1540,60 @@ static int __init detect_init_APIC(void) | |||
1481 | return 0; | 1540 | return 0; |
1482 | } | 1541 | } |
1483 | #else | 1542 | #else |
1543 | |||
1544 | static int __init apic_verify(void) | ||
1545 | { | ||
1546 | u32 features, h, l; | ||
1547 | |||
1548 | /* | ||
1549 | * The APIC feature bit should now be enabled | ||
1550 | * in `cpuid' | ||
1551 | */ | ||
1552 | features = cpuid_edx(1); | ||
1553 | if (!(features & (1 << X86_FEATURE_APIC))) { | ||
1554 | pr_warning("Could not enable APIC!\n"); | ||
1555 | return -1; | ||
1556 | } | ||
1557 | set_cpu_cap(&boot_cpu_data, X86_FEATURE_APIC); | ||
1558 | mp_lapic_addr = APIC_DEFAULT_PHYS_BASE; | ||
1559 | |||
1560 | /* The BIOS may have set up the APIC at some other address */ | ||
1561 | rdmsr(MSR_IA32_APICBASE, l, h); | ||
1562 | if (l & MSR_IA32_APICBASE_ENABLE) | ||
1563 | mp_lapic_addr = l & MSR_IA32_APICBASE_BASE; | ||
1564 | |||
1565 | pr_info("Found and enabled local APIC!\n"); | ||
1566 | return 0; | ||
1567 | } | ||
1568 | |||
1569 | int __init apic_force_enable(unsigned long addr) | ||
1570 | { | ||
1571 | u32 h, l; | ||
1572 | |||
1573 | if (disable_apic) | ||
1574 | return -1; | ||
1575 | |||
1576 | /* | ||
1577 | * Some BIOSes disable the local APIC in the APIC_BASE | ||
1578 | * MSR. This can only be done in software for Intel P6 or later | ||
1579 | * and AMD K7 (Model > 1) or later. | ||
1580 | */ | ||
1581 | rdmsr(MSR_IA32_APICBASE, l, h); | ||
1582 | if (!(l & MSR_IA32_APICBASE_ENABLE)) { | ||
1583 | pr_info("Local APIC disabled by BIOS -- reenabling.\n"); | ||
1584 | l &= ~MSR_IA32_APICBASE_BASE; | ||
1585 | l |= MSR_IA32_APICBASE_ENABLE | addr; | ||
1586 | wrmsr(MSR_IA32_APICBASE, l, h); | ||
1587 | enabled_via_apicbase = 1; | ||
1588 | } | ||
1589 | return apic_verify(); | ||
1590 | } | ||
1591 | |||
1484 | /* | 1592 | /* |
1485 | * Detect and initialize APIC | 1593 | * Detect and initialize APIC |
1486 | */ | 1594 | */ |
1487 | static int __init detect_init_APIC(void) | 1595 | static int __init detect_init_APIC(void) |
1488 | { | 1596 | { |
1489 | u32 h, l, features; | ||
1490 | |||
1491 | /* Disabled by kernel option? */ | 1597 | /* Disabled by kernel option? */ |
1492 | if (disable_apic) | 1598 | if (disable_apic) |
1493 | return -1; | 1599 | return -1; |
@@ -1517,38 +1623,12 @@ static int __init detect_init_APIC(void) | |||
1517 | "you can enable it with \"lapic\"\n"); | 1623 | "you can enable it with \"lapic\"\n"); |
1518 | return -1; | 1624 | return -1; |
1519 | } | 1625 | } |
1520 | /* | 1626 | if (apic_force_enable(APIC_DEFAULT_PHYS_BASE)) |
1521 | * Some BIOSes disable the local APIC in the APIC_BASE | 1627 | return -1; |
1522 | * MSR. This can only be done in software for Intel P6 or later | 1628 | } else { |
1523 | * and AMD K7 (Model > 1) or later. | 1629 | if (apic_verify()) |
1524 | */ | 1630 | return -1; |
1525 | rdmsr(MSR_IA32_APICBASE, l, h); | ||
1526 | if (!(l & MSR_IA32_APICBASE_ENABLE)) { | ||
1527 | pr_info("Local APIC disabled by BIOS -- reenabling.\n"); | ||
1528 | l &= ~MSR_IA32_APICBASE_BASE; | ||
1529 | l |= MSR_IA32_APICBASE_ENABLE | APIC_DEFAULT_PHYS_BASE; | ||
1530 | wrmsr(MSR_IA32_APICBASE, l, h); | ||
1531 | enabled_via_apicbase = 1; | ||
1532 | } | ||
1533 | } | ||
1534 | /* | ||
1535 | * The APIC feature bit should now be enabled | ||
1536 | * in `cpuid' | ||
1537 | */ | ||
1538 | features = cpuid_edx(1); | ||
1539 | if (!(features & (1 << X86_FEATURE_APIC))) { | ||
1540 | pr_warning("Could not enable APIC!\n"); | ||
1541 | return -1; | ||
1542 | } | 1631 | } |
1543 | set_cpu_cap(&boot_cpu_data, X86_FEATURE_APIC); | ||
1544 | mp_lapic_addr = APIC_DEFAULT_PHYS_BASE; | ||
1545 | |||
1546 | /* The BIOS may have set up the APIC at some other address */ | ||
1547 | rdmsr(MSR_IA32_APICBASE, l, h); | ||
1548 | if (l & MSR_IA32_APICBASE_ENABLE) | ||
1549 | mp_lapic_addr = l & MSR_IA32_APICBASE_BASE; | ||
1550 | |||
1551 | pr_info("Found and enabled local APIC!\n"); | ||
1552 | 1632 | ||
1553 | apic_pm_activate(); | 1633 | apic_pm_activate(); |
1554 | 1634 | ||
@@ -1560,28 +1640,6 @@ no_apic: | |||
1560 | } | 1640 | } |
1561 | #endif | 1641 | #endif |
1562 | 1642 | ||
1563 | #ifdef CONFIG_X86_64 | ||
1564 | void __init early_init_lapic_mapping(void) | ||
1565 | { | ||
1566 | /* | ||
1567 | * If no local APIC can be found then go out | ||
1568 | * : it means there is no mpatable and MADT | ||
1569 | */ | ||
1570 | if (!smp_found_config) | ||
1571 | return; | ||
1572 | |||
1573 | set_fixmap_nocache(FIX_APIC_BASE, mp_lapic_addr); | ||
1574 | apic_printk(APIC_VERBOSE, "mapped APIC to %16lx (%16lx)\n", | ||
1575 | APIC_BASE, mp_lapic_addr); | ||
1576 | |||
1577 | /* | ||
1578 | * Fetch the APIC ID of the BSP in case we have a | ||
1579 | * default configuration (or the MP table is broken). | ||
1580 | */ | ||
1581 | boot_cpu_physical_apicid = read_apic_id(); | ||
1582 | } | ||
1583 | #endif | ||
1584 | |||
1585 | /** | 1643 | /** |
1586 | * init_apic_mappings - initialize APIC mappings | 1644 | * init_apic_mappings - initialize APIC mappings |
1587 | */ | 1645 | */ |
@@ -1607,10 +1665,7 @@ void __init init_apic_mappings(void) | |||
1607 | * acpi_register_lapic_address() | 1665 | * acpi_register_lapic_address() |
1608 | */ | 1666 | */ |
1609 | if (!acpi_lapic && !smp_found_config) | 1667 | if (!acpi_lapic && !smp_found_config) |
1610 | set_fixmap_nocache(FIX_APIC_BASE, apic_phys); | 1668 | register_lapic_address(apic_phys); |
1611 | |||
1612 | apic_printk(APIC_VERBOSE, "mapped APIC to %08lx (%08lx)\n", | ||
1613 | APIC_BASE, apic_phys); | ||
1614 | } | 1669 | } |
1615 | 1670 | ||
1616 | /* | 1671 | /* |
@@ -1632,11 +1687,27 @@ void __init init_apic_mappings(void) | |||
1632 | } | 1687 | } |
1633 | } | 1688 | } |
1634 | 1689 | ||
1690 | void __init register_lapic_address(unsigned long address) | ||
1691 | { | ||
1692 | mp_lapic_addr = address; | ||
1693 | |||
1694 | if (!x2apic_mode) { | ||
1695 | set_fixmap_nocache(FIX_APIC_BASE, address); | ||
1696 | apic_printk(APIC_VERBOSE, "mapped APIC to %16lx (%16lx)\n", | ||
1697 | APIC_BASE, mp_lapic_addr); | ||
1698 | } | ||
1699 | if (boot_cpu_physical_apicid == -1U) { | ||
1700 | boot_cpu_physical_apicid = read_apic_id(); | ||
1701 | apic_version[boot_cpu_physical_apicid] = | ||
1702 | GET_APIC_VERSION(apic_read(APIC_LVR)); | ||
1703 | } | ||
1704 | } | ||
1705 | |||
1635 | /* | 1706 | /* |
1636 | * This initializes the IO-APIC and APIC hardware if this is | 1707 | * This initializes the IO-APIC and APIC hardware if this is |
1637 | * a UP kernel. | 1708 | * a UP kernel. |
1638 | */ | 1709 | */ |
1639 | int apic_version[MAX_APICS]; | 1710 | int apic_version[MAX_LOCAL_APIC]; |
1640 | 1711 | ||
1641 | int __init APIC_init_uniprocessor(void) | 1712 | int __init APIC_init_uniprocessor(void) |
1642 | { | 1713 | { |
@@ -1665,10 +1736,7 @@ int __init APIC_init_uniprocessor(void) | |||
1665 | } | 1736 | } |
1666 | #endif | 1737 | #endif |
1667 | 1738 | ||
1668 | #ifndef CONFIG_SMP | ||
1669 | enable_IR_x2apic(); | ||
1670 | default_setup_apic_routing(); | 1739 | default_setup_apic_routing(); |
1671 | #endif | ||
1672 | 1740 | ||
1673 | verify_local_APIC(); | 1741 | verify_local_APIC(); |
1674 | connect_bsp_APIC(); | 1742 | connect_bsp_APIC(); |
@@ -1697,24 +1765,17 @@ int __init APIC_init_uniprocessor(void) | |||
1697 | enable_IO_APIC(); | 1765 | enable_IO_APIC(); |
1698 | #endif | 1766 | #endif |
1699 | 1767 | ||
1700 | end_local_APIC_setup(); | 1768 | bsp_end_local_APIC_setup(); |
1701 | 1769 | ||
1702 | #ifdef CONFIG_X86_IO_APIC | 1770 | #ifdef CONFIG_X86_IO_APIC |
1703 | if (smp_found_config && !skip_ioapic_setup && nr_ioapics) | 1771 | if (smp_found_config && !skip_ioapic_setup && nr_ioapics) |
1704 | setup_IO_APIC(); | 1772 | setup_IO_APIC(); |
1705 | else { | 1773 | else { |
1706 | nr_ioapics = 0; | 1774 | nr_ioapics = 0; |
1707 | localise_nmi_watchdog(); | ||
1708 | } | 1775 | } |
1709 | #else | ||
1710 | localise_nmi_watchdog(); | ||
1711 | #endif | 1776 | #endif |
1712 | 1777 | ||
1713 | x86_init.timers.setup_percpu_clockev(); | 1778 | x86_init.timers.setup_percpu_clockev(); |
1714 | #ifdef CONFIG_X86_64 | ||
1715 | check_nmi_watchdog(); | ||
1716 | #endif | ||
1717 | |||
1718 | return 0; | 1779 | return 0; |
1719 | } | 1780 | } |
1720 | 1781 | ||
@@ -1753,30 +1814,41 @@ void smp_spurious_interrupt(struct pt_regs *regs) | |||
1753 | */ | 1814 | */ |
1754 | void smp_error_interrupt(struct pt_regs *regs) | 1815 | void smp_error_interrupt(struct pt_regs *regs) |
1755 | { | 1816 | { |
1756 | u32 v, v1; | 1817 | u32 v0, v1; |
1818 | u32 i = 0; | ||
1819 | static const char * const error_interrupt_reason[] = { | ||
1820 | "Send CS error", /* APIC Error Bit 0 */ | ||
1821 | "Receive CS error", /* APIC Error Bit 1 */ | ||
1822 | "Send accept error", /* APIC Error Bit 2 */ | ||
1823 | "Receive accept error", /* APIC Error Bit 3 */ | ||
1824 | "Redirectable IPI", /* APIC Error Bit 4 */ | ||
1825 | "Send illegal vector", /* APIC Error Bit 5 */ | ||
1826 | "Received illegal vector", /* APIC Error Bit 6 */ | ||
1827 | "Illegal register address", /* APIC Error Bit 7 */ | ||
1828 | }; | ||
1757 | 1829 | ||
1758 | exit_idle(); | 1830 | exit_idle(); |
1759 | irq_enter(); | 1831 | irq_enter(); |
1760 | /* First tickle the hardware, only then report what went on. -- REW */ | 1832 | /* First tickle the hardware, only then report what went on. -- REW */ |
1761 | v = apic_read(APIC_ESR); | 1833 | v0 = apic_read(APIC_ESR); |
1762 | apic_write(APIC_ESR, 0); | 1834 | apic_write(APIC_ESR, 0); |
1763 | v1 = apic_read(APIC_ESR); | 1835 | v1 = apic_read(APIC_ESR); |
1764 | ack_APIC_irq(); | 1836 | ack_APIC_irq(); |
1765 | atomic_inc(&irq_err_count); | 1837 | atomic_inc(&irq_err_count); |
1766 | 1838 | ||
1767 | /* | 1839 | apic_printk(APIC_DEBUG, KERN_DEBUG "APIC error on CPU%d: %02x(%02x)", |
1768 | * Here is what the APIC error bits mean: | 1840 | smp_processor_id(), v0 , v1); |
1769 | * 0: Send CS error | 1841 | |
1770 | * 1: Receive CS error | 1842 | v1 = v1 & 0xff; |
1771 | * 2: Send accept error | 1843 | while (v1) { |
1772 | * 3: Receive accept error | 1844 | if (v1 & 0x1) |
1773 | * 4: Reserved | 1845 | apic_printk(APIC_DEBUG, KERN_CONT " : %s", error_interrupt_reason[i]); |
1774 | * 5: Send illegal vector | 1846 | i++; |
1775 | * 6: Received illegal vector | 1847 | v1 >>= 1; |
1776 | * 7: Illegal register address | 1848 | }; |
1777 | */ | 1849 | |
1778 | pr_debug("APIC error on CPU%d: %02x(%02x)\n", | 1850 | apic_printk(APIC_DEBUG, KERN_CONT "\n"); |
1779 | smp_processor_id(), v , v1); | 1851 | |
1780 | irq_exit(); | 1852 | irq_exit(); |
1781 | } | 1853 | } |
1782 | 1854 | ||
@@ -1873,17 +1945,6 @@ void __cpuinit generic_processor_info(int apicid, int version) | |||
1873 | { | 1945 | { |
1874 | int cpu; | 1946 | int cpu; |
1875 | 1947 | ||
1876 | /* | ||
1877 | * Validate version | ||
1878 | */ | ||
1879 | if (version == 0x0) { | ||
1880 | pr_warning("BIOS bug, APIC version is 0 for CPU#%d! " | ||
1881 | "fixing up to 0x10. (tell your hw vendor)\n", | ||
1882 | version); | ||
1883 | version = 0x10; | ||
1884 | } | ||
1885 | apic_version[apicid] = version; | ||
1886 | |||
1887 | if (num_processors >= nr_cpu_ids) { | 1948 | if (num_processors >= nr_cpu_ids) { |
1888 | int max = nr_cpu_ids; | 1949 | int max = nr_cpu_ids; |
1889 | int thiscpu = max + disabled_cpus; | 1950 | int thiscpu = max + disabled_cpus; |
@@ -1897,22 +1958,34 @@ void __cpuinit generic_processor_info(int apicid, int version) | |||
1897 | } | 1958 | } |
1898 | 1959 | ||
1899 | num_processors++; | 1960 | num_processors++; |
1900 | cpu = cpumask_next_zero(-1, cpu_present_mask); | ||
1901 | |||
1902 | if (version != apic_version[boot_cpu_physical_apicid]) | ||
1903 | WARN_ONCE(1, | ||
1904 | "ACPI: apic version mismatch, bootcpu: %x cpu %d: %x\n", | ||
1905 | apic_version[boot_cpu_physical_apicid], cpu, version); | ||
1906 | |||
1907 | physid_set(apicid, phys_cpu_present_map); | ||
1908 | if (apicid == boot_cpu_physical_apicid) { | 1961 | if (apicid == boot_cpu_physical_apicid) { |
1909 | /* | 1962 | /* |
1910 | * x86_bios_cpu_apicid is required to have processors listed | 1963 | * x86_bios_cpu_apicid is required to have processors listed |
1911 | * in same order as logical cpu numbers. Hence the first | 1964 | * in same order as logical cpu numbers. Hence the first |
1912 | * entry is BSP, and so on. | 1965 | * entry is BSP, and so on. |
1966 | * boot_cpu_init() already hold bit 0 in cpu_present_mask | ||
1967 | * for BSP. | ||
1913 | */ | 1968 | */ |
1914 | cpu = 0; | 1969 | cpu = 0; |
1970 | } else | ||
1971 | cpu = cpumask_next_zero(-1, cpu_present_mask); | ||
1972 | |||
1973 | /* | ||
1974 | * Validate version | ||
1975 | */ | ||
1976 | if (version == 0x0) { | ||
1977 | pr_warning("BIOS bug: APIC version is 0 for CPU %d/0x%x, fixing up to 0x10\n", | ||
1978 | cpu, apicid); | ||
1979 | version = 0x10; | ||
1915 | } | 1980 | } |
1981 | apic_version[apicid] = version; | ||
1982 | |||
1983 | if (version != apic_version[boot_cpu_physical_apicid]) { | ||
1984 | pr_warning("BIOS bug: APIC version mismatch, boot CPU: %x, CPU %d: version %x\n", | ||
1985 | apic_version[boot_cpu_physical_apicid], cpu, version); | ||
1986 | } | ||
1987 | |||
1988 | physid_set(apicid, phys_cpu_present_map); | ||
1916 | if (apicid > max_physical_apicid) | 1989 | if (apicid > max_physical_apicid) |
1917 | max_physical_apicid = apicid; | 1990 | max_physical_apicid = apicid; |
1918 | 1991 | ||
@@ -1920,7 +1993,10 @@ void __cpuinit generic_processor_info(int apicid, int version) | |||
1920 | early_per_cpu(x86_cpu_to_apicid, cpu) = apicid; | 1993 | early_per_cpu(x86_cpu_to_apicid, cpu) = apicid; |
1921 | early_per_cpu(x86_bios_cpu_apicid, cpu) = apicid; | 1994 | early_per_cpu(x86_bios_cpu_apicid, cpu) = apicid; |
1922 | #endif | 1995 | #endif |
1923 | 1996 | #ifdef CONFIG_X86_32 | |
1997 | early_per_cpu(x86_cpu_to_logical_apicid, cpu) = | ||
1998 | apic->x86_32_early_logical_apicid(cpu); | ||
1999 | #endif | ||
1924 | set_cpu_possible(cpu, true); | 2000 | set_cpu_possible(cpu, true); |
1925 | set_cpu_present(cpu, true); | 2001 | set_cpu_present(cpu, true); |
1926 | } | 2002 | } |
@@ -1940,17 +2016,6 @@ void default_init_apic_ldr(void) | |||
1940 | apic_write(APIC_LDR, val); | 2016 | apic_write(APIC_LDR, val); |
1941 | } | 2017 | } |
1942 | 2018 | ||
1943 | #ifdef CONFIG_X86_32 | ||
1944 | int default_apicid_to_node(int logical_apicid) | ||
1945 | { | ||
1946 | #ifdef CONFIG_SMP | ||
1947 | return apicid_2_node[hard_smp_processor_id()]; | ||
1948 | #else | ||
1949 | return 0; | ||
1950 | #endif | ||
1951 | } | ||
1952 | #endif | ||
1953 | |||
1954 | /* | 2019 | /* |
1955 | * Power management | 2020 | * Power management |
1956 | */ | 2021 | */ |
@@ -1979,7 +2044,7 @@ static struct { | |||
1979 | unsigned int apic_thmr; | 2044 | unsigned int apic_thmr; |
1980 | } apic_pm_state; | 2045 | } apic_pm_state; |
1981 | 2046 | ||
1982 | static int lapic_suspend(struct sys_device *dev, pm_message_t state) | 2047 | static int lapic_suspend(void) |
1983 | { | 2048 | { |
1984 | unsigned long flags; | 2049 | unsigned long flags; |
1985 | int maxlvt; | 2050 | int maxlvt; |
@@ -2017,34 +2082,24 @@ static int lapic_suspend(struct sys_device *dev, pm_message_t state) | |||
2017 | return 0; | 2082 | return 0; |
2018 | } | 2083 | } |
2019 | 2084 | ||
2020 | static int lapic_resume(struct sys_device *dev) | 2085 | static void lapic_resume(void) |
2021 | { | 2086 | { |
2022 | unsigned int l, h; | 2087 | unsigned int l, h; |
2023 | unsigned long flags; | 2088 | unsigned long flags; |
2024 | int maxlvt; | 2089 | int maxlvt; |
2025 | int ret = 0; | ||
2026 | struct IO_APIC_route_entry **ioapic_entries = NULL; | ||
2027 | 2090 | ||
2028 | if (!apic_pm_state.active) | 2091 | if (!apic_pm_state.active) |
2029 | return 0; | 2092 | return; |
2030 | 2093 | ||
2031 | local_irq_save(flags); | 2094 | local_irq_save(flags); |
2032 | if (intr_remapping_enabled) { | 2095 | if (intr_remapping_enabled) { |
2033 | ioapic_entries = alloc_ioapic_entries(); | 2096 | /* |
2034 | if (!ioapic_entries) { | 2097 | * IO-APIC and PIC have their own resume routines. |
2035 | WARN(1, "Alloc ioapic_entries in lapic resume failed."); | 2098 | * We just mask them here to make sure the interrupt |
2036 | ret = -ENOMEM; | 2099 | * subsystem is completely quiet while we enable x2apic |
2037 | goto restore; | 2100 | * and interrupt-remapping. |
2038 | } | 2101 | */ |
2039 | 2102 | mask_ioapic_entries(); | |
2040 | ret = save_IO_APIC_setup(ioapic_entries); | ||
2041 | if (ret) { | ||
2042 | WARN(1, "Saving IO-APIC state failed: %d\n", ret); | ||
2043 | free_ioapic_entries(ioapic_entries); | ||
2044 | goto restore; | ||
2045 | } | ||
2046 | |||
2047 | mask_IO_APIC_setup(ioapic_entries); | ||
2048 | legacy_pic->mask_all(); | 2103 | legacy_pic->mask_all(); |
2049 | } | 2104 | } |
2050 | 2105 | ||
@@ -2087,16 +2142,10 @@ static int lapic_resume(struct sys_device *dev) | |||
2087 | apic_write(APIC_ESR, 0); | 2142 | apic_write(APIC_ESR, 0); |
2088 | apic_read(APIC_ESR); | 2143 | apic_read(APIC_ESR); |
2089 | 2144 | ||
2090 | if (intr_remapping_enabled) { | 2145 | if (intr_remapping_enabled) |
2091 | reenable_intr_remapping(x2apic_mode); | 2146 | reenable_intr_remapping(x2apic_mode); |
2092 | legacy_pic->restore_mask(); | ||
2093 | restore_IO_APIC_setup(ioapic_entries); | ||
2094 | free_ioapic_entries(ioapic_entries); | ||
2095 | } | ||
2096 | restore: | ||
2097 | local_irq_restore(flags); | ||
2098 | 2147 | ||
2099 | return ret; | 2148 | local_irq_restore(flags); |
2100 | } | 2149 | } |
2101 | 2150 | ||
2102 | /* | 2151 | /* |
@@ -2104,17 +2153,11 @@ restore: | |||
2104 | * are needed on every CPU up until machine_halt/restart/poweroff. | 2153 | * are needed on every CPU up until machine_halt/restart/poweroff. |
2105 | */ | 2154 | */ |
2106 | 2155 | ||
2107 | static struct sysdev_class lapic_sysclass = { | 2156 | static struct syscore_ops lapic_syscore_ops = { |
2108 | .name = "lapic", | ||
2109 | .resume = lapic_resume, | 2157 | .resume = lapic_resume, |
2110 | .suspend = lapic_suspend, | 2158 | .suspend = lapic_suspend, |
2111 | }; | 2159 | }; |
2112 | 2160 | ||
2113 | static struct sys_device device_lapic = { | ||
2114 | .id = 0, | ||
2115 | .cls = &lapic_sysclass, | ||
2116 | }; | ||
2117 | |||
2118 | static void __cpuinit apic_pm_activate(void) | 2161 | static void __cpuinit apic_pm_activate(void) |
2119 | { | 2162 | { |
2120 | apic_pm_state.active = 1; | 2163 | apic_pm_state.active = 1; |
@@ -2122,16 +2165,11 @@ static void __cpuinit apic_pm_activate(void) | |||
2122 | 2165 | ||
2123 | static int __init init_lapic_sysfs(void) | 2166 | static int __init init_lapic_sysfs(void) |
2124 | { | 2167 | { |
2125 | int error; | ||
2126 | |||
2127 | if (!cpu_has_apic) | ||
2128 | return 0; | ||
2129 | /* XXX: remove suspend/resume procs if !apic_pm_state.active? */ | 2168 | /* XXX: remove suspend/resume procs if !apic_pm_state.active? */ |
2169 | if (cpu_has_apic) | ||
2170 | register_syscore_ops(&lapic_syscore_ops); | ||
2130 | 2171 | ||
2131 | error = sysdev_class_register(&lapic_sysclass); | 2172 | return 0; |
2132 | if (!error) | ||
2133 | error = sysdev_register(&device_lapic); | ||
2134 | return error; | ||
2135 | } | 2173 | } |
2136 | 2174 | ||
2137 | /* local apic needs to resume before other devices access its registers. */ | 2175 | /* local apic needs to resume before other devices access its registers. */ |