This is the 1st patch starting to use perf events as the backend of
Oprofile. Here we move pmu helper functions and macros between pmu.h and
perf_event*.c for mipsxx.
Signed-off-by: Deng-Cheng Zhu <dengcheng.zhu@gmail.com>
---
arch/mips/include/asm/pmu.h | 160 ++--------------------------------
arch/mips/kernel/perf_event.c | 2 +
arch/mips/kernel/perf_event_mipsxx.c | 145 +++++++++++++++++++++++++++++--
3 files changed, 147 insertions(+), 160 deletions(-)
diff --git a/arch/mips/include/asm/pmu.h b/arch/mips/include/asm/pmu.h
index 162b24f..2822810 100644
--- a/arch/mips/include/asm/pmu.h
+++ b/arch/mips/include/asm/pmu.h
@@ -8,9 +8,6 @@
* Author: Wu Zhangjin <wuzhangjin@gmail.com>
* Copyright (C) 2010 MIPS Technologies, Inc. Deng-Cheng Zhu
*
- * This file is shared by Oprofile and Perf. It is also shared across the
- * Oprofile implementation for different MIPS CPUs.
- *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
@@ -39,160 +36,19 @@
#define M_PERFCTL_WIDE (1UL << 30)
#define M_PERFCTL_MORE (1UL << 31)
-#define M_COUNTER_OVERFLOW (1UL << 31)
+#define M_PERFCTL_COUNT_EVENT_WHENEVER \
+ (M_PERFCTL_EXL | M_PERFCTL_KERNEL | \
+ M_PERFCTL_USER | M_PERFCTL_SUPERVISOR | \
+ M_PERFCTL_INTERRUPT_ENABLE)
#ifdef CONFIG_MIPS_MT_SMP
-static int cpu_has_mipsmt_pertccounters;
-#define WHAT (M_TC_EN_VPE | \
- M_PERFCTL_VPEID(cpu_data[smp_processor_id()].vpe_id))
-/*
- * FIXME: For VSMP, vpe_id() is redefined for Perf, because
- * cpu_data[cpuid].vpe_id reports 0 for _both_ CPUs. WHAT is not
- * redefined because Perf does not use it.
- */
-#if defined(CONFIG_HW_PERF_EVENTS)
-#define vpe_id() (cpu_has_mipsmt_pertccounters ? \
- 0 : smp_processor_id())
-#else
-#define vpe_id() (cpu_has_mipsmt_pertccounters ? \
- 0 : cpu_data[smp_processor_id()].vpe_id)
-#endif
-/*
- * The number of bits to shift to convert between counters per core and
- * counters per VPE. There is no reasonable interface atm to obtain the
- * number of VPEs used by Linux and in the 34K this number is fixed to two
- * anyways so we hardcore a few things here for the moment. The way it's
- * done here will ensure that oprofile VSMP kernel will run right on a lesser
- * core like a 24K also or with maxcpus=1.
- */
-static inline unsigned int vpe_shift(void)
-{
- if (num_possible_cpus() > 1)
- return 1;
-
- return 0;
-}
+#define M_PERFCTL_CONFIG_MASK 0x3fff801f
#else
-#define WHAT 0
-#define vpe_id() 0
-static inline unsigned int vpe_shift(void)
-{
- return 0;
-}
+#define M_PERFCTL_CONFIG_MASK 0x1f
#endif
+#define M_PERFCTL_EVENT_MASK 0xfe0
-static inline unsigned int
-counters_total_to_per_cpu(unsigned int counters)
-{
- return counters >> vpe_shift();
-}
-
-static inline unsigned int
-counters_per_cpu_to_total(unsigned int counters)
-{
- return counters << vpe_shift();
-}
-
-#define __define_perf_accessors(r, n, np) \
- \
-static inline unsigned int r_c0_ ## r ## n(void) \
-{ \
- unsigned int cpu = vpe_id(); \
- \
- switch (cpu) { \
- case 0: \
- return read_c0_ ## r ## n(); \
- case 1: \
- return read_c0_ ## r ## np(); \
- default: \
- BUG(); \
- } \
- return 0; \
-} \
- \
-static inline void w_c0_ ## r ## n(unsigned int value) \
-{ \
- unsigned int cpu = vpe_id(); \
- \
- switch (cpu) { \
- case 0: \
- write_c0_ ## r ## n(value); \
- return; \
- case 1: \
- write_c0_ ## r ## np(value); \
- return; \
- default: \
- BUG(); \
- } \
- return; \
-} \
-
-__define_perf_accessors(perfcntr, 0, 2)
-__define_perf_accessors(perfcntr, 1, 3)
-__define_perf_accessors(perfcntr, 2, 0)
-__define_perf_accessors(perfcntr, 3, 1)
-
-__define_perf_accessors(perfctrl, 0, 2)
-__define_perf_accessors(perfctrl, 1, 3)
-__define_perf_accessors(perfctrl, 2, 0)
-__define_perf_accessors(perfctrl, 3, 1)
-
-static inline int __n_counters(void)
-{
- if (!(read_c0_config1() & M_CONFIG1_PC))
- return 0;
- if (!(read_c0_perfctrl0() & M_PERFCTL_MORE))
- return 1;
- if (!(read_c0_perfctrl1() & M_PERFCTL_MORE))
- return 2;
- if (!(read_c0_perfctrl2() & M_PERFCTL_MORE))
- return 3;
-
- return 4;
-}
-
-static inline int n_counters(void)
-{
- int counters;
-
- switch (current_cpu_type()) {
- case CPU_R10000:
- counters = 2;
- break;
-
- case CPU_R12000:
- case CPU_R14000:
- counters = 4;
- break;
-
- default:
- counters = __n_counters();
- }
-
- return counters;
-}
-
-static void reset_counters(void *arg)
-{
- int counters = (int)(long)arg;
- switch (counters) {
- case 4:
- w_c0_perfctrl3(0);
- w_c0_perfcntr3(0);
- case 3:
- w_c0_perfctrl2(0);
- w_c0_perfcntr2(0);
- case 2:
- w_c0_perfctrl1(0);
- w_c0_perfcntr1(0);
- case 1:
- w_c0_perfctrl0(0);
- w_c0_perfcntr0(0);
- }
-}
-
-/* Used by Perf */
-#define MIPS_MAX_HWEVENTS 4
+#define M_COUNTER_OVERFLOW (1UL << 31)
#elif defined(CONFIG_CPU_RM9000)
diff --git a/arch/mips/kernel/perf_event.c b/arch/mips/kernel/perf_event.c
index 24e07f8..0ef54e6 100644
--- a/arch/mips/kernel/perf_event.c
+++ b/arch/mips/kernel/perf_event.c
@@ -27,6 +27,7 @@
#define MAX_PERIOD ((1ULL << 32) - 1)
+#define MIPS_MAX_HWEVENTS 4
struct cpu_hw_events {
/* Array of events on this cpu. */
@@ -428,6 +429,7 @@ static int validate_group(struct perf_event *event)
* specific low-level init routines.
*/
static int __hw_perf_event_init(struct perf_event *event);
+static void reset_counters(void *arg);
static void hw_perf_event_destroy(struct perf_event *event)
{
diff --git a/arch/mips/kernel/perf_event_mipsxx.c
b/arch/mips/kernel/perf_event_mipsxx.c
index 802d98e..1c92917 100644
--- a/arch/mips/kernel/perf_event_mipsxx.c
+++ b/arch/mips/kernel/perf_event_mipsxx.c
@@ -1,17 +1,146 @@
#if defined(CONFIG_CPU_MIPS32) || defined(CONFIG_CPU_MIPS64) || \
defined(CONFIG_CPU_R10000) || defined(CONFIG_CPU_SB1)
-#define M_PERFCTL_COUNT_EVENT_WHENEVER \
- (M_PERFCTL_EXL | M_PERFCTL_KERNEL | \
- M_PERFCTL_USER | M_PERFCTL_SUPERVISOR | \
- M_PERFCTL_INTERRUPT_ENABLE)
-
#ifdef CONFIG_MIPS_MT_SMP
-#define M_PERFCTL_CONFIG_MASK 0x3fff801f
+static int cpu_has_mipsmt_pertccounters;
+/*
+ * FIXME: For VSMP, cpu_data[cpuid].vpe_id reports 0 for _both_ CPUs. So
+ * we use smp_processor_id() to identify VPEs.
+ */
+#define vpe_id() (cpu_has_mipsmt_pertccounters ? \
+ 0 : smp_processor_id())
+/*
+ * The number of bits to shift to convert between counters per core and
+ * counters per VPE. There is no reasonable interface atm to obtain the
+ * number of VPEs used by Linux and in the 34K this number is fixed to two
+ * anyways so we hardcore a few things here for the moment. The way it's
+ * done here will ensure that oprofile VSMP kernel will run right on a lesser
+ * core like a 24K also or with maxcpus=1.
+ */
+static inline unsigned int vpe_shift(void)
+{
+ if (num_possible_cpus() > 1)
+ return 1;
+
+ return 0;
+}
#else
-#define M_PERFCTL_CONFIG_MASK 0x1f
+#define vpe_id() 0
+static inline unsigned int vpe_shift(void)
+{
+ return 0;
+}
#endif
-#define M_PERFCTL_EVENT_MASK 0xfe0
+
+static inline unsigned int
+counters_total_to_per_cpu(unsigned int counters)
+{
+ return counters >> vpe_shift();
+}
+
+static inline unsigned int
+counters_per_cpu_to_total(unsigned int counters)
+{
+ return counters << vpe_shift();
+}
+
+#define __define_perf_accessors(r, n, np) \
+ \
+static inline unsigned int r_c0_ ## r ## n(void) \
+{ \
+ unsigned int cpu = vpe_id(); \
+ \
+ switch (cpu) { \
+ case 0: \
+ return read_c0_ ## r ## n(); \
+ case 1: \
+ return read_c0_ ## r ## np(); \
+ default: \
+ BUG(); \
+ } \
+ return 0; \
+} \
+ \
+static inline void w_c0_ ## r ## n(unsigned int value) \
+{ \
+ unsigned int cpu = vpe_id(); \
+ \
+ switch (cpu) { \
+ case 0: \
+ write_c0_ ## r ## n(value); \
+ return; \
+ case 1: \
+ write_c0_ ## r ## np(value); \
+ return; \
+ default: \
+ BUG(); \
+ } \
+ return; \
+} \
+
+__define_perf_accessors(perfcntr, 0, 2)
+__define_perf_accessors(perfcntr, 1, 3)
+__define_perf_accessors(perfcntr, 2, 0)
+__define_perf_accessors(perfcntr, 3, 1)
+
+__define_perf_accessors(perfctrl, 0, 2)
+__define_perf_accessors(perfctrl, 1, 3)
+__define_perf_accessors(perfctrl, 2, 0)
+__define_perf_accessors(perfctrl, 3, 1)
+
+static inline int __n_counters(void)
+{
+ if (!(read_c0_config1() & M_CONFIG1_PC))
+ return 0;
+ if (!(read_c0_perfctrl0() & M_PERFCTL_MORE))
+ return 1;
+ if (!(read_c0_perfctrl1() & M_PERFCTL_MORE))
+ return 2;
+ if (!(read_c0_perfctrl2() & M_PERFCTL_MORE))
+ return 3;
+
+ return 4;
+}
+
+static inline int n_counters(void)
+{
+ int counters;
+
+ switch (current_cpu_type()) {
+ case CPU_R10000:
+ counters = 2;
+ break;
+
+ case CPU_R12000:
+ case CPU_R14000:
+ counters = 4;
+ break;
+
+ default:
+ counters = __n_counters();
+ }
+
+ return counters;
+}
+
+static void reset_counters(void *arg)
+{
+ int counters = (int)(long)arg;
+ switch (counters) {
+ case 4:
+ w_c0_perfctrl3(0);
+ w_c0_perfcntr3(0);
+ case 3:
+ w_c0_perfctrl2(0);
+ w_c0_perfcntr2(0);
+ case 2:
+ w_c0_perfctrl1(0);
+ w_c0_perfcntr1(0);
+ case 1:
+ w_c0_perfctrl0(0);
+ w_c0_perfcntr0(0);
+ }
+}
static inline unsigned int
mipsxx_pmu_read_counter(unsigned int idx)
--
1.6.3.3
|