diff options
Diffstat (limited to 'arch/x86/kernel/apic_32.c')
-rw-r--r-- | arch/x86/kernel/apic_32.c | 441 |
1 files changed, 257 insertions, 184 deletions
diff --git a/arch/x86/kernel/apic_32.c b/arch/x86/kernel/apic_32.c index f88bd0d982b0..21c831d96af3 100644 --- a/arch/x86/kernel/apic_32.c +++ b/arch/x86/kernel/apic_32.c | |||
@@ -60,10 +60,8 @@ unsigned long mp_lapic_addr; | |||
60 | static int force_enable_local_apic; | 60 | static int force_enable_local_apic; |
61 | int disable_apic; | 61 | int disable_apic; |
62 | 62 | ||
63 | /* Local APIC timer verification ok */ | ||
64 | static int local_apic_timer_verify_ok; | ||
65 | /* Disable local APIC timer from the kernel commandline or via dmi quirk */ | 63 | /* Disable local APIC timer from the kernel commandline or via dmi quirk */ |
66 | static int local_apic_timer_disabled; | 64 | static int disable_apic_timer __cpuinitdata; |
67 | /* Local APIC timer works in C2 */ | 65 | /* Local APIC timer works in C2 */ |
68 | int local_apic_timer_c2_ok; | 66 | int local_apic_timer_c2_ok; |
69 | EXPORT_SYMBOL_GPL(local_apic_timer_c2_ok); | 67 | EXPORT_SYMBOL_GPL(local_apic_timer_c2_ok); |
@@ -130,7 +128,11 @@ static inline int lapic_get_version(void) | |||
130 | */ | 128 | */ |
131 | static inline int lapic_is_integrated(void) | 129 | static inline int lapic_is_integrated(void) |
132 | { | 130 | { |
131 | #ifdef CONFIG_X86_64 | ||
132 | return 1; | ||
133 | #else | ||
133 | return APIC_INTEGRATED(lapic_get_version()); | 134 | return APIC_INTEGRATED(lapic_get_version()); |
135 | #endif | ||
134 | } | 136 | } |
135 | 137 | ||
136 | /* | 138 | /* |
@@ -145,13 +147,18 @@ static int modern_apic(void) | |||
145 | return lapic_get_version() >= 0x14; | 147 | return lapic_get_version() >= 0x14; |
146 | } | 148 | } |
147 | 149 | ||
148 | void apic_wait_icr_idle(void) | 150 | /* |
151 | * Paravirt kernels also might be using these below ops. So we still | ||
152 | * use generic apic_read()/apic_write(), which might be pointing to different | ||
153 | * ops in PARAVIRT case. | ||
154 | */ | ||
155 | void xapic_wait_icr_idle(void) | ||
149 | { | 156 | { |
150 | while (apic_read(APIC_ICR) & APIC_ICR_BUSY) | 157 | while (apic_read(APIC_ICR) & APIC_ICR_BUSY) |
151 | cpu_relax(); | 158 | cpu_relax(); |
152 | } | 159 | } |
153 | 160 | ||
154 | u32 safe_apic_wait_icr_idle(void) | 161 | u32 safe_xapic_wait_icr_idle(void) |
155 | { | 162 | { |
156 | u32 send_status; | 163 | u32 send_status; |
157 | int timeout; | 164 | int timeout; |
@@ -167,16 +174,48 @@ u32 safe_apic_wait_icr_idle(void) | |||
167 | return send_status; | 174 | return send_status; |
168 | } | 175 | } |
169 | 176 | ||
177 | void xapic_icr_write(u32 low, u32 id) | ||
178 | { | ||
179 | apic_write(APIC_ICR2, SET_APIC_DEST_FIELD(id)); | ||
180 | apic_write(APIC_ICR, low); | ||
181 | } | ||
182 | |||
183 | u64 xapic_icr_read(void) | ||
184 | { | ||
185 | u32 icr1, icr2; | ||
186 | |||
187 | icr2 = apic_read(APIC_ICR2); | ||
188 | icr1 = apic_read(APIC_ICR); | ||
189 | |||
190 | return icr1 | ((u64)icr2 << 32); | ||
191 | } | ||
192 | |||
193 | static struct apic_ops xapic_ops = { | ||
194 | .read = native_apic_mem_read, | ||
195 | .write = native_apic_mem_write, | ||
196 | .icr_read = xapic_icr_read, | ||
197 | .icr_write = xapic_icr_write, | ||
198 | .wait_icr_idle = xapic_wait_icr_idle, | ||
199 | .safe_wait_icr_idle = safe_xapic_wait_icr_idle, | ||
200 | }; | ||
201 | |||
202 | struct apic_ops __read_mostly *apic_ops = &xapic_ops; | ||
203 | EXPORT_SYMBOL_GPL(apic_ops); | ||
204 | |||
170 | /** | 205 | /** |
171 | * enable_NMI_through_LVT0 - enable NMI through local vector table 0 | 206 | * enable_NMI_through_LVT0 - enable NMI through local vector table 0 |
172 | */ | 207 | */ |
173 | void __cpuinit enable_NMI_through_LVT0(void) | 208 | void __cpuinit enable_NMI_through_LVT0(void) |
174 | { | 209 | { |
175 | unsigned int v = APIC_DM_NMI; | 210 | unsigned int v; |
176 | 211 | ||
177 | /* Level triggered for 82489DX */ | 212 | /* unmask and set to NMI */ |
213 | v = APIC_DM_NMI; | ||
214 | |||
215 | /* Level triggered for 82489DX (32bit mode) */ | ||
178 | if (!lapic_is_integrated()) | 216 | if (!lapic_is_integrated()) |
179 | v |= APIC_LVT_LEVEL_TRIGGER; | 217 | v |= APIC_LVT_LEVEL_TRIGGER; |
218 | |||
180 | apic_write(APIC_LVT0, v); | 219 | apic_write(APIC_LVT0, v); |
181 | } | 220 | } |
182 | 221 | ||
@@ -193,9 +232,13 @@ int get_physical_broadcast(void) | |||
193 | */ | 232 | */ |
194 | int lapic_get_maxlvt(void) | 233 | int lapic_get_maxlvt(void) |
195 | { | 234 | { |
196 | unsigned int v = apic_read(APIC_LVR); | 235 | unsigned int v; |
197 | 236 | ||
198 | /* 82489DXs do not report # of LVT entries. */ | 237 | v = apic_read(APIC_LVR); |
238 | /* | ||
239 | * - we always have APIC integrated on 64bit mode | ||
240 | * - 82489DXs do not report # of LVT entries | ||
241 | */ | ||
199 | return APIC_INTEGRATED(GET_APIC_VERSION(v)) ? GET_APIC_MAXLVT(v) : 2; | 242 | return APIC_INTEGRATED(GET_APIC_VERSION(v)) ? GET_APIC_MAXLVT(v) : 2; |
200 | } | 243 | } |
201 | 244 | ||
@@ -203,8 +246,12 @@ int lapic_get_maxlvt(void) | |||
203 | * Local APIC timer | 246 | * Local APIC timer |
204 | */ | 247 | */ |
205 | 248 | ||
206 | /* Clock divisor is set to 16 */ | 249 | /* Clock divisor */ |
250 | #ifdef CONFG_X86_64 | ||
251 | #define APIC_DIVISOR 1 | ||
252 | #else | ||
207 | #define APIC_DIVISOR 16 | 253 | #define APIC_DIVISOR 16 |
254 | #endif | ||
208 | 255 | ||
209 | /* | 256 | /* |
210 | * This function sets up the local APIC timer, with a timeout of | 257 | * This function sets up the local APIC timer, with a timeout of |
@@ -212,6 +259,9 @@ int lapic_get_maxlvt(void) | |||
212 | * this function twice on the boot CPU, once with a bogus timeout | 259 | * this function twice on the boot CPU, once with a bogus timeout |
213 | * value, second time for real. The other (noncalibrating) CPUs | 260 | * value, second time for real. The other (noncalibrating) CPUs |
214 | * call this function only once, with the real, calibrated value. | 261 | * call this function only once, with the real, calibrated value. |
262 | * | ||
263 | * We do reads before writes even if unnecessary, to get around the | ||
264 | * P5 APIC double write bug. | ||
215 | */ | 265 | */ |
216 | static void __setup_APIC_LVTT(unsigned int clocks, int oneshot, int irqen) | 266 | static void __setup_APIC_LVTT(unsigned int clocks, int oneshot, int irqen) |
217 | { | 267 | { |
@@ -233,14 +283,48 @@ static void __setup_APIC_LVTT(unsigned int clocks, int oneshot, int irqen) | |||
233 | */ | 283 | */ |
234 | tmp_value = apic_read(APIC_TDCR); | 284 | tmp_value = apic_read(APIC_TDCR); |
235 | apic_write(APIC_TDCR, | 285 | apic_write(APIC_TDCR, |
236 | (tmp_value & ~(APIC_TDR_DIV_1 | APIC_TDR_DIV_TMBASE)) | | 286 | (tmp_value & ~(APIC_TDR_DIV_1 | APIC_TDR_DIV_TMBASE)) | |
237 | APIC_TDR_DIV_16); | 287 | APIC_TDR_DIV_16); |
238 | 288 | ||
239 | if (!oneshot) | 289 | if (!oneshot) |
240 | apic_write(APIC_TMICT, clocks / APIC_DIVISOR); | 290 | apic_write(APIC_TMICT, clocks / APIC_DIVISOR); |
241 | } | 291 | } |
242 | 292 | ||
243 | /* | 293 | /* |
294 | * Setup extended LVT, AMD specific (K8, family 10h) | ||
295 | * | ||
296 | * Vector mappings are hard coded. On K8 only offset 0 (APIC500) and | ||
297 | * MCE interrupts are supported. Thus MCE offset must be set to 0. | ||
298 | * | ||
299 | * If mask=1, the LVT entry does not generate interrupts while mask=0 | ||
300 | * enables the vector. See also the BKDGs. | ||
301 | */ | ||
302 | |||
303 | #define APIC_EILVT_LVTOFF_MCE 0 | ||
304 | #define APIC_EILVT_LVTOFF_IBS 1 | ||
305 | |||
306 | static void setup_APIC_eilvt(u8 lvt_off, u8 vector, u8 msg_type, u8 mask) | ||
307 | { | ||
308 | unsigned long reg = (lvt_off << 4) + APIC_EILVT0; | ||
309 | unsigned int v = (mask << 16) | (msg_type << 8) | vector; | ||
310 | |||
311 | apic_write(reg, v); | ||
312 | } | ||
313 | |||
314 | u8 setup_APIC_eilvt_mce(u8 vector, u8 msg_type, u8 mask) | ||
315 | { | ||
316 | setup_APIC_eilvt(APIC_EILVT_LVTOFF_MCE, vector, msg_type, mask); | ||
317 | return APIC_EILVT_LVTOFF_MCE; | ||
318 | } | ||
319 | |||
320 | u8 setup_APIC_eilvt_ibs(u8 vector, u8 msg_type, u8 mask) | ||
321 | { | ||
322 | setup_APIC_eilvt(APIC_EILVT_LVTOFF_IBS, vector, msg_type, mask); | ||
323 | return APIC_EILVT_LVTOFF_IBS; | ||
324 | } | ||
325 | EXPORT_SYMBOL_GPL(setup_APIC_eilvt_ibs); | ||
326 | |||
327 | /* | ||
244 | * Program the next event, relative to now | 328 | * Program the next event, relative to now |
245 | */ | 329 | */ |
246 | static int lapic_next_event(unsigned long delta, | 330 | static int lapic_next_event(unsigned long delta, |
@@ -259,8 +343,8 @@ static void lapic_timer_setup(enum clock_event_mode mode, | |||
259 | unsigned long flags; | 343 | unsigned long flags; |
260 | unsigned int v; | 344 | unsigned int v; |
261 | 345 | ||
262 | /* Lapic used for broadcast ? */ | 346 | /* Lapic used as dummy for broadcast ? */ |
263 | if (!local_apic_timer_verify_ok) | 347 | if (evt->features & CLOCK_EVT_FEAT_DUMMY) |
264 | return; | 348 | return; |
265 | 349 | ||
266 | local_irq_save(flags); | 350 | local_irq_save(flags); |
@@ -473,7 +557,7 @@ static int __init calibrate_APIC_clock(void) | |||
473 | return -1; | 557 | return -1; |
474 | } | 558 | } |
475 | 559 | ||
476 | local_apic_timer_verify_ok = 1; | 560 | levt->features &= ~CLOCK_EVT_FEAT_DUMMY; |
477 | 561 | ||
478 | /* We trust the pm timer based calibration */ | 562 | /* We trust the pm timer based calibration */ |
479 | if (!pm_referenced) { | 563 | if (!pm_referenced) { |
@@ -507,11 +591,11 @@ static int __init calibrate_APIC_clock(void) | |||
507 | if (deltaj >= LAPIC_CAL_LOOPS-2 && deltaj <= LAPIC_CAL_LOOPS+2) | 591 | if (deltaj >= LAPIC_CAL_LOOPS-2 && deltaj <= LAPIC_CAL_LOOPS+2) |
508 | apic_printk(APIC_VERBOSE, "... jiffies result ok\n"); | 592 | apic_printk(APIC_VERBOSE, "... jiffies result ok\n"); |
509 | else | 593 | else |
510 | local_apic_timer_verify_ok = 0; | 594 | levt->features |= CLOCK_EVT_FEAT_DUMMY; |
511 | } else | 595 | } else |
512 | local_irq_enable(); | 596 | local_irq_enable(); |
513 | 597 | ||
514 | if (!local_apic_timer_verify_ok) { | 598 | if (levt->features & CLOCK_EVT_FEAT_DUMMY) { |
515 | printk(KERN_WARNING | 599 | printk(KERN_WARNING |
516 | "APIC timer disabled due to verification failure.\n"); | 600 | "APIC timer disabled due to verification failure.\n"); |
517 | return -1; | 601 | return -1; |
@@ -533,7 +617,8 @@ void __init setup_boot_APIC_clock(void) | |||
533 | * timer as a dummy clock event source on SMP systems, so the | 617 | * timer as a dummy clock event source on SMP systems, so the |
534 | * broadcast mechanism is used. On UP systems simply ignore it. | 618 | * broadcast mechanism is used. On UP systems simply ignore it. |
535 | */ | 619 | */ |
536 | if (local_apic_timer_disabled) { | 620 | if (disable_apic_timer) { |
621 | printk(KERN_INFO "Disabling APIC timer\n"); | ||
537 | /* No broadcast on UP ! */ | 622 | /* No broadcast on UP ! */ |
538 | if (num_possible_cpus() > 1) { | 623 | if (num_possible_cpus() > 1) { |
539 | lapic_clockevent.mult = 1; | 624 | lapic_clockevent.mult = 1; |
@@ -602,7 +687,11 @@ static void local_apic_timer_interrupt(void) | |||
602 | /* | 687 | /* |
603 | * the NMI deadlock-detector uses this. | 688 | * the NMI deadlock-detector uses this. |
604 | */ | 689 | */ |
690 | #ifdef CONFIG_X86_64 | ||
691 | add_pda(apic_timer_irqs, 1); | ||
692 | #else | ||
605 | per_cpu(irq_stat, cpu).apic_timer_irqs++; | 693 | per_cpu(irq_stat, cpu).apic_timer_irqs++; |
694 | #endif | ||
606 | 695 | ||
607 | evt->event_handler(evt); | 696 | evt->event_handler(evt); |
608 | } | 697 | } |
@@ -642,35 +731,6 @@ int setup_profiling_timer(unsigned int multiplier) | |||
642 | } | 731 | } |
643 | 732 | ||
644 | /* | 733 | /* |
645 | * Setup extended LVT, AMD specific (K8, family 10h) | ||
646 | * | ||
647 | * Vector mappings are hard coded. On K8 only offset 0 (APIC500) and | ||
648 | * MCE interrupts are supported. Thus MCE offset must be set to 0. | ||
649 | */ | ||
650 | |||
651 | #define APIC_EILVT_LVTOFF_MCE 0 | ||
652 | #define APIC_EILVT_LVTOFF_IBS 1 | ||
653 | |||
654 | static void setup_APIC_eilvt(u8 lvt_off, u8 vector, u8 msg_type, u8 mask) | ||
655 | { | ||
656 | unsigned long reg = (lvt_off << 4) + APIC_EILVT0; | ||
657 | unsigned int v = (mask << 16) | (msg_type << 8) | vector; | ||
658 | apic_write(reg, v); | ||
659 | } | ||
660 | |||
661 | u8 setup_APIC_eilvt_mce(u8 vector, u8 msg_type, u8 mask) | ||
662 | { | ||
663 | setup_APIC_eilvt(APIC_EILVT_LVTOFF_MCE, vector, msg_type, mask); | ||
664 | return APIC_EILVT_LVTOFF_MCE; | ||
665 | } | ||
666 | |||
667 | u8 setup_APIC_eilvt_ibs(u8 vector, u8 msg_type, u8 mask) | ||
668 | { | ||
669 | setup_APIC_eilvt(APIC_EILVT_LVTOFF_IBS, vector, msg_type, mask); | ||
670 | return APIC_EILVT_LVTOFF_IBS; | ||
671 | } | ||
672 | |||
673 | /* | ||
674 | * Local APIC start and shutdown | 734 | * Local APIC start and shutdown |
675 | */ | 735 | */ |
676 | 736 | ||
@@ -715,7 +775,7 @@ void clear_local_APIC(void) | |||
715 | } | 775 | } |
716 | 776 | ||
717 | /* lets not touch this if we didn't frob it */ | 777 | /* lets not touch this if we didn't frob it */ |
718 | #ifdef CONFIG_X86_MCE_P4THERMAL | 778 | #if defined(CONFIG_X86_MCE_P4THERMAL) || defined(X86_MCE_INTEL) |
719 | if (maxlvt >= 5) { | 779 | if (maxlvt >= 5) { |
720 | v = apic_read(APIC_LVTTHMR); | 780 | v = apic_read(APIC_LVTTHMR); |
721 | apic_write(APIC_LVTTHMR, v | APIC_LVT_MASKED); | 781 | apic_write(APIC_LVTTHMR, v | APIC_LVT_MASKED); |
@@ -732,10 +792,6 @@ void clear_local_APIC(void) | |||
732 | if (maxlvt >= 4) | 792 | if (maxlvt >= 4) |
733 | apic_write(APIC_LVTPC, APIC_LVT_MASKED); | 793 | apic_write(APIC_LVTPC, APIC_LVT_MASKED); |
734 | 794 | ||
735 | #ifdef CONFIG_X86_MCE_P4THERMAL | ||
736 | if (maxlvt >= 5) | ||
737 | apic_write(APIC_LVTTHMR, APIC_LVT_MASKED); | ||
738 | #endif | ||
739 | /* Integrated APIC (!82489DX) ? */ | 795 | /* Integrated APIC (!82489DX) ? */ |
740 | if (lapic_is_integrated()) { | 796 | if (lapic_is_integrated()) { |
741 | if (maxlvt > 3) | 797 | if (maxlvt > 3) |
@@ -750,7 +806,7 @@ void clear_local_APIC(void) | |||
750 | */ | 806 | */ |
751 | void disable_local_APIC(void) | 807 | void disable_local_APIC(void) |
752 | { | 808 | { |
753 | unsigned long value; | 809 | unsigned int value; |
754 | 810 | ||
755 | clear_local_APIC(); | 811 | clear_local_APIC(); |
756 | 812 | ||
@@ -762,6 +818,7 @@ void disable_local_APIC(void) | |||
762 | value &= ~APIC_SPIV_APIC_ENABLED; | 818 | value &= ~APIC_SPIV_APIC_ENABLED; |
763 | apic_write(APIC_SPIV, value); | 819 | apic_write(APIC_SPIV, value); |
764 | 820 | ||
821 | #ifdef CONFIG_X86_32 | ||
765 | /* | 822 | /* |
766 | * When LAPIC was disabled by the BIOS and enabled by the kernel, | 823 | * When LAPIC was disabled by the BIOS and enabled by the kernel, |
767 | * restore the disabled state. | 824 | * restore the disabled state. |
@@ -773,6 +830,7 @@ void disable_local_APIC(void) | |||
773 | l &= ~MSR_IA32_APICBASE_ENABLE; | 830 | l &= ~MSR_IA32_APICBASE_ENABLE; |
774 | wrmsr(MSR_IA32_APICBASE, l, h); | 831 | wrmsr(MSR_IA32_APICBASE, l, h); |
775 | } | 832 | } |
833 | #endif | ||
776 | } | 834 | } |
777 | 835 | ||
778 | /* | 836 | /* |
@@ -789,11 +847,15 @@ void lapic_shutdown(void) | |||
789 | return; | 847 | return; |
790 | 848 | ||
791 | local_irq_save(flags); | 849 | local_irq_save(flags); |
792 | clear_local_APIC(); | ||
793 | 850 | ||
794 | if (enabled_via_apicbase) | 851 | #ifdef CONFIG_X86_32 |
852 | if (!enabled_via_apicbase) | ||
853 | clear_local_APIC(); | ||
854 | else | ||
855 | #endif | ||
795 | disable_local_APIC(); | 856 | disable_local_APIC(); |
796 | 857 | ||
858 | |||
797 | local_irq_restore(flags); | 859 | local_irq_restore(flags); |
798 | } | 860 | } |
799 | 861 | ||
@@ -838,6 +900,12 @@ int __init verify_local_APIC(void) | |||
838 | */ | 900 | */ |
839 | reg0 = apic_read(APIC_ID); | 901 | reg0 = apic_read(APIC_ID); |
840 | apic_printk(APIC_DEBUG, "Getting ID: %x\n", reg0); | 902 | apic_printk(APIC_DEBUG, "Getting ID: %x\n", reg0); |
903 | apic_write(APIC_ID, reg0 ^ APIC_ID_MASK); | ||
904 | reg1 = apic_read(APIC_ID); | ||
905 | apic_printk(APIC_DEBUG, "Getting ID: %x\n", reg1); | ||
906 | apic_write(APIC_ID, reg0); | ||
907 | if (reg1 != (reg0 ^ APIC_ID_MASK)) | ||
908 | return 0; | ||
841 | 909 | ||
842 | /* | 910 | /* |
843 | * The next two are just to see if we have sane values. | 911 | * The next two are just to see if we have sane values. |
@@ -863,14 +931,15 @@ void __init sync_Arb_IDs(void) | |||
863 | */ | 931 | */ |
864 | if (modern_apic() || boot_cpu_data.x86_vendor == X86_VENDOR_AMD) | 932 | if (modern_apic() || boot_cpu_data.x86_vendor == X86_VENDOR_AMD) |
865 | return; | 933 | return; |
934 | |||
866 | /* | 935 | /* |
867 | * Wait for idle. | 936 | * Wait for idle. |
868 | */ | 937 | */ |
869 | apic_wait_icr_idle(); | 938 | apic_wait_icr_idle(); |
870 | 939 | ||
871 | apic_printk(APIC_DEBUG, "Synchronizing Arb IDs.\n"); | 940 | apic_printk(APIC_DEBUG, "Synchronizing Arb IDs.\n"); |
872 | apic_write(APIC_ICR, | 941 | apic_write(APIC_ICR, APIC_DEST_ALLINC | |
873 | APIC_DEST_ALLINC | APIC_INT_LEVELTRIG | APIC_DM_INIT); | 942 | APIC_INT_LEVELTRIG | APIC_DM_INIT); |
874 | } | 943 | } |
875 | 944 | ||
876 | /* | 945 | /* |
@@ -878,7 +947,7 @@ void __init sync_Arb_IDs(void) | |||
878 | */ | 947 | */ |
879 | void __init init_bsp_APIC(void) | 948 | void __init init_bsp_APIC(void) |
880 | { | 949 | { |
881 | unsigned long value; | 950 | unsigned int value; |
882 | 951 | ||
883 | /* | 952 | /* |
884 | * Don't do the setup now if we have a SMP BIOS as the | 953 | * Don't do the setup now if we have a SMP BIOS as the |
@@ -899,11 +968,13 @@ void __init init_bsp_APIC(void) | |||
899 | value &= ~APIC_VECTOR_MASK; | 968 | value &= ~APIC_VECTOR_MASK; |
900 | value |= APIC_SPIV_APIC_ENABLED; | 969 | value |= APIC_SPIV_APIC_ENABLED; |
901 | 970 | ||
971 | #ifdef CONFIG_X86_32 | ||
902 | /* This bit is reserved on P4/Xeon and should be cleared */ | 972 | /* This bit is reserved on P4/Xeon and should be cleared */ |
903 | if ((boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) && | 973 | if ((boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) && |
904 | (boot_cpu_data.x86 == 15)) | 974 | (boot_cpu_data.x86 == 15)) |
905 | value &= ~APIC_SPIV_FOCUS_DISABLED; | 975 | value &= ~APIC_SPIV_FOCUS_DISABLED; |
906 | else | 976 | else |
977 | #endif | ||
907 | value |= APIC_SPIV_FOCUS_DISABLED; | 978 | value |= APIC_SPIV_FOCUS_DISABLED; |
908 | value |= SPURIOUS_APIC_VECTOR; | 979 | value |= SPURIOUS_APIC_VECTOR; |
909 | apic_write(APIC_SPIV, value); | 980 | apic_write(APIC_SPIV, value); |
@@ -922,6 +993,16 @@ static void __cpuinit lapic_setup_esr(void) | |||
922 | { | 993 | { |
923 | unsigned long oldvalue, value, maxlvt; | 994 | unsigned long oldvalue, value, maxlvt; |
924 | if (lapic_is_integrated() && !esr_disable) { | 995 | if (lapic_is_integrated() && !esr_disable) { |
996 | if (esr_disable) { | ||
997 | /* | ||
998 | * Something untraceable is creating bad interrupts on | ||
999 | * secondary quads ... for the moment, just leave the | ||
1000 | * ESR disabled - we can't do anything useful with the | ||
1001 | * errors anyway - mbligh | ||
1002 | */ | ||
1003 | printk(KERN_INFO "Leaving ESR disabled.\n"); | ||
1004 | return; | ||
1005 | } | ||
925 | /* !82489DX */ | 1006 | /* !82489DX */ |
926 | maxlvt = lapic_get_maxlvt(); | 1007 | maxlvt = lapic_get_maxlvt(); |
927 | if (maxlvt > 3) /* Due to the Pentium erratum 3AP. */ | 1008 | if (maxlvt > 3) /* Due to the Pentium erratum 3AP. */ |
@@ -942,16 +1023,7 @@ static void __cpuinit lapic_setup_esr(void) | |||
942 | "vector: 0x%08lx after: 0x%08lx\n", | 1023 | "vector: 0x%08lx after: 0x%08lx\n", |
943 | oldvalue, value); | 1024 | oldvalue, value); |
944 | } else { | 1025 | } else { |
945 | if (esr_disable) | 1026 | printk(KERN_INFO "No ESR for 82489DX.\n"); |
946 | /* | ||
947 | * Something untraceable is creating bad interrupts on | ||
948 | * secondary quads ... for the moment, just leave the | ||
949 | * ESR disabled - we can't do anything useful with the | ||
950 | * errors anyway - mbligh | ||
951 | */ | ||
952 | printk(KERN_INFO "Leaving ESR disabled.\n"); | ||
953 | else | ||
954 | printk(KERN_INFO "No ESR for 82489DX.\n"); | ||
955 | } | 1027 | } |
956 | } | 1028 | } |
957 | 1029 | ||
@@ -1089,13 +1161,17 @@ void __cpuinit setup_local_APIC(void) | |||
1089 | 1161 | ||
1090 | void __cpuinit end_local_APIC_setup(void) | 1162 | void __cpuinit end_local_APIC_setup(void) |
1091 | { | 1163 | { |
1092 | unsigned long value; | ||
1093 | |||
1094 | lapic_setup_esr(); | 1164 | lapic_setup_esr(); |
1095 | /* Disable the local apic timer */ | 1165 | |
1096 | value = apic_read(APIC_LVTT); | 1166 | #ifdef CONFIG_X86_32 |
1097 | value |= (APIC_LVT_MASKED | LOCAL_TIMER_VECTOR); | 1167 | { |
1098 | apic_write(APIC_LVTT, value); | 1168 | unsigned int value; |
1169 | /* Disable the local apic timer */ | ||
1170 | value = apic_read(APIC_LVTT); | ||
1171 | value |= (APIC_LVT_MASKED | LOCAL_TIMER_VECTOR); | ||
1172 | apic_write(APIC_LVTT, value); | ||
1173 | } | ||
1174 | #endif | ||
1099 | 1175 | ||
1100 | setup_apic_nmi_watchdog(NULL); | 1176 | setup_apic_nmi_watchdog(NULL); |
1101 | apic_pm_activate(); | 1177 | apic_pm_activate(); |
@@ -1205,7 +1281,7 @@ void __init init_apic_mappings(void) | |||
1205 | * default configuration (or the MP table is broken). | 1281 | * default configuration (or the MP table is broken). |
1206 | */ | 1282 | */ |
1207 | if (boot_cpu_physical_apicid == -1U) | 1283 | if (boot_cpu_physical_apicid == -1U) |
1208 | boot_cpu_physical_apicid = GET_APIC_ID(read_apic_id()); | 1284 | boot_cpu_physical_apicid = read_apic_id(); |
1209 | 1285 | ||
1210 | } | 1286 | } |
1211 | 1287 | ||
@@ -1242,7 +1318,7 @@ int __init APIC_init_uniprocessor(void) | |||
1242 | * might be zero if read from MP tables. Get it from LAPIC. | 1318 | * might be zero if read from MP tables. Get it from LAPIC. |
1243 | */ | 1319 | */ |
1244 | #ifdef CONFIG_CRASH_DUMP | 1320 | #ifdef CONFIG_CRASH_DUMP |
1245 | boot_cpu_physical_apicid = GET_APIC_ID(read_apic_id()); | 1321 | boot_cpu_physical_apicid = read_apic_id(); |
1246 | #endif | 1322 | #endif |
1247 | physid_set_mask_of_physid(boot_cpu_physical_apicid, &phys_cpu_present_map); | 1323 | physid_set_mask_of_physid(boot_cpu_physical_apicid, &phys_cpu_present_map); |
1248 | 1324 | ||
@@ -1321,59 +1397,12 @@ void smp_error_interrupt(struct pt_regs *regs) | |||
1321 | irq_exit(); | 1397 | irq_exit(); |
1322 | } | 1398 | } |
1323 | 1399 | ||
1324 | #ifdef CONFIG_SMP | ||
1325 | void __init smp_intr_init(void) | ||
1326 | { | ||
1327 | /* | ||
1328 | * IRQ0 must be given a fixed assignment and initialized, | ||
1329 | * because it's used before the IO-APIC is set up. | ||
1330 | */ | ||
1331 | set_intr_gate(FIRST_DEVICE_VECTOR, interrupt[0]); | ||
1332 | |||
1333 | /* | ||
1334 | * The reschedule interrupt is a CPU-to-CPU reschedule-helper | ||
1335 | * IPI, driven by wakeup. | ||
1336 | */ | ||
1337 | alloc_intr_gate(RESCHEDULE_VECTOR, reschedule_interrupt); | ||
1338 | |||
1339 | /* IPI for invalidation */ | ||
1340 | alloc_intr_gate(INVALIDATE_TLB_VECTOR, invalidate_interrupt); | ||
1341 | |||
1342 | /* IPI for generic function call */ | ||
1343 | alloc_intr_gate(CALL_FUNCTION_VECTOR, call_function_interrupt); | ||
1344 | |||
1345 | /* IPI for single call function */ | ||
1346 | set_intr_gate(CALL_FUNCTION_SINGLE_VECTOR, | ||
1347 | call_function_single_interrupt); | ||
1348 | } | ||
1349 | #endif | ||
1350 | |||
1351 | /* | ||
1352 | * Initialize APIC interrupts | ||
1353 | */ | ||
1354 | void __init apic_intr_init(void) | ||
1355 | { | ||
1356 | #ifdef CONFIG_SMP | ||
1357 | smp_intr_init(); | ||
1358 | #endif | ||
1359 | /* self generated IPI for local APIC timer */ | ||
1360 | alloc_intr_gate(LOCAL_TIMER_VECTOR, apic_timer_interrupt); | ||
1361 | |||
1362 | /* IPI vectors for APIC spurious and error interrupts */ | ||
1363 | alloc_intr_gate(SPURIOUS_APIC_VECTOR, spurious_interrupt); | ||
1364 | alloc_intr_gate(ERROR_APIC_VECTOR, error_interrupt); | ||
1365 | |||
1366 | /* thermal monitor LVT interrupt */ | ||
1367 | #ifdef CONFIG_X86_MCE_P4THERMAL | ||
1368 | alloc_intr_gate(THERMAL_APIC_VECTOR, thermal_interrupt); | ||
1369 | #endif | ||
1370 | } | ||
1371 | |||
1372 | /** | 1400 | /** |
1373 | * connect_bsp_APIC - attach the APIC to the interrupt system | 1401 | * connect_bsp_APIC - attach the APIC to the interrupt system |
1374 | */ | 1402 | */ |
1375 | void __init connect_bsp_APIC(void) | 1403 | void __init connect_bsp_APIC(void) |
1376 | { | 1404 | { |
1405 | #ifdef CONFIG_X86_32 | ||
1377 | if (pic_mode) { | 1406 | if (pic_mode) { |
1378 | /* | 1407 | /* |
1379 | * Do not trust the local APIC being empty at bootup. | 1408 | * Do not trust the local APIC being empty at bootup. |
@@ -1388,6 +1417,7 @@ void __init connect_bsp_APIC(void) | |||
1388 | outb(0x70, 0x22); | 1417 | outb(0x70, 0x22); |
1389 | outb(0x01, 0x23); | 1418 | outb(0x01, 0x23); |
1390 | } | 1419 | } |
1420 | #endif | ||
1391 | enable_apic_mode(); | 1421 | enable_apic_mode(); |
1392 | } | 1422 | } |
1393 | 1423 | ||
@@ -1400,6 +1430,9 @@ void __init connect_bsp_APIC(void) | |||
1400 | */ | 1430 | */ |
1401 | void disconnect_bsp_APIC(int virt_wire_setup) | 1431 | void disconnect_bsp_APIC(int virt_wire_setup) |
1402 | { | 1432 | { |
1433 | unsigned int value; | ||
1434 | |||
1435 | #ifdef CONFIG_X86_32 | ||
1403 | if (pic_mode) { | 1436 | if (pic_mode) { |
1404 | /* | 1437 | /* |
1405 | * Put the board back into PIC mode (has an effect only on | 1438 | * Put the board back into PIC mode (has an effect only on |
@@ -1411,54 +1444,53 @@ void disconnect_bsp_APIC(int virt_wire_setup) | |||
1411 | "entering PIC mode.\n"); | 1444 | "entering PIC mode.\n"); |
1412 | outb(0x70, 0x22); | 1445 | outb(0x70, 0x22); |
1413 | outb(0x00, 0x23); | 1446 | outb(0x00, 0x23); |
1414 | } else { | 1447 | return; |
1415 | /* Go back to Virtual Wire compatibility mode */ | 1448 | } |
1416 | unsigned long value; | 1449 | #endif |
1417 | 1450 | ||
1418 | /* For the spurious interrupt use vector F, and enable it */ | 1451 | /* Go back to Virtual Wire compatibility mode */ |
1419 | value = apic_read(APIC_SPIV); | ||
1420 | value &= ~APIC_VECTOR_MASK; | ||
1421 | value |= APIC_SPIV_APIC_ENABLED; | ||
1422 | value |= 0xf; | ||
1423 | apic_write(APIC_SPIV, value); | ||
1424 | 1452 | ||
1425 | if (!virt_wire_setup) { | 1453 | /* For the spurious interrupt use vector F, and enable it */ |
1426 | /* | 1454 | value = apic_read(APIC_SPIV); |
1427 | * For LVT0 make it edge triggered, active high, | 1455 | value &= ~APIC_VECTOR_MASK; |
1428 | * external and enabled | 1456 | value |= APIC_SPIV_APIC_ENABLED; |
1429 | */ | 1457 | value |= 0xf; |
1430 | value = apic_read(APIC_LVT0); | 1458 | apic_write(APIC_SPIV, value); |
1431 | value &= ~(APIC_MODE_MASK | APIC_SEND_PENDING | | ||
1432 | APIC_INPUT_POLARITY | APIC_LVT_REMOTE_IRR | | ||
1433 | APIC_LVT_LEVEL_TRIGGER | APIC_LVT_MASKED); | ||
1434 | value |= APIC_LVT_REMOTE_IRR | APIC_SEND_PENDING; | ||
1435 | value = SET_APIC_DELIVERY_MODE(value, APIC_MODE_EXTINT); | ||
1436 | apic_write(APIC_LVT0, value); | ||
1437 | } else { | ||
1438 | /* Disable LVT0 */ | ||
1439 | apic_write(APIC_LVT0, APIC_LVT_MASKED); | ||
1440 | } | ||
1441 | 1459 | ||
1460 | if (!virt_wire_setup) { | ||
1442 | /* | 1461 | /* |
1443 | * For LVT1 make it edge triggered, active high, nmi and | 1462 | * For LVT0 make it edge triggered, active high, |
1444 | * enabled | 1463 | * external and enabled |
1445 | */ | 1464 | */ |
1446 | value = apic_read(APIC_LVT1); | 1465 | value = apic_read(APIC_LVT0); |
1447 | value &= ~( | 1466 | value &= ~(APIC_MODE_MASK | APIC_SEND_PENDING | |
1448 | APIC_MODE_MASK | APIC_SEND_PENDING | | ||
1449 | APIC_INPUT_POLARITY | APIC_LVT_REMOTE_IRR | | 1467 | APIC_INPUT_POLARITY | APIC_LVT_REMOTE_IRR | |
1450 | APIC_LVT_LEVEL_TRIGGER | APIC_LVT_MASKED); | 1468 | APIC_LVT_LEVEL_TRIGGER | APIC_LVT_MASKED); |
1451 | value |= APIC_LVT_REMOTE_IRR | APIC_SEND_PENDING; | 1469 | value |= APIC_LVT_REMOTE_IRR | APIC_SEND_PENDING; |
1452 | value = SET_APIC_DELIVERY_MODE(value, APIC_MODE_NMI); | 1470 | value = SET_APIC_DELIVERY_MODE(value, APIC_MODE_EXTINT); |
1453 | apic_write(APIC_LVT1, value); | 1471 | apic_write(APIC_LVT0, value); |
1472 | } else { | ||
1473 | /* Disable LVT0 */ | ||
1474 | apic_write(APIC_LVT0, APIC_LVT_MASKED); | ||
1454 | } | 1475 | } |
1476 | |||
1477 | /* | ||
1478 | * For LVT1 make it edge triggered, active high, | ||
1479 | * nmi and enabled | ||
1480 | */ | ||
1481 | value = apic_read(APIC_LVT1); | ||
1482 | value &= ~(APIC_MODE_MASK | APIC_SEND_PENDING | | ||
1483 | APIC_INPUT_POLARITY | APIC_LVT_REMOTE_IRR | | ||
1484 | APIC_LVT_LEVEL_TRIGGER | APIC_LVT_MASKED); | ||
1485 | value |= APIC_LVT_REMOTE_IRR | APIC_SEND_PENDING; | ||
1486 | value = SET_APIC_DELIVERY_MODE(value, APIC_MODE_NMI); | ||
1487 | apic_write(APIC_LVT1, value); | ||
1455 | } | 1488 | } |
1456 | 1489 | ||
1457 | void __cpuinit generic_processor_info(int apicid, int version) | 1490 | void __cpuinit generic_processor_info(int apicid, int version) |
1458 | { | 1491 | { |
1459 | int cpu; | 1492 | int cpu; |
1460 | cpumask_t tmp_map; | 1493 | cpumask_t tmp_map; |
1461 | physid_mask_t phys_cpu; | ||
1462 | 1494 | ||
1463 | /* | 1495 | /* |
1464 | * Validate version | 1496 | * Validate version |
@@ -1471,9 +1503,6 @@ void __cpuinit generic_processor_info(int apicid, int version) | |||
1471 | } | 1503 | } |
1472 | apic_version[apicid] = version; | 1504 | apic_version[apicid] = version; |
1473 | 1505 | ||
1474 | phys_cpu = apicid_to_cpu_present(apicid); | ||
1475 | physids_or(phys_cpu_present_map, phys_cpu_present_map, phys_cpu); | ||
1476 | |||
1477 | if (num_processors >= NR_CPUS) { | 1506 | if (num_processors >= NR_CPUS) { |
1478 | printk(KERN_WARNING "WARNING: NR_CPUS limit of %i reached." | 1507 | printk(KERN_WARNING "WARNING: NR_CPUS limit of %i reached." |
1479 | " Processor ignored.\n", NR_CPUS); | 1508 | " Processor ignored.\n", NR_CPUS); |
@@ -1484,17 +1513,19 @@ void __cpuinit generic_processor_info(int apicid, int version) | |||
1484 | cpus_complement(tmp_map, cpu_present_map); | 1513 | cpus_complement(tmp_map, cpu_present_map); |
1485 | cpu = first_cpu(tmp_map); | 1514 | cpu = first_cpu(tmp_map); |
1486 | 1515 | ||
1487 | if (apicid == boot_cpu_physical_apicid) | 1516 | physid_set(apicid, phys_cpu_present_map); |
1517 | if (apicid == boot_cpu_physical_apicid) { | ||
1488 | /* | 1518 | /* |
1489 | * x86_bios_cpu_apicid is required to have processors listed | 1519 | * x86_bios_cpu_apicid is required to have processors listed |
1490 | * in same order as logical cpu numbers. Hence the first | 1520 | * in same order as logical cpu numbers. Hence the first |
1491 | * entry is BSP, and so on. | 1521 | * entry is BSP, and so on. |
1492 | */ | 1522 | */ |
1493 | cpu = 0; | 1523 | cpu = 0; |
1494 | 1524 | } | |
1495 | if (apicid > max_physical_apicid) | 1525 | if (apicid > max_physical_apicid) |
1496 | max_physical_apicid = apicid; | 1526 | max_physical_apicid = apicid; |
1497 | 1527 | ||
1528 | #ifdef CONFIG_X86_32 | ||
1498 | /* | 1529 | /* |
1499 | * Would be preferable to switch to bigsmp when CONFIG_HOTPLUG_CPU=y | 1530 | * Would be preferable to switch to bigsmp when CONFIG_HOTPLUG_CPU=y |
1500 | * but we need to work other dependencies like SMP_SUSPEND etc | 1531 | * but we need to work other dependencies like SMP_SUSPEND etc |
@@ -1514,7 +1545,9 @@ void __cpuinit generic_processor_info(int apicid, int version) | |||
1514 | def_to_bigsmp = 1; | 1545 | def_to_bigsmp = 1; |
1515 | } | 1546 | } |
1516 | } | 1547 | } |
1517 | #ifdef CONFIG_SMP | 1548 | #endif |
1549 | |||
1550 | #if defined(CONFIG_X86_SMP) || defined(CONFIG_X86_64) | ||
1518 | /* are we being called early in kernel startup? */ | 1551 | /* are we being called early in kernel startup? */ |
1519 | if (early_per_cpu_ptr(x86_cpu_to_apicid)) { | 1552 | if (early_per_cpu_ptr(x86_cpu_to_apicid)) { |
1520 | u16 *cpu_to_apicid = early_per_cpu_ptr(x86_cpu_to_apicid); | 1553 | u16 *cpu_to_apicid = early_per_cpu_ptr(x86_cpu_to_apicid); |
@@ -1527,6 +1560,7 @@ void __cpuinit generic_processor_info(int apicid, int version) | |||
1527 | per_cpu(x86_bios_cpu_apicid, cpu) = apicid; | 1560 | per_cpu(x86_bios_cpu_apicid, cpu) = apicid; |
1528 | } | 1561 | } |
1529 | #endif | 1562 | #endif |
1563 | |||
1530 | cpu_set(cpu, cpu_possible_map); | 1564 | cpu_set(cpu, cpu_possible_map); |
1531 | cpu_set(cpu, cpu_present_map); | 1565 | cpu_set(cpu, cpu_present_map); |
1532 | } | 1566 | } |
@@ -1537,6 +1571,11 @@ void __cpuinit generic_processor_info(int apicid, int version) | |||
1537 | #ifdef CONFIG_PM | 1571 | #ifdef CONFIG_PM |
1538 | 1572 | ||
1539 | static struct { | 1573 | static struct { |
1574 | /* | ||
1575 | * 'active' is true if the local APIC was enabled by us and | ||
1576 | * not the BIOS; this signifies that we are also responsible | ||
1577 | * for disabling it before entering apm/acpi suspend | ||
1578 | */ | ||
1540 | int active; | 1579 | int active; |
1541 | /* r/w apic fields */ | 1580 | /* r/w apic fields */ |
1542 | unsigned int apic_id; | 1581 | unsigned int apic_id; |
@@ -1577,7 +1616,7 @@ static int lapic_suspend(struct sys_device *dev, pm_message_t state) | |||
1577 | apic_pm_state.apic_lvterr = apic_read(APIC_LVTERR); | 1616 | apic_pm_state.apic_lvterr = apic_read(APIC_LVTERR); |
1578 | apic_pm_state.apic_tmict = apic_read(APIC_TMICT); | 1617 | apic_pm_state.apic_tmict = apic_read(APIC_TMICT); |
1579 | apic_pm_state.apic_tdcr = apic_read(APIC_TDCR); | 1618 | apic_pm_state.apic_tdcr = apic_read(APIC_TDCR); |
1580 | #ifdef CONFIG_X86_MCE_P4THERMAL | 1619 | #if defined(CONFIG_X86_MCE_P4THERMAL) || defined(CONFIG_X86_MCE_INTEL) |
1581 | if (maxlvt >= 5) | 1620 | if (maxlvt >= 5) |
1582 | apic_pm_state.apic_thmr = apic_read(APIC_LVTTHMR); | 1621 | apic_pm_state.apic_thmr = apic_read(APIC_LVTTHMR); |
1583 | #endif | 1622 | #endif |
@@ -1601,16 +1640,23 @@ static int lapic_resume(struct sys_device *dev) | |||
1601 | 1640 | ||
1602 | local_irq_save(flags); | 1641 | local_irq_save(flags); |
1603 | 1642 | ||
1604 | /* | 1643 | #ifdef CONFIG_X86_64 |
1605 | * Make sure the APICBASE points to the right address | 1644 | if (x2apic) |
1606 | * | 1645 | enable_x2apic(); |
1607 | * FIXME! This will be wrong if we ever support suspend on | 1646 | else |
1608 | * SMP! We'll need to do this as part of the CPU restore! | 1647 | #endif |
1609 | */ | 1648 | { |
1610 | rdmsr(MSR_IA32_APICBASE, l, h); | 1649 | /* |
1611 | l &= ~MSR_IA32_APICBASE_BASE; | 1650 | * Make sure the APICBASE points to the right address |
1612 | l |= MSR_IA32_APICBASE_ENABLE | mp_lapic_addr; | 1651 | * |
1613 | wrmsr(MSR_IA32_APICBASE, l, h); | 1652 | * FIXME! This will be wrong if we ever support suspend on |
1653 | * SMP! We'll need to do this as part of the CPU restore! | ||
1654 | */ | ||
1655 | rdmsr(MSR_IA32_APICBASE, l, h); | ||
1656 | l &= ~MSR_IA32_APICBASE_BASE; | ||
1657 | l |= MSR_IA32_APICBASE_ENABLE | mp_lapic_addr; | ||
1658 | wrmsr(MSR_IA32_APICBASE, l, h); | ||
1659 | } | ||
1614 | 1660 | ||
1615 | apic_write(APIC_LVTERR, ERROR_APIC_VECTOR | APIC_LVT_MASKED); | 1661 | apic_write(APIC_LVTERR, ERROR_APIC_VECTOR | APIC_LVT_MASKED); |
1616 | apic_write(APIC_ID, apic_pm_state.apic_id); | 1662 | apic_write(APIC_ID, apic_pm_state.apic_id); |
@@ -1620,7 +1666,7 @@ static int lapic_resume(struct sys_device *dev) | |||
1620 | apic_write(APIC_SPIV, apic_pm_state.apic_spiv); | 1666 | apic_write(APIC_SPIV, apic_pm_state.apic_spiv); |
1621 | apic_write(APIC_LVT0, apic_pm_state.apic_lvt0); | 1667 | apic_write(APIC_LVT0, apic_pm_state.apic_lvt0); |
1622 | apic_write(APIC_LVT1, apic_pm_state.apic_lvt1); | 1668 | apic_write(APIC_LVT1, apic_pm_state.apic_lvt1); |
1623 | #ifdef CONFIG_X86_MCE_P4THERMAL | 1669 | #if defined(CONFIG_X86_MCE_P4THERMAL) || defined(CONFIG_X86_MCE_INTEL) |
1624 | if (maxlvt >= 5) | 1670 | if (maxlvt >= 5) |
1625 | apic_write(APIC_LVTTHMR, apic_pm_state.apic_thmr); | 1671 | apic_write(APIC_LVTTHMR, apic_pm_state.apic_thmr); |
1626 | #endif | 1672 | #endif |
@@ -1634,7 +1680,9 @@ static int lapic_resume(struct sys_device *dev) | |||
1634 | apic_write(APIC_LVTERR, apic_pm_state.apic_lvterr); | 1680 | apic_write(APIC_LVTERR, apic_pm_state.apic_lvterr); |
1635 | apic_write(APIC_ESR, 0); | 1681 | apic_write(APIC_ESR, 0); |
1636 | apic_read(APIC_ESR); | 1682 | apic_read(APIC_ESR); |
1683 | |||
1637 | local_irq_restore(flags); | 1684 | local_irq_restore(flags); |
1685 | |||
1638 | return 0; | 1686 | return 0; |
1639 | } | 1687 | } |
1640 | 1688 | ||
@@ -1690,20 +1738,20 @@ static int __init parse_lapic(char *arg) | |||
1690 | } | 1738 | } |
1691 | early_param("lapic", parse_lapic); | 1739 | early_param("lapic", parse_lapic); |
1692 | 1740 | ||
1693 | static int __init parse_nolapic(char *arg) | 1741 | static int __init setup_disableapic(char *arg) |
1694 | { | 1742 | { |
1695 | disable_apic = 1; | 1743 | disable_apic = 1; |
1696 | setup_clear_cpu_cap(X86_FEATURE_APIC); | 1744 | setup_clear_cpu_cap(X86_FEATURE_APIC); |
1697 | return 0; | 1745 | return 0; |
1698 | } | 1746 | } |
1699 | early_param("nolapic", parse_nolapic); | 1747 | early_param("disableapic", setup_disableapic); |
1700 | 1748 | ||
1701 | static int __init parse_disable_lapic_timer(char *arg) | 1749 | /* same as disableapic, for compatibility */ |
1750 | static int __init setup_nolapic(char *arg) | ||
1702 | { | 1751 | { |
1703 | local_apic_timer_disabled = 1; | 1752 | return setup_disableapic(arg); |
1704 | return 0; | ||
1705 | } | 1753 | } |
1706 | early_param("nolapic_timer", parse_disable_lapic_timer); | 1754 | early_param("nolapic", setup_nolapic); |
1707 | 1755 | ||
1708 | static int __init parse_lapic_timer_c2_ok(char *arg) | 1756 | static int __init parse_lapic_timer_c2_ok(char *arg) |
1709 | { | 1757 | { |
@@ -1712,15 +1760,40 @@ static int __init parse_lapic_timer_c2_ok(char *arg) | |||
1712 | } | 1760 | } |
1713 | early_param("lapic_timer_c2_ok", parse_lapic_timer_c2_ok); | 1761 | early_param("lapic_timer_c2_ok", parse_lapic_timer_c2_ok); |
1714 | 1762 | ||
1763 | static int __init parse_disable_apic_timer(char *arg) | ||
1764 | { | ||
1765 | disable_apic_timer = 1; | ||
1766 | return 0; | ||
1767 | } | ||
1768 | early_param("noapictimer", parse_disable_apic_timer); | ||
1769 | |||
1770 | static int __init parse_nolapic_timer(char *arg) | ||
1771 | { | ||
1772 | disable_apic_timer = 1; | ||
1773 | return 0; | ||
1774 | } | ||
1775 | early_param("nolapic_timer", parse_nolapic_timer); | ||
1776 | |||
1715 | static int __init apic_set_verbosity(char *arg) | 1777 | static int __init apic_set_verbosity(char *arg) |
1716 | { | 1778 | { |
1717 | if (!arg) | 1779 | if (!arg) { |
1780 | #ifdef CONFIG_X86_64 | ||
1781 | skip_ioapic_setup = 0; | ||
1782 | ioapic_force = 1; | ||
1783 | return 0; | ||
1784 | #endif | ||
1718 | return -EINVAL; | 1785 | return -EINVAL; |
1786 | } | ||
1719 | 1787 | ||
1720 | if (strcmp(arg, "debug") == 0) | 1788 | if (strcmp("debug", arg) == 0) |
1721 | apic_verbosity = APIC_DEBUG; | 1789 | apic_verbosity = APIC_DEBUG; |
1722 | else if (strcmp(arg, "verbose") == 0) | 1790 | else if (strcmp("verbose", arg) == 0) |
1723 | apic_verbosity = APIC_VERBOSE; | 1791 | apic_verbosity = APIC_VERBOSE; |
1792 | else { | ||
1793 | printk(KERN_WARNING "APIC Verbosity level %s not recognised" | ||
1794 | " use apic=verbose or apic=debug\n", arg); | ||
1795 | return -EINVAL; | ||
1796 | } | ||
1724 | 1797 | ||
1725 | return 0; | 1798 | return 0; |
1726 | } | 1799 | } |