diff options
Diffstat (limited to 'arch/x86/kernel/apic_32.c')
-rw-r--r-- | arch/x86/kernel/apic_32.c | 437 |
1 files changed, 253 insertions, 184 deletions
diff --git a/arch/x86/kernel/apic_32.c b/arch/x86/kernel/apic_32.c index f88bd0d982b0..a91c57cb666a 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,44 @@ 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 | |||
300 | #define APIC_EILVT_LVTOFF_MCE 0 | ||
301 | #define APIC_EILVT_LVTOFF_IBS 1 | ||
302 | |||
303 | static void setup_APIC_eilvt(u8 lvt_off, u8 vector, u8 msg_type, u8 mask) | ||
304 | { | ||
305 | unsigned long reg = (lvt_off << 4) + APIC_EILVT0; | ||
306 | unsigned int v = (mask << 16) | (msg_type << 8) | vector; | ||
307 | |||
308 | apic_write(reg, v); | ||
309 | } | ||
310 | |||
311 | u8 setup_APIC_eilvt_mce(u8 vector, u8 msg_type, u8 mask) | ||
312 | { | ||
313 | setup_APIC_eilvt(APIC_EILVT_LVTOFF_MCE, vector, msg_type, mask); | ||
314 | return APIC_EILVT_LVTOFF_MCE; | ||
315 | } | ||
316 | |||
317 | u8 setup_APIC_eilvt_ibs(u8 vector, u8 msg_type, u8 mask) | ||
318 | { | ||
319 | setup_APIC_eilvt(APIC_EILVT_LVTOFF_IBS, vector, msg_type, mask); | ||
320 | return APIC_EILVT_LVTOFF_IBS; | ||
321 | } | ||
322 | |||
323 | /* | ||
244 | * Program the next event, relative to now | 324 | * Program the next event, relative to now |
245 | */ | 325 | */ |
246 | static int lapic_next_event(unsigned long delta, | 326 | static int lapic_next_event(unsigned long delta, |
@@ -259,8 +339,8 @@ static void lapic_timer_setup(enum clock_event_mode mode, | |||
259 | unsigned long flags; | 339 | unsigned long flags; |
260 | unsigned int v; | 340 | unsigned int v; |
261 | 341 | ||
262 | /* Lapic used for broadcast ? */ | 342 | /* Lapic used as dummy for broadcast ? */ |
263 | if (!local_apic_timer_verify_ok) | 343 | if (evt->features & CLOCK_EVT_FEAT_DUMMY) |
264 | return; | 344 | return; |
265 | 345 | ||
266 | local_irq_save(flags); | 346 | local_irq_save(flags); |
@@ -473,7 +553,7 @@ static int __init calibrate_APIC_clock(void) | |||
473 | return -1; | 553 | return -1; |
474 | } | 554 | } |
475 | 555 | ||
476 | local_apic_timer_verify_ok = 1; | 556 | levt->features &= ~CLOCK_EVT_FEAT_DUMMY; |
477 | 557 | ||
478 | /* We trust the pm timer based calibration */ | 558 | /* We trust the pm timer based calibration */ |
479 | if (!pm_referenced) { | 559 | if (!pm_referenced) { |
@@ -507,11 +587,11 @@ static int __init calibrate_APIC_clock(void) | |||
507 | if (deltaj >= LAPIC_CAL_LOOPS-2 && deltaj <= LAPIC_CAL_LOOPS+2) | 587 | if (deltaj >= LAPIC_CAL_LOOPS-2 && deltaj <= LAPIC_CAL_LOOPS+2) |
508 | apic_printk(APIC_VERBOSE, "... jiffies result ok\n"); | 588 | apic_printk(APIC_VERBOSE, "... jiffies result ok\n"); |
509 | else | 589 | else |
510 | local_apic_timer_verify_ok = 0; | 590 | levt->features |= CLOCK_EVT_FEAT_DUMMY; |
511 | } else | 591 | } else |
512 | local_irq_enable(); | 592 | local_irq_enable(); |
513 | 593 | ||
514 | if (!local_apic_timer_verify_ok) { | 594 | if (levt->features & CLOCK_EVT_FEAT_DUMMY) { |
515 | printk(KERN_WARNING | 595 | printk(KERN_WARNING |
516 | "APIC timer disabled due to verification failure.\n"); | 596 | "APIC timer disabled due to verification failure.\n"); |
517 | return -1; | 597 | return -1; |
@@ -533,7 +613,8 @@ void __init setup_boot_APIC_clock(void) | |||
533 | * timer as a dummy clock event source on SMP systems, so the | 613 | * timer as a dummy clock event source on SMP systems, so the |
534 | * broadcast mechanism is used. On UP systems simply ignore it. | 614 | * broadcast mechanism is used. On UP systems simply ignore it. |
535 | */ | 615 | */ |
536 | if (local_apic_timer_disabled) { | 616 | if (disable_apic_timer) { |
617 | printk(KERN_INFO "Disabling APIC timer\n"); | ||
537 | /* No broadcast on UP ! */ | 618 | /* No broadcast on UP ! */ |
538 | if (num_possible_cpus() > 1) { | 619 | if (num_possible_cpus() > 1) { |
539 | lapic_clockevent.mult = 1; | 620 | lapic_clockevent.mult = 1; |
@@ -602,7 +683,11 @@ static void local_apic_timer_interrupt(void) | |||
602 | /* | 683 | /* |
603 | * the NMI deadlock-detector uses this. | 684 | * the NMI deadlock-detector uses this. |
604 | */ | 685 | */ |
686 | #ifdef CONFIG_X86_64 | ||
687 | add_pda(apic_timer_irqs, 1); | ||
688 | #else | ||
605 | per_cpu(irq_stat, cpu).apic_timer_irqs++; | 689 | per_cpu(irq_stat, cpu).apic_timer_irqs++; |
690 | #endif | ||
606 | 691 | ||
607 | evt->event_handler(evt); | 692 | evt->event_handler(evt); |
608 | } | 693 | } |
@@ -642,35 +727,6 @@ int setup_profiling_timer(unsigned int multiplier) | |||
642 | } | 727 | } |
643 | 728 | ||
644 | /* | 729 | /* |
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 | 730 | * Local APIC start and shutdown |
675 | */ | 731 | */ |
676 | 732 | ||
@@ -715,7 +771,7 @@ void clear_local_APIC(void) | |||
715 | } | 771 | } |
716 | 772 | ||
717 | /* lets not touch this if we didn't frob it */ | 773 | /* lets not touch this if we didn't frob it */ |
718 | #ifdef CONFIG_X86_MCE_P4THERMAL | 774 | #if defined(CONFIG_X86_MCE_P4THERMAL) || defined(X86_MCE_INTEL) |
719 | if (maxlvt >= 5) { | 775 | if (maxlvt >= 5) { |
720 | v = apic_read(APIC_LVTTHMR); | 776 | v = apic_read(APIC_LVTTHMR); |
721 | apic_write(APIC_LVTTHMR, v | APIC_LVT_MASKED); | 777 | apic_write(APIC_LVTTHMR, v | APIC_LVT_MASKED); |
@@ -732,10 +788,6 @@ void clear_local_APIC(void) | |||
732 | if (maxlvt >= 4) | 788 | if (maxlvt >= 4) |
733 | apic_write(APIC_LVTPC, APIC_LVT_MASKED); | 789 | apic_write(APIC_LVTPC, APIC_LVT_MASKED); |
734 | 790 | ||
735 | #ifdef CONFIG_X86_MCE_P4THERMAL | ||
736 | if (maxlvt >= 5) | ||
737 | apic_write(APIC_LVTTHMR, APIC_LVT_MASKED); | ||
738 | #endif | ||
739 | /* Integrated APIC (!82489DX) ? */ | 791 | /* Integrated APIC (!82489DX) ? */ |
740 | if (lapic_is_integrated()) { | 792 | if (lapic_is_integrated()) { |
741 | if (maxlvt > 3) | 793 | if (maxlvt > 3) |
@@ -750,7 +802,7 @@ void clear_local_APIC(void) | |||
750 | */ | 802 | */ |
751 | void disable_local_APIC(void) | 803 | void disable_local_APIC(void) |
752 | { | 804 | { |
753 | unsigned long value; | 805 | unsigned int value; |
754 | 806 | ||
755 | clear_local_APIC(); | 807 | clear_local_APIC(); |
756 | 808 | ||
@@ -762,6 +814,7 @@ void disable_local_APIC(void) | |||
762 | value &= ~APIC_SPIV_APIC_ENABLED; | 814 | value &= ~APIC_SPIV_APIC_ENABLED; |
763 | apic_write(APIC_SPIV, value); | 815 | apic_write(APIC_SPIV, value); |
764 | 816 | ||
817 | #ifdef CONFIG_X86_32 | ||
765 | /* | 818 | /* |
766 | * When LAPIC was disabled by the BIOS and enabled by the kernel, | 819 | * When LAPIC was disabled by the BIOS and enabled by the kernel, |
767 | * restore the disabled state. | 820 | * restore the disabled state. |
@@ -773,6 +826,7 @@ void disable_local_APIC(void) | |||
773 | l &= ~MSR_IA32_APICBASE_ENABLE; | 826 | l &= ~MSR_IA32_APICBASE_ENABLE; |
774 | wrmsr(MSR_IA32_APICBASE, l, h); | 827 | wrmsr(MSR_IA32_APICBASE, l, h); |
775 | } | 828 | } |
829 | #endif | ||
776 | } | 830 | } |
777 | 831 | ||
778 | /* | 832 | /* |
@@ -789,11 +843,15 @@ void lapic_shutdown(void) | |||
789 | return; | 843 | return; |
790 | 844 | ||
791 | local_irq_save(flags); | 845 | local_irq_save(flags); |
792 | clear_local_APIC(); | ||
793 | 846 | ||
794 | if (enabled_via_apicbase) | 847 | #ifdef CONFIG_X86_32 |
848 | if (!enabled_via_apicbase) | ||
849 | clear_local_APIC(); | ||
850 | else | ||
851 | #endif | ||
795 | disable_local_APIC(); | 852 | disable_local_APIC(); |
796 | 853 | ||
854 | |||
797 | local_irq_restore(flags); | 855 | local_irq_restore(flags); |
798 | } | 856 | } |
799 | 857 | ||
@@ -838,6 +896,12 @@ int __init verify_local_APIC(void) | |||
838 | */ | 896 | */ |
839 | reg0 = apic_read(APIC_ID); | 897 | reg0 = apic_read(APIC_ID); |
840 | apic_printk(APIC_DEBUG, "Getting ID: %x\n", reg0); | 898 | apic_printk(APIC_DEBUG, "Getting ID: %x\n", reg0); |
899 | apic_write(APIC_ID, reg0 ^ APIC_ID_MASK); | ||
900 | reg1 = apic_read(APIC_ID); | ||
901 | apic_printk(APIC_DEBUG, "Getting ID: %x\n", reg1); | ||
902 | apic_write(APIC_ID, reg0); | ||
903 | if (reg1 != (reg0 ^ APIC_ID_MASK)) | ||
904 | return 0; | ||
841 | 905 | ||
842 | /* | 906 | /* |
843 | * The next two are just to see if we have sane values. | 907 | * The next two are just to see if we have sane values. |
@@ -863,14 +927,15 @@ void __init sync_Arb_IDs(void) | |||
863 | */ | 927 | */ |
864 | if (modern_apic() || boot_cpu_data.x86_vendor == X86_VENDOR_AMD) | 928 | if (modern_apic() || boot_cpu_data.x86_vendor == X86_VENDOR_AMD) |
865 | return; | 929 | return; |
930 | |||
866 | /* | 931 | /* |
867 | * Wait for idle. | 932 | * Wait for idle. |
868 | */ | 933 | */ |
869 | apic_wait_icr_idle(); | 934 | apic_wait_icr_idle(); |
870 | 935 | ||
871 | apic_printk(APIC_DEBUG, "Synchronizing Arb IDs.\n"); | 936 | apic_printk(APIC_DEBUG, "Synchronizing Arb IDs.\n"); |
872 | apic_write(APIC_ICR, | 937 | apic_write(APIC_ICR, APIC_DEST_ALLINC | |
873 | APIC_DEST_ALLINC | APIC_INT_LEVELTRIG | APIC_DM_INIT); | 938 | APIC_INT_LEVELTRIG | APIC_DM_INIT); |
874 | } | 939 | } |
875 | 940 | ||
876 | /* | 941 | /* |
@@ -878,7 +943,7 @@ void __init sync_Arb_IDs(void) | |||
878 | */ | 943 | */ |
879 | void __init init_bsp_APIC(void) | 944 | void __init init_bsp_APIC(void) |
880 | { | 945 | { |
881 | unsigned long value; | 946 | unsigned int value; |
882 | 947 | ||
883 | /* | 948 | /* |
884 | * Don't do the setup now if we have a SMP BIOS as the | 949 | * Don't do the setup now if we have a SMP BIOS as the |
@@ -899,11 +964,13 @@ void __init init_bsp_APIC(void) | |||
899 | value &= ~APIC_VECTOR_MASK; | 964 | value &= ~APIC_VECTOR_MASK; |
900 | value |= APIC_SPIV_APIC_ENABLED; | 965 | value |= APIC_SPIV_APIC_ENABLED; |
901 | 966 | ||
967 | #ifdef CONFIG_X86_32 | ||
902 | /* This bit is reserved on P4/Xeon and should be cleared */ | 968 | /* This bit is reserved on P4/Xeon and should be cleared */ |
903 | if ((boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) && | 969 | if ((boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) && |
904 | (boot_cpu_data.x86 == 15)) | 970 | (boot_cpu_data.x86 == 15)) |
905 | value &= ~APIC_SPIV_FOCUS_DISABLED; | 971 | value &= ~APIC_SPIV_FOCUS_DISABLED; |
906 | else | 972 | else |
973 | #endif | ||
907 | value |= APIC_SPIV_FOCUS_DISABLED; | 974 | value |= APIC_SPIV_FOCUS_DISABLED; |
908 | value |= SPURIOUS_APIC_VECTOR; | 975 | value |= SPURIOUS_APIC_VECTOR; |
909 | apic_write(APIC_SPIV, value); | 976 | apic_write(APIC_SPIV, value); |
@@ -922,6 +989,16 @@ static void __cpuinit lapic_setup_esr(void) | |||
922 | { | 989 | { |
923 | unsigned long oldvalue, value, maxlvt; | 990 | unsigned long oldvalue, value, maxlvt; |
924 | if (lapic_is_integrated() && !esr_disable) { | 991 | if (lapic_is_integrated() && !esr_disable) { |
992 | if (esr_disable) { | ||
993 | /* | ||
994 | * Something untraceable is creating bad interrupts on | ||
995 | * secondary quads ... for the moment, just leave the | ||
996 | * ESR disabled - we can't do anything useful with the | ||
997 | * errors anyway - mbligh | ||
998 | */ | ||
999 | printk(KERN_INFO "Leaving ESR disabled.\n"); | ||
1000 | return; | ||
1001 | } | ||
925 | /* !82489DX */ | 1002 | /* !82489DX */ |
926 | maxlvt = lapic_get_maxlvt(); | 1003 | maxlvt = lapic_get_maxlvt(); |
927 | if (maxlvt > 3) /* Due to the Pentium erratum 3AP. */ | 1004 | if (maxlvt > 3) /* Due to the Pentium erratum 3AP. */ |
@@ -942,16 +1019,7 @@ static void __cpuinit lapic_setup_esr(void) | |||
942 | "vector: 0x%08lx after: 0x%08lx\n", | 1019 | "vector: 0x%08lx after: 0x%08lx\n", |
943 | oldvalue, value); | 1020 | oldvalue, value); |
944 | } else { | 1021 | } else { |
945 | if (esr_disable) | 1022 | 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 | } | 1023 | } |
956 | } | 1024 | } |
957 | 1025 | ||
@@ -1089,13 +1157,17 @@ void __cpuinit setup_local_APIC(void) | |||
1089 | 1157 | ||
1090 | void __cpuinit end_local_APIC_setup(void) | 1158 | void __cpuinit end_local_APIC_setup(void) |
1091 | { | 1159 | { |
1092 | unsigned long value; | ||
1093 | |||
1094 | lapic_setup_esr(); | 1160 | lapic_setup_esr(); |
1095 | /* Disable the local apic timer */ | 1161 | |
1096 | value = apic_read(APIC_LVTT); | 1162 | #ifdef CONFIG_X86_32 |
1097 | value |= (APIC_LVT_MASKED | LOCAL_TIMER_VECTOR); | 1163 | { |
1098 | apic_write(APIC_LVTT, value); | 1164 | unsigned int value; |
1165 | /* Disable the local apic timer */ | ||
1166 | value = apic_read(APIC_LVTT); | ||
1167 | value |= (APIC_LVT_MASKED | LOCAL_TIMER_VECTOR); | ||
1168 | apic_write(APIC_LVTT, value); | ||
1169 | } | ||
1170 | #endif | ||
1099 | 1171 | ||
1100 | setup_apic_nmi_watchdog(NULL); | 1172 | setup_apic_nmi_watchdog(NULL); |
1101 | apic_pm_activate(); | 1173 | apic_pm_activate(); |
@@ -1205,7 +1277,7 @@ void __init init_apic_mappings(void) | |||
1205 | * default configuration (or the MP table is broken). | 1277 | * default configuration (or the MP table is broken). |
1206 | */ | 1278 | */ |
1207 | if (boot_cpu_physical_apicid == -1U) | 1279 | if (boot_cpu_physical_apicid == -1U) |
1208 | boot_cpu_physical_apicid = GET_APIC_ID(read_apic_id()); | 1280 | boot_cpu_physical_apicid = read_apic_id(); |
1209 | 1281 | ||
1210 | } | 1282 | } |
1211 | 1283 | ||
@@ -1242,7 +1314,7 @@ int __init APIC_init_uniprocessor(void) | |||
1242 | * might be zero if read from MP tables. Get it from LAPIC. | 1314 | * might be zero if read from MP tables. Get it from LAPIC. |
1243 | */ | 1315 | */ |
1244 | #ifdef CONFIG_CRASH_DUMP | 1316 | #ifdef CONFIG_CRASH_DUMP |
1245 | boot_cpu_physical_apicid = GET_APIC_ID(read_apic_id()); | 1317 | boot_cpu_physical_apicid = read_apic_id(); |
1246 | #endif | 1318 | #endif |
1247 | physid_set_mask_of_physid(boot_cpu_physical_apicid, &phys_cpu_present_map); | 1319 | physid_set_mask_of_physid(boot_cpu_physical_apicid, &phys_cpu_present_map); |
1248 | 1320 | ||
@@ -1321,59 +1393,12 @@ void smp_error_interrupt(struct pt_regs *regs) | |||
1321 | irq_exit(); | 1393 | irq_exit(); |
1322 | } | 1394 | } |
1323 | 1395 | ||
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 | /** | 1396 | /** |
1373 | * connect_bsp_APIC - attach the APIC to the interrupt system | 1397 | * connect_bsp_APIC - attach the APIC to the interrupt system |
1374 | */ | 1398 | */ |
1375 | void __init connect_bsp_APIC(void) | 1399 | void __init connect_bsp_APIC(void) |
1376 | { | 1400 | { |
1401 | #ifdef CONFIG_X86_32 | ||
1377 | if (pic_mode) { | 1402 | if (pic_mode) { |
1378 | /* | 1403 | /* |
1379 | * Do not trust the local APIC being empty at bootup. | 1404 | * Do not trust the local APIC being empty at bootup. |
@@ -1388,6 +1413,7 @@ void __init connect_bsp_APIC(void) | |||
1388 | outb(0x70, 0x22); | 1413 | outb(0x70, 0x22); |
1389 | outb(0x01, 0x23); | 1414 | outb(0x01, 0x23); |
1390 | } | 1415 | } |
1416 | #endif | ||
1391 | enable_apic_mode(); | 1417 | enable_apic_mode(); |
1392 | } | 1418 | } |
1393 | 1419 | ||
@@ -1400,6 +1426,9 @@ void __init connect_bsp_APIC(void) | |||
1400 | */ | 1426 | */ |
1401 | void disconnect_bsp_APIC(int virt_wire_setup) | 1427 | void disconnect_bsp_APIC(int virt_wire_setup) |
1402 | { | 1428 | { |
1429 | unsigned int value; | ||
1430 | |||
1431 | #ifdef CONFIG_X86_32 | ||
1403 | if (pic_mode) { | 1432 | if (pic_mode) { |
1404 | /* | 1433 | /* |
1405 | * Put the board back into PIC mode (has an effect only on | 1434 | * Put the board back into PIC mode (has an effect only on |
@@ -1411,54 +1440,53 @@ void disconnect_bsp_APIC(int virt_wire_setup) | |||
1411 | "entering PIC mode.\n"); | 1440 | "entering PIC mode.\n"); |
1412 | outb(0x70, 0x22); | 1441 | outb(0x70, 0x22); |
1413 | outb(0x00, 0x23); | 1442 | outb(0x00, 0x23); |
1414 | } else { | 1443 | return; |
1415 | /* Go back to Virtual Wire compatibility mode */ | 1444 | } |
1416 | unsigned long value; | 1445 | #endif |
1417 | 1446 | ||
1418 | /* For the spurious interrupt use vector F, and enable it */ | 1447 | /* 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 | 1448 | ||
1425 | if (!virt_wire_setup) { | 1449 | /* For the spurious interrupt use vector F, and enable it */ |
1426 | /* | 1450 | value = apic_read(APIC_SPIV); |
1427 | * For LVT0 make it edge triggered, active high, | 1451 | value &= ~APIC_VECTOR_MASK; |
1428 | * external and enabled | 1452 | value |= APIC_SPIV_APIC_ENABLED; |
1429 | */ | 1453 | value |= 0xf; |
1430 | value = apic_read(APIC_LVT0); | 1454 | 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 | 1455 | ||
1456 | if (!virt_wire_setup) { | ||
1442 | /* | 1457 | /* |
1443 | * For LVT1 make it edge triggered, active high, nmi and | 1458 | * For LVT0 make it edge triggered, active high, |
1444 | * enabled | 1459 | * external and enabled |
1445 | */ | 1460 | */ |
1446 | value = apic_read(APIC_LVT1); | 1461 | value = apic_read(APIC_LVT0); |
1447 | value &= ~( | 1462 | value &= ~(APIC_MODE_MASK | APIC_SEND_PENDING | |
1448 | APIC_MODE_MASK | APIC_SEND_PENDING | | ||
1449 | APIC_INPUT_POLARITY | APIC_LVT_REMOTE_IRR | | 1463 | APIC_INPUT_POLARITY | APIC_LVT_REMOTE_IRR | |
1450 | APIC_LVT_LEVEL_TRIGGER | APIC_LVT_MASKED); | 1464 | APIC_LVT_LEVEL_TRIGGER | APIC_LVT_MASKED); |
1451 | value |= APIC_LVT_REMOTE_IRR | APIC_SEND_PENDING; | 1465 | value |= APIC_LVT_REMOTE_IRR | APIC_SEND_PENDING; |
1452 | value = SET_APIC_DELIVERY_MODE(value, APIC_MODE_NMI); | 1466 | value = SET_APIC_DELIVERY_MODE(value, APIC_MODE_EXTINT); |
1453 | apic_write(APIC_LVT1, value); | 1467 | apic_write(APIC_LVT0, value); |
1468 | } else { | ||
1469 | /* Disable LVT0 */ | ||
1470 | apic_write(APIC_LVT0, APIC_LVT_MASKED); | ||
1454 | } | 1471 | } |
1472 | |||
1473 | /* | ||
1474 | * For LVT1 make it edge triggered, active high, | ||
1475 | * nmi and enabled | ||
1476 | */ | ||
1477 | value = apic_read(APIC_LVT1); | ||
1478 | value &= ~(APIC_MODE_MASK | APIC_SEND_PENDING | | ||
1479 | APIC_INPUT_POLARITY | APIC_LVT_REMOTE_IRR | | ||
1480 | APIC_LVT_LEVEL_TRIGGER | APIC_LVT_MASKED); | ||
1481 | value |= APIC_LVT_REMOTE_IRR | APIC_SEND_PENDING; | ||
1482 | value = SET_APIC_DELIVERY_MODE(value, APIC_MODE_NMI); | ||
1483 | apic_write(APIC_LVT1, value); | ||
1455 | } | 1484 | } |
1456 | 1485 | ||
1457 | void __cpuinit generic_processor_info(int apicid, int version) | 1486 | void __cpuinit generic_processor_info(int apicid, int version) |
1458 | { | 1487 | { |
1459 | int cpu; | 1488 | int cpu; |
1460 | cpumask_t tmp_map; | 1489 | cpumask_t tmp_map; |
1461 | physid_mask_t phys_cpu; | ||
1462 | 1490 | ||
1463 | /* | 1491 | /* |
1464 | * Validate version | 1492 | * Validate version |
@@ -1471,9 +1499,6 @@ void __cpuinit generic_processor_info(int apicid, int version) | |||
1471 | } | 1499 | } |
1472 | apic_version[apicid] = version; | 1500 | apic_version[apicid] = version; |
1473 | 1501 | ||
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) { | 1502 | if (num_processors >= NR_CPUS) { |
1478 | printk(KERN_WARNING "WARNING: NR_CPUS limit of %i reached." | 1503 | printk(KERN_WARNING "WARNING: NR_CPUS limit of %i reached." |
1479 | " Processor ignored.\n", NR_CPUS); | 1504 | " Processor ignored.\n", NR_CPUS); |
@@ -1484,17 +1509,19 @@ void __cpuinit generic_processor_info(int apicid, int version) | |||
1484 | cpus_complement(tmp_map, cpu_present_map); | 1509 | cpus_complement(tmp_map, cpu_present_map); |
1485 | cpu = first_cpu(tmp_map); | 1510 | cpu = first_cpu(tmp_map); |
1486 | 1511 | ||
1487 | if (apicid == boot_cpu_physical_apicid) | 1512 | physid_set(apicid, phys_cpu_present_map); |
1513 | if (apicid == boot_cpu_physical_apicid) { | ||
1488 | /* | 1514 | /* |
1489 | * x86_bios_cpu_apicid is required to have processors listed | 1515 | * x86_bios_cpu_apicid is required to have processors listed |
1490 | * in same order as logical cpu numbers. Hence the first | 1516 | * in same order as logical cpu numbers. Hence the first |
1491 | * entry is BSP, and so on. | 1517 | * entry is BSP, and so on. |
1492 | */ | 1518 | */ |
1493 | cpu = 0; | 1519 | cpu = 0; |
1494 | 1520 | } | |
1495 | if (apicid > max_physical_apicid) | 1521 | if (apicid > max_physical_apicid) |
1496 | max_physical_apicid = apicid; | 1522 | max_physical_apicid = apicid; |
1497 | 1523 | ||
1524 | #ifdef CONFIG_X86_32 | ||
1498 | /* | 1525 | /* |
1499 | * Would be preferable to switch to bigsmp when CONFIG_HOTPLUG_CPU=y | 1526 | * Would be preferable to switch to bigsmp when CONFIG_HOTPLUG_CPU=y |
1500 | * but we need to work other dependencies like SMP_SUSPEND etc | 1527 | * but we need to work other dependencies like SMP_SUSPEND etc |
@@ -1514,7 +1541,9 @@ void __cpuinit generic_processor_info(int apicid, int version) | |||
1514 | def_to_bigsmp = 1; | 1541 | def_to_bigsmp = 1; |
1515 | } | 1542 | } |
1516 | } | 1543 | } |
1517 | #ifdef CONFIG_SMP | 1544 | #endif |
1545 | |||
1546 | #if defined(CONFIG_X86_SMP) || defined(CONFIG_X86_64) | ||
1518 | /* are we being called early in kernel startup? */ | 1547 | /* are we being called early in kernel startup? */ |
1519 | if (early_per_cpu_ptr(x86_cpu_to_apicid)) { | 1548 | if (early_per_cpu_ptr(x86_cpu_to_apicid)) { |
1520 | u16 *cpu_to_apicid = early_per_cpu_ptr(x86_cpu_to_apicid); | 1549 | u16 *cpu_to_apicid = early_per_cpu_ptr(x86_cpu_to_apicid); |
@@ -1527,6 +1556,7 @@ void __cpuinit generic_processor_info(int apicid, int version) | |||
1527 | per_cpu(x86_bios_cpu_apicid, cpu) = apicid; | 1556 | per_cpu(x86_bios_cpu_apicid, cpu) = apicid; |
1528 | } | 1557 | } |
1529 | #endif | 1558 | #endif |
1559 | |||
1530 | cpu_set(cpu, cpu_possible_map); | 1560 | cpu_set(cpu, cpu_possible_map); |
1531 | cpu_set(cpu, cpu_present_map); | 1561 | cpu_set(cpu, cpu_present_map); |
1532 | } | 1562 | } |
@@ -1537,6 +1567,11 @@ void __cpuinit generic_processor_info(int apicid, int version) | |||
1537 | #ifdef CONFIG_PM | 1567 | #ifdef CONFIG_PM |
1538 | 1568 | ||
1539 | static struct { | 1569 | static struct { |
1570 | /* | ||
1571 | * 'active' is true if the local APIC was enabled by us and | ||
1572 | * not the BIOS; this signifies that we are also responsible | ||
1573 | * for disabling it before entering apm/acpi suspend | ||
1574 | */ | ||
1540 | int active; | 1575 | int active; |
1541 | /* r/w apic fields */ | 1576 | /* r/w apic fields */ |
1542 | unsigned int apic_id; | 1577 | unsigned int apic_id; |
@@ -1577,7 +1612,7 @@ static int lapic_suspend(struct sys_device *dev, pm_message_t state) | |||
1577 | apic_pm_state.apic_lvterr = apic_read(APIC_LVTERR); | 1612 | apic_pm_state.apic_lvterr = apic_read(APIC_LVTERR); |
1578 | apic_pm_state.apic_tmict = apic_read(APIC_TMICT); | 1613 | apic_pm_state.apic_tmict = apic_read(APIC_TMICT); |
1579 | apic_pm_state.apic_tdcr = apic_read(APIC_TDCR); | 1614 | apic_pm_state.apic_tdcr = apic_read(APIC_TDCR); |
1580 | #ifdef CONFIG_X86_MCE_P4THERMAL | 1615 | #if defined(CONFIG_X86_MCE_P4THERMAL) || defined(CONFIG_X86_MCE_INTEL) |
1581 | if (maxlvt >= 5) | 1616 | if (maxlvt >= 5) |
1582 | apic_pm_state.apic_thmr = apic_read(APIC_LVTTHMR); | 1617 | apic_pm_state.apic_thmr = apic_read(APIC_LVTTHMR); |
1583 | #endif | 1618 | #endif |
@@ -1601,16 +1636,23 @@ static int lapic_resume(struct sys_device *dev) | |||
1601 | 1636 | ||
1602 | local_irq_save(flags); | 1637 | local_irq_save(flags); |
1603 | 1638 | ||
1604 | /* | 1639 | #ifdef CONFIG_X86_64 |
1605 | * Make sure the APICBASE points to the right address | 1640 | if (x2apic) |
1606 | * | 1641 | enable_x2apic(); |
1607 | * FIXME! This will be wrong if we ever support suspend on | 1642 | else |
1608 | * SMP! We'll need to do this as part of the CPU restore! | 1643 | #endif |
1609 | */ | 1644 | { |
1610 | rdmsr(MSR_IA32_APICBASE, l, h); | 1645 | /* |
1611 | l &= ~MSR_IA32_APICBASE_BASE; | 1646 | * Make sure the APICBASE points to the right address |
1612 | l |= MSR_IA32_APICBASE_ENABLE | mp_lapic_addr; | 1647 | * |
1613 | wrmsr(MSR_IA32_APICBASE, l, h); | 1648 | * FIXME! This will be wrong if we ever support suspend on |
1649 | * SMP! We'll need to do this as part of the CPU restore! | ||
1650 | */ | ||
1651 | rdmsr(MSR_IA32_APICBASE, l, h); | ||
1652 | l &= ~MSR_IA32_APICBASE_BASE; | ||
1653 | l |= MSR_IA32_APICBASE_ENABLE | mp_lapic_addr; | ||
1654 | wrmsr(MSR_IA32_APICBASE, l, h); | ||
1655 | } | ||
1614 | 1656 | ||
1615 | apic_write(APIC_LVTERR, ERROR_APIC_VECTOR | APIC_LVT_MASKED); | 1657 | apic_write(APIC_LVTERR, ERROR_APIC_VECTOR | APIC_LVT_MASKED); |
1616 | apic_write(APIC_ID, apic_pm_state.apic_id); | 1658 | apic_write(APIC_ID, apic_pm_state.apic_id); |
@@ -1620,7 +1662,7 @@ static int lapic_resume(struct sys_device *dev) | |||
1620 | apic_write(APIC_SPIV, apic_pm_state.apic_spiv); | 1662 | apic_write(APIC_SPIV, apic_pm_state.apic_spiv); |
1621 | apic_write(APIC_LVT0, apic_pm_state.apic_lvt0); | 1663 | apic_write(APIC_LVT0, apic_pm_state.apic_lvt0); |
1622 | apic_write(APIC_LVT1, apic_pm_state.apic_lvt1); | 1664 | apic_write(APIC_LVT1, apic_pm_state.apic_lvt1); |
1623 | #ifdef CONFIG_X86_MCE_P4THERMAL | 1665 | #if defined(CONFIG_X86_MCE_P4THERMAL) || defined(CONFIG_X86_MCE_INTEL) |
1624 | if (maxlvt >= 5) | 1666 | if (maxlvt >= 5) |
1625 | apic_write(APIC_LVTTHMR, apic_pm_state.apic_thmr); | 1667 | apic_write(APIC_LVTTHMR, apic_pm_state.apic_thmr); |
1626 | #endif | 1668 | #endif |
@@ -1634,7 +1676,9 @@ static int lapic_resume(struct sys_device *dev) | |||
1634 | apic_write(APIC_LVTERR, apic_pm_state.apic_lvterr); | 1676 | apic_write(APIC_LVTERR, apic_pm_state.apic_lvterr); |
1635 | apic_write(APIC_ESR, 0); | 1677 | apic_write(APIC_ESR, 0); |
1636 | apic_read(APIC_ESR); | 1678 | apic_read(APIC_ESR); |
1679 | |||
1637 | local_irq_restore(flags); | 1680 | local_irq_restore(flags); |
1681 | |||
1638 | return 0; | 1682 | return 0; |
1639 | } | 1683 | } |
1640 | 1684 | ||
@@ -1690,20 +1734,20 @@ static int __init parse_lapic(char *arg) | |||
1690 | } | 1734 | } |
1691 | early_param("lapic", parse_lapic); | 1735 | early_param("lapic", parse_lapic); |
1692 | 1736 | ||
1693 | static int __init parse_nolapic(char *arg) | 1737 | static int __init setup_disableapic(char *arg) |
1694 | { | 1738 | { |
1695 | disable_apic = 1; | 1739 | disable_apic = 1; |
1696 | setup_clear_cpu_cap(X86_FEATURE_APIC); | 1740 | setup_clear_cpu_cap(X86_FEATURE_APIC); |
1697 | return 0; | 1741 | return 0; |
1698 | } | 1742 | } |
1699 | early_param("nolapic", parse_nolapic); | 1743 | early_param("disableapic", setup_disableapic); |
1700 | 1744 | ||
1701 | static int __init parse_disable_lapic_timer(char *arg) | 1745 | /* same as disableapic, for compatibility */ |
1746 | static int __init setup_nolapic(char *arg) | ||
1702 | { | 1747 | { |
1703 | local_apic_timer_disabled = 1; | 1748 | return setup_disableapic(arg); |
1704 | return 0; | ||
1705 | } | 1749 | } |
1706 | early_param("nolapic_timer", parse_disable_lapic_timer); | 1750 | early_param("nolapic", setup_nolapic); |
1707 | 1751 | ||
1708 | static int __init parse_lapic_timer_c2_ok(char *arg) | 1752 | static int __init parse_lapic_timer_c2_ok(char *arg) |
1709 | { | 1753 | { |
@@ -1712,15 +1756,40 @@ static int __init parse_lapic_timer_c2_ok(char *arg) | |||
1712 | } | 1756 | } |
1713 | early_param("lapic_timer_c2_ok", parse_lapic_timer_c2_ok); | 1757 | early_param("lapic_timer_c2_ok", parse_lapic_timer_c2_ok); |
1714 | 1758 | ||
1759 | static int __init parse_disable_apic_timer(char *arg) | ||
1760 | { | ||
1761 | disable_apic_timer = 1; | ||
1762 | return 0; | ||
1763 | } | ||
1764 | early_param("noapictimer", parse_disable_apic_timer); | ||
1765 | |||
1766 | static int __init parse_nolapic_timer(char *arg) | ||
1767 | { | ||
1768 | disable_apic_timer = 1; | ||
1769 | return 0; | ||
1770 | } | ||
1771 | early_param("nolapic_timer", parse_nolapic_timer); | ||
1772 | |||
1715 | static int __init apic_set_verbosity(char *arg) | 1773 | static int __init apic_set_verbosity(char *arg) |
1716 | { | 1774 | { |
1717 | if (!arg) | 1775 | if (!arg) { |
1776 | #ifdef CONFIG_X86_64 | ||
1777 | skip_ioapic_setup = 0; | ||
1778 | ioapic_force = 1; | ||
1779 | return 0; | ||
1780 | #endif | ||
1718 | return -EINVAL; | 1781 | return -EINVAL; |
1782 | } | ||
1719 | 1783 | ||
1720 | if (strcmp(arg, "debug") == 0) | 1784 | if (strcmp("debug", arg) == 0) |
1721 | apic_verbosity = APIC_DEBUG; | 1785 | apic_verbosity = APIC_DEBUG; |
1722 | else if (strcmp(arg, "verbose") == 0) | 1786 | else if (strcmp("verbose", arg) == 0) |
1723 | apic_verbosity = APIC_VERBOSE; | 1787 | apic_verbosity = APIC_VERBOSE; |
1788 | else { | ||
1789 | printk(KERN_WARNING "APIC Verbosity level %s not recognised" | ||
1790 | " use apic=verbose or apic=debug\n", arg); | ||
1791 | return -EINVAL; | ||
1792 | } | ||
1724 | 1793 | ||
1725 | return 0; | 1794 | return 0; |
1726 | } | 1795 | } |