diff options
author | Anton Blanchard <anton@samba.org> | 2009-10-26 14:49:14 -0400 |
---|---|---|
committer | Paul Mackerras <paulus@samba.org> | 2009-10-28 01:13:03 -0400 |
commit | 6795b85c6a4f690e61e7be31aa150d945c723fb5 (patch) | |
tree | 2979f2fc5dcb2585e99774a0487b2b640a51adaa | |
parent | 1bf4af165050d90ea6659ffb2536ec8ca783aab5 (diff) |
powerpc: tracing: Add powerpc tracepoints for timer entry and exit
We can monitor the effectiveness of our power management of both the
kernel and hypervisor by probing the timer interrupt. For example, on
this box we see 10.37s timer interrupts on an idle core:
<idle>-0 [010] 3900.671297: timer_interrupt_entry: pt_regs=c0000000ce1e7b10
<idle>-0 [010] 3900.671302: timer_interrupt_exit: pt_regs=c0000000ce1e7b10
<idle>-0 [010] 3911.042963: timer_interrupt_entry: pt_regs=c0000000ce1e7b10
<idle>-0 [010] 3911.042968: timer_interrupt_exit: pt_regs=c0000000ce1e7b10
<idle>-0 [010] 3921.414630: timer_interrupt_entry: pt_regs=c0000000ce1e7b10
<idle>-0 [010] 3921.414635: timer_interrupt_exit: pt_regs=c0000000ce1e7b10
Since we have a 207MHz decrementer it will go negative and fire every 10.37s
even if Linux is completely idle.
Signed-off-by: Anton Blanchard <anton@samba.org>
Signed-off-by: Paul Mackerras <paulus@samba.org>
-rw-r--r-- | arch/powerpc/include/asm/trace.h | 34 | ||||
-rw-r--r-- | arch/powerpc/kernel/time.c | 6 |
2 files changed, 40 insertions, 0 deletions
diff --git a/arch/powerpc/include/asm/trace.h b/arch/powerpc/include/asm/trace.h index 187696da5ae7..b558c31d409e 100644 --- a/arch/powerpc/include/asm/trace.h +++ b/arch/powerpc/include/asm/trace.h | |||
@@ -42,6 +42,40 @@ TRACE_EVENT(irq_exit, | |||
42 | TP_printk("pt_regs=%p", __entry->regs) | 42 | TP_printk("pt_regs=%p", __entry->regs) |
43 | ); | 43 | ); |
44 | 44 | ||
45 | TRACE_EVENT(timer_interrupt_entry, | ||
46 | |||
47 | TP_PROTO(struct pt_regs *regs), | ||
48 | |||
49 | TP_ARGS(regs), | ||
50 | |||
51 | TP_STRUCT__entry( | ||
52 | __field(struct pt_regs *, regs) | ||
53 | ), | ||
54 | |||
55 | TP_fast_assign( | ||
56 | __entry->regs = regs; | ||
57 | ), | ||
58 | |||
59 | TP_printk("pt_regs=%p", __entry->regs) | ||
60 | ); | ||
61 | |||
62 | TRACE_EVENT(timer_interrupt_exit, | ||
63 | |||
64 | TP_PROTO(struct pt_regs *regs), | ||
65 | |||
66 | TP_ARGS(regs), | ||
67 | |||
68 | TP_STRUCT__entry( | ||
69 | __field(struct pt_regs *, regs) | ||
70 | ), | ||
71 | |||
72 | TP_fast_assign( | ||
73 | __entry->regs = regs; | ||
74 | ), | ||
75 | |||
76 | TP_printk("pt_regs=%p", __entry->regs) | ||
77 | ); | ||
78 | |||
45 | #endif /* _TRACE_POWERPC_H */ | 79 | #endif /* _TRACE_POWERPC_H */ |
46 | 80 | ||
47 | #undef TRACE_INCLUDE_PATH | 81 | #undef TRACE_INCLUDE_PATH |
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c index 92dc844299b6..d6e88df4630c 100644 --- a/arch/powerpc/kernel/time.c +++ b/arch/powerpc/kernel/time.c | |||
@@ -54,6 +54,7 @@ | |||
54 | #include <linux/irq.h> | 54 | #include <linux/irq.h> |
55 | #include <linux/delay.h> | 55 | #include <linux/delay.h> |
56 | #include <linux/perf_event.h> | 56 | #include <linux/perf_event.h> |
57 | #include <asm/trace.h> | ||
57 | 58 | ||
58 | #include <asm/io.h> | 59 | #include <asm/io.h> |
59 | #include <asm/processor.h> | 60 | #include <asm/processor.h> |
@@ -571,6 +572,8 @@ void timer_interrupt(struct pt_regs * regs) | |||
571 | struct clock_event_device *evt = &decrementer->event; | 572 | struct clock_event_device *evt = &decrementer->event; |
572 | u64 now; | 573 | u64 now; |
573 | 574 | ||
575 | trace_timer_interrupt_entry(regs); | ||
576 | |||
574 | /* Ensure a positive value is written to the decrementer, or else | 577 | /* Ensure a positive value is written to the decrementer, or else |
575 | * some CPUs will continuue to take decrementer exceptions */ | 578 | * some CPUs will continuue to take decrementer exceptions */ |
576 | set_dec(DECREMENTER_MAX); | 579 | set_dec(DECREMENTER_MAX); |
@@ -590,6 +593,7 @@ void timer_interrupt(struct pt_regs * regs) | |||
590 | now = decrementer->next_tb - now; | 593 | now = decrementer->next_tb - now; |
591 | if (now <= DECREMENTER_MAX) | 594 | if (now <= DECREMENTER_MAX) |
592 | set_dec((int)now); | 595 | set_dec((int)now); |
596 | trace_timer_interrupt_exit(regs); | ||
593 | return; | 597 | return; |
594 | } | 598 | } |
595 | old_regs = set_irq_regs(regs); | 599 | old_regs = set_irq_regs(regs); |
@@ -620,6 +624,8 @@ void timer_interrupt(struct pt_regs * regs) | |||
620 | 624 | ||
621 | irq_exit(); | 625 | irq_exit(); |
622 | set_irq_regs(old_regs); | 626 | set_irq_regs(old_regs); |
627 | |||
628 | trace_timer_interrupt_exit(regs); | ||
623 | } | 629 | } |
624 | 630 | ||
625 | void wakeup_decrementer(void) | 631 | void wakeup_decrementer(void) |