aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/apic_32.c
diff options
context:
space:
mode:
authorMaciej W. Rozycki <macro@linux-mips.org>2008-07-16 14:15:30 -0400
committerIngo Molnar <mingo@elte.hu>2008-07-18 06:51:21 -0400
commit593f4a788e5d09e9f00182561437461b0b564de4 (patch)
treeaafdcb1b8553e1d3012bc81e809131482300d3f2 /arch/x86/kernel/apic_32.c
parent5b664cb235e97afbf34db9c4d77f08ebd725335e (diff)
x86: APIC: remove apic_write_around(); use alternatives
Use alternatives to select the workaround for the 11AP Pentium erratum for the affected steppings on the fly rather than build time. Remove the X86_GOOD_APIC configuration option and replace all the calls to apic_write_around() with plain apic_write(), protecting accesses to the ESR as appropriate due to the 3AP Pentium erratum. Remove apic_read_around() and all its invocations altogether as not needed. Remove apic_write_atomic() and all its implementing backends. The use of ASM_OUTPUT2() is not strictly needed for input constraints, but I have used it for readability's sake. I had the feeling no one else was brave enough to do it, so I went ahead and here it is. Verified by checking the generated assembly and tested with both a 32-bit and a 64-bit configuration, also with the 11AP "feature" forced on and verified with gdb on /proc/kcore to work as expected (as an 11AP machines are quite hard to get hands on these days). Some script complained about the use of "volatile", but apic_write() needs it for the same reason and is effectively a replacement for writel(), so I have disregarded it. I am not sure what the policy wrt defconfig files is, they are generated and there is risk of a conflict resulting from an unrelated change, so I have left changes to them out. The option will get removed from them at the next run. Some testing with machines other than mine will be needed to avoid some stupid mistake, but despite its volume, the change is not really that intrusive, so I am fairly confident that because it works for me, it will everywhere. Signed-off-by: Maciej W. Rozycki <macro@linux-mips.org> 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.c75
1 files changed, 36 insertions, 39 deletions
diff --git a/arch/x86/kernel/apic_32.c b/arch/x86/kernel/apic_32.c
index a437d027f20b..2bc1186cc95a 100644
--- a/arch/x86/kernel/apic_32.c
+++ b/arch/x86/kernel/apic_32.c
@@ -177,7 +177,7 @@ void __cpuinit enable_NMI_through_LVT0(void)
177 /* Level triggered for 82489DX */ 177 /* Level triggered for 82489DX */
178 if (!lapic_is_integrated()) 178 if (!lapic_is_integrated())
179 v |= APIC_LVT_LEVEL_TRIGGER; 179 v |= APIC_LVT_LEVEL_TRIGGER;
180 apic_write_around(APIC_LVT0, v); 180 apic_write(APIC_LVT0, v);
181} 181}
182 182
183/** 183/**
@@ -212,9 +212,6 @@ int lapic_get_maxlvt(void)
212 * this function twice on the boot CPU, once with a bogus timeout 212 * this function twice on the boot CPU, once with a bogus timeout
213 * value, second time for real. The other (noncalibrating) CPUs 213 * value, second time for real. The other (noncalibrating) CPUs
214 * call this function only once, with the real, calibrated value. 214 * call this function only once, with the real, calibrated value.
215 *
216 * We do reads before writes even if unnecessary, to get around the
217 * P5 APIC double write bug.
218 */ 215 */
219static void __setup_APIC_LVTT(unsigned int clocks, int oneshot, int irqen) 216static void __setup_APIC_LVTT(unsigned int clocks, int oneshot, int irqen)
220{ 217{
@@ -229,18 +226,18 @@ static void __setup_APIC_LVTT(unsigned int clocks, int oneshot, int irqen)
229 if (!irqen) 226 if (!irqen)
230 lvtt_value |= APIC_LVT_MASKED; 227 lvtt_value |= APIC_LVT_MASKED;
231 228
232 apic_write_around(APIC_LVTT, lvtt_value); 229 apic_write(APIC_LVTT, lvtt_value);
233 230
234 /* 231 /*
235 * Divide PICLK by 16 232 * Divide PICLK by 16
236 */ 233 */
237 tmp_value = apic_read(APIC_TDCR); 234 tmp_value = apic_read(APIC_TDCR);
238 apic_write_around(APIC_TDCR, (tmp_value 235 apic_write(APIC_TDCR,
239 & ~(APIC_TDR_DIV_1 | APIC_TDR_DIV_TMBASE)) 236 (tmp_value & ~(APIC_TDR_DIV_1 | APIC_TDR_DIV_TMBASE)) |
240 | APIC_TDR_DIV_16); 237 APIC_TDR_DIV_16);
241 238
242 if (!oneshot) 239 if (!oneshot)
243 apic_write_around(APIC_TMICT, clocks/APIC_DIVISOR); 240 apic_write(APIC_TMICT, clocks / APIC_DIVISOR);
244} 241}
245 242
246/* 243/*
@@ -249,7 +246,7 @@ static void __setup_APIC_LVTT(unsigned int clocks, int oneshot, int irqen)
249static int lapic_next_event(unsigned long delta, 246static int lapic_next_event(unsigned long delta,
250 struct clock_event_device *evt) 247 struct clock_event_device *evt)
251{ 248{
252 apic_write_around(APIC_TMICT, delta); 249 apic_write(APIC_TMICT, delta);
253 return 0; 250 return 0;
254} 251}
255 252
@@ -278,7 +275,7 @@ static void lapic_timer_setup(enum clock_event_mode mode,
278 case CLOCK_EVT_MODE_SHUTDOWN: 275 case CLOCK_EVT_MODE_SHUTDOWN:
279 v = apic_read(APIC_LVTT); 276 v = apic_read(APIC_LVTT);
280 v |= (APIC_LVT_MASKED | LOCAL_TIMER_VECTOR); 277 v |= (APIC_LVT_MASKED | LOCAL_TIMER_VECTOR);
281 apic_write_around(APIC_LVTT, v); 278 apic_write(APIC_LVTT, v);
282 break; 279 break;
283 case CLOCK_EVT_MODE_RESUME: 280 case CLOCK_EVT_MODE_RESUME:
284 /* Nothing to do here */ 281 /* Nothing to do here */
@@ -693,44 +690,44 @@ void clear_local_APIC(void)
693 */ 690 */
694 if (maxlvt >= 3) { 691 if (maxlvt >= 3) {
695 v = ERROR_APIC_VECTOR; /* any non-zero vector will do */ 692 v = ERROR_APIC_VECTOR; /* any non-zero vector will do */
696 apic_write_around(APIC_LVTERR, v | APIC_LVT_MASKED); 693 apic_write(APIC_LVTERR, v | APIC_LVT_MASKED);
697 } 694 }
698 /* 695 /*
699 * Careful: we have to set masks only first to deassert 696 * Careful: we have to set masks only first to deassert
700 * any level-triggered sources. 697 * any level-triggered sources.
701 */ 698 */
702 v = apic_read(APIC_LVTT); 699 v = apic_read(APIC_LVTT);
703 apic_write_around(APIC_LVTT, v | APIC_LVT_MASKED); 700 apic_write(APIC_LVTT, v | APIC_LVT_MASKED);
704 v = apic_read(APIC_LVT0); 701 v = apic_read(APIC_LVT0);
705 apic_write_around(APIC_LVT0, v | APIC_LVT_MASKED); 702 apic_write(APIC_LVT0, v | APIC_LVT_MASKED);
706 v = apic_read(APIC_LVT1); 703 v = apic_read(APIC_LVT1);
707 apic_write_around(APIC_LVT1, v | APIC_LVT_MASKED); 704 apic_write(APIC_LVT1, v | APIC_LVT_MASKED);
708 if (maxlvt >= 4) { 705 if (maxlvt >= 4) {
709 v = apic_read(APIC_LVTPC); 706 v = apic_read(APIC_LVTPC);
710 apic_write_around(APIC_LVTPC, v | APIC_LVT_MASKED); 707 apic_write(APIC_LVTPC, v | APIC_LVT_MASKED);
711 } 708 }
712 709
713 /* lets not touch this if we didn't frob it */ 710 /* lets not touch this if we didn't frob it */
714#ifdef CONFIG_X86_MCE_P4THERMAL 711#ifdef CONFIG_X86_MCE_P4THERMAL
715 if (maxlvt >= 5) { 712 if (maxlvt >= 5) {
716 v = apic_read(APIC_LVTTHMR); 713 v = apic_read(APIC_LVTTHMR);
717 apic_write_around(APIC_LVTTHMR, v | APIC_LVT_MASKED); 714 apic_write(APIC_LVTTHMR, v | APIC_LVT_MASKED);
718 } 715 }
719#endif 716#endif
720 /* 717 /*
721 * Clean APIC state for other OSs: 718 * Clean APIC state for other OSs:
722 */ 719 */
723 apic_write_around(APIC_LVTT, APIC_LVT_MASKED); 720 apic_write(APIC_LVTT, APIC_LVT_MASKED);
724 apic_write_around(APIC_LVT0, APIC_LVT_MASKED); 721 apic_write(APIC_LVT0, APIC_LVT_MASKED);
725 apic_write_around(APIC_LVT1, APIC_LVT_MASKED); 722 apic_write(APIC_LVT1, APIC_LVT_MASKED);
726 if (maxlvt >= 3) 723 if (maxlvt >= 3)
727 apic_write_around(APIC_LVTERR, APIC_LVT_MASKED); 724 apic_write(APIC_LVTERR, APIC_LVT_MASKED);
728 if (maxlvt >= 4) 725 if (maxlvt >= 4)
729 apic_write_around(APIC_LVTPC, APIC_LVT_MASKED); 726 apic_write(APIC_LVTPC, APIC_LVT_MASKED);
730 727
731#ifdef CONFIG_X86_MCE_P4THERMAL 728#ifdef CONFIG_X86_MCE_P4THERMAL
732 if (maxlvt >= 5) 729 if (maxlvt >= 5)
733 apic_write_around(APIC_LVTTHMR, APIC_LVT_MASKED); 730 apic_write(APIC_LVTTHMR, APIC_LVT_MASKED);
734#endif 731#endif
735 /* Integrated APIC (!82489DX) ? */ 732 /* Integrated APIC (!82489DX) ? */
736 if (lapic_is_integrated()) { 733 if (lapic_is_integrated()) {
@@ -756,7 +753,7 @@ void disable_local_APIC(void)
756 */ 753 */
757 value = apic_read(APIC_SPIV); 754 value = apic_read(APIC_SPIV);
758 value &= ~APIC_SPIV_APIC_ENABLED; 755 value &= ~APIC_SPIV_APIC_ENABLED;
759 apic_write_around(APIC_SPIV, value); 756 apic_write(APIC_SPIV, value);
760 757
761 /* 758 /*
762 * When LAPIC was disabled by the BIOS and enabled by the kernel, 759 * When LAPIC was disabled by the BIOS and enabled by the kernel,
@@ -865,8 +862,8 @@ void __init sync_Arb_IDs(void)
865 apic_wait_icr_idle(); 862 apic_wait_icr_idle();
866 863
867 apic_printk(APIC_DEBUG, "Synchronizing Arb IDs.\n"); 864 apic_printk(APIC_DEBUG, "Synchronizing Arb IDs.\n");
868 apic_write_around(APIC_ICR, APIC_DEST_ALLINC | APIC_INT_LEVELTRIG 865 apic_write(APIC_ICR,
869 | APIC_DM_INIT); 866 APIC_DEST_ALLINC | APIC_INT_LEVELTRIG | APIC_DM_INIT);
870} 867}
871 868
872/* 869/*
@@ -902,16 +899,16 @@ void __init init_bsp_APIC(void)
902 else 899 else
903 value |= APIC_SPIV_FOCUS_DISABLED; 900 value |= APIC_SPIV_FOCUS_DISABLED;
904 value |= SPURIOUS_APIC_VECTOR; 901 value |= SPURIOUS_APIC_VECTOR;
905 apic_write_around(APIC_SPIV, value); 902 apic_write(APIC_SPIV, value);
906 903
907 /* 904 /*
908 * Set up the virtual wire mode. 905 * Set up the virtual wire mode.
909 */ 906 */
910 apic_write_around(APIC_LVT0, APIC_DM_EXTINT); 907 apic_write(APIC_LVT0, APIC_DM_EXTINT);
911 value = APIC_DM_NMI; 908 value = APIC_DM_NMI;
912 if (!lapic_is_integrated()) /* 82489DX */ 909 if (!lapic_is_integrated()) /* 82489DX */
913 value |= APIC_LVT_LEVEL_TRIGGER; 910 value |= APIC_LVT_LEVEL_TRIGGER;
914 apic_write_around(APIC_LVT1, value); 911 apic_write(APIC_LVT1, value);
915} 912}
916 913
917static void __cpuinit lapic_setup_esr(void) 914static void __cpuinit lapic_setup_esr(void)
@@ -926,7 +923,7 @@ static void __cpuinit lapic_setup_esr(void)
926 923
927 /* enables sending errors */ 924 /* enables sending errors */
928 value = ERROR_APIC_VECTOR; 925 value = ERROR_APIC_VECTOR;
929 apic_write_around(APIC_LVTERR, value); 926 apic_write(APIC_LVTERR, value);
930 /* 927 /*
931 * spec says clear errors after enabling vector. 928 * spec says clear errors after enabling vector.
932 */ 929 */
@@ -989,7 +986,7 @@ void __cpuinit setup_local_APIC(void)
989 */ 986 */
990 value = apic_read(APIC_TASKPRI); 987 value = apic_read(APIC_TASKPRI);
991 value &= ~APIC_TPRI_MASK; 988 value &= ~APIC_TPRI_MASK;
992 apic_write_around(APIC_TASKPRI, value); 989 apic_write(APIC_TASKPRI, value);
993 990
994 /* 991 /*
995 * After a crash, we no longer service the interrupts and a pending 992 * After a crash, we no longer service the interrupts and a pending
@@ -1047,7 +1044,7 @@ void __cpuinit setup_local_APIC(void)
1047 * Set spurious IRQ vector 1044 * Set spurious IRQ vector
1048 */ 1045 */
1049 value |= SPURIOUS_APIC_VECTOR; 1046 value |= SPURIOUS_APIC_VECTOR;
1050 apic_write_around(APIC_SPIV, value); 1047 apic_write(APIC_SPIV, value);
1051 1048
1052 /* 1049 /*
1053 * Set up LVT0, LVT1: 1050 * Set up LVT0, LVT1:
@@ -1069,7 +1066,7 @@ void __cpuinit setup_local_APIC(void)
1069 apic_printk(APIC_VERBOSE, "masked ExtINT on CPU#%d\n", 1066 apic_printk(APIC_VERBOSE, "masked ExtINT on CPU#%d\n",
1070 smp_processor_id()); 1067 smp_processor_id());
1071 } 1068 }
1072 apic_write_around(APIC_LVT0, value); 1069 apic_write(APIC_LVT0, value);
1073 1070
1074 /* 1071 /*
1075 * only the BP should see the LINT1 NMI signal, obviously. 1072 * only the BP should see the LINT1 NMI signal, obviously.
@@ -1080,7 +1077,7 @@ void __cpuinit setup_local_APIC(void)
1080 value = APIC_DM_NMI | APIC_LVT_MASKED; 1077 value = APIC_DM_NMI | APIC_LVT_MASKED;
1081 if (!integrated) /* 82489DX */ 1078 if (!integrated) /* 82489DX */
1082 value |= APIC_LVT_LEVEL_TRIGGER; 1079 value |= APIC_LVT_LEVEL_TRIGGER;
1083 apic_write_around(APIC_LVT1, value); 1080 apic_write(APIC_LVT1, value);
1084} 1081}
1085 1082
1086void __cpuinit end_local_APIC_setup(void) 1083void __cpuinit end_local_APIC_setup(void)
@@ -1091,7 +1088,7 @@ void __cpuinit end_local_APIC_setup(void)
1091 /* Disable the local apic timer */ 1088 /* Disable the local apic timer */
1092 value = apic_read(APIC_LVTT); 1089 value = apic_read(APIC_LVTT);
1093 value |= (APIC_LVT_MASKED | LOCAL_TIMER_VECTOR); 1090 value |= (APIC_LVT_MASKED | LOCAL_TIMER_VECTOR);
1094 apic_write_around(APIC_LVTT, value); 1091 apic_write(APIC_LVTT, value);
1095 1092
1096 setup_apic_nmi_watchdog(NULL); 1093 setup_apic_nmi_watchdog(NULL);
1097 apic_pm_activate(); 1094 apic_pm_activate();
@@ -1419,7 +1416,7 @@ void disconnect_bsp_APIC(int virt_wire_setup)
1419 value &= ~APIC_VECTOR_MASK; 1416 value &= ~APIC_VECTOR_MASK;
1420 value |= APIC_SPIV_APIC_ENABLED; 1417 value |= APIC_SPIV_APIC_ENABLED;
1421 value |= 0xf; 1418 value |= 0xf;
1422 apic_write_around(APIC_SPIV, value); 1419 apic_write(APIC_SPIV, value);
1423 1420
1424 if (!virt_wire_setup) { 1421 if (!virt_wire_setup) {
1425 /* 1422 /*
@@ -1432,10 +1429,10 @@ void disconnect_bsp_APIC(int virt_wire_setup)
1432 APIC_LVT_LEVEL_TRIGGER | APIC_LVT_MASKED); 1429 APIC_LVT_LEVEL_TRIGGER | APIC_LVT_MASKED);
1433 value |= APIC_LVT_REMOTE_IRR | APIC_SEND_PENDING; 1430 value |= APIC_LVT_REMOTE_IRR | APIC_SEND_PENDING;
1434 value = SET_APIC_DELIVERY_MODE(value, APIC_MODE_EXTINT); 1431 value = SET_APIC_DELIVERY_MODE(value, APIC_MODE_EXTINT);
1435 apic_write_around(APIC_LVT0, value); 1432 apic_write(APIC_LVT0, value);
1436 } else { 1433 } else {
1437 /* Disable LVT0 */ 1434 /* Disable LVT0 */
1438 apic_write_around(APIC_LVT0, APIC_LVT_MASKED); 1435 apic_write(APIC_LVT0, APIC_LVT_MASKED);
1439 } 1436 }
1440 1437
1441 /* 1438 /*
@@ -1449,7 +1446,7 @@ void disconnect_bsp_APIC(int virt_wire_setup)
1449 APIC_LVT_LEVEL_TRIGGER | APIC_LVT_MASKED); 1446 APIC_LVT_LEVEL_TRIGGER | APIC_LVT_MASKED);
1450 value |= APIC_LVT_REMOTE_IRR | APIC_SEND_PENDING; 1447 value |= APIC_LVT_REMOTE_IRR | APIC_SEND_PENDING;
1451 value = SET_APIC_DELIVERY_MODE(value, APIC_MODE_NMI); 1448 value = SET_APIC_DELIVERY_MODE(value, APIC_MODE_NMI);
1452 apic_write_around(APIC_LVT1, value); 1449 apic_write(APIC_LVT1, value);
1453 } 1450 }
1454} 1451}
1455 1452