MIPS: oprofile: Support for XLR/XLS processors
authorMadhusudan Bhat <mbhat@netlogicmicro.com>
Wed, 31 Oct 2012 12:01:27 +0000 (12:01 +0000)
committerJohn Crispin <blogic@openwrt.org>
Fri, 9 Nov 2012 10:37:18 +0000 (11:37 +0100)
Add support for XLR and XLS processors in MIPS Oprofile code. These
processors are multi-threaded and have two counters per core. Each
counter can track either all the events in the core (global mode),
or events in just one thread.

We use the counters in the global mode, and use only the first thread
in each core to handle the configuration etc.

Signed-off-by: Madhusudan Bhat <mbhat@netlogicmicro.com>
Signed-off-by: Jayachandran C <jchandra@broadcom.com>
Patchwork: http://patchwork.linux-mips.org/patch/4471
Signed-off-by: John Crispin <blogic@openwrt.org>
arch/mips/oprofile/Makefile
arch/mips/oprofile/common.c
arch/mips/oprofile/op_model_mipsxx.c

index 1208c280f77dbb0cc2596890dbccab3f1c45c3e0..65f5237ec821eee6c61349642b519c01511ae3eb 100644 (file)
@@ -12,5 +12,6 @@ oprofile-$(CONFIG_CPU_MIPS32)         += op_model_mipsxx.o
 oprofile-$(CONFIG_CPU_MIPS64)          += op_model_mipsxx.o
 oprofile-$(CONFIG_CPU_R10000)          += op_model_mipsxx.o
 oprofile-$(CONFIG_CPU_SB1)             += op_model_mipsxx.o
+oprofile-$(CONFIG_CPU_XLR)             += op_model_mipsxx.o
 oprofile-$(CONFIG_CPU_RM9000)          += op_model_rm9000.o
 oprofile-$(CONFIG_CPU_LOONGSON2)       += op_model_loongson2.o
index f80480a5a0328b3a79d45950c2679577d0345e4a..abd5a02f47cf31b997220309a056c6f88d90fc18 100644 (file)
@@ -91,6 +91,7 @@ int __init oprofile_arch_init(struct oprofile_operations *ops)
        case CPU_R10000:
        case CPU_R12000:
        case CPU_R14000:
+       case CPU_XLR:
                lmodel = &op_model_mipsxx_ops;
                break;
 
index 28ea1a4cc576c0bb8e566a63a7d4d0caf9221692..786254630403ab62e02dde6197038f3b976cc9e4 100644 (file)
 
 #define M_COUNTER_OVERFLOW             (1UL      << 31)
 
+/* Netlogic XLR specific, count events in all threads in a core */
+#define M_PERFCTL_COUNT_ALL_THREADS    (1UL      << 13)
+
 static int (*save_perf_irq)(void);
 
+/*
+ * XLR has only one set of counters per core. Designate the
+ * first hardware thread in the core for setup and init.
+ * Skip CPUs with non-zero hardware thread id (4 hwt per core)
+ */
+#ifdef CONFIG_CPU_XLR
+#define oprofile_skip_cpu(c)   ((cpu_logical_map(c) & 0x3) != 0)
+#else
+#define oprofile_skip_cpu(c)   0
+#endif
+
 #ifdef CONFIG_MIPS_MT_SMP
 static int cpu_has_mipsmt_pertccounters;
 #define WHAT           (M_TC_EN_VPE | \
@@ -152,6 +166,8 @@ static void mipsxx_reg_setup(struct op_counter_config *ctr)
                        reg.control[i] |= M_PERFCTL_USER;
                if (ctr[i].exl)
                        reg.control[i] |= M_PERFCTL_EXL;
+               if (current_cpu_type() == CPU_XLR)
+                       reg.control[i] |= M_PERFCTL_COUNT_ALL_THREADS;
                reg.counter[i] = 0x80000000 - ctr[i].count;
        }
 }
@@ -162,6 +178,9 @@ static void mipsxx_cpu_setup(void *args)
 {
        unsigned int counters = op_model_mipsxx_ops.num_counters;
 
+       if (oprofile_skip_cpu(smp_processor_id()))
+               return;
+
        switch (counters) {
        case 4:
                w_c0_perfctrl3(0);
@@ -183,6 +202,9 @@ static void mipsxx_cpu_start(void *args)
 {
        unsigned int counters = op_model_mipsxx_ops.num_counters;
 
+       if (oprofile_skip_cpu(smp_processor_id()))
+               return;
+
        switch (counters) {
        case 4:
                w_c0_perfctrl3(WHAT | reg.control[3]);
@@ -200,6 +222,9 @@ static void mipsxx_cpu_stop(void *args)
 {
        unsigned int counters = op_model_mipsxx_ops.num_counters;
 
+       if (oprofile_skip_cpu(smp_processor_id()))
+               return;
+
        switch (counters) {
        case 4:
                w_c0_perfctrl3(0);
@@ -372,6 +397,10 @@ static int __init mipsxx_init(void)
                op_model_mipsxx_ops.cpu_type = "mips/loongson1";
                break;
 
+       case CPU_XLR:
+               op_model_mipsxx_ops.cpu_type = "mips/xlr";
+               break;
+
        default:
                printk(KERN_ERR "Profiling unsupported for this CPU\n");