Back to home page

LXR

 
 

    


0001 /*
0002  * This file is subject to the terms and conditions of the GNU General Public
0003  * License.  See the file "COPYING" in the main directory of this archive
0004  * for more details.
0005  *
0006  * Copyright (C) 2004, 05, 06 by Ralf Baechle
0007  * Copyright (C) 2005 by MIPS Technologies, Inc.
0008  */
0009 #include <linux/cpumask.h>
0010 #include <linux/oprofile.h>
0011 #include <linux/interrupt.h>
0012 #include <linux/smp.h>
0013 #include <asm/irq_regs.h>
0014 #include <asm/time.h>
0015 
0016 #include "op_impl.h"
0017 
0018 #define M_PERFCTL_EXL           (1UL      <<  0)
0019 #define M_PERFCTL_KERNEL        (1UL      <<  1)
0020 #define M_PERFCTL_SUPERVISOR        (1UL      <<  2)
0021 #define M_PERFCTL_USER          (1UL      <<  3)
0022 #define M_PERFCTL_INTERRUPT_ENABLE  (1UL      <<  4)
0023 #define M_PERFCTL_EVENT(event)      (((event) & 0x3ff)  << 5)
0024 #define M_PERFCTL_VPEID(vpe)        ((vpe)    << 16)
0025 #define M_PERFCTL_MT_EN(filter)     ((filter) << 20)
0026 #define    M_TC_EN_ALL          M_PERFCTL_MT_EN(0)
0027 #define    M_TC_EN_VPE          M_PERFCTL_MT_EN(1)
0028 #define    M_TC_EN_TC           M_PERFCTL_MT_EN(2)
0029 #define M_PERFCTL_TCID(tcid)        ((tcid)   << 22)
0030 #define M_PERFCTL_WIDE          (1UL      << 30)
0031 #define M_PERFCTL_MORE          (1UL      << 31)
0032 
0033 #define M_COUNTER_OVERFLOW      (1UL      << 31)
0034 
0035 /* Netlogic XLR specific, count events in all threads in a core */
0036 #define M_PERFCTL_COUNT_ALL_THREADS (1UL      << 13)
0037 
0038 static int (*save_perf_irq)(void);
0039 static int perfcount_irq;
0040 
0041 /*
0042  * XLR has only one set of counters per core. Designate the
0043  * first hardware thread in the core for setup and init.
0044  * Skip CPUs with non-zero hardware thread id (4 hwt per core)
0045  */
0046 #if defined(CONFIG_CPU_XLR) && defined(CONFIG_SMP)
0047 #define oprofile_skip_cpu(c)    ((cpu_logical_map(c) & 0x3) != 0)
0048 #else
0049 #define oprofile_skip_cpu(c)    0
0050 #endif
0051 
0052 #ifdef CONFIG_MIPS_MT_SMP
0053 static int cpu_has_mipsmt_pertccounters;
0054 #define WHAT        (M_TC_EN_VPE | \
0055              M_PERFCTL_VPEID(cpu_data[smp_processor_id()].vpe_id))
0056 #define vpe_id()    (cpu_has_mipsmt_pertccounters ? \
0057             0 : cpu_data[smp_processor_id()].vpe_id)
0058 
0059 /*
0060  * The number of bits to shift to convert between counters per core and
0061  * counters per VPE.  There is no reasonable interface atm to obtain the
0062  * number of VPEs used by Linux and in the 34K this number is fixed to two
0063  * anyways so we hardcore a few things here for the moment.  The way it's
0064  * done here will ensure that oprofile VSMP kernel will run right on a lesser
0065  * core like a 24K also or with maxcpus=1.
0066  */
0067 static inline unsigned int vpe_shift(void)
0068 {
0069     if (num_possible_cpus() > 1)
0070         return 1;
0071 
0072     return 0;
0073 }
0074 
0075 #else
0076 
0077 #define WHAT        0
0078 #define vpe_id()    0
0079 
0080 static inline unsigned int vpe_shift(void)
0081 {
0082     return 0;
0083 }
0084 
0085 #endif
0086 
0087 static inline unsigned int counters_total_to_per_cpu(unsigned int counters)
0088 {
0089     return counters >> vpe_shift();
0090 }
0091 
0092 static inline unsigned int counters_per_cpu_to_total(unsigned int counters)
0093 {
0094     return counters << vpe_shift();
0095 }
0096 
0097 #define __define_perf_accessors(r, n, np)               \
0098                                     \
0099 static inline unsigned int r_c0_ ## r ## n(void)            \
0100 {                                   \
0101     unsigned int cpu = vpe_id();                    \
0102                                     \
0103     switch (cpu) {                          \
0104     case 0:                             \
0105         return read_c0_ ## r ## n();                \
0106     case 1:                             \
0107         return read_c0_ ## r ## np();               \
0108     default:                            \
0109         BUG();                          \
0110     }                               \
0111     return 0;                           \
0112 }                                   \
0113                                     \
0114 static inline void w_c0_ ## r ## n(unsigned int value)          \
0115 {                                   \
0116     unsigned int cpu = vpe_id();                    \
0117                                     \
0118     switch (cpu) {                          \
0119     case 0:                             \
0120         write_c0_ ## r ## n(value);             \
0121         return;                         \
0122     case 1:                             \
0123         write_c0_ ## r ## np(value);                \
0124         return;                         \
0125     default:                            \
0126         BUG();                          \
0127     }                               \
0128     return;                             \
0129 }                                   \
0130 
0131 __define_perf_accessors(perfcntr, 0, 2)
0132 __define_perf_accessors(perfcntr, 1, 3)
0133 __define_perf_accessors(perfcntr, 2, 0)
0134 __define_perf_accessors(perfcntr, 3, 1)
0135 
0136 __define_perf_accessors(perfctrl, 0, 2)
0137 __define_perf_accessors(perfctrl, 1, 3)
0138 __define_perf_accessors(perfctrl, 2, 0)
0139 __define_perf_accessors(perfctrl, 3, 1)
0140 
0141 struct op_mips_model op_model_mipsxx_ops;
0142 
0143 static struct mipsxx_register_config {
0144     unsigned int control[4];
0145     unsigned int counter[4];
0146 } reg;
0147 
0148 /* Compute all of the registers in preparation for enabling profiling.  */
0149 
0150 static void mipsxx_reg_setup(struct op_counter_config *ctr)
0151 {
0152     unsigned int counters = op_model_mipsxx_ops.num_counters;
0153     int i;
0154 
0155     /* Compute the performance counter control word.  */
0156     for (i = 0; i < counters; i++) {
0157         reg.control[i] = 0;
0158         reg.counter[i] = 0;
0159 
0160         if (!ctr[i].enabled)
0161             continue;
0162 
0163         reg.control[i] = M_PERFCTL_EVENT(ctr[i].event) |
0164                  M_PERFCTL_INTERRUPT_ENABLE;
0165         if (ctr[i].kernel)
0166             reg.control[i] |= M_PERFCTL_KERNEL;
0167         if (ctr[i].user)
0168             reg.control[i] |= M_PERFCTL_USER;
0169         if (ctr[i].exl)
0170             reg.control[i] |= M_PERFCTL_EXL;
0171         if (boot_cpu_type() == CPU_XLR)
0172             reg.control[i] |= M_PERFCTL_COUNT_ALL_THREADS;
0173         reg.counter[i] = 0x80000000 - ctr[i].count;
0174     }
0175 }
0176 
0177 /* Program all of the registers in preparation for enabling profiling.  */
0178 
0179 static void mipsxx_cpu_setup(void *args)
0180 {
0181     unsigned int counters = op_model_mipsxx_ops.num_counters;
0182 
0183     if (oprofile_skip_cpu(smp_processor_id()))
0184         return;
0185 
0186     switch (counters) {
0187     case 4:
0188         w_c0_perfctrl3(0);
0189         w_c0_perfcntr3(reg.counter[3]);
0190     case 3:
0191         w_c0_perfctrl2(0);
0192         w_c0_perfcntr2(reg.counter[2]);
0193     case 2:
0194         w_c0_perfctrl1(0);
0195         w_c0_perfcntr1(reg.counter[1]);
0196     case 1:
0197         w_c0_perfctrl0(0);
0198         w_c0_perfcntr0(reg.counter[0]);
0199     }
0200 }
0201 
0202 /* Start all counters on current CPU */
0203 static void mipsxx_cpu_start(void *args)
0204 {
0205     unsigned int counters = op_model_mipsxx_ops.num_counters;
0206 
0207     if (oprofile_skip_cpu(smp_processor_id()))
0208         return;
0209 
0210     switch (counters) {
0211     case 4:
0212         w_c0_perfctrl3(WHAT | reg.control[3]);
0213     case 3:
0214         w_c0_perfctrl2(WHAT | reg.control[2]);
0215     case 2:
0216         w_c0_perfctrl1(WHAT | reg.control[1]);
0217     case 1:
0218         w_c0_perfctrl0(WHAT | reg.control[0]);
0219     }
0220 }
0221 
0222 /* Stop all counters on current CPU */
0223 static void mipsxx_cpu_stop(void *args)
0224 {
0225     unsigned int counters = op_model_mipsxx_ops.num_counters;
0226 
0227     if (oprofile_skip_cpu(smp_processor_id()))
0228         return;
0229 
0230     switch (counters) {
0231     case 4:
0232         w_c0_perfctrl3(0);
0233     case 3:
0234         w_c0_perfctrl2(0);
0235     case 2:
0236         w_c0_perfctrl1(0);
0237     case 1:
0238         w_c0_perfctrl0(0);
0239     }
0240 }
0241 
0242 static int mipsxx_perfcount_handler(void)
0243 {
0244     unsigned int counters = op_model_mipsxx_ops.num_counters;
0245     unsigned int control;
0246     unsigned int counter;
0247     int handled = IRQ_NONE;
0248 
0249     if (cpu_has_mips_r2 && !(read_c0_cause() & CAUSEF_PCI))
0250         return handled;
0251 
0252     switch (counters) {
0253 #define HANDLE_COUNTER(n)                       \
0254     case n + 1:                         \
0255         control = r_c0_perfctrl ## n();             \
0256         counter = r_c0_perfcntr ## n();             \
0257         if ((control & M_PERFCTL_INTERRUPT_ENABLE) &&       \
0258             (counter & M_COUNTER_OVERFLOW)) {           \
0259             oprofile_add_sample(get_irq_regs(), n);     \
0260             w_c0_perfcntr ## n(reg.counter[n]);     \
0261             handled = IRQ_HANDLED;              \
0262         }
0263     HANDLE_COUNTER(3)
0264     HANDLE_COUNTER(2)
0265     HANDLE_COUNTER(1)
0266     HANDLE_COUNTER(0)
0267     }
0268 
0269     return handled;
0270 }
0271 
0272 static inline int __n_counters(void)
0273 {
0274     if (!cpu_has_perf)
0275         return 0;
0276     if (!(read_c0_perfctrl0() & M_PERFCTL_MORE))
0277         return 1;
0278     if (!(read_c0_perfctrl1() & M_PERFCTL_MORE))
0279         return 2;
0280     if (!(read_c0_perfctrl2() & M_PERFCTL_MORE))
0281         return 3;
0282 
0283     return 4;
0284 }
0285 
0286 static inline int n_counters(void)
0287 {
0288     int counters;
0289 
0290     switch (current_cpu_type()) {
0291     case CPU_R10000:
0292         counters = 2;
0293         break;
0294 
0295     case CPU_R12000:
0296     case CPU_R14000:
0297     case CPU_R16000:
0298         counters = 4;
0299         break;
0300 
0301     default:
0302         counters = __n_counters();
0303     }
0304 
0305     return counters;
0306 }
0307 
0308 static void reset_counters(void *arg)
0309 {
0310     int counters = (int)(long)arg;
0311     switch (counters) {
0312     case 4:
0313         w_c0_perfctrl3(0);
0314         w_c0_perfcntr3(0);
0315     case 3:
0316         w_c0_perfctrl2(0);
0317         w_c0_perfcntr2(0);
0318     case 2:
0319         w_c0_perfctrl1(0);
0320         w_c0_perfcntr1(0);
0321     case 1:
0322         w_c0_perfctrl0(0);
0323         w_c0_perfcntr0(0);
0324     }
0325 }
0326 
0327 static irqreturn_t mipsxx_perfcount_int(int irq, void *dev_id)
0328 {
0329     return mipsxx_perfcount_handler();
0330 }
0331 
0332 static int __init mipsxx_init(void)
0333 {
0334     int counters;
0335 
0336     counters = n_counters();
0337     if (counters == 0) {
0338         printk(KERN_ERR "Oprofile: CPU has no performance counters\n");
0339         return -ENODEV;
0340     }
0341 
0342 #ifdef CONFIG_MIPS_MT_SMP
0343     cpu_has_mipsmt_pertccounters = read_c0_config7() & (1<<19);
0344     if (!cpu_has_mipsmt_pertccounters)
0345         counters = counters_total_to_per_cpu(counters);
0346 #endif
0347     on_each_cpu(reset_counters, (void *)(long)counters, 1);
0348 
0349     op_model_mipsxx_ops.num_counters = counters;
0350     switch (current_cpu_type()) {
0351     case CPU_M14KC:
0352         op_model_mipsxx_ops.cpu_type = "mips/M14Kc";
0353         break;
0354 
0355     case CPU_M14KEC:
0356         op_model_mipsxx_ops.cpu_type = "mips/M14KEc";
0357         break;
0358 
0359     case CPU_20KC:
0360         op_model_mipsxx_ops.cpu_type = "mips/20K";
0361         break;
0362 
0363     case CPU_24K:
0364         op_model_mipsxx_ops.cpu_type = "mips/24K";
0365         break;
0366 
0367     case CPU_25KF:
0368         op_model_mipsxx_ops.cpu_type = "mips/25K";
0369         break;
0370 
0371     case CPU_1004K:
0372     case CPU_34K:
0373         op_model_mipsxx_ops.cpu_type = "mips/34K";
0374         break;
0375 
0376     case CPU_1074K:
0377     case CPU_74K:
0378         op_model_mipsxx_ops.cpu_type = "mips/74K";
0379         break;
0380 
0381     case CPU_INTERAPTIV:
0382         op_model_mipsxx_ops.cpu_type = "mips/interAptiv";
0383         break;
0384 
0385     case CPU_PROAPTIV:
0386         op_model_mipsxx_ops.cpu_type = "mips/proAptiv";
0387         break;
0388 
0389     case CPU_P5600:
0390         op_model_mipsxx_ops.cpu_type = "mips/P5600";
0391         break;
0392 
0393     case CPU_I6400:
0394         op_model_mipsxx_ops.cpu_type = "mips/I6400";
0395         break;
0396 
0397     case CPU_M5150:
0398         op_model_mipsxx_ops.cpu_type = "mips/M5150";
0399         break;
0400 
0401     case CPU_5KC:
0402         op_model_mipsxx_ops.cpu_type = "mips/5K";
0403         break;
0404 
0405     case CPU_R10000:
0406         if ((current_cpu_data.processor_id & 0xff) == 0x20)
0407             op_model_mipsxx_ops.cpu_type = "mips/r10000-v2.x";
0408         else
0409             op_model_mipsxx_ops.cpu_type = "mips/r10000";
0410         break;
0411 
0412     case CPU_R12000:
0413     case CPU_R14000:
0414         op_model_mipsxx_ops.cpu_type = "mips/r12000";
0415         break;
0416 
0417     case CPU_R16000:
0418         op_model_mipsxx_ops.cpu_type = "mips/r16000";
0419         break;
0420 
0421     case CPU_SB1:
0422     case CPU_SB1A:
0423         op_model_mipsxx_ops.cpu_type = "mips/sb1";
0424         break;
0425 
0426     case CPU_LOONGSON1:
0427         op_model_mipsxx_ops.cpu_type = "mips/loongson1";
0428         break;
0429 
0430     case CPU_XLR:
0431         op_model_mipsxx_ops.cpu_type = "mips/xlr";
0432         break;
0433 
0434     default:
0435         printk(KERN_ERR "Profiling unsupported for this CPU\n");
0436 
0437         return -ENODEV;
0438     }
0439 
0440     save_perf_irq = perf_irq;
0441     perf_irq = mipsxx_perfcount_handler;
0442 
0443     if (get_c0_perfcount_int)
0444         perfcount_irq = get_c0_perfcount_int();
0445     else if (cp0_perfcount_irq >= 0)
0446         perfcount_irq = MIPS_CPU_IRQ_BASE + cp0_perfcount_irq;
0447     else
0448         perfcount_irq = -1;
0449 
0450     if (perfcount_irq >= 0)
0451         return request_irq(perfcount_irq, mipsxx_perfcount_int,
0452                    IRQF_PERCPU | IRQF_NOBALANCING |
0453                    IRQF_NO_THREAD | IRQF_NO_SUSPEND |
0454                    IRQF_SHARED,
0455                    "Perfcounter", save_perf_irq);
0456 
0457     return 0;
0458 }
0459 
0460 static void mipsxx_exit(void)
0461 {
0462     int counters = op_model_mipsxx_ops.num_counters;
0463 
0464     if (perfcount_irq >= 0)
0465         free_irq(perfcount_irq, save_perf_irq);
0466 
0467     counters = counters_per_cpu_to_total(counters);
0468     on_each_cpu(reset_counters, (void *)(long)counters, 1);
0469 
0470     perf_irq = save_perf_irq;
0471 }
0472 
0473 struct op_mips_model op_model_mipsxx_ops = {
0474     .reg_setup  = mipsxx_reg_setup,
0475     .cpu_setup  = mipsxx_cpu_setup,
0476     .init       = mipsxx_init,
0477     .exit       = mipsxx_exit,
0478     .cpu_start  = mipsxx_cpu_start,
0479     .cpu_stop   = mipsxx_cpu_stop,
0480 };