2 * Local APIC handling, local APIC timers
4 * (c) 1999, 2000 Ingo Molnar <mingo@redhat.com>
7 * Maciej W. Rozycki : Bits for genuine 82489DX APICs;
8 * thanks to Eric Gilmore
10 * for testing these extensively.
11 * Maciej W. Rozycki : Various updates and fixes.
12 * Mikael Pettersson : Power Management for UP-APIC.
14 * Mikael Pettersson : PM converted to driver model.
17 #include <linux/init.h>
20 #include <linux/delay.h>
21 #include <linux/bootmem.h>
22 #include <linux/smp_lock.h>
23 #include <linux/interrupt.h>
24 #include <linux/mc146818rtc.h>
25 #include <linux/kernel_stat.h>
26 #include <linux/sysdev.h>
27 #include <linux/cpu.h>
28 #include <linux/module.h>
30 #include <asm/atomic.h>
33 #include <asm/mpspec.h>
35 #include <asm/arch_hooks.h>
37 #include <asm/i8253.h>
40 #include <mach_apic.h>
41 #include <mach_apicdef.h>
48 * cpu_mask that denotes the CPUs that needs timer interrupt coming in as
49 * IPIs in place of local APIC timers
51 static cpumask_t timer_bcast_ipi;
55 * Knob to control our willingness to enable the local APIC.
57 int enable_local_apic __initdata = 0; /* -1=force-disable, +1=force-enable */
64 static int modern_apic(void)
67 unsigned int lvr, version;
68 /* AMD systems use old APIC versions, so check the CPU */
69 if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD &&
70 boot_cpu_data.x86 >= 0xf)
72 lvr = apic_read(APIC_LVR);
73 version = GET_APIC_VERSION(lvr);
74 return version >= 0x14;
81 * 'what should we do if we get a hw irq event on an illegal vector'.
82 * each architecture has to answer this themselves.
84 void ack_bad_irq(unsigned int irq)
86 printk("unexpected IRQ trap at vector %02x\n", irq);
88 * Currently unexpected vectors happen only on SMP and APIC.
89 * We _must_ ack these because every local APIC has only N
90 * irq slots per priority level, and a 'hanging, unacked' IRQ
91 * holds up an irq slot - in excessive cases (when multiple
92 * unexpected vectors occur) that might lock up the APIC
94 * But only ack when the APIC is enabled -AK
100 int get_physical_broadcast(void)
110 static void up_apic_timer_interrupt_call(struct pt_regs *regs)
112 int cpu = smp_processor_id();
115 * the NMI deadlock-detector uses this.
117 per_cpu(irq_stat, cpu).apic_timer_irqs++;
119 smp_local_timer_interrupt(regs);
123 void smp_send_timer_broadcast_ipi(struct pt_regs *regs)
127 cpus_and(mask, cpu_online_map, timer_bcast_ipi);
128 if (!cpus_empty(mask)) {
130 send_IPI_mask(mask, LOCAL_TIMER_VECTOR);
133 * We can directly call the apic timer interrupt handler
134 * in UP case. Minus all irq related functions
136 up_apic_timer_interrupt_call(regs);
142 int setup_profiling_timer(unsigned int multiplier)
148 * This initializes the IO-APIC and APIC hardware if this is
151 int __init APIC_init_uniprocessor (void)
153 #ifdef CONFIG_X86_IO_APIC
154 if (smp_found_config)
155 if (!skip_ioapic_setup && nr_ioapics)