diff options
author | Thomas Gleixner <tglx@linutronix.de> | 2007-10-11 05:17:24 -0400 |
---|---|---|
committer | Thomas Gleixner <tglx@linutronix.de> | 2007-10-11 05:17:24 -0400 |
commit | 250c22777fe1ccd7ac588579a6c16db4c0161cc5 (patch) | |
tree | 55c317efb7d792ec6fdae1d1937c67a502c48dec /arch/x86/kernel/apic_64.c | |
parent | 2db55d344e529492545cb3b755c7e9ba8e4fa94e (diff) |
x86_64: move kernel
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch/x86/kernel/apic_64.c')
-rw-r--r-- | arch/x86/kernel/apic_64.c | 1253 |
1 files changed, 1253 insertions, 0 deletions
diff --git a/arch/x86/kernel/apic_64.c b/arch/x86/kernel/apic_64.c new file mode 100644 index 000000000000..925758dbca0c --- /dev/null +++ b/arch/x86/kernel/apic_64.c | |||
@@ -0,0 +1,1253 @@ | |||
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/interrupt.h> | ||
23 | #include <linux/mc146818rtc.h> | ||
24 | #include <linux/kernel_stat.h> | ||
25 | #include <linux/sysdev.h> | ||
26 | #include <linux/module.h> | ||
27 | #include <linux/ioport.h> | ||
28 | |||
29 | #include <asm/atomic.h> | ||
30 | #include <asm/smp.h> | ||
31 | #include <asm/mtrr.h> | ||
32 | #include <asm/mpspec.h> | ||
33 | #include <asm/pgalloc.h> | ||
34 | #include <asm/mach_apic.h> | ||
35 | #include <asm/nmi.h> | ||
36 | #include <asm/idle.h> | ||
37 | #include <asm/proto.h> | ||
38 | #include <asm/timex.h> | ||
39 | #include <asm/hpet.h> | ||
40 | #include <asm/apic.h> | ||
41 | |||
42 | int apic_mapped; | ||
43 | int apic_verbosity; | ||
44 | int apic_runs_main_timer; | ||
45 | int apic_calibrate_pmtmr __initdata; | ||
46 | |||
47 | int disable_apic_timer __initdata; | ||
48 | |||
49 | /* Local APIC timer works in C2? */ | ||
50 | int local_apic_timer_c2_ok; | ||
51 | EXPORT_SYMBOL_GPL(local_apic_timer_c2_ok); | ||
52 | |||
53 | static struct resource *ioapic_resources; | ||
54 | static struct resource lapic_resource = { | ||
55 | .name = "Local APIC", | ||
56 | .flags = IORESOURCE_MEM | IORESOURCE_BUSY, | ||
57 | }; | ||
58 | |||
59 | /* | ||
60 | * cpu_mask that denotes the CPUs that needs timer interrupt coming in as | ||
61 | * IPIs in place of local APIC timers | ||
62 | */ | ||
63 | static cpumask_t timer_interrupt_broadcast_ipi_mask; | ||
64 | |||
65 | /* Using APIC to generate smp_local_timer_interrupt? */ | ||
66 | int using_apic_timer __read_mostly = 0; | ||
67 | |||
68 | static void apic_pm_activate(void); | ||
69 | |||
70 | void apic_wait_icr_idle(void) | ||
71 | { | ||
72 | while (apic_read(APIC_ICR) & APIC_ICR_BUSY) | ||
73 | cpu_relax(); | ||
74 | } | ||
75 | |||
76 | unsigned int safe_apic_wait_icr_idle(void) | ||
77 | { | ||
78 | unsigned int send_status; | ||
79 | int timeout; | ||
80 | |||
81 | timeout = 0; | ||
82 | do { | ||
83 | send_status = apic_read(APIC_ICR) & APIC_ICR_BUSY; | ||
84 | if (!send_status) | ||
85 | break; | ||
86 | udelay(100); | ||
87 | } while (timeout++ < 1000); | ||
88 | |||
89 | return send_status; | ||
90 | } | ||
91 | |||
92 | void enable_NMI_through_LVT0 (void * dummy) | ||
93 | { | ||
94 | unsigned int v; | ||
95 | |||
96 | /* unmask and set to NMI */ | ||
97 | v = APIC_DM_NMI; | ||
98 | apic_write(APIC_LVT0, v); | ||
99 | } | ||
100 | |||
101 | int get_maxlvt(void) | ||
102 | { | ||
103 | unsigned int v, maxlvt; | ||
104 | |||
105 | v = apic_read(APIC_LVR); | ||
106 | maxlvt = GET_APIC_MAXLVT(v); | ||
107 | return maxlvt; | ||
108 | } | ||
109 | |||
110 | /* | ||
111 | * 'what should we do if we get a hw irq event on an illegal vector'. | ||
112 | * each architecture has to answer this themselves. | ||
113 | */ | ||
114 | void ack_bad_irq(unsigned int irq) | ||
115 | { | ||
116 | printk("unexpected IRQ trap at vector %02x\n", irq); | ||
117 | /* | ||
118 | * Currently unexpected vectors happen only on SMP and APIC. | ||
119 | * We _must_ ack these because every local APIC has only N | ||
120 | * irq slots per priority level, and a 'hanging, unacked' IRQ | ||
121 | * holds up an irq slot - in excessive cases (when multiple | ||
122 | * unexpected vectors occur) that might lock up the APIC | ||
123 | * completely. | ||
124 | * But don't ack when the APIC is disabled. -AK | ||
125 | */ | ||
126 | if (!disable_apic) | ||
127 | ack_APIC_irq(); | ||
128 | } | ||
129 | |||
130 | void clear_local_APIC(void) | ||
131 | { | ||
132 | int maxlvt; | ||
133 | unsigned int v; | ||
134 | |||
135 | maxlvt = get_maxlvt(); | ||
136 | |||
137 | /* | ||
138 | * Masking an LVT entry can trigger a local APIC error | ||
139 | * if the vector is zero. Mask LVTERR first to prevent this. | ||
140 | */ | ||
141 | if (maxlvt >= 3) { | ||
142 | v = ERROR_APIC_VECTOR; /* any non-zero vector will do */ | ||
143 | apic_write(APIC_LVTERR, v | APIC_LVT_MASKED); | ||
144 | } | ||
145 | /* | ||
146 | * Careful: we have to set masks only first to deassert | ||
147 | * any level-triggered sources. | ||
148 | */ | ||
149 | v = apic_read(APIC_LVTT); | ||
150 | apic_write(APIC_LVTT, v | APIC_LVT_MASKED); | ||
151 | v = apic_read(APIC_LVT0); | ||
152 | apic_write(APIC_LVT0, v | APIC_LVT_MASKED); | ||
153 | v = apic_read(APIC_LVT1); | ||
154 | apic_write(APIC_LVT1, v | APIC_LVT_MASKED); | ||
155 | if (maxlvt >= 4) { | ||
156 | v = apic_read(APIC_LVTPC); | ||
157 | apic_write(APIC_LVTPC, v | APIC_LVT_MASKED); | ||
158 | } | ||
159 | |||
160 | /* | ||
161 | * Clean APIC state for other OSs: | ||
162 | */ | ||
163 | apic_write(APIC_LVTT, APIC_LVT_MASKED); | ||
164 | apic_write(APIC_LVT0, APIC_LVT_MASKED); | ||
165 | apic_write(APIC_LVT1, APIC_LVT_MASKED); | ||
166 | if (maxlvt >= 3) | ||
167 | apic_write(APIC_LVTERR, APIC_LVT_MASKED); | ||
168 | if (maxlvt >= 4) | ||
169 | apic_write(APIC_LVTPC, APIC_LVT_MASKED); | ||
170 | apic_write(APIC_ESR, 0); | ||
171 | apic_read(APIC_ESR); | ||
172 | } | ||
173 | |||
174 | void disconnect_bsp_APIC(int virt_wire_setup) | ||
175 | { | ||
176 | /* Go back to Virtual Wire compatibility mode */ | ||
177 | unsigned long value; | ||
178 | |||
179 | /* For the spurious interrupt use vector F, and enable it */ | ||
180 | value = apic_read(APIC_SPIV); | ||
181 | value &= ~APIC_VECTOR_MASK; | ||
182 | value |= APIC_SPIV_APIC_ENABLED; | ||
183 | value |= 0xf; | ||
184 | apic_write(APIC_SPIV, value); | ||
185 | |||
186 | if (!virt_wire_setup) { | ||
187 | /* For LVT0 make it edge triggered, active high, external and enabled */ | ||
188 | value = apic_read(APIC_LVT0); | ||
189 | value &= ~(APIC_MODE_MASK | APIC_SEND_PENDING | | ||
190 | APIC_INPUT_POLARITY | APIC_LVT_REMOTE_IRR | | ||
191 | APIC_LVT_LEVEL_TRIGGER | APIC_LVT_MASKED ); | ||
192 | value |= APIC_LVT_REMOTE_IRR | APIC_SEND_PENDING; | ||
193 | value = SET_APIC_DELIVERY_MODE(value, APIC_MODE_EXTINT); | ||
194 | apic_write(APIC_LVT0, value); | ||
195 | } else { | ||
196 | /* Disable LVT0 */ | ||
197 | apic_write(APIC_LVT0, APIC_LVT_MASKED); | ||
198 | } | ||
199 | |||
200 | /* For LVT1 make it edge triggered, active high, nmi and enabled */ | ||
201 | value = apic_read(APIC_LVT1); | ||
202 | value &= ~(APIC_MODE_MASK | APIC_SEND_PENDING | | ||
203 | APIC_INPUT_POLARITY | APIC_LVT_REMOTE_IRR | | ||
204 | APIC_LVT_LEVEL_TRIGGER | APIC_LVT_MASKED); | ||
205 | value |= APIC_LVT_REMOTE_IRR | APIC_SEND_PENDING; | ||
206 | value = SET_APIC_DELIVERY_MODE(value, APIC_MODE_NMI); | ||
207 | apic_write(APIC_LVT1, value); | ||
208 | } | ||
209 | |||
210 | void disable_local_APIC(void) | ||
211 | { | ||
212 | unsigned int value; | ||
213 | |||
214 | clear_local_APIC(); | ||
215 | |||
216 | /* | ||
217 | * Disable APIC (implies clearing of registers | ||
218 | * for 82489DX!). | ||
219 | */ | ||
220 | value = apic_read(APIC_SPIV); | ||
221 | value &= ~APIC_SPIV_APIC_ENABLED; | ||
222 | apic_write(APIC_SPIV, value); | ||
223 | } | ||
224 | |||
225 | /* | ||
226 | * This is to verify that we're looking at a real local APIC. | ||
227 | * Check these against your board if the CPUs aren't getting | ||
228 | * started for no apparent reason. | ||
229 | */ | ||
230 | int __init verify_local_APIC(void) | ||
231 | { | ||
232 | unsigned int reg0, reg1; | ||
233 | |||
234 | /* | ||
235 | * The version register is read-only in a real APIC. | ||
236 | */ | ||
237 | reg0 = apic_read(APIC_LVR); | ||
238 | apic_printk(APIC_DEBUG, "Getting VERSION: %x\n", reg0); | ||
239 | apic_write(APIC_LVR, reg0 ^ APIC_LVR_MASK); | ||
240 | reg1 = apic_read(APIC_LVR); | ||
241 | apic_printk(APIC_DEBUG, "Getting VERSION: %x\n", reg1); | ||
242 | |||
243 | /* | ||
244 | * The two version reads above should print the same | ||
245 | * numbers. If the second one is different, then we | ||
246 | * poke at a non-APIC. | ||
247 | */ | ||
248 | if (reg1 != reg0) | ||
249 | return 0; | ||
250 | |||
251 | /* | ||
252 | * Check if the version looks reasonably. | ||
253 | */ | ||
254 | reg1 = GET_APIC_VERSION(reg0); | ||
255 | if (reg1 == 0x00 || reg1 == 0xff) | ||
256 | return 0; | ||
257 | reg1 = get_maxlvt(); | ||
258 | if (reg1 < 0x02 || reg1 == 0xff) | ||
259 | return 0; | ||
260 | |||
261 | /* | ||
262 | * The ID register is read/write in a real APIC. | ||
263 | */ | ||
264 | reg0 = apic_read(APIC_ID); | ||
265 | apic_printk(APIC_DEBUG, "Getting ID: %x\n", reg0); | ||
266 | apic_write(APIC_ID, reg0 ^ APIC_ID_MASK); | ||
267 | reg1 = apic_read(APIC_ID); | ||
268 | apic_printk(APIC_DEBUG, "Getting ID: %x\n", reg1); | ||
269 | apic_write(APIC_ID, reg0); | ||
270 | if (reg1 != (reg0 ^ APIC_ID_MASK)) | ||
271 | return 0; | ||
272 | |||
273 | /* | ||
274 | * The next two are just to see if we have sane values. | ||
275 | * They're only really relevant if we're in Virtual Wire | ||
276 | * compatibility mode, but most boxes are anymore. | ||
277 | */ | ||
278 | reg0 = apic_read(APIC_LVT0); | ||
279 | apic_printk(APIC_DEBUG,"Getting LVT0: %x\n", reg0); | ||
280 | reg1 = apic_read(APIC_LVT1); | ||
281 | apic_printk(APIC_DEBUG, "Getting LVT1: %x\n", reg1); | ||
282 | |||
283 | return 1; | ||
284 | } | ||
285 | |||
286 | void __init sync_Arb_IDs(void) | ||
287 | { | ||
288 | /* Unsupported on P4 - see Intel Dev. Manual Vol. 3, Ch. 8.6.1 */ | ||
289 | unsigned int ver = GET_APIC_VERSION(apic_read(APIC_LVR)); | ||
290 | if (ver >= 0x14) /* P4 or higher */ | ||
291 | return; | ||
292 | |||
293 | /* | ||
294 | * Wait for idle. | ||
295 | */ | ||
296 | apic_wait_icr_idle(); | ||
297 | |||
298 | apic_printk(APIC_DEBUG, "Synchronizing Arb IDs.\n"); | ||
299 | apic_write(APIC_ICR, APIC_DEST_ALLINC | APIC_INT_LEVELTRIG | ||
300 | | APIC_DM_INIT); | ||
301 | } | ||
302 | |||
303 | /* | ||
304 | * An initial setup of the virtual wire mode. | ||
305 | */ | ||
306 | void __init init_bsp_APIC(void) | ||
307 | { | ||
308 | unsigned int value; | ||
309 | |||
310 | /* | ||
311 | * Don't do the setup now if we have a SMP BIOS as the | ||
312 | * through-I/O-APIC virtual wire mode might be active. | ||
313 | */ | ||
314 | if (smp_found_config || !cpu_has_apic) | ||
315 | return; | ||
316 | |||
317 | value = apic_read(APIC_LVR); | ||
318 | |||
319 | /* | ||
320 | * Do not trust the local APIC being empty at bootup. | ||
321 | */ | ||
322 | clear_local_APIC(); | ||
323 | |||
324 | /* | ||
325 | * Enable APIC. | ||
326 | */ | ||
327 | value = apic_read(APIC_SPIV); | ||
328 | value &= ~APIC_VECTOR_MASK; | ||
329 | value |= APIC_SPIV_APIC_ENABLED; | ||
330 | value |= APIC_SPIV_FOCUS_DISABLED; | ||
331 | value |= SPURIOUS_APIC_VECTOR; | ||
332 | apic_write(APIC_SPIV, value); | ||
333 | |||
334 | /* | ||
335 | * Set up the virtual wire mode. | ||
336 | */ | ||
337 | apic_write(APIC_LVT0, APIC_DM_EXTINT); | ||
338 | value = APIC_DM_NMI; | ||
339 | apic_write(APIC_LVT1, value); | ||
340 | } | ||
341 | |||
342 | void __cpuinit setup_local_APIC (void) | ||
343 | { | ||
344 | unsigned int value, maxlvt; | ||
345 | int i, j; | ||
346 | |||
347 | value = apic_read(APIC_LVR); | ||
348 | |||
349 | BUILD_BUG_ON((SPURIOUS_APIC_VECTOR & 0x0f) != 0x0f); | ||
350 | |||
351 | /* | ||
352 | * Double-check whether this APIC is really registered. | ||
353 | * This is meaningless in clustered apic mode, so we skip it. | ||
354 | */ | ||
355 | if (!apic_id_registered()) | ||
356 | BUG(); | ||
357 | |||
358 | /* | ||
359 | * Intel recommends to set DFR, LDR and TPR before enabling | ||
360 | * an APIC. See e.g. "AP-388 82489DX User's Manual" (Intel | ||
361 | * document number 292116). So here it goes... | ||
362 | */ | ||
363 | init_apic_ldr(); | ||
364 | |||
365 | /* | ||
366 | * Set Task Priority to 'accept all'. We never change this | ||
367 | * later on. | ||
368 | */ | ||
369 | value = apic_read(APIC_TASKPRI); | ||
370 | value &= ~APIC_TPRI_MASK; | ||
371 | apic_write(APIC_TASKPRI, value); | ||
372 | |||
373 | /* | ||
374 | * After a crash, we no longer service the interrupts and a pending | ||
375 | * interrupt from previous kernel might still have ISR bit set. | ||
376 | * | ||
377 | * Most probably by now CPU has serviced that pending interrupt and | ||
378 | * it might not have done the ack_APIC_irq() because it thought, | ||
379 | * interrupt came from i8259 as ExtInt. LAPIC did not get EOI so it | ||
380 | * does not clear the ISR bit and cpu thinks it has already serivced | ||
381 | * the interrupt. Hence a vector might get locked. It was noticed | ||
382 | * for timer irq (vector 0x31). Issue an extra EOI to clear ISR. | ||
383 | */ | ||
384 | for (i = APIC_ISR_NR - 1; i >= 0; i--) { | ||
385 | value = apic_read(APIC_ISR + i*0x10); | ||
386 | for (j = 31; j >= 0; j--) { | ||
387 | if (value & (1<<j)) | ||
388 | ack_APIC_irq(); | ||
389 | } | ||
390 | } | ||
391 | |||
392 | /* | ||
393 | * Now that we are all set up, enable the APIC | ||
394 | */ | ||
395 | value = apic_read(APIC_SPIV); | ||
396 | value &= ~APIC_VECTOR_MASK; | ||
397 | /* | ||
398 | * Enable APIC | ||
399 | */ | ||
400 | value |= APIC_SPIV_APIC_ENABLED; | ||
401 | |||
402 | /* We always use processor focus */ | ||
403 | |||
404 | /* | ||
405 | * Set spurious IRQ vector | ||
406 | */ | ||
407 | value |= SPURIOUS_APIC_VECTOR; | ||
408 | apic_write(APIC_SPIV, value); | ||
409 | |||
410 | /* | ||
411 | * Set up LVT0, LVT1: | ||
412 | * | ||
413 | * set up through-local-APIC on the BP's LINT0. This is not | ||
414 | * strictly necessary in pure symmetric-IO mode, but sometimes | ||
415 | * we delegate interrupts to the 8259A. | ||
416 | */ | ||
417 | /* | ||
418 | * TODO: set up through-local-APIC from through-I/O-APIC? --macro | ||
419 | */ | ||
420 | value = apic_read(APIC_LVT0) & APIC_LVT_MASKED; | ||
421 | if (!smp_processor_id() && !value) { | ||
422 | value = APIC_DM_EXTINT; | ||
423 | apic_printk(APIC_VERBOSE, "enabled ExtINT on CPU#%d\n", smp_processor_id()); | ||
424 | } else { | ||
425 | value = APIC_DM_EXTINT | APIC_LVT_MASKED; | ||
426 | apic_printk(APIC_VERBOSE, "masked ExtINT on CPU#%d\n", smp_processor_id()); | ||
427 | } | ||
428 | apic_write(APIC_LVT0, value); | ||
429 | |||
430 | /* | ||
431 | * only the BP should see the LINT1 NMI signal, obviously. | ||
432 | */ | ||
433 | if (!smp_processor_id()) | ||
434 | value = APIC_DM_NMI; | ||
435 | else | ||
436 | value = APIC_DM_NMI | APIC_LVT_MASKED; | ||
437 | apic_write(APIC_LVT1, value); | ||
438 | |||
439 | { | ||
440 | unsigned oldvalue; | ||
441 | maxlvt = get_maxlvt(); | ||
442 | oldvalue = apic_read(APIC_ESR); | ||
443 | value = ERROR_APIC_VECTOR; // enables sending errors | ||
444 | apic_write(APIC_LVTERR, value); | ||
445 | /* | ||
446 | * spec says clear errors after enabling vector. | ||
447 | */ | ||
448 | if (maxlvt > 3) | ||
449 | apic_write(APIC_ESR, 0); | ||
450 | value = apic_read(APIC_ESR); | ||
451 | if (value != oldvalue) | ||
452 | apic_printk(APIC_VERBOSE, | ||
453 | "ESR value after enabling vector: %08x, after %08x\n", | ||
454 | oldvalue, value); | ||
455 | } | ||
456 | |||
457 | nmi_watchdog_default(); | ||
458 | setup_apic_nmi_watchdog(NULL); | ||
459 | apic_pm_activate(); | ||
460 | } | ||
461 | |||
462 | #ifdef CONFIG_PM | ||
463 | |||
464 | static struct { | ||
465 | /* 'active' is true if the local APIC was enabled by us and | ||
466 | not the BIOS; this signifies that we are also responsible | ||
467 | for disabling it before entering apm/acpi suspend */ | ||
468 | int active; | ||
469 | /* r/w apic fields */ | ||
470 | unsigned int apic_id; | ||
471 | unsigned int apic_taskpri; | ||
472 | unsigned int apic_ldr; | ||
473 | unsigned int apic_dfr; | ||
474 | unsigned int apic_spiv; | ||
475 | unsigned int apic_lvtt; | ||
476 | unsigned int apic_lvtpc; | ||
477 | unsigned int apic_lvt0; | ||
478 | unsigned int apic_lvt1; | ||
479 | unsigned int apic_lvterr; | ||
480 | unsigned int apic_tmict; | ||
481 | unsigned int apic_tdcr; | ||
482 | unsigned int apic_thmr; | ||
483 | } apic_pm_state; | ||
484 | |||
485 | static int lapic_suspend(struct sys_device *dev, pm_message_t state) | ||
486 | { | ||
487 | unsigned long flags; | ||
488 | int maxlvt; | ||
489 | |||
490 | if (!apic_pm_state.active) | ||
491 | return 0; | ||
492 | |||
493 | maxlvt = get_maxlvt(); | ||
494 | |||
495 | apic_pm_state.apic_id = apic_read(APIC_ID); | ||
496 | apic_pm_state.apic_taskpri = apic_read(APIC_TASKPRI); | ||
497 | apic_pm_state.apic_ldr = apic_read(APIC_LDR); | ||
498 | apic_pm_state.apic_dfr = apic_read(APIC_DFR); | ||
499 | apic_pm_state.apic_spiv = apic_read(APIC_SPIV); | ||
500 | apic_pm_state.apic_lvtt = apic_read(APIC_LVTT); | ||
501 | if (maxlvt >= 4) | ||
502 | apic_pm_state.apic_lvtpc = apic_read(APIC_LVTPC); | ||
503 | apic_pm_state.apic_lvt0 = apic_read(APIC_LVT0); | ||
504 | apic_pm_state.apic_lvt1 = apic_read(APIC_LVT1); | ||
505 | apic_pm_state.apic_lvterr = apic_read(APIC_LVTERR); | ||
506 | apic_pm_state.apic_tmict = apic_read(APIC_TMICT); | ||
507 | apic_pm_state.apic_tdcr = apic_read(APIC_TDCR); | ||
508 | #ifdef CONFIG_X86_MCE_INTEL | ||
509 | if (maxlvt >= 5) | ||
510 | apic_pm_state.apic_thmr = apic_read(APIC_LVTTHMR); | ||
511 | #endif | ||
512 | local_irq_save(flags); | ||
513 | disable_local_APIC(); | ||
514 | local_irq_restore(flags); | ||
515 | return 0; | ||
516 | } | ||
517 | |||
518 | static int lapic_resume(struct sys_device *dev) | ||
519 | { | ||
520 | unsigned int l, h; | ||
521 | unsigned long flags; | ||
522 | int maxlvt; | ||
523 | |||
524 | if (!apic_pm_state.active) | ||
525 | return 0; | ||
526 | |||
527 | maxlvt = get_maxlvt(); | ||
528 | |||
529 | local_irq_save(flags); | ||
530 | rdmsr(MSR_IA32_APICBASE, l, h); | ||
531 | l &= ~MSR_IA32_APICBASE_BASE; | ||
532 | l |= MSR_IA32_APICBASE_ENABLE | mp_lapic_addr; | ||
533 | wrmsr(MSR_IA32_APICBASE, l, h); | ||
534 | apic_write(APIC_LVTERR, ERROR_APIC_VECTOR | APIC_LVT_MASKED); | ||
535 | apic_write(APIC_ID, apic_pm_state.apic_id); | ||
536 | apic_write(APIC_DFR, apic_pm_state.apic_dfr); | ||
537 | apic_write(APIC_LDR, apic_pm_state.apic_ldr); | ||
538 | apic_write(APIC_TASKPRI, apic_pm_state.apic_taskpri); | ||
539 | apic_write(APIC_SPIV, apic_pm_state.apic_spiv); | ||
540 | apic_write(APIC_LVT0, apic_pm_state.apic_lvt0); | ||
541 | apic_write(APIC_LVT1, apic_pm_state.apic_lvt1); | ||
542 | #ifdef CONFIG_X86_MCE_INTEL | ||
543 | if (maxlvt >= 5) | ||
544 | apic_write(APIC_LVTTHMR, apic_pm_state.apic_thmr); | ||
545 | #endif | ||
546 | if (maxlvt >= 4) | ||
547 | apic_write(APIC_LVTPC, apic_pm_state.apic_lvtpc); | ||
548 | apic_write(APIC_LVTT, apic_pm_state.apic_lvtt); | ||
549 | apic_write(APIC_TDCR, apic_pm_state.apic_tdcr); | ||
550 | apic_write(APIC_TMICT, apic_pm_state.apic_tmict); | ||
551 | apic_write(APIC_ESR, 0); | ||
552 | apic_read(APIC_ESR); | ||
553 | apic_write(APIC_LVTERR, apic_pm_state.apic_lvterr); | ||
554 | apic_write(APIC_ESR, 0); | ||
555 | apic_read(APIC_ESR); | ||
556 | local_irq_restore(flags); | ||
557 | return 0; | ||
558 | } | ||
559 | |||
560 | static struct sysdev_class lapic_sysclass = { | ||
561 | set_kset_name("lapic"), | ||
562 | .resume = lapic_resume, | ||
563 | .suspend = lapic_suspend, | ||
564 | }; | ||
565 | |||
566 | static struct sys_device device_lapic = { | ||
567 | .id = 0, | ||
568 | .cls = &lapic_sysclass, | ||
569 | }; | ||
570 | |||
571 | static void __cpuinit apic_pm_activate(void) | ||
572 | { | ||
573 | apic_pm_state.active = 1; | ||
574 | } | ||
575 | |||
576 | static int __init init_lapic_sysfs(void) | ||
577 | { | ||
578 | int error; | ||
579 | if (!cpu_has_apic) | ||
580 | return 0; | ||
581 | /* XXX: remove suspend/resume procs if !apic_pm_state.active? */ | ||
582 | error = sysdev_class_register(&lapic_sysclass); | ||
583 | if (!error) | ||
584 | error = sysdev_register(&device_lapic); | ||
585 | return error; | ||
586 | } | ||
587 | device_initcall(init_lapic_sysfs); | ||
588 | |||
589 | #else /* CONFIG_PM */ | ||
590 | |||
591 | static void apic_pm_activate(void) { } | ||
592 | |||
593 | #endif /* CONFIG_PM */ | ||
594 | |||
595 | static int __init apic_set_verbosity(char *str) | ||
596 | { | ||
597 | if (str == NULL) { | ||
598 | skip_ioapic_setup = 0; | ||
599 | ioapic_force = 1; | ||
600 | return 0; | ||
601 | } | ||
602 | if (strcmp("debug", str) == 0) | ||
603 | apic_verbosity = APIC_DEBUG; | ||
604 | else if (strcmp("verbose", str) == 0) | ||
605 | apic_verbosity = APIC_VERBOSE; | ||
606 | else { | ||
607 | printk(KERN_WARNING "APIC Verbosity level %s not recognised" | ||
608 | " use apic=verbose or apic=debug\n", str); | ||
609 | return -EINVAL; | ||
610 | } | ||
611 | |||
612 | return 0; | ||
613 | } | ||
614 | early_param("apic", apic_set_verbosity); | ||
615 | |||
616 | /* | ||
617 | * Detect and enable local APICs on non-SMP boards. | ||
618 | * Original code written by Keir Fraser. | ||
619 | * On AMD64 we trust the BIOS - if it says no APIC it is likely | ||
620 | * not correctly set up (usually the APIC timer won't work etc.) | ||
621 | */ | ||
622 | |||
623 | static int __init detect_init_APIC (void) | ||
624 | { | ||
625 | if (!cpu_has_apic) { | ||
626 | printk(KERN_INFO "No local APIC present\n"); | ||
627 | return -1; | ||
628 | } | ||
629 | |||
630 | mp_lapic_addr = APIC_DEFAULT_PHYS_BASE; | ||
631 | boot_cpu_id = 0; | ||
632 | return 0; | ||
633 | } | ||
634 | |||
635 | #ifdef CONFIG_X86_IO_APIC | ||
636 | static struct resource * __init ioapic_setup_resources(void) | ||
637 | { | ||
638 | #define IOAPIC_RESOURCE_NAME_SIZE 11 | ||
639 | unsigned long n; | ||
640 | struct resource *res; | ||
641 | char *mem; | ||
642 | int i; | ||
643 | |||
644 | if (nr_ioapics <= 0) | ||
645 | return NULL; | ||
646 | |||
647 | n = IOAPIC_RESOURCE_NAME_SIZE + sizeof(struct resource); | ||
648 | n *= nr_ioapics; | ||
649 | |||
650 | mem = alloc_bootmem(n); | ||
651 | res = (void *)mem; | ||
652 | |||
653 | if (mem != NULL) { | ||
654 | memset(mem, 0, n); | ||
655 | mem += sizeof(struct resource) * nr_ioapics; | ||
656 | |||
657 | for (i = 0; i < nr_ioapics; i++) { | ||
658 | res[i].name = mem; | ||
659 | res[i].flags = IORESOURCE_MEM | IORESOURCE_BUSY; | ||
660 | sprintf(mem, "IOAPIC %u", i); | ||
661 | mem += IOAPIC_RESOURCE_NAME_SIZE; | ||
662 | } | ||
663 | } | ||
664 | |||
665 | ioapic_resources = res; | ||
666 | |||
667 | return res; | ||
668 | } | ||
669 | |||
670 | static int __init ioapic_insert_resources(void) | ||
671 | { | ||
672 | int i; | ||
673 | struct resource *r = ioapic_resources; | ||
674 | |||
675 | if (!r) { | ||
676 | printk("IO APIC resources could be not be allocated.\n"); | ||
677 | return -1; | ||
678 | } | ||
679 | |||
680 | for (i = 0; i < nr_ioapics; i++) { | ||
681 | insert_resource(&iomem_resource, r); | ||
682 | r++; | ||
683 | } | ||
684 | |||
685 | return 0; | ||
686 | } | ||
687 | |||
688 | /* Insert the IO APIC resources after PCI initialization has occured to handle | ||
689 | * IO APICS that are mapped in on a BAR in PCI space. */ | ||
690 | late_initcall(ioapic_insert_resources); | ||
691 | #endif | ||
692 | |||
693 | void __init init_apic_mappings(void) | ||
694 | { | ||
695 | unsigned long apic_phys; | ||
696 | |||
697 | /* | ||
698 | * If no local APIC can be found then set up a fake all | ||
699 | * zeroes page to simulate the local APIC and another | ||
700 | * one for the IO-APIC. | ||
701 | */ | ||
702 | if (!smp_found_config && detect_init_APIC()) { | ||
703 | apic_phys = (unsigned long) alloc_bootmem_pages(PAGE_SIZE); | ||
704 | apic_phys = __pa(apic_phys); | ||
705 | } else | ||
706 | apic_phys = mp_lapic_addr; | ||
707 | |||
708 | set_fixmap_nocache(FIX_APIC_BASE, apic_phys); | ||
709 | apic_mapped = 1; | ||
710 | apic_printk(APIC_VERBOSE,"mapped APIC to %16lx (%16lx)\n", APIC_BASE, apic_phys); | ||
711 | |||
712 | /* Put local APIC into the resource map. */ | ||
713 | lapic_resource.start = apic_phys; | ||
714 | lapic_resource.end = lapic_resource.start + PAGE_SIZE - 1; | ||
715 | insert_resource(&iomem_resource, &lapic_resource); | ||
716 | |||
717 | /* | ||
718 | * Fetch the APIC ID of the BSP in case we have a | ||
719 | * default configuration (or the MP table is broken). | ||
720 | */ | ||
721 | boot_cpu_id = GET_APIC_ID(apic_read(APIC_ID)); | ||
722 | |||
723 | { | ||
724 | unsigned long ioapic_phys, idx = FIX_IO_APIC_BASE_0; | ||
725 | int i; | ||
726 | struct resource *ioapic_res; | ||
727 | |||
728 | ioapic_res = ioapic_setup_resources(); | ||
729 | for (i = 0; i < nr_ioapics; i++) { | ||
730 | if (smp_found_config) { | ||
731 | ioapic_phys = mp_ioapics[i].mpc_apicaddr; | ||
732 | } else { | ||
733 | ioapic_phys = (unsigned long) alloc_bootmem_pages(PAGE_SIZE); | ||
734 | ioapic_phys = __pa(ioapic_phys); | ||
735 | } | ||
736 | set_fixmap_nocache(idx, ioapic_phys); | ||
737 | apic_printk(APIC_VERBOSE,"mapped IOAPIC to %016lx (%016lx)\n", | ||
738 | __fix_to_virt(idx), ioapic_phys); | ||
739 | idx++; | ||
740 | |||
741 | if (ioapic_res != NULL) { | ||
742 | ioapic_res->start = ioapic_phys; | ||
743 | ioapic_res->end = ioapic_phys + (4 * 1024) - 1; | ||
744 | ioapic_res++; | ||
745 | } | ||
746 | } | ||
747 | } | ||
748 | } | ||
749 | |||
750 | /* | ||
751 | * This function sets up the local APIC timer, with a timeout of | ||
752 | * 'clocks' APIC bus clock. During calibration we actually call | ||
753 | * this function twice on the boot CPU, once with a bogus timeout | ||
754 | * value, second time for real. The other (noncalibrating) CPUs | ||
755 | * call this function only once, with the real, calibrated value. | ||
756 | * | ||
757 | * We do reads before writes even if unnecessary, to get around the | ||
758 | * P5 APIC double write bug. | ||
759 | */ | ||
760 | |||
761 | #define APIC_DIVISOR 16 | ||
762 | |||
763 | static void __setup_APIC_LVTT(unsigned int clocks) | ||
764 | { | ||
765 | unsigned int lvtt_value, tmp_value; | ||
766 | int cpu = smp_processor_id(); | ||
767 | |||
768 | lvtt_value = APIC_LVT_TIMER_PERIODIC | LOCAL_TIMER_VECTOR; | ||
769 | |||
770 | if (cpu_isset(cpu, timer_interrupt_broadcast_ipi_mask)) | ||
771 | lvtt_value |= APIC_LVT_MASKED; | ||
772 | |||
773 | apic_write(APIC_LVTT, lvtt_value); | ||
774 | |||
775 | /* | ||
776 | * Divide PICLK by 16 | ||
777 | */ | ||
778 | tmp_value = apic_read(APIC_TDCR); | ||
779 | apic_write(APIC_TDCR, (tmp_value | ||
780 | & ~(APIC_TDR_DIV_1 | APIC_TDR_DIV_TMBASE)) | ||
781 | | APIC_TDR_DIV_16); | ||
782 | |||
783 | apic_write(APIC_TMICT, clocks/APIC_DIVISOR); | ||
784 | } | ||
785 | |||
786 | static void setup_APIC_timer(unsigned int clocks) | ||
787 | { | ||
788 | unsigned long flags; | ||
789 | |||
790 | local_irq_save(flags); | ||
791 | |||
792 | /* wait for irq slice */ | ||
793 | if (hpet_address && hpet_use_timer) { | ||
794 | u32 trigger = hpet_readl(HPET_T0_CMP); | ||
795 | while (hpet_readl(HPET_T0_CMP) == trigger) | ||
796 | /* do nothing */ ; | ||
797 | } else { | ||
798 | int c1, c2; | ||
799 | outb_p(0x00, 0x43); | ||
800 | c2 = inb_p(0x40); | ||
801 | c2 |= inb_p(0x40) << 8; | ||
802 | do { | ||
803 | c1 = c2; | ||
804 | outb_p(0x00, 0x43); | ||
805 | c2 = inb_p(0x40); | ||
806 | c2 |= inb_p(0x40) << 8; | ||
807 | } while (c2 - c1 < 300); | ||
808 | } | ||
809 | __setup_APIC_LVTT(clocks); | ||
810 | /* Turn off PIT interrupt if we use APIC timer as main timer. | ||
811 | Only works with the PM timer right now | ||
812 | TBD fix it for HPET too. */ | ||
813 | if ((pmtmr_ioport != 0) && | ||
814 | smp_processor_id() == boot_cpu_id && | ||
815 | apic_runs_main_timer == 1 && | ||
816 | !cpu_isset(boot_cpu_id, timer_interrupt_broadcast_ipi_mask)) { | ||
817 | stop_timer_interrupt(); | ||
818 | apic_runs_main_timer++; | ||
819 | } | ||
820 | local_irq_restore(flags); | ||
821 | } | ||
822 | |||
823 | /* | ||
824 | * In this function we calibrate APIC bus clocks to the external | ||
825 | * timer. Unfortunately we cannot use jiffies and the timer irq | ||
826 | * to calibrate, since some later bootup code depends on getting | ||
827 | * the first irq? Ugh. | ||
828 | * | ||
829 | * We want to do the calibration only once since we | ||
830 | * want to have local timer irqs syncron. CPUs connected | ||
831 | * by the same APIC bus have the very same bus frequency. | ||
832 | * And we want to have irqs off anyways, no accidental | ||
833 | * APIC irq that way. | ||
834 | */ | ||
835 | |||
836 | #define TICK_COUNT 100000000 | ||
837 | |||
838 | static int __init calibrate_APIC_clock(void) | ||
839 | { | ||
840 | unsigned apic, apic_start; | ||
841 | unsigned long tsc, tsc_start; | ||
842 | int result; | ||
843 | /* | ||
844 | * Put whatever arbitrary (but long enough) timeout | ||
845 | * value into the APIC clock, we just want to get the | ||
846 | * counter running for calibration. | ||
847 | */ | ||
848 | __setup_APIC_LVTT(4000000000); | ||
849 | |||
850 | apic_start = apic_read(APIC_TMCCT); | ||
851 | #ifdef CONFIG_X86_PM_TIMER | ||
852 | if (apic_calibrate_pmtmr && pmtmr_ioport) { | ||
853 | pmtimer_wait(5000); /* 5ms wait */ | ||
854 | apic = apic_read(APIC_TMCCT); | ||
855 | result = (apic_start - apic) * 1000L / 5; | ||
856 | } else | ||
857 | #endif | ||
858 | { | ||
859 | rdtscll(tsc_start); | ||
860 | |||
861 | do { | ||
862 | apic = apic_read(APIC_TMCCT); | ||
863 | rdtscll(tsc); | ||
864 | } while ((tsc - tsc_start) < TICK_COUNT && | ||
865 | (apic_start - apic) < TICK_COUNT); | ||
866 | |||
867 | result = (apic_start - apic) * 1000L * tsc_khz / | ||
868 | (tsc - tsc_start); | ||
869 | } | ||
870 | printk("result %d\n", result); | ||
871 | |||
872 | |||
873 | printk(KERN_INFO "Detected %d.%03d MHz APIC timer.\n", | ||
874 | result / 1000 / 1000, result / 1000 % 1000); | ||
875 | |||
876 | return result * APIC_DIVISOR / HZ; | ||
877 | } | ||
878 | |||
879 | static unsigned int calibration_result; | ||
880 | |||
881 | void __init setup_boot_APIC_clock (void) | ||
882 | { | ||
883 | if (disable_apic_timer) { | ||
884 | printk(KERN_INFO "Disabling APIC timer\n"); | ||
885 | return; | ||
886 | } | ||
887 | |||
888 | printk(KERN_INFO "Using local APIC timer interrupts.\n"); | ||
889 | using_apic_timer = 1; | ||
890 | |||
891 | local_irq_disable(); | ||
892 | |||
893 | calibration_result = calibrate_APIC_clock(); | ||
894 | /* | ||
895 | * Now set up the timer for real. | ||
896 | */ | ||
897 | setup_APIC_timer(calibration_result); | ||
898 | |||
899 | local_irq_enable(); | ||
900 | } | ||
901 | |||
902 | void __cpuinit setup_secondary_APIC_clock(void) | ||
903 | { | ||
904 | local_irq_disable(); /* FIXME: Do we need this? --RR */ | ||
905 | setup_APIC_timer(calibration_result); | ||
906 | local_irq_enable(); | ||
907 | } | ||
908 | |||
909 | void disable_APIC_timer(void) | ||
910 | { | ||
911 | if (using_apic_timer) { | ||
912 | unsigned long v; | ||
913 | |||
914 | v = apic_read(APIC_LVTT); | ||
915 | /* | ||
916 | * When an illegal vector value (0-15) is written to an LVT | ||
917 | * entry and delivery mode is Fixed, the APIC may signal an | ||
918 | * illegal vector error, with out regard to whether the mask | ||
919 | * bit is set or whether an interrupt is actually seen on input. | ||
920 | * | ||
921 | * Boot sequence might call this function when the LVTT has | ||
922 | * '0' vector value. So make sure vector field is set to | ||
923 | * valid value. | ||
924 | */ | ||
925 | v |= (APIC_LVT_MASKED | LOCAL_TIMER_VECTOR); | ||
926 | apic_write(APIC_LVTT, v); | ||
927 | } | ||
928 | } | ||
929 | |||
930 | void enable_APIC_timer(void) | ||
931 | { | ||
932 | int cpu = smp_processor_id(); | ||
933 | |||
934 | if (using_apic_timer && | ||
935 | !cpu_isset(cpu, timer_interrupt_broadcast_ipi_mask)) { | ||
936 | unsigned long v; | ||
937 | |||
938 | v = apic_read(APIC_LVTT); | ||
939 | apic_write(APIC_LVTT, v & ~APIC_LVT_MASKED); | ||
940 | } | ||
941 | } | ||
942 | |||
943 | void switch_APIC_timer_to_ipi(void *cpumask) | ||
944 | { | ||
945 | cpumask_t mask = *(cpumask_t *)cpumask; | ||
946 | int cpu = smp_processor_id(); | ||
947 | |||
948 | if (cpu_isset(cpu, mask) && | ||
949 | !cpu_isset(cpu, timer_interrupt_broadcast_ipi_mask)) { | ||
950 | disable_APIC_timer(); | ||
951 | cpu_set(cpu, timer_interrupt_broadcast_ipi_mask); | ||
952 | } | ||
953 | } | ||
954 | EXPORT_SYMBOL(switch_APIC_timer_to_ipi); | ||
955 | |||
956 | void smp_send_timer_broadcast_ipi(void) | ||
957 | { | ||
958 | int cpu = smp_processor_id(); | ||
959 | cpumask_t mask; | ||
960 | |||
961 | cpus_and(mask, cpu_online_map, timer_interrupt_broadcast_ipi_mask); | ||
962 | |||
963 | if (cpu_isset(cpu, mask)) { | ||
964 | cpu_clear(cpu, mask); | ||
965 | add_pda(apic_timer_irqs, 1); | ||
966 | smp_local_timer_interrupt(); | ||
967 | } | ||
968 | |||
969 | if (!cpus_empty(mask)) { | ||
970 | send_IPI_mask(mask, LOCAL_TIMER_VECTOR); | ||
971 | } | ||
972 | } | ||
973 | |||
974 | void switch_ipi_to_APIC_timer(void *cpumask) | ||
975 | { | ||
976 | cpumask_t mask = *(cpumask_t *)cpumask; | ||
977 | int cpu = smp_processor_id(); | ||
978 | |||
979 | if (cpu_isset(cpu, mask) && | ||
980 | cpu_isset(cpu, timer_interrupt_broadcast_ipi_mask)) { | ||
981 | cpu_clear(cpu, timer_interrupt_broadcast_ipi_mask); | ||
982 | enable_APIC_timer(); | ||
983 | } | ||
984 | } | ||
985 | EXPORT_SYMBOL(switch_ipi_to_APIC_timer); | ||
986 | |||
987 | int setup_profiling_timer(unsigned int multiplier) | ||
988 | { | ||
989 | return -EINVAL; | ||
990 | } | ||
991 | |||
992 | void setup_APIC_extended_lvt(unsigned char lvt_off, unsigned char vector, | ||
993 | unsigned char msg_type, unsigned char mask) | ||
994 | { | ||
995 | unsigned long reg = (lvt_off << 4) + K8_APIC_EXT_LVT_BASE; | ||
996 | unsigned int v = (mask << 16) | (msg_type << 8) | vector; | ||
997 | apic_write(reg, v); | ||
998 | } | ||
999 | |||
1000 | #undef APIC_DIVISOR | ||
1001 | |||
1002 | /* | ||
1003 | * Local timer interrupt handler. It does both profiling and | ||
1004 | * process statistics/rescheduling. | ||
1005 | * | ||
1006 | * We do profiling in every local tick, statistics/rescheduling | ||
1007 | * happen only every 'profiling multiplier' ticks. The default | ||
1008 | * multiplier is 1 and it can be changed by writing the new multiplier | ||
1009 | * value into /proc/profile. | ||
1010 | */ | ||
1011 | |||
1012 | void smp_local_timer_interrupt(void) | ||
1013 | { | ||
1014 | profile_tick(CPU_PROFILING); | ||
1015 | #ifdef CONFIG_SMP | ||
1016 | update_process_times(user_mode(get_irq_regs())); | ||
1017 | #endif | ||
1018 | if (apic_runs_main_timer > 1 && smp_processor_id() == boot_cpu_id) | ||
1019 | main_timer_handler(); | ||
1020 | /* | ||
1021 | * We take the 'long' return path, and there every subsystem | ||
1022 | * grabs the appropriate locks (kernel lock/ irq lock). | ||
1023 | * | ||
1024 | * We might want to decouple profiling from the 'long path', | ||
1025 | * and do the profiling totally in assembly. | ||
1026 | * | ||
1027 | * Currently this isn't too much of an issue (performance wise), | ||
1028 | * we can take more than 100K local irqs per second on a 100 MHz P5. | ||
1029 | */ | ||
1030 | } | ||
1031 | |||
1032 | /* | ||
1033 | * Local APIC timer interrupt. This is the most natural way for doing | ||
1034 | * local interrupts, but local timer interrupts can be emulated by | ||
1035 | * broadcast interrupts too. [in case the hw doesn't support APIC timers] | ||
1036 | * | ||
1037 | * [ if a single-CPU system runs an SMP kernel then we call the local | ||
1038 | * interrupt as well. Thus we cannot inline the local irq ... ] | ||
1039 | */ | ||
1040 | void smp_apic_timer_interrupt(struct pt_regs *regs) | ||
1041 | { | ||
1042 | struct pt_regs *old_regs = set_irq_regs(regs); | ||
1043 | |||
1044 | /* | ||
1045 | * the NMI deadlock-detector uses this. | ||
1046 | */ | ||
1047 | add_pda(apic_timer_irqs, 1); | ||
1048 | |||
1049 | /* | ||
1050 | * NOTE! We'd better ACK the irq immediately, | ||
1051 | * because timer handling can be slow. | ||
1052 | */ | ||
1053 | ack_APIC_irq(); | ||
1054 | /* | ||
1055 | * update_process_times() expects us to have done irq_enter(). | ||
1056 | * Besides, if we don't timer interrupts ignore the global | ||
1057 | * interrupt lock, which is the WrongThing (tm) to do. | ||
1058 | */ | ||
1059 | exit_idle(); | ||
1060 | irq_enter(); | ||
1061 | smp_local_timer_interrupt(); | ||
1062 | irq_exit(); | ||
1063 | set_irq_regs(old_regs); | ||
1064 | } | ||
1065 | |||
1066 | /* | ||
1067 | * apic_is_clustered_box() -- Check if we can expect good TSC | ||
1068 | * | ||
1069 | * Thus far, the major user of this is IBM's Summit2 series: | ||
1070 | * | ||
1071 | * Clustered boxes may have unsynced TSC problems if they are | ||
1072 | * multi-chassis. Use available data to take a good guess. | ||
1073 | * If in doubt, go HPET. | ||
1074 | */ | ||
1075 | __cpuinit int apic_is_clustered_box(void) | ||
1076 | { | ||
1077 | int i, clusters, zeros; | ||
1078 | unsigned id; | ||
1079 | DECLARE_BITMAP(clustermap, NUM_APIC_CLUSTERS); | ||
1080 | |||
1081 | bitmap_zero(clustermap, NUM_APIC_CLUSTERS); | ||
1082 | |||
1083 | for (i = 0; i < NR_CPUS; i++) { | ||
1084 | id = bios_cpu_apicid[i]; | ||
1085 | if (id != BAD_APICID) | ||
1086 | __set_bit(APIC_CLUSTERID(id), clustermap); | ||
1087 | } | ||
1088 | |||
1089 | /* Problem: Partially populated chassis may not have CPUs in some of | ||
1090 | * the APIC clusters they have been allocated. Only present CPUs have | ||
1091 | * bios_cpu_apicid entries, thus causing zeroes in the bitmap. Since | ||
1092 | * clusters are allocated sequentially, count zeros only if they are | ||
1093 | * bounded by ones. | ||
1094 | */ | ||
1095 | clusters = 0; | ||
1096 | zeros = 0; | ||
1097 | for (i = 0; i < NUM_APIC_CLUSTERS; i++) { | ||
1098 | if (test_bit(i, clustermap)) { | ||
1099 | clusters += 1 + zeros; | ||
1100 | zeros = 0; | ||
1101 | } else | ||
1102 | ++zeros; | ||
1103 | } | ||
1104 | |||
1105 | /* | ||
1106 | * If clusters > 2, then should be multi-chassis. | ||
1107 | * May have to revisit this when multi-core + hyperthreaded CPUs come | ||
1108 | * out, but AFAIK this will work even for them. | ||
1109 | */ | ||
1110 | return (clusters > 2); | ||
1111 | } | ||
1112 | |||
1113 | /* | ||
1114 | * This interrupt should _never_ happen with our APIC/SMP architecture | ||
1115 | */ | ||
1116 | asmlinkage void smp_spurious_interrupt(void) | ||
1117 | { | ||
1118 | unsigned int v; | ||
1119 | exit_idle(); | ||
1120 | irq_enter(); | ||
1121 | /* | ||
1122 | * Check if this really is a spurious interrupt and ACK it | ||
1123 | * if it is a vectored one. Just in case... | ||
1124 | * Spurious interrupts should not be ACKed. | ||
1125 | */ | ||
1126 | v = apic_read(APIC_ISR + ((SPURIOUS_APIC_VECTOR & ~0x1f) >> 1)); | ||
1127 | if (v & (1 << (SPURIOUS_APIC_VECTOR & 0x1f))) | ||
1128 | ack_APIC_irq(); | ||
1129 | |||
1130 | irq_exit(); | ||
1131 | } | ||
1132 | |||
1133 | /* | ||
1134 | * This interrupt should never happen with our APIC/SMP architecture | ||
1135 | */ | ||
1136 | |||
1137 | asmlinkage void smp_error_interrupt(void) | ||
1138 | { | ||
1139 | unsigned int v, v1; | ||
1140 | |||
1141 | exit_idle(); | ||
1142 | irq_enter(); | ||
1143 | /* First tickle the hardware, only then report what went on. -- REW */ | ||
1144 | v = apic_read(APIC_ESR); | ||
1145 | apic_write(APIC_ESR, 0); | ||
1146 | v1 = apic_read(APIC_ESR); | ||
1147 | ack_APIC_irq(); | ||
1148 | atomic_inc(&irq_err_count); | ||
1149 | |||
1150 | /* Here is what the APIC error bits mean: | ||
1151 | 0: Send CS error | ||
1152 | 1: Receive CS error | ||
1153 | 2: Send accept error | ||
1154 | 3: Receive accept error | ||
1155 | 4: Reserved | ||
1156 | 5: Send illegal vector | ||
1157 | 6: Received illegal vector | ||
1158 | 7: Illegal register address | ||
1159 | */ | ||
1160 | printk (KERN_DEBUG "APIC error on CPU%d: %02x(%02x)\n", | ||
1161 | smp_processor_id(), v , v1); | ||
1162 | irq_exit(); | ||
1163 | } | ||
1164 | |||
1165 | int disable_apic; | ||
1166 | |||
1167 | /* | ||
1168 | * This initializes the IO-APIC and APIC hardware if this is | ||
1169 | * a UP kernel. | ||
1170 | */ | ||
1171 | int __init APIC_init_uniprocessor (void) | ||
1172 | { | ||
1173 | if (disable_apic) { | ||
1174 | printk(KERN_INFO "Apic disabled\n"); | ||
1175 | return -1; | ||
1176 | } | ||
1177 | if (!cpu_has_apic) { | ||
1178 | disable_apic = 1; | ||
1179 | printk(KERN_INFO "Apic disabled by BIOS\n"); | ||
1180 | return -1; | ||
1181 | } | ||
1182 | |||
1183 | verify_local_APIC(); | ||
1184 | |||
1185 | phys_cpu_present_map = physid_mask_of_physid(boot_cpu_id); | ||
1186 | apic_write(APIC_ID, SET_APIC_ID(boot_cpu_id)); | ||
1187 | |||
1188 | setup_local_APIC(); | ||
1189 | |||
1190 | if (smp_found_config && !skip_ioapic_setup && nr_ioapics) | ||
1191 | setup_IO_APIC(); | ||
1192 | else | ||
1193 | nr_ioapics = 0; | ||
1194 | setup_boot_APIC_clock(); | ||
1195 | check_nmi_watchdog(); | ||
1196 | return 0; | ||
1197 | } | ||
1198 | |||
1199 | static __init int setup_disableapic(char *str) | ||
1200 | { | ||
1201 | disable_apic = 1; | ||
1202 | clear_bit(X86_FEATURE_APIC, boot_cpu_data.x86_capability); | ||
1203 | return 0; | ||
1204 | } | ||
1205 | early_param("disableapic", setup_disableapic); | ||
1206 | |||
1207 | /* same as disableapic, for compatibility */ | ||
1208 | static __init int setup_nolapic(char *str) | ||
1209 | { | ||
1210 | return setup_disableapic(str); | ||
1211 | } | ||
1212 | early_param("nolapic", setup_nolapic); | ||
1213 | |||
1214 | static int __init parse_lapic_timer_c2_ok(char *arg) | ||
1215 | { | ||
1216 | local_apic_timer_c2_ok = 1; | ||
1217 | return 0; | ||
1218 | } | ||
1219 | early_param("lapic_timer_c2_ok", parse_lapic_timer_c2_ok); | ||
1220 | |||
1221 | static __init int setup_noapictimer(char *str) | ||
1222 | { | ||
1223 | if (str[0] != ' ' && str[0] != 0) | ||
1224 | return 0; | ||
1225 | disable_apic_timer = 1; | ||
1226 | return 1; | ||
1227 | } | ||
1228 | |||
1229 | static __init int setup_apicmaintimer(char *str) | ||
1230 | { | ||
1231 | apic_runs_main_timer = 1; | ||
1232 | nohpet = 1; | ||
1233 | return 1; | ||
1234 | } | ||
1235 | __setup("apicmaintimer", setup_apicmaintimer); | ||
1236 | |||
1237 | static __init int setup_noapicmaintimer(char *str) | ||
1238 | { | ||
1239 | apic_runs_main_timer = -1; | ||
1240 | return 1; | ||
1241 | } | ||
1242 | __setup("noapicmaintimer", setup_noapicmaintimer); | ||
1243 | |||
1244 | static __init int setup_apicpmtimer(char *s) | ||
1245 | { | ||
1246 | apic_calibrate_pmtmr = 1; | ||
1247 | notsc_setup(NULL); | ||
1248 | return setup_apicmaintimer(NULL); | ||
1249 | } | ||
1250 | __setup("apicpmtimer", setup_apicpmtimer); | ||
1251 | |||
1252 | __setup("noapictimer", setup_noapictimer); | ||
1253 | |||