fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / arch / i386 / kernel / apic-xen.c
1 /*
2  *      Local APIC handling, local APIC timers
3  *
4  *      (c) 1999, 2000 Ingo Molnar <mingo@redhat.com>
5  *
6  *      Fixes
7  *      Maciej W. Rozycki       :       Bits for genuine 82489DX APICs;
8  *                                      thanks to Eric Gilmore
9  *                                      and Rolf G. Tews
10  *                                      for testing these extensively.
11  *      Maciej W. Rozycki       :       Various updates and fixes.
12  *      Mikael Pettersson       :       Power Management for UP-APIC.
13  *      Pavel Machek and
14  *      Mikael Pettersson       :       PM converted to driver model.
15  */
16
17 #include <linux/init.h>
18
19 #include <linux/mm.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>
29
30 #include <asm/atomic.h>
31 #include <asm/smp.h>
32 #include <asm/mtrr.h>
33 #include <asm/mpspec.h>
34 #include <asm/desc.h>
35 #include <asm/arch_hooks.h>
36 #include <asm/hpet.h>
37 #include <asm/i8253.h>
38 #include <asm/nmi.h>
39
40 #include <mach_apic.h>
41 #include <mach_apicdef.h>
42 #include <mach_ipi.h>
43
44 #include "io_ports.h"
45
46 #ifndef CONFIG_XEN
47 /*
48  * cpu_mask that denotes the CPUs that needs timer interrupt coming in as
49  * IPIs in place of local APIC timers
50  */
51 static cpumask_t timer_bcast_ipi;
52 #endif
53
54 /*
55  * Knob to control our willingness to enable the local APIC.
56  */
57 static int enable_local_apic __initdata = 0; /* -1=force-disable, +1=force-enable */
58
59 static inline void lapic_disable(void)
60 {
61         enable_local_apic = -1;
62         clear_bit(X86_FEATURE_APIC, boot_cpu_data.x86_capability);
63 }
64
65 static inline void lapic_enable(void)
66 {
67         enable_local_apic = 1;
68 }
69
70 /*
71  * Debug level
72  */
73 int apic_verbosity;
74
75 static int modern_apic(void)
76 {
77 #ifndef CONFIG_XEN
78         unsigned int lvr, version;
79         /* AMD systems use old APIC versions, so check the CPU */
80         if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD &&
81                 boot_cpu_data.x86 >= 0xf)
82                 return 1;
83         lvr = apic_read(APIC_LVR);
84         version = GET_APIC_VERSION(lvr);
85         return version >= 0x14;
86 #else
87         return 1;
88 #endif
89 }
90
91 /*
92  * 'what should we do if we get a hw irq event on an illegal vector'.
93  * each architecture has to answer this themselves.
94  */
95 void ack_bad_irq(unsigned int irq)
96 {
97         printk("unexpected IRQ trap at vector %02x\n", irq);
98         /*
99          * Currently unexpected vectors happen only on SMP and APIC.
100          * We _must_ ack these because every local APIC has only N
101          * irq slots per priority level, and a 'hanging, unacked' IRQ
102          * holds up an irq slot - in excessive cases (when multiple
103          * unexpected vectors occur) that might lock up the APIC
104          * completely.
105          * But only ack when the APIC is enabled -AK
106          */
107         if (cpu_has_apic)
108                 ack_APIC_irq();
109 }
110
111 #ifndef CONFIG_XEN
112 void __init apic_intr_init(void)
113 {
114 #ifdef CONFIG_SMP
115         smp_intr_init();
116 #endif
117         /* self generated IPI for local APIC timer */
118         set_intr_gate(LOCAL_TIMER_VECTOR, apic_timer_interrupt);
119
120         /* IPI vectors for APIC spurious and error interrupts */
121         set_intr_gate(SPURIOUS_APIC_VECTOR, spurious_interrupt);
122         set_intr_gate(ERROR_APIC_VECTOR, error_interrupt);
123
124         /* thermal monitor LVT interrupt */
125 #ifdef CONFIG_X86_MCE_P4THERMAL
126         set_intr_gate(THERMAL_APIC_VECTOR, thermal_interrupt);
127 #endif
128 }
129
130 /* Using APIC to generate smp_local_timer_interrupt? */
131 int using_apic_timer __read_mostly = 0;
132
133 static int enabled_via_apicbase;
134
135 void enable_NMI_through_LVT0 (void * dummy)
136 {
137         unsigned int v, ver;
138
139         ver = apic_read(APIC_LVR);
140         ver = GET_APIC_VERSION(ver);
141         v = APIC_DM_NMI;                        /* unmask and set to NMI */
142         if (!APIC_INTEGRATED(ver))              /* 82489DX */
143                 v |= APIC_LVT_LEVEL_TRIGGER;
144         apic_write_around(APIC_LVT0, v);
145 }
146 #endif /* !CONFIG_XEN */
147
148 int get_physical_broadcast(void)
149 {
150         if (modern_apic())
151                 return 0xff;
152         else
153                 return 0xf;
154 }
155
156 #ifndef CONFIG_XEN
157 #ifndef CONFIG_SMP
158 static void up_apic_timer_interrupt_call(void)
159 {
160         int cpu = smp_processor_id();
161
162         /*
163          * the NMI deadlock-detector uses this.
164          */
165         per_cpu(irq_stat, cpu).apic_timer_irqs++;
166
167         smp_local_timer_interrupt();
168 }
169 #endif
170
171 void smp_send_timer_broadcast_ipi(void)
172 {
173         cpumask_t mask;
174
175         cpus_and(mask, cpu_online_map, timer_bcast_ipi);
176         if (!cpus_empty(mask)) {
177 #ifdef CONFIG_SMP
178                 send_IPI_mask(mask, LOCAL_TIMER_VECTOR);
179 #else
180                 /*
181                  * We can directly call the apic timer interrupt handler
182                  * in UP case. Minus all irq related functions
183                  */
184                 up_apic_timer_interrupt_call();
185 #endif
186         }
187 }
188 #endif
189
190 int setup_profiling_timer(unsigned int multiplier)
191 {
192         return -EINVAL;
193 }
194
195 /*
196  * This initializes the IO-APIC and APIC hardware if this is
197  * a UP kernel.
198  */
199 int __init APIC_init_uniprocessor (void)
200 {
201 #ifdef CONFIG_X86_IO_APIC
202         if (smp_found_config)
203                 if (!skip_ioapic_setup && nr_ioapics)
204                         setup_IO_APIC();
205 #endif
206
207         return 0;
208 }
209
210 static int __init parse_lapic(char *arg)
211 {
212         lapic_enable();
213         return 0;
214 }
215 early_param("lapic", parse_lapic);
216
217 static int __init parse_nolapic(char *arg)
218 {
219         lapic_disable();
220         return 0;
221 }
222 early_param("nolapic", parse_nolapic);
223