linux/arch/mips/oprofile/common.c
Yanjiang Jin fa0c879ffc MIPS: oprofile: Fix a preemption issue
Use boot_cpu_type() instead of current_cpu_type() in oprofile_arch_init()
to avoid the below warning, cpu_type is normally consistent in a MIPS SMP
system.  There are a few exceptions such as SGI servers where it is
possible to mix R10000, R12000, R14000 and R16000 within certain
constraints.  Let's not worry about those now.

BUG: using smp_processor_id() in preemptible [00000000] code: insmod/952
caller is oprofile_arch_init+0x30/0x194 [oprofile]
CPU: 5 PID: 952 Comm: insmod Not tainted 4.1.13-WR8.0.0.0_standard #1
Stack : ffffffff80c10000 0000000000000001 8000000025bf0790 ffffffff80e10000
	  ffffffff80e50000 ffffffff80254e2c ffffffff80b64428 ffffffff80e10790
	  0000000000000000 ffffffff801caeb8 0000000000000045 0000000000000005
	  ffffffff80c10000 ffffffff801cb798 0000000000000000 ffffffff80e30000
	  0000000000000000 ffffffff801ff1c0 ffffffff80e2d2f8 000000000000000b
	  ffffffff801cbba0 ffffffff80e107b0 ffffffff80a77828 0000000000000005
	  00000000000003b8 ffffffff80e2d2f8 800000040ad39960 ffffffff801f9950
	  0000000000000124 80000004093b7990 80000004093b7ab8 ffffffff80925108
	  ffffffff80b69a07 ffffffff80a6f0d0 8000000407240e00 ffffffff801cc934
	  000000000000005d ffffffff80159080 0000000000000005 00000000000003b8
	  ...
Call Trace:
[<ffffffff80159080>] show_stack+0xe8/0x108
[<ffffffff80925108>] dump_stack+0x8c/0xd8
[<ffffffff80606570>] check_preemption_disabled+0x110/0x118
[<ffffffffc0086104>] oprofile_arch_init+0x30/0x194 [oprofile]
[<ffffffffc008602c>] oprofile_init+0x2c/0xc0 [oprofile]
[<ffffffff80100550>] do_one_initcall+0xa0/0x1c0
[<ffffffff80921e04>] do_init_module+0x80/0x1d8
[<ffffffff801fd0d4>] load_module+0x1b74/0x2278
[<ffffffff801fdab4>] SyS_finit_module+0xcc/0xf0
[<ffffffff80165884>] handle_sysn32+0x44/0x70

[ralf@linux-mips.org: Correct commit message.]

Signed-off-by: Yanjiang Jin <yanjiang.jin@windriver.com>
Cc: rric@kernel.org
Cc: jinyanjiang@gmail.com
Cc: linux-mips@linux-mips.org
Cc: oprofile-list@lists.sf.net
Cc: linux-kernel@vger.kernel.org
Patchwork: https://patchwork.linux-mips.org/patch/11769/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
2016-05-09 12:00:03 +02:00

148 lines
3.1 KiB
C

/*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
* Copyright (C) 2004, 2005 Ralf Baechle
* Copyright (C) 2005 MIPS Technologies, Inc.
*/
#include <linux/compiler.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/oprofile.h>
#include <linux/smp.h>
#include <asm/cpu-info.h>
#include <asm/cpu-type.h>
#include "op_impl.h"
extern struct op_mips_model op_model_mipsxx_ops __weak;
extern struct op_mips_model op_model_loongson2_ops __weak;
extern struct op_mips_model op_model_loongson3_ops __weak;
static struct op_mips_model *model;
static struct op_counter_config ctr[20];
static int op_mips_setup(void)
{
/* Pre-compute the values to stuff in the hardware registers. */
model->reg_setup(ctr);
/* Configure the registers on all cpus. */
on_each_cpu(model->cpu_setup, NULL, 1);
return 0;
}
static int op_mips_create_files(struct dentry *root)
{
int i;
for (i = 0; i < model->num_counters; ++i) {
struct dentry *dir;
char buf[4];
snprintf(buf, sizeof buf, "%d", i);
dir = oprofilefs_mkdir(root, buf);
oprofilefs_create_ulong(dir, "enabled", &ctr[i].enabled);
oprofilefs_create_ulong(dir, "event", &ctr[i].event);
oprofilefs_create_ulong(dir, "count", &ctr[i].count);
oprofilefs_create_ulong(dir, "kernel", &ctr[i].kernel);
oprofilefs_create_ulong(dir, "user", &ctr[i].user);
oprofilefs_create_ulong(dir, "exl", &ctr[i].exl);
/* Dummy. */
oprofilefs_create_ulong(dir, "unit_mask", &ctr[i].unit_mask);
}
return 0;
}
static int op_mips_start(void)
{
on_each_cpu(model->cpu_start, NULL, 1);
return 0;
}
static void op_mips_stop(void)
{
/* Disable performance monitoring for all counters. */
on_each_cpu(model->cpu_stop, NULL, 1);
}
int __init oprofile_arch_init(struct oprofile_operations *ops)
{
struct op_mips_model *lmodel = NULL;
int res;
switch (boot_cpu_type()) {
case CPU_5KC:
case CPU_M14KC:
case CPU_M14KEC:
case CPU_20KC:
case CPU_24K:
case CPU_25KF:
case CPU_34K:
case CPU_1004K:
case CPU_74K:
case CPU_1074K:
case CPU_INTERAPTIV:
case CPU_PROAPTIV:
case CPU_P5600:
case CPU_I6400:
case CPU_M5150:
case CPU_LOONGSON1:
case CPU_SB1:
case CPU_SB1A:
case CPU_R10000:
case CPU_R12000:
case CPU_R14000:
case CPU_R16000:
case CPU_XLR:
lmodel = &op_model_mipsxx_ops;
break;
case CPU_LOONGSON2:
lmodel = &op_model_loongson2_ops;
break;
case CPU_LOONGSON3:
lmodel = &op_model_loongson3_ops;
break;
};
/*
* Always set the backtrace. This allows unsupported CPU types to still
* use timer-based oprofile.
*/
ops->backtrace = op_mips_backtrace;
if (!lmodel)
return -ENODEV;
res = lmodel->init();
if (res)
return res;
model = lmodel;
ops->create_files = op_mips_create_files;
ops->setup = op_mips_setup;
//ops->shutdown = op_mips_shutdown;
ops->start = op_mips_start;
ops->stop = op_mips_stop;
ops->cpu_type = lmodel->cpu_type;
printk(KERN_INFO "oprofile: using %s performance monitoring.\n",
lmodel->cpu_type);
return 0;
}
void oprofile_arch_exit(void)
{
if (model)
model->exit();
}