Merge branch 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull perf fixes from Ingo Molnar. * 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: perf/x86: Add Intel IvyBridge event scheduling constraints ftrace: Call ftrace cleanup module notifier after all other notifiers tracing/syscalls: Allow archs to ignore tracing compat syscalls
This commit is contained in:
@@ -3996,37 +3996,51 @@ static void ftrace_init_module(struct module *mod,
|
||||
ftrace_process_locs(mod, start, end);
|
||||
}
|
||||
|
||||
static int ftrace_module_notify(struct notifier_block *self,
|
||||
unsigned long val, void *data)
|
||||
static int ftrace_module_notify_enter(struct notifier_block *self,
|
||||
unsigned long val, void *data)
|
||||
{
|
||||
struct module *mod = data;
|
||||
|
||||
switch (val) {
|
||||
case MODULE_STATE_COMING:
|
||||
if (val == MODULE_STATE_COMING)
|
||||
ftrace_init_module(mod, mod->ftrace_callsites,
|
||||
mod->ftrace_callsites +
|
||||
mod->num_ftrace_callsites);
|
||||
break;
|
||||
case MODULE_STATE_GOING:
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ftrace_module_notify_exit(struct notifier_block *self,
|
||||
unsigned long val, void *data)
|
||||
{
|
||||
struct module *mod = data;
|
||||
|
||||
if (val == MODULE_STATE_GOING)
|
||||
ftrace_release_mod(mod);
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
static int ftrace_module_notify(struct notifier_block *self,
|
||||
unsigned long val, void *data)
|
||||
static int ftrace_module_notify_enter(struct notifier_block *self,
|
||||
unsigned long val, void *data)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static int ftrace_module_notify_exit(struct notifier_block *self,
|
||||
unsigned long val, void *data)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_MODULES */
|
||||
|
||||
struct notifier_block ftrace_module_nb = {
|
||||
.notifier_call = ftrace_module_notify,
|
||||
struct notifier_block ftrace_module_enter_nb = {
|
||||
.notifier_call = ftrace_module_notify_enter,
|
||||
.priority = INT_MAX, /* Run before anything that can use kprobes */
|
||||
};
|
||||
|
||||
struct notifier_block ftrace_module_exit_nb = {
|
||||
.notifier_call = ftrace_module_notify_exit,
|
||||
.priority = INT_MIN, /* Run after anything that can remove kprobes */
|
||||
};
|
||||
|
||||
extern unsigned long __start_mcount_loc[];
|
||||
extern unsigned long __stop_mcount_loc[];
|
||||
|
||||
@@ -4058,9 +4072,13 @@ void __init ftrace_init(void)
|
||||
__start_mcount_loc,
|
||||
__stop_mcount_loc);
|
||||
|
||||
ret = register_module_notifier(&ftrace_module_nb);
|
||||
ret = register_module_notifier(&ftrace_module_enter_nb);
|
||||
if (ret)
|
||||
pr_warning("Failed to register trace ftrace module notifier\n");
|
||||
pr_warning("Failed to register trace ftrace module enter notifier\n");
|
||||
|
||||
ret = register_module_notifier(&ftrace_module_exit_nb);
|
||||
if (ret)
|
||||
pr_warning("Failed to register trace ftrace module exit notifier\n");
|
||||
|
||||
set_ftrace_early_filters();
|
||||
|
||||
|
@@ -1,5 +1,6 @@
|
||||
#include <trace/syscall.h>
|
||||
#include <trace/events/syscalls.h>
|
||||
#include <linux/syscalls.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h> /* for MODULE_NAME_LEN via KSYM_SYMBOL_LEN */
|
||||
@@ -47,6 +48,38 @@ static inline bool arch_syscall_match_sym_name(const char *sym, const char *name
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ARCH_TRACE_IGNORE_COMPAT_SYSCALLS
|
||||
/*
|
||||
* Some architectures that allow for 32bit applications
|
||||
* to run on a 64bit kernel, do not map the syscalls for
|
||||
* the 32bit tasks the same as they do for 64bit tasks.
|
||||
*
|
||||
* *cough*x86*cough*
|
||||
*
|
||||
* In such a case, instead of reporting the wrong syscalls,
|
||||
* simply ignore them.
|
||||
*
|
||||
* For an arch to ignore the compat syscalls it needs to
|
||||
* define ARCH_TRACE_IGNORE_COMPAT_SYSCALLS as well as
|
||||
* define the function arch_trace_is_compat_syscall() to let
|
||||
* the tracing system know that it should ignore it.
|
||||
*/
|
||||
static int
|
||||
trace_get_syscall_nr(struct task_struct *task, struct pt_regs *regs)
|
||||
{
|
||||
if (unlikely(arch_trace_is_compat_syscall(regs)))
|
||||
return -1;
|
||||
|
||||
return syscall_get_nr(task, regs);
|
||||
}
|
||||
#else
|
||||
static inline int
|
||||
trace_get_syscall_nr(struct task_struct *task, struct pt_regs *regs)
|
||||
{
|
||||
return syscall_get_nr(task, regs);
|
||||
}
|
||||
#endif /* ARCH_TRACE_IGNORE_COMPAT_SYSCALLS */
|
||||
|
||||
static __init struct syscall_metadata *
|
||||
find_syscall_meta(unsigned long syscall)
|
||||
{
|
||||
@@ -276,10 +309,10 @@ static void ftrace_syscall_enter(void *ignore, struct pt_regs *regs, long id)
|
||||
struct syscall_metadata *sys_data;
|
||||
struct ring_buffer_event *event;
|
||||
struct ring_buffer *buffer;
|
||||
int size;
|
||||
int syscall_nr;
|
||||
int size;
|
||||
|
||||
syscall_nr = syscall_get_nr(current, regs);
|
||||
syscall_nr = trace_get_syscall_nr(current, regs);
|
||||
if (syscall_nr < 0)
|
||||
return;
|
||||
if (!test_bit(syscall_nr, enabled_enter_syscalls))
|
||||
@@ -313,7 +346,7 @@ static void ftrace_syscall_exit(void *ignore, struct pt_regs *regs, long ret)
|
||||
struct ring_buffer *buffer;
|
||||
int syscall_nr;
|
||||
|
||||
syscall_nr = syscall_get_nr(current, regs);
|
||||
syscall_nr = trace_get_syscall_nr(current, regs);
|
||||
if (syscall_nr < 0)
|
||||
return;
|
||||
if (!test_bit(syscall_nr, enabled_exit_syscalls))
|
||||
@@ -502,7 +535,7 @@ static void perf_syscall_enter(void *ignore, struct pt_regs *regs, long id)
|
||||
int rctx;
|
||||
int size;
|
||||
|
||||
syscall_nr = syscall_get_nr(current, regs);
|
||||
syscall_nr = trace_get_syscall_nr(current, regs);
|
||||
if (syscall_nr < 0)
|
||||
return;
|
||||
if (!test_bit(syscall_nr, enabled_perf_enter_syscalls))
|
||||
@@ -578,7 +611,7 @@ static void perf_syscall_exit(void *ignore, struct pt_regs *regs, long ret)
|
||||
int rctx;
|
||||
int size;
|
||||
|
||||
syscall_nr = syscall_get_nr(current, regs);
|
||||
syscall_nr = trace_get_syscall_nr(current, regs);
|
||||
if (syscall_nr < 0)
|
||||
return;
|
||||
if (!test_bit(syscall_nr, enabled_perf_exit_syscalls))
|
||||
|
Reference in New Issue
Block a user