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, 2005 Ralf Baechle
0007  * Copyright (C) 2005 MIPS Technologies, Inc.
0008  */
0009 #include <linux/compiler.h>
0010 #include <linux/errno.h>
0011 #include <linux/init.h>
0012 #include <linux/oprofile.h>
0013 #include <linux/smp.h>
0014 #include <asm/cpu-info.h>
0015 #include <asm/cpu-type.h>
0016 
0017 #include "op_impl.h"
0018 
0019 extern struct op_mips_model op_model_mipsxx_ops __weak;
0020 extern struct op_mips_model op_model_loongson2_ops __weak;
0021 extern struct op_mips_model op_model_loongson3_ops __weak;
0022 
0023 static struct op_mips_model *model;
0024 
0025 static struct op_counter_config ctr[20];
0026 
0027 static int op_mips_setup(void)
0028 {
0029     /* Pre-compute the values to stuff in the hardware registers.  */
0030     model->reg_setup(ctr);
0031 
0032     /* Configure the registers on all cpus.  */
0033     on_each_cpu(model->cpu_setup, NULL, 1);
0034 
0035     return 0;
0036 }
0037 
0038 static int op_mips_create_files(struct dentry *root)
0039 {
0040     int i;
0041 
0042     for (i = 0; i < model->num_counters; ++i) {
0043         struct dentry *dir;
0044         char buf[4];
0045 
0046         snprintf(buf, sizeof buf, "%d", i);
0047         dir = oprofilefs_mkdir(root, buf);
0048 
0049         oprofilefs_create_ulong(dir, "enabled", &ctr[i].enabled);
0050         oprofilefs_create_ulong(dir, "event", &ctr[i].event);
0051         oprofilefs_create_ulong(dir, "count", &ctr[i].count);
0052         oprofilefs_create_ulong(dir, "kernel", &ctr[i].kernel);
0053         oprofilefs_create_ulong(dir, "user", &ctr[i].user);
0054         oprofilefs_create_ulong(dir, "exl", &ctr[i].exl);
0055         /* Dummy.  */
0056         oprofilefs_create_ulong(dir, "unit_mask", &ctr[i].unit_mask);
0057     }
0058 
0059     return 0;
0060 }
0061 
0062 static int op_mips_start(void)
0063 {
0064     on_each_cpu(model->cpu_start, NULL, 1);
0065 
0066     return 0;
0067 }
0068 
0069 static void op_mips_stop(void)
0070 {
0071     /* Disable performance monitoring for all counters.  */
0072     on_each_cpu(model->cpu_stop, NULL, 1);
0073 }
0074 
0075 int __init oprofile_arch_init(struct oprofile_operations *ops)
0076 {
0077     struct op_mips_model *lmodel = NULL;
0078     int res;
0079 
0080     switch (boot_cpu_type()) {
0081     case CPU_5KC:
0082     case CPU_M14KC:
0083     case CPU_M14KEC:
0084     case CPU_20KC:
0085     case CPU_24K:
0086     case CPU_25KF:
0087     case CPU_34K:
0088     case CPU_1004K:
0089     case CPU_74K:
0090     case CPU_1074K:
0091     case CPU_INTERAPTIV:
0092     case CPU_PROAPTIV:
0093     case CPU_P5600:
0094     case CPU_I6400:
0095     case CPU_M5150:
0096     case CPU_LOONGSON1:
0097     case CPU_SB1:
0098     case CPU_SB1A:
0099     case CPU_R10000:
0100     case CPU_R12000:
0101     case CPU_R14000:
0102     case CPU_R16000:
0103     case CPU_XLR:
0104         lmodel = &op_model_mipsxx_ops;
0105         break;
0106 
0107     case CPU_LOONGSON2:
0108         lmodel = &op_model_loongson2_ops;
0109         break;
0110     case CPU_LOONGSON3:
0111         lmodel = &op_model_loongson3_ops;
0112         break;
0113     };
0114 
0115     /*
0116      * Always set the backtrace. This allows unsupported CPU types to still
0117      * use timer-based oprofile.
0118      */
0119     ops->backtrace = op_mips_backtrace;
0120 
0121     if (!lmodel)
0122         return -ENODEV;
0123 
0124     res = lmodel->init();
0125     if (res)
0126         return res;
0127 
0128     model = lmodel;
0129 
0130     ops->create_files   = op_mips_create_files;
0131     ops->setup      = op_mips_setup;
0132     //ops->shutdown     = op_mips_shutdown;
0133     ops->start      = op_mips_start;
0134     ops->stop       = op_mips_stop;
0135     ops->cpu_type       = lmodel->cpu_type;
0136 
0137     printk(KERN_INFO "oprofile: using %s performance monitoring.\n",
0138            lmodel->cpu_type);
0139 
0140     return 0;
0141 }
0142 
0143 void oprofile_arch_exit(void)
0144 {
0145     if (model)
0146         model->exit();
0147 }