1/* 2 * This file is subject to the terms and conditions of the GNU General Public 3 * License. See the file "COPYING" in the main directory of this archive 4 * for more details. 5 * 6 * Copyright (C) 2004, 2005 Ralf Baechle 7 * Copyright (C) 2005 MIPS Technologies, Inc. 8 */ 9#include <linux/compiler.h> 10#include <linux/errno.h> 11#include <linux/init.h> 12#include <linux/oprofile.h> 13#include <linux/smp.h> 14#include <asm/cpu-info.h> 15 16#include "op_impl.h" 17 18extern struct op_mips_model op_model_mipsxx_ops __weak; 19extern struct op_mips_model op_model_rm9000_ops __weak; 20extern struct op_mips_model op_model_loongson2_ops __weak; 21 22static struct op_mips_model *model; 23 24static struct op_counter_config ctr[20]; 25 26static int op_mips_setup(void) 27{ 28 /* Pre-compute the values to stuff in the hardware registers. */ 29 model->reg_setup(ctr); 30 31 /* Configure the registers on all cpus. */ 32 on_each_cpu(model->cpu_setup, NULL, 1); 33 34 return 0; 35} 36 37static int op_mips_create_files(struct super_block *sb, struct dentry *root) 38{ 39 int i; 40 41 for (i = 0; i < model->num_counters; ++i) { 42 struct dentry *dir; 43 char buf[4]; 44 45 snprintf(buf, sizeof buf, "%d", i); 46 dir = oprofilefs_mkdir(sb, root, buf); 47 48 oprofilefs_create_ulong(sb, dir, "enabled", &ctr[i].enabled); 49 oprofilefs_create_ulong(sb, dir, "event", &ctr[i].event); 50 oprofilefs_create_ulong(sb, dir, "count", &ctr[i].count); 51 oprofilefs_create_ulong(sb, dir, "kernel", &ctr[i].kernel); 52 oprofilefs_create_ulong(sb, dir, "user", &ctr[i].user); 53 oprofilefs_create_ulong(sb, dir, "exl", &ctr[i].exl); 54 /* Dummy. */ 55 oprofilefs_create_ulong(sb, dir, "unit_mask", &ctr[i].unit_mask); 56 } 57 58 return 0; 59} 60 61static int op_mips_start(void) 62{ 63 on_each_cpu(model->cpu_start, NULL, 1); 64 65 return 0; 66} 67 68static void op_mips_stop(void) 69{ 70 /* Disable performance monitoring for all counters. */ 71 on_each_cpu(model->cpu_stop, NULL, 1); 72} 73 74int __init oprofile_arch_init(struct oprofile_operations *ops) 75{ 76 struct op_mips_model *lmodel = NULL; 77 int res; 78 79 switch (current_cpu_type()) { 80 case CPU_5KC: 81 case CPU_14K: 82 case CPU_14KE: 83 case CPU_20KC: 84 case CPU_24K: 85 case CPU_25KF: 86 case CPU_34K: 87 case CPU_1004K: 88 case CPU_1074K: 89 case CPU_74K: 90 case CPU_SB1: 91 case CPU_SB1A: 92 case CPU_R10000: 93 case CPU_R12000: 94 case CPU_R14000: 95 lmodel = &op_model_mipsxx_ops; 96 break; 97 98 case CPU_RM9000: 99 lmodel = &op_model_rm9000_ops; 100 break; 101 case CPU_LOONGSON2: 102 lmodel = &op_model_loongson2_ops; 103 break; 104 }; 105 106 if (!lmodel) 107 return -ENODEV; 108 109 res = lmodel->init(); 110 if (res) 111 return res; 112 113 model = lmodel; 114 115 ops->create_files = op_mips_create_files; 116 ops->setup = op_mips_setup; 117 //ops->shutdown = op_mips_shutdown; 118 ops->start = op_mips_start; 119 ops->stop = op_mips_stop; 120 ops->cpu_type = lmodel->cpu_type; 121 122 printk(KERN_INFO "oprofile: using %s performance monitoring.\n", 123 lmodel->cpu_type); 124 125 return 0; 126} 127 128void oprofile_arch_exit(void) 129{ 130 if (model) 131 model->exit(); 132} 133