aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/apic_32.c
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2008-07-18 17:00:05 -0400
committerIngo Molnar <mingo@elte.hu>2008-07-18 17:00:05 -0400
commit453c1404c5273a30d715e5a83372a78cff70b6d9 (patch)
tree94a5a3abd85137c4def416a84a45989751260f20 /arch/x86/kernel/apic_32.c
parenta208f37a465e222218974ab20a31b42b7b4893b2 (diff)
parent35b680557f95564f70f21a8d3f5c72e101fab260 (diff)
Merge branch 'x86/apic' into x86/x2apic
Conflicts: arch/x86/kernel/paravirt.c arch/x86/kernel/smpboot.c arch/x86/kernel/vmi_32.c arch/x86/lguest/boot.c arch/x86/xen/enlighten.c include/asm-x86/apic.h include/asm-x86/paravirt.h Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch/x86/kernel/apic_32.c')
-rw-r--r--arch/x86/kernel/apic_32.c170
1 files changed, 87 insertions, 83 deletions
diff --git a/arch/x86/kernel/apic_32.c b/arch/x86/kernel/apic_32.c
index 34101962fb0e..dcb897f22aa2 100644
--- a/arch/x86/kernel/apic_32.c
+++ b/arch/x86/kernel/apic_32.c
@@ -75,7 +75,7 @@ char system_vectors[NR_VECTORS] = { [0 ... NR_VECTORS-1] = SYS_VECTOR_FREE};
75/* 75/*
76 * Debug level, exported for io_apic.c 76 * Debug level, exported for io_apic.c
77 */ 77 */
78int apic_verbosity; 78unsigned int apic_verbosity;
79 79
80int pic_mode; 80int pic_mode;
81 81
@@ -211,7 +211,7 @@ void __cpuinit enable_NMI_through_LVT0(void)
211 /* Level triggered for 82489DX */ 211 /* Level triggered for 82489DX */
212 if (!lapic_is_integrated()) 212 if (!lapic_is_integrated())
213 v |= APIC_LVT_LEVEL_TRIGGER; 213 v |= APIC_LVT_LEVEL_TRIGGER;
214 apic_write_around(APIC_LVT0, v); 214 apic_write(APIC_LVT0, v);
215} 215}
216 216
217/** 217/**
@@ -246,9 +246,6 @@ int lapic_get_maxlvt(void)
246 * this function twice on the boot CPU, once with a bogus timeout 246 * this function twice on the boot CPU, once with a bogus timeout
247 * value, second time for real. The other (noncalibrating) CPUs 247 * value, second time for real. The other (noncalibrating) CPUs
248 * call this function only once, with the real, calibrated value. 248 * call this function only once, with the real, calibrated value.
249 *
250 * We do reads before writes even if unnecessary, to get around the
251 * P5 APIC double write bug.
252 */ 249 */
253static void __setup_APIC_LVTT(unsigned int clocks, int oneshot, int irqen) 250static void __setup_APIC_LVTT(unsigned int clocks, int oneshot, int irqen)
254{ 251{
@@ -263,18 +260,18 @@ static void __setup_APIC_LVTT(unsigned int clocks, int oneshot, int irqen)
263 if (!irqen) 260 if (!irqen)
264 lvtt_value |= APIC_LVT_MASKED; 261 lvtt_value |= APIC_LVT_MASKED;
265 262
266 apic_write_around(APIC_LVTT, lvtt_value); 263 apic_write(APIC_LVTT, lvtt_value);
267 264
268 /* 265 /*
269 * Divide PICLK by 16 266 * Divide PICLK by 16
270 */ 267 */
271 tmp_value = apic_read(APIC_TDCR); 268 tmp_value = apic_read(APIC_TDCR);
272 apic_write_around(APIC_TDCR, (tmp_value 269 apic_write(APIC_TDCR,
273 & ~(APIC_TDR_DIV_1 | APIC_TDR_DIV_TMBASE)) 270 (tmp_value & ~(APIC_TDR_DIV_1 | APIC_TDR_DIV_TMBASE)) |
274 | APIC_TDR_DIV_16); 271 APIC_TDR_DIV_16);
275 272
276 if (!oneshot) 273 if (!oneshot)
277 apic_write_around(APIC_TMICT, clocks/APIC_DIVISOR); 274 apic_write(APIC_TMICT, clocks / APIC_DIVISOR);
278} 275}
279 276
280/* 277/*
@@ -283,7 +280,7 @@ static void __setup_APIC_LVTT(unsigned int clocks, int oneshot, int irqen)
283static int lapic_next_event(unsigned long delta, 280static int lapic_next_event(unsigned long delta,
284 struct clock_event_device *evt) 281 struct clock_event_device *evt)
285{ 282{
286 apic_write_around(APIC_TMICT, delta); 283 apic_write(APIC_TMICT, delta);
287 return 0; 284 return 0;
288} 285}
289 286
@@ -312,7 +309,7 @@ static void lapic_timer_setup(enum clock_event_mode mode,
312 case CLOCK_EVT_MODE_SHUTDOWN: 309 case CLOCK_EVT_MODE_SHUTDOWN:
313 v = apic_read(APIC_LVTT); 310 v = apic_read(APIC_LVTT);
314 v |= (APIC_LVT_MASKED | LOCAL_TIMER_VECTOR); 311 v |= (APIC_LVT_MASKED | LOCAL_TIMER_VECTOR);
315 apic_write_around(APIC_LVTT, v); 312 apic_write(APIC_LVTT, v);
316 break; 313 break;
317 case CLOCK_EVT_MODE_RESUME: 314 case CLOCK_EVT_MODE_RESUME:
318 /* Nothing to do here */ 315 /* Nothing to do here */
@@ -406,12 +403,7 @@ static void __init lapic_cal_handler(struct clock_event_device *dev)
406 } 403 }
407} 404}
408 405
409/* 406static int __init calibrate_APIC_clock(void)
410 * Setup the boot APIC
411 *
412 * Calibrate and verify the result.
413 */
414void __init setup_boot_APIC_clock(void)
415{ 407{
416 struct clock_event_device *levt = &__get_cpu_var(lapic_events); 408 struct clock_event_device *levt = &__get_cpu_var(lapic_events);
417 const long pm_100ms = PMTMR_TICKS_PER_SEC/10; 409 const long pm_100ms = PMTMR_TICKS_PER_SEC/10;
@@ -421,24 +413,6 @@ void __init setup_boot_APIC_clock(void)
421 long delta, deltapm; 413 long delta, deltapm;
422 int pm_referenced = 0; 414 int pm_referenced = 0;
423 415
424 /*
425 * The local apic timer can be disabled via the kernel
426 * commandline or from the CPU detection code. Register the lapic
427 * timer as a dummy clock event source on SMP systems, so the
428 * broadcast mechanism is used. On UP systems simply ignore it.
429 */
430 if (local_apic_timer_disabled) {
431 /* No broadcast on UP ! */
432 if (num_possible_cpus() > 1) {
433 lapic_clockevent.mult = 1;
434 setup_APIC_timer();
435 }
436 return;
437 }
438
439 apic_printk(APIC_VERBOSE, "Using local APIC timer interrupts.\n"
440 "calibrating APIC timer ...\n");
441
442 local_irq_disable(); 416 local_irq_disable();
443 417
444 /* Replace the global interrupt handler */ 418 /* Replace the global interrupt handler */
@@ -523,8 +497,6 @@ void __init setup_boot_APIC_clock(void)
523 calibration_result / (1000000 / HZ), 497 calibration_result / (1000000 / HZ),
524 calibration_result % (1000000 / HZ)); 498 calibration_result % (1000000 / HZ));
525 499
526 local_apic_timer_verify_ok = 1;
527
528 /* 500 /*
529 * Do a sanity check on the APIC calibration result 501 * Do a sanity check on the APIC calibration result
530 */ 502 */
@@ -532,12 +504,11 @@ void __init setup_boot_APIC_clock(void)
532 local_irq_enable(); 504 local_irq_enable();
533 printk(KERN_WARNING 505 printk(KERN_WARNING
534 "APIC frequency too slow, disabling apic timer\n"); 506 "APIC frequency too slow, disabling apic timer\n");
535 /* No broadcast on UP ! */ 507 return -1;
536 if (num_possible_cpus() > 1)
537 setup_APIC_timer();
538 return;
539 } 508 }
540 509
510 local_apic_timer_verify_ok = 1;
511
541 /* We trust the pm timer based calibration */ 512 /* We trust the pm timer based calibration */
542 if (!pm_referenced) { 513 if (!pm_referenced) {
543 apic_printk(APIC_VERBOSE, "... verify APIC timer\n"); 514 apic_printk(APIC_VERBOSE, "... verify APIC timer\n");
@@ -577,22 +548,55 @@ void __init setup_boot_APIC_clock(void)
577 if (!local_apic_timer_verify_ok) { 548 if (!local_apic_timer_verify_ok) {
578 printk(KERN_WARNING 549 printk(KERN_WARNING
579 "APIC timer disabled due to verification failure.\n"); 550 "APIC timer disabled due to verification failure.\n");
551 return -1;
552 }
553
554 return 0;
555}
556
557/*
558 * Setup the boot APIC
559 *
560 * Calibrate and verify the result.
561 */
562void __init setup_boot_APIC_clock(void)
563{
564 /*
565 * The local apic timer can be disabled via the kernel
566 * commandline or from the CPU detection code. Register the lapic
567 * timer as a dummy clock event source on SMP systems, so the
568 * broadcast mechanism is used. On UP systems simply ignore it.
569 */
570 if (local_apic_timer_disabled) {
580 /* No broadcast on UP ! */ 571 /* No broadcast on UP ! */
581 if (num_possible_cpus() == 1) 572 if (num_possible_cpus() > 1) {
582 return; 573 lapic_clockevent.mult = 1;
583 } else { 574 setup_APIC_timer();
584 /* 575 }
585 * If nmi_watchdog is set to IO_APIC, we need the 576 return;
586 * PIT/HPET going. Otherwise register lapic as a dummy
587 * device.
588 */
589 if (nmi_watchdog != NMI_IO_APIC)
590 lapic_clockevent.features &= ~CLOCK_EVT_FEAT_DUMMY;
591 else
592 printk(KERN_WARNING "APIC timer registered as dummy,"
593 " due to nmi_watchdog=%d!\n", nmi_watchdog);
594 } 577 }
595 578
579 apic_printk(APIC_VERBOSE, "Using local APIC timer interrupts.\n"
580 "calibrating APIC timer ...\n");
581
582 if (calibrate_APIC_clock()) {
583 /* No broadcast on UP ! */
584 if (num_possible_cpus() > 1)
585 setup_APIC_timer();
586 return;
587 }
588
589 /*
590 * If nmi_watchdog is set to IO_APIC, we need the
591 * PIT/HPET going. Otherwise register lapic as a dummy
592 * device.
593 */
594 if (nmi_watchdog != NMI_IO_APIC)
595 lapic_clockevent.features &= ~CLOCK_EVT_FEAT_DUMMY;
596 else
597 printk(KERN_WARNING "APIC timer registered as dummy,"
598 " due to nmi_watchdog=%d!\n", nmi_watchdog);
599
596 /* Setup the lapic or request the broadcast */ 600 /* Setup the lapic or request the broadcast */
597 setup_APIC_timer(); 601 setup_APIC_timer();
598} 602}
@@ -727,44 +731,44 @@ void clear_local_APIC(void)
727 */ 731 */
728 if (maxlvt >= 3) { 732 if (maxlvt >= 3) {
729 v = ERROR_APIC_VECTOR; /* any non-zero vector will do */ 733 v = ERROR_APIC_VECTOR; /* any non-zero vector will do */
730 apic_write_around(APIC_LVTERR, v | APIC_LVT_MASKED); 734 apic_write(APIC_LVTERR, v | APIC_LVT_MASKED);
731 } 735 }
732 /* 736 /*
733 * Careful: we have to set masks only first to deassert 737 * Careful: we have to set masks only first to deassert
734 * any level-triggered sources. 738 * any level-triggered sources.
735 */ 739 */
736 v = apic_read(APIC_LVTT); 740 v = apic_read(APIC_LVTT);
737 apic_write_around(APIC_LVTT, v | APIC_LVT_MASKED); 741 apic_write(APIC_LVTT, v | APIC_LVT_MASKED);
738 v = apic_read(APIC_LVT0); 742 v = apic_read(APIC_LVT0);
739 apic_write_around(APIC_LVT0, v | APIC_LVT_MASKED); 743 apic_write(APIC_LVT0, v | APIC_LVT_MASKED);
740 v = apic_read(APIC_LVT1); 744 v = apic_read(APIC_LVT1);
741 apic_write_around(APIC_LVT1, v | APIC_LVT_MASKED); 745 apic_write(APIC_LVT1, v | APIC_LVT_MASKED);
742 if (maxlvt >= 4) { 746 if (maxlvt >= 4) {
743 v = apic_read(APIC_LVTPC); 747 v = apic_read(APIC_LVTPC);
744 apic_write_around(APIC_LVTPC, v | APIC_LVT_MASKED); 748 apic_write(APIC_LVTPC, v | APIC_LVT_MASKED);
745 } 749 }
746 750
747 /* lets not touch this if we didn't frob it */ 751 /* lets not touch this if we didn't frob it */
748#ifdef CONFIG_X86_MCE_P4THERMAL 752#ifdef CONFIG_X86_MCE_P4THERMAL
749 if (maxlvt >= 5) { 753 if (maxlvt >= 5) {
750 v = apic_read(APIC_LVTTHMR); 754 v = apic_read(APIC_LVTTHMR);
751 apic_write_around(APIC_LVTTHMR, v | APIC_LVT_MASKED); 755 apic_write(APIC_LVTTHMR, v | APIC_LVT_MASKED);
752 } 756 }
753#endif 757#endif
754 /* 758 /*
755 * Clean APIC state for other OSs: 759 * Clean APIC state for other OSs:
756 */ 760 */
757 apic_write_around(APIC_LVTT, APIC_LVT_MASKED); 761 apic_write(APIC_LVTT, APIC_LVT_MASKED);
758 apic_write_around(APIC_LVT0, APIC_LVT_MASKED); 762 apic_write(APIC_LVT0, APIC_LVT_MASKED);
759 apic_write_around(APIC_LVT1, APIC_LVT_MASKED); 763 apic_write(APIC_LVT1, APIC_LVT_MASKED);
760 if (maxlvt >= 3) 764 if (maxlvt >= 3)
761 apic_write_around(APIC_LVTERR, APIC_LVT_MASKED); 765 apic_write(APIC_LVTERR, APIC_LVT_MASKED);
762 if (maxlvt >= 4) 766 if (maxlvt >= 4)
763 apic_write_around(APIC_LVTPC, APIC_LVT_MASKED); 767 apic_write(APIC_LVTPC, APIC_LVT_MASKED);
764 768
765#ifdef CONFIG_X86_MCE_P4THERMAL 769#ifdef CONFIG_X86_MCE_P4THERMAL
766 if (maxlvt >= 5) 770 if (maxlvt >= 5)
767 apic_write_around(APIC_LVTTHMR, APIC_LVT_MASKED); 771 apic_write(APIC_LVTTHMR, APIC_LVT_MASKED);
768#endif 772#endif
769 /* Integrated APIC (!82489DX) ? */ 773 /* Integrated APIC (!82489DX) ? */
770 if (lapic_is_integrated()) { 774 if (lapic_is_integrated()) {
@@ -790,7 +794,7 @@ void disable_local_APIC(void)
790 */ 794 */
791 value = apic_read(APIC_SPIV); 795 value = apic_read(APIC_SPIV);
792 value &= ~APIC_SPIV_APIC_ENABLED; 796 value &= ~APIC_SPIV_APIC_ENABLED;
793 apic_write_around(APIC_SPIV, value); 797 apic_write(APIC_SPIV, value);
794 798
795 /* 799 /*
796 * When LAPIC was disabled by the BIOS and enabled by the kernel, 800 * When LAPIC was disabled by the BIOS and enabled by the kernel,
@@ -899,8 +903,8 @@ void __init sync_Arb_IDs(void)
899 apic_wait_icr_idle(); 903 apic_wait_icr_idle();
900 904
901 apic_printk(APIC_DEBUG, "Synchronizing Arb IDs.\n"); 905 apic_printk(APIC_DEBUG, "Synchronizing Arb IDs.\n");
902 apic_write_around(APIC_ICR, APIC_DEST_ALLINC | APIC_INT_LEVELTRIG 906 apic_write(APIC_ICR,
903 | APIC_DM_INIT); 907 APIC_DEST_ALLINC | APIC_INT_LEVELTRIG | APIC_DM_INIT);
904} 908}
905 909
906/* 910/*
@@ -936,16 +940,16 @@ void __init init_bsp_APIC(void)
936 else 940 else
937 value |= APIC_SPIV_FOCUS_DISABLED; 941 value |= APIC_SPIV_FOCUS_DISABLED;
938 value |= SPURIOUS_APIC_VECTOR; 942 value |= SPURIOUS_APIC_VECTOR;
939 apic_write_around(APIC_SPIV, value); 943 apic_write(APIC_SPIV, value);
940 944
941 /* 945 /*
942 * Set up the virtual wire mode. 946 * Set up the virtual wire mode.
943 */ 947 */
944 apic_write_around(APIC_LVT0, APIC_DM_EXTINT); 948 apic_write(APIC_LVT0, APIC_DM_EXTINT);
945 value = APIC_DM_NMI; 949 value = APIC_DM_NMI;
946 if (!lapic_is_integrated()) /* 82489DX */ 950 if (!lapic_is_integrated()) /* 82489DX */
947 value |= APIC_LVT_LEVEL_TRIGGER; 951 value |= APIC_LVT_LEVEL_TRIGGER;
948 apic_write_around(APIC_LVT1, value); 952 apic_write(APIC_LVT1, value);
949} 953}
950 954
951static void __cpuinit lapic_setup_esr(void) 955static void __cpuinit lapic_setup_esr(void)
@@ -960,7 +964,7 @@ static void __cpuinit lapic_setup_esr(void)
960 964
961 /* enables sending errors */ 965 /* enables sending errors */
962 value = ERROR_APIC_VECTOR; 966 value = ERROR_APIC_VECTOR;
963 apic_write_around(APIC_LVTERR, value); 967 apic_write(APIC_LVTERR, value);
964 /* 968 /*
965 * spec says clear errors after enabling vector. 969 * spec says clear errors after enabling vector.
966 */ 970 */
@@ -1023,7 +1027,7 @@ void __cpuinit setup_local_APIC(void)
1023 */ 1027 */
1024 value = apic_read(APIC_TASKPRI); 1028 value = apic_read(APIC_TASKPRI);
1025 value &= ~APIC_TPRI_MASK; 1029 value &= ~APIC_TPRI_MASK;
1026 apic_write_around(APIC_TASKPRI, value); 1030 apic_write(APIC_TASKPRI, value);
1027 1031
1028 /* 1032 /*
1029 * After a crash, we no longer service the interrupts and a pending 1033 * After a crash, we no longer service the interrupts and a pending
@@ -1081,7 +1085,7 @@ void __cpuinit setup_local_APIC(void)
1081 * Set spurious IRQ vector 1085 * Set spurious IRQ vector
1082 */ 1086 */
1083 value |= SPURIOUS_APIC_VECTOR; 1087 value |= SPURIOUS_APIC_VECTOR;
1084 apic_write_around(APIC_SPIV, value); 1088 apic_write(APIC_SPIV, value);
1085 1089
1086 /* 1090 /*
1087 * Set up LVT0, LVT1: 1091 * Set up LVT0, LVT1:
@@ -1103,7 +1107,7 @@ void __cpuinit setup_local_APIC(void)
1103 apic_printk(APIC_VERBOSE, "masked ExtINT on CPU#%d\n", 1107 apic_printk(APIC_VERBOSE, "masked ExtINT on CPU#%d\n",
1104 smp_processor_id()); 1108 smp_processor_id());
1105 } 1109 }
1106 apic_write_around(APIC_LVT0, value); 1110 apic_write(APIC_LVT0, value);
1107 1111
1108 /* 1112 /*
1109 * only the BP should see the LINT1 NMI signal, obviously. 1113 * only the BP should see the LINT1 NMI signal, obviously.
@@ -1114,7 +1118,7 @@ void __cpuinit setup_local_APIC(void)
1114 value = APIC_DM_NMI | APIC_LVT_MASKED; 1118 value = APIC_DM_NMI | APIC_LVT_MASKED;
1115 if (!integrated) /* 82489DX */ 1119 if (!integrated) /* 82489DX */
1116 value |= APIC_LVT_LEVEL_TRIGGER; 1120 value |= APIC_LVT_LEVEL_TRIGGER;
1117 apic_write_around(APIC_LVT1, value); 1121 apic_write(APIC_LVT1, value);
1118} 1122}
1119 1123
1120void __cpuinit end_local_APIC_setup(void) 1124void __cpuinit end_local_APIC_setup(void)
@@ -1125,7 +1129,7 @@ void __cpuinit end_local_APIC_setup(void)
1125 /* Disable the local apic timer */ 1129 /* Disable the local apic timer */
1126 value = apic_read(APIC_LVTT); 1130 value = apic_read(APIC_LVTT);
1127 value |= (APIC_LVT_MASKED | LOCAL_TIMER_VECTOR); 1131 value |= (APIC_LVT_MASKED | LOCAL_TIMER_VECTOR);
1128 apic_write_around(APIC_LVTT, value); 1132 apic_write(APIC_LVTT, value);
1129 1133
1130 setup_apic_nmi_watchdog(NULL); 1134 setup_apic_nmi_watchdog(NULL);
1131 apic_pm_activate(); 1135 apic_pm_activate();
@@ -1453,7 +1457,7 @@ void disconnect_bsp_APIC(int virt_wire_setup)
1453 value &= ~APIC_VECTOR_MASK; 1457 value &= ~APIC_VECTOR_MASK;
1454 value |= APIC_SPIV_APIC_ENABLED; 1458 value |= APIC_SPIV_APIC_ENABLED;
1455 value |= 0xf; 1459 value |= 0xf;
1456 apic_write_around(APIC_SPIV, value); 1460 apic_write(APIC_SPIV, value);
1457 1461
1458 if (!virt_wire_setup) { 1462 if (!virt_wire_setup) {
1459 /* 1463 /*
@@ -1466,10 +1470,10 @@ void disconnect_bsp_APIC(int virt_wire_setup)
1466 APIC_LVT_LEVEL_TRIGGER | APIC_LVT_MASKED); 1470 APIC_LVT_LEVEL_TRIGGER | APIC_LVT_MASKED);
1467 value |= APIC_LVT_REMOTE_IRR | APIC_SEND_PENDING; 1471 value |= APIC_LVT_REMOTE_IRR | APIC_SEND_PENDING;
1468 value = SET_APIC_DELIVERY_MODE(value, APIC_MODE_EXTINT); 1472 value = SET_APIC_DELIVERY_MODE(value, APIC_MODE_EXTINT);
1469 apic_write_around(APIC_LVT0, value); 1473 apic_write(APIC_LVT0, value);
1470 } else { 1474 } else {
1471 /* Disable LVT0 */ 1475 /* Disable LVT0 */
1472 apic_write_around(APIC_LVT0, APIC_LVT_MASKED); 1476 apic_write(APIC_LVT0, APIC_LVT_MASKED);
1473 } 1477 }
1474 1478
1475 /* 1479 /*
@@ -1483,7 +1487,7 @@ void disconnect_bsp_APIC(int virt_wire_setup)
1483 APIC_LVT_LEVEL_TRIGGER | APIC_LVT_MASKED); 1487 APIC_LVT_LEVEL_TRIGGER | APIC_LVT_MASKED);
1484 value |= APIC_LVT_REMOTE_IRR | APIC_SEND_PENDING; 1488 value |= APIC_LVT_REMOTE_IRR | APIC_SEND_PENDING;
1485 value = SET_APIC_DELIVERY_MODE(value, APIC_MODE_NMI); 1489 value = SET_APIC_DELIVERY_MODE(value, APIC_MODE_NMI);
1486 apic_write_around(APIC_LVT1, value); 1490 apic_write(APIC_LVT1, value);
1487 } 1491 }
1488} 1492}
1489 1493