aboutsummaryrefslogtreecommitdiffstats
path: root/arch/i386/kernel/apic.c
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2007-02-16 04:28:04 -0500
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-02-16 11:13:59 -0500
commite9e2cdb412412326c4827fc78ba27f410d837e6e (patch)
treecd4ca03e6bdc3691619024492fb9414427b2f813 /arch/i386/kernel/apic.c
parent79bf2bb335b85db25d27421c798595a2fa2a0e82 (diff)
[PATCH] clockevents: i386 drivers
Add clockevent drivers for i386: lapic (local) and PIT/HPET (global). Update the timer IRQ to call into the PIT/HPET driver's event handler and the lapic-timer IRQ to call into the lapic clockevent driver. The assignement of timer functionality is delegated to the core framework code and replaces the compile and runtime evalution in do_timer_interrupt_hook() Use the clockevents broadcast support and implement the lapic_broadcast function for ACPI. No changes to existing functionality. [ kdump fix from Vivek Goyal <vgoyal@in.ibm.com> ] [ fixes based on review feedback from Arjan van de Ven <arjan@infradead.org> ] Cleanups-from: Adrian Bunk <bunk@stusta.de> Build-fixes-from: Andrew Morton <akpm@osdl.org> Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Ingo Molnar <mingo@elte.hu> Cc: john stultz <johnstul@us.ibm.com> Cc: Roman Zippel <zippel@linux-m68k.org> Cc: Andi Kleen <ak@suse.de> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'arch/i386/kernel/apic.c')
-rw-r--r--arch/i386/kernel/apic.c291
1 files changed, 148 insertions, 143 deletions
diff --git a/arch/i386/kernel/apic.c b/arch/i386/kernel/apic.c
index b56448f214a7..e98b5c750bdf 100644
--- a/arch/i386/kernel/apic.c
+++ b/arch/i386/kernel/apic.c
@@ -25,6 +25,7 @@
25#include <linux/kernel_stat.h> 25#include <linux/kernel_stat.h>
26#include <linux/sysdev.h> 26#include <linux/sysdev.h>
27#include <linux/cpu.h> 27#include <linux/cpu.h>
28#include <linux/clockchips.h>
28#include <linux/module.h> 29#include <linux/module.h>
29 30
30#include <asm/atomic.h> 31#include <asm/atomic.h>
@@ -52,28 +53,44 @@
52#endif 53#endif
53 54
54/* 55/*
55 * cpu_mask that denotes the CPUs that needs timer interrupt coming in as
56 * IPIs in place of local APIC timers
57 */
58static cpumask_t timer_bcast_ipi;
59
60/*
61 * Knob to control our willingness to enable the local APIC. 56 * Knob to control our willingness to enable the local APIC.
62 * 57 *
63 * -1=force-disable, +1=force-enable 58 * -1=force-disable, +1=force-enable
64 */ 59 */
65static int enable_local_apic __initdata = 0; 60static int enable_local_apic __initdata = 0;
66 61
62/* Enable local APIC timer for highres/dyntick on UP */
63static int enable_local_apic_timer __initdata = 0;
64
67/* 65/*
68 * Debug level, exported for io_apic.c 66 * Debug level, exported for io_apic.c
69 */ 67 */
70int apic_verbosity; 68int apic_verbosity;
71 69
72static void apic_pm_activate(void); 70static unsigned int calibration_result;
73 71
72static int lapic_next_event(unsigned long delta,
73 struct clock_event_device *evt);
74static void lapic_timer_setup(enum clock_event_mode mode,
75 struct clock_event_device *evt);
76static void lapic_timer_broadcast(cpumask_t mask);
77static void apic_pm_activate(void);
74 78
75/* Using APIC to generate smp_local_timer_interrupt? */ 79/*
76int using_apic_timer __read_mostly = 0; 80 * The local apic timer can be used for any function which is CPU local.
81 */
82static struct clock_event_device lapic_clockevent = {
83 .name = "lapic",
84 .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT
85 | CLOCK_EVT_FEAT_C3STOP,
86 .shift = 32,
87 .set_mode = lapic_timer_setup,
88 .set_next_event = lapic_next_event,
89 .broadcast = lapic_timer_broadcast,
90 .rating = 100,
91 .irq = -1,
92};
93static DEFINE_PER_CPU(struct clock_event_device, lapic_events);
77 94
78/* Local APIC was disabled by the BIOS and enabled by the kernel */ 95/* Local APIC was disabled by the BIOS and enabled by the kernel */
79static int enabled_via_apicbase; 96static int enabled_via_apicbase;
@@ -152,6 +169,11 @@ int lapic_get_maxlvt(void)
152 */ 169 */
153 170
154/* 171/*
172 * FIXME: Move this to i8253.h. There is no need to keep the access to
173 * the PIT scattered all around the place -tglx
174 */
175
176/*
155 * The timer chip is already set up at HZ interrupts per second here, 177 * The timer chip is already set up at HZ interrupts per second here,
156 * but we do not accept timer interrupts yet. We only allow the BP 178 * but we do not accept timer interrupts yet. We only allow the BP
157 * to calibrate. 179 * to calibrate.
@@ -209,16 +231,17 @@ void (*wait_timer_tick)(void) __devinitdata = wait_8254_wraparound;
209 231
210#define APIC_DIVISOR 16 232#define APIC_DIVISOR 16
211 233
212static void __setup_APIC_LVTT(unsigned int clocks) 234static void __setup_APIC_LVTT(unsigned int clocks, int oneshot, int irqen)
213{ 235{
214 unsigned int lvtt_value, tmp_value; 236 unsigned int lvtt_value, tmp_value;
215 int cpu = smp_processor_id();
216 237
217 lvtt_value = APIC_LVT_TIMER_PERIODIC | LOCAL_TIMER_VECTOR; 238 lvtt_value = LOCAL_TIMER_VECTOR;
239 if (!oneshot)
240 lvtt_value |= APIC_LVT_TIMER_PERIODIC;
218 if (!lapic_is_integrated()) 241 if (!lapic_is_integrated())
219 lvtt_value |= SET_APIC_TIMER_BASE(APIC_TIMER_BASE_DIV); 242 lvtt_value |= SET_APIC_TIMER_BASE(APIC_TIMER_BASE_DIV);
220 243
221 if (cpu_isset(cpu, timer_bcast_ipi)) 244 if (!irqen)
222 lvtt_value |= APIC_LVT_MASKED; 245 lvtt_value |= APIC_LVT_MASKED;
223 246
224 apic_write_around(APIC_LVTT, lvtt_value); 247 apic_write_around(APIC_LVTT, lvtt_value);
@@ -231,31 +254,80 @@ static void __setup_APIC_LVTT(unsigned int clocks)
231 & ~(APIC_TDR_DIV_1 | APIC_TDR_DIV_TMBASE)) 254 & ~(APIC_TDR_DIV_1 | APIC_TDR_DIV_TMBASE))
232 | APIC_TDR_DIV_16); 255 | APIC_TDR_DIV_16);
233 256
234 apic_write_around(APIC_TMICT, clocks/APIC_DIVISOR); 257 if (!oneshot)
258 apic_write_around(APIC_TMICT, clocks/APIC_DIVISOR);
259}
260
261/*
262 * Program the next event, relative to now
263 */
264static int lapic_next_event(unsigned long delta,
265 struct clock_event_device *evt)
266{
267 apic_write_around(APIC_TMICT, delta);
268 return 0;
235} 269}
236 270
237static void __devinit setup_APIC_timer(unsigned int clocks) 271/*
272 * Setup the lapic timer in periodic or oneshot mode
273 */
274static void lapic_timer_setup(enum clock_event_mode mode,
275 struct clock_event_device *evt)
238{ 276{
239 unsigned long flags; 277 unsigned long flags;
278 unsigned int v;
240 279
241 local_irq_save(flags); 280 local_irq_save(flags);
242 281
243 /* 282 switch (mode) {
244 * Wait for IRQ0's slice: 283 case CLOCK_EVT_MODE_PERIODIC:
245 */ 284 case CLOCK_EVT_MODE_ONESHOT:
246 wait_timer_tick(); 285 __setup_APIC_LVTT(calibration_result,
247 286 mode != CLOCK_EVT_MODE_PERIODIC, 1);
248 __setup_APIC_LVTT(clocks); 287 break;
288 case CLOCK_EVT_MODE_UNUSED:
289 case CLOCK_EVT_MODE_SHUTDOWN:
290 v = apic_read(APIC_LVTT);
291 v |= (APIC_LVT_MASKED | LOCAL_TIMER_VECTOR);
292 apic_write_around(APIC_LVTT, v);
293 break;
294 }
249 295
250 local_irq_restore(flags); 296 local_irq_restore(flags);
251} 297}
252 298
253/* 299/*
300 * Local APIC timer broadcast function
301 */
302static void lapic_timer_broadcast(cpumask_t mask)
303{
304#ifdef CONFIG_SMP
305 send_IPI_mask(mask, LOCAL_TIMER_VECTOR);
306#endif
307}
308
309/*
310 * Setup the local APIC timer for this CPU. Copy the initilized values
311 * of the boot CPU and register the clock event in the framework.
312 */
313static void __devinit setup_APIC_timer(void)
314{
315 struct clock_event_device *levt = &__get_cpu_var(lapic_events);
316
317 memcpy(levt, &lapic_clockevent, sizeof(*levt));
318 levt->cpumask = cpumask_of_cpu(smp_processor_id());
319
320 clockevents_register_device(levt);
321}
322
323/*
254 * In this function we calibrate APIC bus clocks to the external 324 * In this function we calibrate APIC bus clocks to the external
255 * timer. Unfortunately we cannot use jiffies and the timer irq 325 * timer. Unfortunately we cannot use jiffies and the timer irq
256 * to calibrate, since some later bootup code depends on getting 326 * to calibrate, since some later bootup code depends on getting
257 * the first irq? Ugh. 327 * the first irq? Ugh.
258 * 328 *
329 * TODO: Fix this rather than saying "Ugh" -tglx
330 *
259 * We want to do the calibration only once since we 331 * We want to do the calibration only once since we
260 * want to have local timer irqs syncron. CPUs connected 332 * want to have local timer irqs syncron. CPUs connected
261 * by the same APIC bus have the very same bus frequency. 333 * by the same APIC bus have the very same bus frequency.
@@ -278,7 +350,7 @@ static int __init calibrate_APIC_clock(void)
278 * value into the APIC clock, we just want to get the 350 * value into the APIC clock, we just want to get the
279 * counter running for calibration. 351 * counter running for calibration.
280 */ 352 */
281 __setup_APIC_LVTT(1000000000); 353 __setup_APIC_LVTT(1000000000, 0, 0);
282 354
283 /* 355 /*
284 * The timer chip counts down to zero. Let's wait 356 * The timer chip counts down to zero. Let's wait
@@ -315,6 +387,17 @@ static int __init calibrate_APIC_clock(void)
315 387
316 result = (tt1-tt2)*APIC_DIVISOR/LOOPS; 388 result = (tt1-tt2)*APIC_DIVISOR/LOOPS;
317 389
390 /* Calculate the scaled math multiplication factor */
391 lapic_clockevent.mult = div_sc(tt1-tt2, TICK_NSEC * LOOPS, 32);
392 lapic_clockevent.max_delta_ns =
393 clockevent_delta2ns(0x7FFFFF, &lapic_clockevent);
394 lapic_clockevent.min_delta_ns =
395 clockevent_delta2ns(0xF, &lapic_clockevent);
396
397 apic_printk(APIC_VERBOSE, "..... tt1-tt2 %ld\n", tt1 - tt2);
398 apic_printk(APIC_VERBOSE, "..... mult: %ld\n", lapic_clockevent.mult);
399 apic_printk(APIC_VERBOSE, "..... calibration result: %ld\n", result);
400
318 if (cpu_has_tsc) 401 if (cpu_has_tsc)
319 apic_printk(APIC_VERBOSE, "..... CPU clock speed is " 402 apic_printk(APIC_VERBOSE, "..... CPU clock speed is "
320 "%ld.%04ld MHz.\n", 403 "%ld.%04ld MHz.\n",
@@ -329,13 +412,10 @@ static int __init calibrate_APIC_clock(void)
329 return result; 412 return result;
330} 413}
331 414
332static unsigned int calibration_result;
333
334void __init setup_boot_APIC_clock(void) 415void __init setup_boot_APIC_clock(void)
335{ 416{
336 unsigned long flags; 417 unsigned long flags;
337 apic_printk(APIC_VERBOSE, "Using local APIC timer interrupts.\n"); 418 apic_printk(APIC_VERBOSE, "Using local APIC timer interrupts.\n");
338 using_apic_timer = 1;
339 419
340 local_irq_save(flags); 420 local_irq_save(flags);
341 421
@@ -343,97 +423,47 @@ void __init setup_boot_APIC_clock(void)
343 /* 423 /*
344 * Now set up the timer for real. 424 * Now set up the timer for real.
345 */ 425 */
346 setup_APIC_timer(calibration_result); 426 setup_APIC_timer();
347 427
348 local_irq_restore(flags); 428 local_irq_restore(flags);
349} 429}
350 430
351void __devinit setup_secondary_APIC_clock(void) 431void __devinit setup_secondary_APIC_clock(void)
352{ 432{
353 setup_APIC_timer(calibration_result); 433 setup_APIC_timer();
354}
355
356void disable_APIC_timer(void)
357{
358 if (using_apic_timer) {
359 unsigned long v;
360
361 v = apic_read(APIC_LVTT);
362 /*
363 * When an illegal vector value (0-15) is written to an LVT
364 * entry and delivery mode is Fixed, the APIC may signal an
365 * illegal vector error, with out regard to whether the mask
366 * bit is set or whether an interrupt is actually seen on
367 * input.
368 *
369 * Boot sequence might call this function when the LVTT has
370 * '0' vector value. So make sure vector field is set to
371 * valid value.
372 */
373 v |= (APIC_LVT_MASKED | LOCAL_TIMER_VECTOR);
374 apic_write_around(APIC_LVTT, v);
375 }
376}
377
378void enable_APIC_timer(void)
379{
380 int cpu = smp_processor_id();
381
382 if (using_apic_timer && !cpu_isset(cpu, timer_bcast_ipi)) {
383 unsigned long v;
384
385 v = apic_read(APIC_LVTT);
386 apic_write_around(APIC_LVTT, v & ~APIC_LVT_MASKED);
387 }
388}
389
390void switch_APIC_timer_to_ipi(void *cpumask)
391{
392 cpumask_t mask = *(cpumask_t *)cpumask;
393 int cpu = smp_processor_id();
394
395 if (cpu_isset(cpu, mask) &&
396 !cpu_isset(cpu, timer_bcast_ipi)) {
397 disable_APIC_timer();
398 cpu_set(cpu, timer_bcast_ipi);
399 }
400}
401EXPORT_SYMBOL(switch_APIC_timer_to_ipi);
402
403void switch_ipi_to_APIC_timer(void *cpumask)
404{
405 cpumask_t mask = *(cpumask_t *)cpumask;
406 int cpu = smp_processor_id();
407
408 if (cpu_isset(cpu, mask) &&
409 cpu_isset(cpu, timer_bcast_ipi)) {
410 cpu_clear(cpu, timer_bcast_ipi);
411 enable_APIC_timer();
412 }
413} 434}
414EXPORT_SYMBOL(switch_ipi_to_APIC_timer);
415 435
416/* 436/*
417 * Local timer interrupt handler. It does both profiling and 437 * The guts of the apic timer interrupt
418 * process statistics/rescheduling.
419 */ 438 */
420inline void smp_local_timer_interrupt(void) 439static void local_apic_timer_interrupt(void)
421{ 440{
422 profile_tick(CPU_PROFILING); 441 int cpu = smp_processor_id();
423#ifdef CONFIG_SMP 442 struct clock_event_device *evt = &per_cpu(lapic_events, cpu);
424 update_process_times(user_mode_vm(get_irq_regs()));
425#endif
426 443
427 /* 444 /*
428 * We take the 'long' return path, and there every subsystem 445 * Normally we should not be here till LAPIC has been
429 * grabs the apropriate locks (kernel lock/ irq lock). 446 * initialized but in some cases like kdump, its possible that
447 * there is a pending LAPIC timer interrupt from previous
448 * kernel's context and is delivered in new kernel the moment
449 * interrupts are enabled.
430 * 450 *
431 * we might want to decouple profiling from the 'long path', 451 * Interrupts are enabled early and LAPIC is setup much later,
432 * and do the profiling totally in assembly. 452 * hence its possible that when we get here evt->event_handler
433 * 453 * is NULL. Check for event_handler being NULL and discard
434 * Currently this isn't too much of an issue (performance wise), 454 * the interrupt as spurious.
435 * we can take more than 100K local irqs per second on a 100 MHz P5.
436 */ 455 */
456 if (!evt->event_handler) {
457 printk(KERN_WARNING
458 "Spurious LAPIC timer interrupt on cpu %d\n", cpu);
459 /* Switch it off */
460 lapic_timer_setup(CLOCK_EVT_MODE_SHUTDOWN, evt);
461 return;
462 }
463
464 per_cpu(irq_stat, cpu).apic_timer_irqs++;
465
466 evt->event_handler(evt);
437} 467}
438 468
439/* 469/*
@@ -445,15 +475,9 @@ inline void smp_local_timer_interrupt(void)
445 * interrupt as well. Thus we cannot inline the local irq ... ] 475 * interrupt as well. Thus we cannot inline the local irq ... ]
446 */ 476 */
447 477
448fastcall void smp_apic_timer_interrupt(struct pt_regs *regs) 478void fastcall smp_apic_timer_interrupt(struct pt_regs *regs)
449{ 479{
450 struct pt_regs *old_regs = set_irq_regs(regs); 480 struct pt_regs *old_regs = set_irq_regs(regs);
451 int cpu = smp_processor_id();
452
453 /*
454 * the NMI deadlock-detector uses this.
455 */
456 per_cpu(irq_stat, cpu).apic_timer_irqs++;
457 481
458 /* 482 /*
459 * NOTE! We'd better ACK the irq immediately, 483 * NOTE! We'd better ACK the irq immediately,
@@ -467,41 +491,10 @@ fastcall void smp_apic_timer_interrupt(struct pt_regs *regs)
467 */ 491 */
468 exit_idle(); 492 exit_idle();
469 irq_enter(); 493 irq_enter();
470 smp_local_timer_interrupt(); 494 local_apic_timer_interrupt();
471 irq_exit(); 495 irq_exit();
472 set_irq_regs(old_regs);
473}
474 496
475#ifndef CONFIG_SMP 497 set_irq_regs(old_regs);
476static void up_apic_timer_interrupt_call(void)
477{
478 int cpu = smp_processor_id();
479
480 /*
481 * the NMI deadlock-detector uses this.
482 */
483 per_cpu(irq_stat, cpu).apic_timer_irqs++;
484
485 smp_local_timer_interrupt();
486}
487#endif
488
489void smp_send_timer_broadcast_ipi(void)
490{
491 cpumask_t mask;
492
493 cpus_and(mask, cpu_online_map, timer_bcast_ipi);
494 if (!cpus_empty(mask)) {
495#ifdef CONFIG_SMP
496 send_IPI_mask(mask, LOCAL_TIMER_VECTOR);
497#else
498 /*
499 * We can directly call the apic timer interrupt handler
500 * in UP case. Minus all irq related functions
501 */
502 up_apic_timer_interrupt_call();
503#endif
504 }
505} 498}
506 499
507int setup_profiling_timer(unsigned int multiplier) 500int setup_profiling_timer(unsigned int multiplier)
@@ -914,6 +907,11 @@ void __devinit setup_local_APIC(void)
914 printk(KERN_INFO "No ESR for 82489DX.\n"); 907 printk(KERN_INFO "No ESR for 82489DX.\n");
915 } 908 }
916 909
910 /* Disable the local apic timer */
911 value = apic_read(APIC_LVTT);
912 value |= (APIC_LVT_MASKED | LOCAL_TIMER_VECTOR);
913 apic_write_around(APIC_LVTT, value);
914
917 setup_apic_nmi_watchdog(NULL); 915 setup_apic_nmi_watchdog(NULL);
918 apic_pm_activate(); 916 apic_pm_activate();
919} 917}
@@ -1128,6 +1126,13 @@ static int __init parse_nolapic(char *arg)
1128} 1126}
1129early_param("nolapic", parse_nolapic); 1127early_param("nolapic", parse_nolapic);
1130 1128
1129static int __init apic_enable_lapic_timer(char *str)
1130{
1131 enable_local_apic_timer = 1;
1132 return 0;
1133}
1134early_param("lapictimer", apic_enable_lapic_timer);
1135
1131static int __init apic_set_verbosity(char *str) 1136static int __init apic_set_verbosity(char *str)
1132{ 1137{
1133 if (strcmp("debug", str) == 0) 1138 if (strcmp("debug", str) == 0)
@@ -1147,7 +1152,7 @@ __setup("apic=", apic_set_verbosity);
1147/* 1152/*
1148 * This interrupt should _never_ happen with our APIC/SMP architecture 1153 * This interrupt should _never_ happen with our APIC/SMP architecture
1149 */ 1154 */
1150fastcall void smp_spurious_interrupt(struct pt_regs *regs) 1155void smp_spurious_interrupt(struct pt_regs *regs)
1151{ 1156{
1152 unsigned long v; 1157 unsigned long v;
1153 1158
@@ -1171,7 +1176,7 @@ fastcall void smp_spurious_interrupt(struct pt_regs *regs)
1171/* 1176/*
1172 * This interrupt should never happen with our APIC/SMP architecture 1177 * This interrupt should never happen with our APIC/SMP architecture
1173 */ 1178 */
1174fastcall void smp_error_interrupt(struct pt_regs *regs) 1179void smp_error_interrupt(struct pt_regs *regs)
1175{ 1180{
1176 unsigned long v, v1; 1181 unsigned long v, v1;
1177 1182