aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc
diff options
context:
space:
mode:
authorPaul Mackerras <paulus@samba.org>2009-06-17 07:50:04 -0400
committerIngo Molnar <mingo@elte.hu>2009-06-18 05:11:44 -0400
commit105988c015943e77092a6568bc5fb7e386df6ccd (patch)
treebd352fe5e68a66de2e08a8b91c8f8cccf422f346 /arch/powerpc
parenta73c7d84a1975b44c0ebd03c2dec288af1426349 (diff)
perf_counter: powerpc: Enable use of software counters on 32-bit powerpc
This enables the perf_counter subsystem on 32-bit powerpc. Since we don't have any support for hardware counters on 32-bit powerpc yet, only software counters can be used. Besides selecting HAVE_PERF_COUNTERS for 32-bit powerpc as well as 64-bit, the main thing this does is add an implementation of set_perf_counter_pending(). This needs to arrange for perf_counter_do_pending() to be called when interrupts are enabled. Rather than add code to local_irq_restore as 64-bit does, the 32-bit set_perf_counter_pending() generates an interrupt by setting the decrementer to 1 so that a decrementer interrupt will become pending in 1 or 2 timebase ticks (if a decrementer interrupt isn't already pending). When interrupts are enabled, timer_interrupt() will be called, and some new code in there calls perf_counter_do_pending(). We use a per-cpu array of flags to indicate whether we need to call perf_counter_do_pending() or not. This introduces a couple of new Kconfig symbols: PPC_HAVE_PMU_SUPPORT, which is selected by processor families for which we have hardware PMU support (currently only PPC64), and PPC_PERF_CTRS, which enables the powerpc-specific perf_counter back-end. Signed-off-by: Paul Mackerras <paulus@samba.org> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: linuxppc-dev@ozlabs.org Cc: benh@kernel.crashing.org LKML-Reference: <19000.55404.103840.393470@cargo.ozlabs.ibm.com> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch/powerpc')
-rw-r--r--arch/powerpc/Kconfig1
-rw-r--r--arch/powerpc/include/asm/hw_irq.h5
-rw-r--r--arch/powerpc/include/asm/perf_counter.h10
-rw-r--r--arch/powerpc/kernel/Makefile6
-rw-r--r--arch/powerpc/kernel/time.c25
-rw-r--r--arch/powerpc/platforms/Kconfig.cputype11
6 files changed, 51 insertions, 7 deletions
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 9fb344d5a86a..bf6cedfa05db 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -126,6 +126,7 @@ config PPC
126 select HAVE_OPROFILE 126 select HAVE_OPROFILE
127 select HAVE_SYSCALL_WRAPPERS if PPC64 127 select HAVE_SYSCALL_WRAPPERS if PPC64
128 select GENERIC_ATOMIC64 if PPC32 128 select GENERIC_ATOMIC64 if PPC32
129 select HAVE_PERF_COUNTERS
129 130
130config EARLY_PRINTK 131config EARLY_PRINTK
131 bool 132 bool
diff --git a/arch/powerpc/include/asm/hw_irq.h b/arch/powerpc/include/asm/hw_irq.h
index 10a642df014e..867ab8ed69b3 100644
--- a/arch/powerpc/include/asm/hw_irq.h
+++ b/arch/powerpc/include/asm/hw_irq.h
@@ -131,6 +131,8 @@ static inline int irqs_disabled_flags(unsigned long flags)
131struct irq_chip; 131struct irq_chip;
132 132
133#ifdef CONFIG_PERF_COUNTERS 133#ifdef CONFIG_PERF_COUNTERS
134
135#ifdef CONFIG_PPC64
134static inline unsigned long test_perf_counter_pending(void) 136static inline unsigned long test_perf_counter_pending(void)
135{ 137{
136 unsigned long x; 138 unsigned long x;
@@ -154,8 +156,9 @@ static inline void clear_perf_counter_pending(void)
154 "r" (0), 156 "r" (0),
155 "i" (offsetof(struct paca_struct, perf_counter_pending))); 157 "i" (offsetof(struct paca_struct, perf_counter_pending)));
156} 158}
159#endif /* CONFIG_PPC64 */
157 160
158#else 161#else /* CONFIG_PERF_COUNTERS */
159 162
160static inline unsigned long test_perf_counter_pending(void) 163static inline unsigned long test_perf_counter_pending(void)
161{ 164{
diff --git a/arch/powerpc/include/asm/perf_counter.h b/arch/powerpc/include/asm/perf_counter.h
index b398a84edced..2c2d9f643df0 100644
--- a/arch/powerpc/include/asm/perf_counter.h
+++ b/arch/powerpc/include/asm/perf_counter.h
@@ -57,11 +57,17 @@ extern struct power_pmu *ppmu;
57 57
58struct pt_regs; 58struct pt_regs;
59extern unsigned long perf_misc_flags(struct pt_regs *regs); 59extern unsigned long perf_misc_flags(struct pt_regs *regs);
60#define perf_misc_flags(regs) perf_misc_flags(regs)
61
62extern unsigned long perf_instruction_pointer(struct pt_regs *regs); 60extern unsigned long perf_instruction_pointer(struct pt_regs *regs);
63 61
64/* 62/*
63 * Only override the default definitions in include/linux/perf_counter.h
64 * if we have hardware PMU support.
65 */
66#ifdef CONFIG_PPC_PERF_CTRS
67#define perf_misc_flags(regs) perf_misc_flags(regs)
68#endif
69
70/*
65 * The power_pmu.get_constraint function returns a 64-bit value and 71 * The power_pmu.get_constraint function returns a 64-bit value and
66 * a 64-bit mask that express the constraints between this event and 72 * a 64-bit mask that express the constraints between this event and
67 * other events. 73 * other events.
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
index 612b0c4dc26d..c5f93f061927 100644
--- a/arch/powerpc/kernel/Makefile
+++ b/arch/powerpc/kernel/Makefile
@@ -95,9 +95,9 @@ obj64-$(CONFIG_AUDIT) += compat_audit.o
95 95
96obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o 96obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o
97obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o 97obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o
98obj-$(CONFIG_PERF_COUNTERS) += perf_counter.o power4-pmu.o ppc970-pmu.o \ 98obj-$(CONFIG_PPC_PERF_CTRS) += perf_counter.o
99 power5-pmu.o power5+-pmu.o power6-pmu.o \ 99obj64-$(CONFIG_PPC_PERF_CTRS) += power4-pmu.o ppc970-pmu.o power5-pmu.o \
100 power7-pmu.o 100 power5+-pmu.o power6-pmu.o power7-pmu.o
101 101
102obj-$(CONFIG_8XX_MINIMAL_FPEMU) += softemu8xx.o 102obj-$(CONFIG_8XX_MINIMAL_FPEMU) += softemu8xx.o
103 103
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c
index 15391c2ab013..eae4511ceeac 100644
--- a/arch/powerpc/kernel/time.c
+++ b/arch/powerpc/kernel/time.c
@@ -53,6 +53,7 @@
53#include <linux/posix-timers.h> 53#include <linux/posix-timers.h>
54#include <linux/irq.h> 54#include <linux/irq.h>
55#include <linux/delay.h> 55#include <linux/delay.h>
56#include <linux/perf_counter.h>
56 57
57#include <asm/io.h> 58#include <asm/io.h>
58#include <asm/processor.h> 59#include <asm/processor.h>
@@ -525,6 +526,26 @@ void __init iSeries_time_init_early(void)
525} 526}
526#endif /* CONFIG_PPC_ISERIES */ 527#endif /* CONFIG_PPC_ISERIES */
527 528
529#if defined(CONFIG_PERF_COUNTERS) && defined(CONFIG_PPC32)
530DEFINE_PER_CPU(u8, perf_counter_pending);
531
532void set_perf_counter_pending(void)
533{
534 get_cpu_var(perf_counter_pending) = 1;
535 set_dec(1);
536 put_cpu_var(perf_counter_pending);
537}
538
539#define test_perf_counter_pending() __get_cpu_var(perf_counter_pending)
540#define clear_perf_counter_pending() __get_cpu_var(perf_counter_pending) = 0
541
542#else /* CONFIG_PERF_COUNTERS && CONFIG_PPC32 */
543
544#define test_perf_counter_pending() 0
545#define clear_perf_counter_pending()
546
547#endif /* CONFIG_PERF_COUNTERS && CONFIG_PPC32 */
548
528/* 549/*
529 * For iSeries shared processors, we have to let the hypervisor 550 * For iSeries shared processors, we have to let the hypervisor
530 * set the hardware decrementer. We set a virtual decrementer 551 * set the hardware decrementer. We set a virtual decrementer
@@ -551,6 +572,10 @@ void timer_interrupt(struct pt_regs * regs)
551 set_dec(DECREMENTER_MAX); 572 set_dec(DECREMENTER_MAX);
552 573
553#ifdef CONFIG_PPC32 574#ifdef CONFIG_PPC32
575 if (test_perf_counter_pending()) {
576 clear_perf_counter_pending();
577 perf_counter_do_pending();
578 }
554 if (atomic_read(&ppc_n_lost_interrupts) != 0) 579 if (atomic_read(&ppc_n_lost_interrupts) != 0)
555 do_IRQ(regs); 580 do_IRQ(regs);
556#endif 581#endif
diff --git a/arch/powerpc/platforms/Kconfig.cputype b/arch/powerpc/platforms/Kconfig.cputype
index cca6b4fc719a..dd9f3ec5ee30 100644
--- a/arch/powerpc/platforms/Kconfig.cputype
+++ b/arch/powerpc/platforms/Kconfig.cputype
@@ -1,7 +1,7 @@
1config PPC64 1config PPC64
2 bool "64-bit kernel" 2 bool "64-bit kernel"
3 default n 3 default n
4 select HAVE_PERF_COUNTERS 4 select PPC_HAVE_PMU_SUPPORT
5 help 5 help
6 This option selects whether a 32-bit or a 64-bit kernel 6 This option selects whether a 32-bit or a 64-bit kernel
7 will be built. 7 will be built.
@@ -243,6 +243,15 @@ config VIRT_CPU_ACCOUNTING
243 243
244 If in doubt, say Y here. 244 If in doubt, say Y here.
245 245
246config PPC_HAVE_PMU_SUPPORT
247 bool
248
249config PPC_PERF_CTRS
250 def_bool y
251 depends on PERF_COUNTERS && PPC_HAVE_PMU_SUPPORT
252 help
253 This enables the powerpc-specific perf_counter back-end.
254
246config SMP 255config SMP
247 depends on PPC_STD_MMU || FSL_BOOKE 256 depends on PPC_STD_MMU || FSL_BOOKE
248 bool "Symmetric multi-processing support" 257 bool "Symmetric multi-processing support"