perf_counter: powerpc: Enable use of software counters on 32-bit powerpc
authorPaul Mackerras <paulus@samba.org>
Wed, 17 Jun 2009 11:50:04 +0000 (21:50 +1000)
committerIngo Molnar <mingo@elte.hu>
Thu, 18 Jun 2009 09:11:44 +0000 (11:11 +0200)
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>
arch/powerpc/Kconfig
arch/powerpc/include/asm/hw_irq.h
arch/powerpc/include/asm/perf_counter.h
arch/powerpc/kernel/Makefile
arch/powerpc/kernel/time.c
arch/powerpc/platforms/Kconfig.cputype

index 9fb344d5a86a737e459c998d8e83a653ccf19501..bf6cedfa05dbfbef2073ec2b9d652dd21fac504d 100644 (file)
@@ -126,6 +126,7 @@ config PPC
        select HAVE_OPROFILE
        select HAVE_SYSCALL_WRAPPERS if PPC64
        select GENERIC_ATOMIC64 if PPC32
+       select HAVE_PERF_COUNTERS
 
 config EARLY_PRINTK
        bool
index 10a642df014ed0c432e9fe8127ba4edffc936eeb..867ab8ed69b303658a07d6c67d660eece712d5cf 100644 (file)
@@ -131,6 +131,8 @@ static inline int irqs_disabled_flags(unsigned long flags)
 struct irq_chip;
 
 #ifdef CONFIG_PERF_COUNTERS
+
+#ifdef CONFIG_PPC64
 static inline unsigned long test_perf_counter_pending(void)
 {
        unsigned long x;
@@ -154,8 +156,9 @@ static inline void clear_perf_counter_pending(void)
                "r" (0),
                "i" (offsetof(struct paca_struct, perf_counter_pending)));
 }
+#endif /* CONFIG_PPC64 */
 
-#else
+#else  /* CONFIG_PERF_COUNTERS */
 
 static inline unsigned long test_perf_counter_pending(void)
 {
index b398a84edceda63be674123f24d950d7687d38e6..2c2d9f643df0591f2afb4e4c3bb471a86e82f6bd 100644 (file)
@@ -57,10 +57,16 @@ extern struct power_pmu *ppmu;
 
 struct pt_regs;
 extern unsigned long perf_misc_flags(struct pt_regs *regs);
-#define perf_misc_flags(regs)  perf_misc_flags(regs)
-
 extern unsigned long perf_instruction_pointer(struct pt_regs *regs);
 
+/*
+ * Only override the default definitions in include/linux/perf_counter.h
+ * if we have hardware PMU support.
+ */
+#ifdef CONFIG_PPC_PERF_CTRS
+#define perf_misc_flags(regs)  perf_misc_flags(regs)
+#endif
+
 /*
  * The power_pmu.get_constraint function returns a 64-bit value and
  * a 64-bit mask that express the constraints between this event and
index 612b0c4dc26d90d818d299805a34c7b453eb09c3..c5f93f06192713917970a24491764eba7c8d7dd7 100644 (file)
@@ -95,9 +95,9 @@ obj64-$(CONFIG_AUDIT)         += compat_audit.o
 
 obj-$(CONFIG_DYNAMIC_FTRACE)   += ftrace.o
 obj-$(CONFIG_FUNCTION_GRAPH_TRACER)    += ftrace.o
-obj-$(CONFIG_PERF_COUNTERS)    += perf_counter.o power4-pmu.o ppc970-pmu.o \
-                                  power5-pmu.o power5+-pmu.o power6-pmu.o \
-                                  power7-pmu.o
+obj-$(CONFIG_PPC_PERF_CTRS)    += perf_counter.o
+obj64-$(CONFIG_PPC_PERF_CTRS)  += power4-pmu.o ppc970-pmu.o power5-pmu.o \
+                                  power5+-pmu.o power6-pmu.o power7-pmu.o
 
 obj-$(CONFIG_8XX_MINIMAL_FPEMU) += softemu8xx.o
 
index 15391c2ab013bc0691228b97076d126fa5dc1aa1..eae4511ceeac272947f3e164befc73a3145481dd 100644 (file)
@@ -53,6 +53,7 @@
 #include <linux/posix-timers.h>
 #include <linux/irq.h>
 #include <linux/delay.h>
+#include <linux/perf_counter.h>
 
 #include <asm/io.h>
 #include <asm/processor.h>
@@ -525,6 +526,26 @@ void __init iSeries_time_init_early(void)
 }
 #endif /* CONFIG_PPC_ISERIES */
 
+#if defined(CONFIG_PERF_COUNTERS) && defined(CONFIG_PPC32)
+DEFINE_PER_CPU(u8, perf_counter_pending);
+
+void set_perf_counter_pending(void)
+{
+       get_cpu_var(perf_counter_pending) = 1;
+       set_dec(1);
+       put_cpu_var(perf_counter_pending);
+}
+
+#define test_perf_counter_pending()    __get_cpu_var(perf_counter_pending)
+#define clear_perf_counter_pending()   __get_cpu_var(perf_counter_pending) = 0
+
+#else  /* CONFIG_PERF_COUNTERS && CONFIG_PPC32 */
+
+#define test_perf_counter_pending()    0
+#define clear_perf_counter_pending()
+
+#endif /* CONFIG_PERF_COUNTERS && CONFIG_PPC32 */
+
 /*
  * For iSeries shared processors, we have to let the hypervisor
  * set the hardware decrementer.  We set a virtual decrementer
@@ -551,6 +572,10 @@ void timer_interrupt(struct pt_regs * regs)
        set_dec(DECREMENTER_MAX);
 
 #ifdef CONFIG_PPC32
+       if (test_perf_counter_pending()) {
+               clear_perf_counter_pending();
+               perf_counter_do_pending();
+       }
        if (atomic_read(&ppc_n_lost_interrupts) != 0)
                do_IRQ(regs);
 #endif
index cca6b4fc719a2a3eb3b7d774c5c2c4d2329e8c8d..dd9f3ec5ee30f923998ba62411148c534e25f013 100644 (file)
@@ -1,7 +1,7 @@
 config PPC64
        bool "64-bit kernel"
        default n
-       select HAVE_PERF_COUNTERS
+       select PPC_HAVE_PMU_SUPPORT
        help
          This option selects whether a 32-bit or a 64-bit kernel
          will be built.
@@ -243,6 +243,15 @@ config VIRT_CPU_ACCOUNTING
 
          If in doubt, say Y here.
 
+config PPC_HAVE_PMU_SUPPORT
+       bool
+
+config PPC_PERF_CTRS
+       def_bool y
+       depends on PERF_COUNTERS && PPC_HAVE_PMU_SUPPORT
+       help
+         This enables the powerpc-specific perf_counter back-end.
+
 config SMP
        depends on PPC_STD_MMU || FSL_BOOKE
        bool "Symmetric multi-processing support"