Merge branch 'core' of git://amd64.org/linux/rric into perf/core
This commit is contained in:
@@ -4,9 +4,8 @@ DRIVER_OBJS = $(addprefix ../../../drivers/oprofile/, \
|
||||
oprof.o cpu_buffer.o buffer_sync.o \
|
||||
event_buffer.o oprofile_files.o \
|
||||
oprofilefs.o oprofile_stats.o \
|
||||
timer_int.o )
|
||||
timer_int.o nmi_timer_int.o )
|
||||
|
||||
oprofile-y := $(DRIVER_OBJS) init.o backtrace.o
|
||||
oprofile-$(CONFIG_X86_LOCAL_APIC) += nmi_int.o op_model_amd.o \
|
||||
op_model_ppro.o op_model_p4.o
|
||||
oprofile-$(CONFIG_X86_IO_APIC) += nmi_timer_int.o
|
||||
|
@@ -16,34 +16,23 @@
|
||||
* with the NMI mode driver.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_X86_LOCAL_APIC
|
||||
extern int op_nmi_init(struct oprofile_operations *ops);
|
||||
extern int op_nmi_timer_init(struct oprofile_operations *ops);
|
||||
extern void op_nmi_exit(void);
|
||||
extern void x86_backtrace(struct pt_regs * const regs, unsigned int depth);
|
||||
#else
|
||||
static int op_nmi_init(struct oprofile_operations *ops) { return -ENODEV; }
|
||||
static void op_nmi_exit(void) { }
|
||||
#endif
|
||||
|
||||
extern void x86_backtrace(struct pt_regs * const regs, unsigned int depth);
|
||||
|
||||
int __init oprofile_arch_init(struct oprofile_operations *ops)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = -ENODEV;
|
||||
|
||||
#ifdef CONFIG_X86_LOCAL_APIC
|
||||
ret = op_nmi_init(ops);
|
||||
#endif
|
||||
#ifdef CONFIG_X86_IO_APIC
|
||||
if (ret < 0)
|
||||
ret = op_nmi_timer_init(ops);
|
||||
#endif
|
||||
ops->backtrace = x86_backtrace;
|
||||
|
||||
return ret;
|
||||
return op_nmi_init(ops);
|
||||
}
|
||||
|
||||
|
||||
void oprofile_arch_exit(void)
|
||||
{
|
||||
#ifdef CONFIG_X86_LOCAL_APIC
|
||||
op_nmi_exit();
|
||||
#endif
|
||||
}
|
||||
|
@@ -595,24 +595,36 @@ static int __init p4_init(char **cpu_type)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int force_arch_perfmon;
|
||||
static int force_cpu_type(const char *str, struct kernel_param *kp)
|
||||
enum __force_cpu_type {
|
||||
reserved = 0, /* do not force */
|
||||
timer,
|
||||
arch_perfmon,
|
||||
};
|
||||
|
||||
static int force_cpu_type;
|
||||
|
||||
static int set_cpu_type(const char *str, struct kernel_param *kp)
|
||||
{
|
||||
if (!strcmp(str, "arch_perfmon")) {
|
||||
force_arch_perfmon = 1;
|
||||
if (!strcmp(str, "timer")) {
|
||||
force_cpu_type = timer;
|
||||
printk(KERN_INFO "oprofile: forcing NMI timer mode\n");
|
||||
} else if (!strcmp(str, "arch_perfmon")) {
|
||||
force_cpu_type = arch_perfmon;
|
||||
printk(KERN_INFO "oprofile: forcing architectural perfmon\n");
|
||||
} else {
|
||||
force_cpu_type = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
module_param_call(cpu_type, force_cpu_type, NULL, NULL, 0);
|
||||
module_param_call(cpu_type, set_cpu_type, NULL, NULL, 0);
|
||||
|
||||
static int __init ppro_init(char **cpu_type)
|
||||
{
|
||||
__u8 cpu_model = boot_cpu_data.x86_model;
|
||||
struct op_x86_model_spec *spec = &op_ppro_spec; /* default */
|
||||
|
||||
if (force_arch_perfmon && cpu_has_arch_perfmon)
|
||||
if (force_cpu_type == arch_perfmon && cpu_has_arch_perfmon)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
@@ -679,6 +691,9 @@ int __init op_nmi_init(struct oprofile_operations *ops)
|
||||
if (!cpu_has_apic)
|
||||
return -ENODEV;
|
||||
|
||||
if (force_cpu_type == timer)
|
||||
return -ENODEV;
|
||||
|
||||
switch (vendor) {
|
||||
case X86_VENDOR_AMD:
|
||||
/* Needs to be at least an Athlon (or hammer in 32bit mode) */
|
||||
|
@@ -1,50 +0,0 @@
|
||||
/**
|
||||
* @file nmi_timer_int.c
|
||||
*
|
||||
* @remark Copyright 2003 OProfile authors
|
||||
* @remark Read the file COPYING
|
||||
*
|
||||
* @author Zwane Mwaikambo <zwane@linuxpower.ca>
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/smp.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/oprofile.h>
|
||||
#include <linux/rcupdate.h>
|
||||
#include <linux/kdebug.h>
|
||||
|
||||
#include <asm/nmi.h>
|
||||
#include <asm/apic.h>
|
||||
#include <asm/ptrace.h>
|
||||
|
||||
static int profile_timer_exceptions_notify(unsigned int val, struct pt_regs *regs)
|
||||
{
|
||||
oprofile_add_sample(regs, 0);
|
||||
return NMI_HANDLED;
|
||||
}
|
||||
|
||||
static int timer_start(void)
|
||||
{
|
||||
if (register_nmi_handler(NMI_LOCAL, profile_timer_exceptions_notify,
|
||||
0, "oprofile-timer"))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void timer_stop(void)
|
||||
{
|
||||
unregister_nmi_handler(NMI_LOCAL, "oprofile-timer");
|
||||
synchronize_sched(); /* Allow already-started NMIs to complete. */
|
||||
}
|
||||
|
||||
|
||||
int __init op_nmi_timer_init(struct oprofile_operations *ops)
|
||||
{
|
||||
ops->start = timer_start;
|
||||
ops->stop = timer_stop;
|
||||
ops->cpu_type = "timer";
|
||||
printk(KERN_INFO "oprofile: using NMI timer interrupt.\n");
|
||||
return 0;
|
||||
}
|
Reference in New Issue
Block a user