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