Merge branch 'perf-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip
* 'perf-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip: (470 commits) x86: Fix comments of register/stack access functions perf tools: Replace %m with %a in sscanf hw-breakpoints: Keep track of user disabled breakpoints tracing/syscalls: Make syscall events print callbacks static tracing: Add DEFINE_EVENT(), DEFINE_SINGLE_EVENT() support to docbook perf: Don't free perf_mmap_data until work has been done perf_event: Fix compile error perf tools: Fix _GNU_SOURCE macro related strndup() build error trace_syscalls: Remove unused syscall_name_to_nr() trace_syscalls: Simplify syscall profile trace_syscalls: Remove duplicate init_enter_##sname() trace_syscalls: Add syscall_nr field to struct syscall_metadata trace_syscalls: Remove enter_id exit_id trace_syscalls: Set event_enter_##sname->data to its metadata trace_syscalls: Remove unused event_syscall_enter and event_syscall_exit perf_event: Initialize data.period in perf_swevent_hrtimer() perf probe: Simplify event naming perf probe: Add --list option for listing current probe events perf probe: Add argv_split() from lib/argv_split.c perf probe: Move probe event utility functions to probe-event.c ...
This commit is contained in:
@ -18,6 +18,26 @@
|
||||
|
||||
#include <linux/ftrace_event.h>
|
||||
|
||||
/*
|
||||
* DECLARE_EVENT_CLASS can be used to add a generic function
|
||||
* handlers for events. That is, if all events have the same
|
||||
* parameters and just have distinct trace points.
|
||||
* Each tracepoint can be defined with DEFINE_EVENT and that
|
||||
* will map the DECLARE_EVENT_CLASS to the tracepoint.
|
||||
*
|
||||
* TRACE_EVENT is a one to one mapping between tracepoint and template.
|
||||
*/
|
||||
#undef TRACE_EVENT
|
||||
#define TRACE_EVENT(name, proto, args, tstruct, assign, print) \
|
||||
DECLARE_EVENT_CLASS(name, \
|
||||
PARAMS(proto), \
|
||||
PARAMS(args), \
|
||||
PARAMS(tstruct), \
|
||||
PARAMS(assign), \
|
||||
PARAMS(print)); \
|
||||
DEFINE_EVENT(name, name, PARAMS(proto), PARAMS(args));
|
||||
|
||||
|
||||
#undef __field
|
||||
#define __field(type, item) type item;
|
||||
|
||||
@ -36,15 +56,21 @@
|
||||
#undef TP_STRUCT__entry
|
||||
#define TP_STRUCT__entry(args...) args
|
||||
|
||||
#undef TRACE_EVENT
|
||||
#define TRACE_EVENT(name, proto, args, tstruct, assign, print) \
|
||||
struct ftrace_raw_##name { \
|
||||
struct trace_entry ent; \
|
||||
tstruct \
|
||||
char __data[0]; \
|
||||
}; \
|
||||
#undef DECLARE_EVENT_CLASS
|
||||
#define DECLARE_EVENT_CLASS(name, proto, args, tstruct, assign, print) \
|
||||
struct ftrace_raw_##name { \
|
||||
struct trace_entry ent; \
|
||||
tstruct \
|
||||
char __data[0]; \
|
||||
};
|
||||
#undef DEFINE_EVENT
|
||||
#define DEFINE_EVENT(template, name, proto, args) \
|
||||
static struct ftrace_event_call event_##name
|
||||
|
||||
#undef DEFINE_EVENT_PRINT
|
||||
#define DEFINE_EVENT_PRINT(template, name, proto, args, print) \
|
||||
DEFINE_EVENT(template, name, PARAMS(proto), PARAMS(args))
|
||||
|
||||
#undef __cpparg
|
||||
#define __cpparg(arg...) arg
|
||||
|
||||
@ -89,12 +115,19 @@
|
||||
#undef __string
|
||||
#define __string(item, src) __dynamic_array(char, item, -1)
|
||||
|
||||
#undef TRACE_EVENT
|
||||
#define TRACE_EVENT(call, proto, args, tstruct, assign, print) \
|
||||
#undef DECLARE_EVENT_CLASS
|
||||
#define DECLARE_EVENT_CLASS(call, proto, args, tstruct, assign, print) \
|
||||
struct ftrace_data_offsets_##call { \
|
||||
tstruct; \
|
||||
};
|
||||
|
||||
#undef DEFINE_EVENT
|
||||
#define DEFINE_EVENT(template, name, proto, args)
|
||||
|
||||
#undef DEFINE_EVENT_PRINT
|
||||
#define DEFINE_EVENT_PRINT(template, name, proto, args, print) \
|
||||
DEFINE_EVENT(template, name, PARAMS(proto), PARAMS(args))
|
||||
|
||||
#include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
|
||||
|
||||
/*
|
||||
@ -120,9 +153,10 @@
|
||||
#undef __field
|
||||
#define __field(type, item) \
|
||||
ret = trace_seq_printf(s, "\tfield:" #type " " #item ";\t" \
|
||||
"offset:%u;\tsize:%u;\n", \
|
||||
"offset:%u;\tsize:%u;\tsigned:%u;\n", \
|
||||
(unsigned int)offsetof(typeof(field), item), \
|
||||
(unsigned int)sizeof(field.item)); \
|
||||
(unsigned int)sizeof(field.item), \
|
||||
(unsigned int)is_signed_type(type)); \
|
||||
if (!ret) \
|
||||
return 0;
|
||||
|
||||
@ -132,19 +166,21 @@
|
||||
#undef __array
|
||||
#define __array(type, item, len) \
|
||||
ret = trace_seq_printf(s, "\tfield:" #type " " #item "[" #len "];\t" \
|
||||
"offset:%u;\tsize:%u;\n", \
|
||||
"offset:%u;\tsize:%u;\tsigned:%u;\n", \
|
||||
(unsigned int)offsetof(typeof(field), item), \
|
||||
(unsigned int)sizeof(field.item)); \
|
||||
(unsigned int)sizeof(field.item), \
|
||||
(unsigned int)is_signed_type(type)); \
|
||||
if (!ret) \
|
||||
return 0;
|
||||
|
||||
#undef __dynamic_array
|
||||
#define __dynamic_array(type, item, len) \
|
||||
ret = trace_seq_printf(s, "\tfield:__data_loc " #type "[] " #item ";\t"\
|
||||
"offset:%u;\tsize:%u;\n", \
|
||||
"offset:%u;\tsize:%u;\tsigned:%u;\n", \
|
||||
(unsigned int)offsetof(typeof(field), \
|
||||
__data_loc_##item), \
|
||||
(unsigned int)sizeof(field.__data_loc_##item)); \
|
||||
(unsigned int)sizeof(field.__data_loc_##item), \
|
||||
(unsigned int)is_signed_type(type)); \
|
||||
if (!ret) \
|
||||
return 0;
|
||||
|
||||
@ -167,17 +203,50 @@
|
||||
#undef TP_perf_assign
|
||||
#define TP_perf_assign(args...)
|
||||
|
||||
#undef TRACE_EVENT
|
||||
#define TRACE_EVENT(call, proto, args, tstruct, func, print) \
|
||||
#undef DECLARE_EVENT_CLASS
|
||||
#define DECLARE_EVENT_CLASS(call, proto, args, tstruct, func, print) \
|
||||
static int \
|
||||
ftrace_format_##call(struct ftrace_event_call *unused, \
|
||||
struct trace_seq *s) \
|
||||
ftrace_format_setup_##call(struct ftrace_event_call *unused, \
|
||||
struct trace_seq *s) \
|
||||
{ \
|
||||
struct ftrace_raw_##call field __attribute__((unused)); \
|
||||
int ret = 0; \
|
||||
\
|
||||
tstruct; \
|
||||
\
|
||||
return ret; \
|
||||
} \
|
||||
\
|
||||
static int \
|
||||
ftrace_format_##call(struct ftrace_event_call *unused, \
|
||||
struct trace_seq *s) \
|
||||
{ \
|
||||
int ret = 0; \
|
||||
\
|
||||
ret = ftrace_format_setup_##call(unused, s); \
|
||||
if (!ret) \
|
||||
return ret; \
|
||||
\
|
||||
ret = trace_seq_printf(s, "\nprint fmt: " print); \
|
||||
\
|
||||
return ret; \
|
||||
}
|
||||
|
||||
#undef DEFINE_EVENT
|
||||
#define DEFINE_EVENT(template, name, proto, args)
|
||||
|
||||
#undef DEFINE_EVENT_PRINT
|
||||
#define DEFINE_EVENT_PRINT(template, name, proto, args, print) \
|
||||
static int \
|
||||
ftrace_format_##name(struct ftrace_event_call *unused, \
|
||||
struct trace_seq *s) \
|
||||
{ \
|
||||
int ret = 0; \
|
||||
\
|
||||
ret = ftrace_format_setup_##template(unused, s); \
|
||||
if (!ret) \
|
||||
return ret; \
|
||||
\
|
||||
trace_seq_printf(s, "\nprint fmt: " print); \
|
||||
\
|
||||
return ret; \
|
||||
@ -252,13 +321,55 @@ ftrace_format_##call(struct ftrace_event_call *unused, \
|
||||
ftrace_print_symbols_seq(p, value, symbols); \
|
||||
})
|
||||
|
||||
#undef TRACE_EVENT
|
||||
#define TRACE_EVENT(call, proto, args, tstruct, assign, print) \
|
||||
#undef DECLARE_EVENT_CLASS
|
||||
#define DECLARE_EVENT_CLASS(call, proto, args, tstruct, assign, print) \
|
||||
static enum print_line_t \
|
||||
ftrace_raw_output_id_##call(int event_id, const char *name, \
|
||||
struct trace_iterator *iter, int flags) \
|
||||
{ \
|
||||
struct trace_seq *s = &iter->seq; \
|
||||
struct ftrace_raw_##call *field; \
|
||||
struct trace_entry *entry; \
|
||||
struct trace_seq *p; \
|
||||
int ret; \
|
||||
\
|
||||
entry = iter->ent; \
|
||||
\
|
||||
if (entry->type != event_id) { \
|
||||
WARN_ON_ONCE(1); \
|
||||
return TRACE_TYPE_UNHANDLED; \
|
||||
} \
|
||||
\
|
||||
field = (typeof(field))entry; \
|
||||
\
|
||||
p = &get_cpu_var(ftrace_event_seq); \
|
||||
trace_seq_init(p); \
|
||||
ret = trace_seq_printf(s, "%s: ", name); \
|
||||
if (ret) \
|
||||
ret = trace_seq_printf(s, print); \
|
||||
put_cpu(); \
|
||||
if (!ret) \
|
||||
return TRACE_TYPE_PARTIAL_LINE; \
|
||||
\
|
||||
return TRACE_TYPE_HANDLED; \
|
||||
}
|
||||
|
||||
#undef DEFINE_EVENT
|
||||
#define DEFINE_EVENT(template, name, proto, args) \
|
||||
static enum print_line_t \
|
||||
ftrace_raw_output_##name(struct trace_iterator *iter, int flags) \
|
||||
{ \
|
||||
return ftrace_raw_output_id_##template(event_##name.id, \
|
||||
#name, iter, flags); \
|
||||
}
|
||||
|
||||
#undef DEFINE_EVENT_PRINT
|
||||
#define DEFINE_EVENT_PRINT(template, call, proto, args, print) \
|
||||
static enum print_line_t \
|
||||
ftrace_raw_output_##call(struct trace_iterator *iter, int flags) \
|
||||
{ \
|
||||
struct trace_seq *s = &iter->seq; \
|
||||
struct ftrace_raw_##call *field; \
|
||||
struct ftrace_raw_##template *field; \
|
||||
struct trace_entry *entry; \
|
||||
struct trace_seq *p; \
|
||||
int ret; \
|
||||
@ -274,14 +385,16 @@ ftrace_raw_output_##call(struct trace_iterator *iter, int flags) \
|
||||
\
|
||||
p = &get_cpu_var(ftrace_event_seq); \
|
||||
trace_seq_init(p); \
|
||||
ret = trace_seq_printf(s, #call ": " print); \
|
||||
ret = trace_seq_printf(s, "%s: ", #call); \
|
||||
if (ret) \
|
||||
ret = trace_seq_printf(s, print); \
|
||||
put_cpu(); \
|
||||
if (!ret) \
|
||||
return TRACE_TYPE_PARTIAL_LINE; \
|
||||
\
|
||||
return TRACE_TYPE_HANDLED; \
|
||||
}
|
||||
|
||||
|
||||
#include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
|
||||
|
||||
#undef __field_ext
|
||||
@ -315,8 +428,8 @@ ftrace_raw_output_##call(struct trace_iterator *iter, int flags) \
|
||||
#undef __string
|
||||
#define __string(item, src) __dynamic_array(char, item, -1)
|
||||
|
||||
#undef TRACE_EVENT
|
||||
#define TRACE_EVENT(call, proto, args, tstruct, func, print) \
|
||||
#undef DECLARE_EVENT_CLASS
|
||||
#define DECLARE_EVENT_CLASS(call, proto, args, tstruct, func, print) \
|
||||
static int \
|
||||
ftrace_define_fields_##call(struct ftrace_event_call *event_call) \
|
||||
{ \
|
||||
@ -332,6 +445,13 @@ ftrace_define_fields_##call(struct ftrace_event_call *event_call) \
|
||||
return ret; \
|
||||
}
|
||||
|
||||
#undef DEFINE_EVENT
|
||||
#define DEFINE_EVENT(template, name, proto, args)
|
||||
|
||||
#undef DEFINE_EVENT_PRINT
|
||||
#define DEFINE_EVENT_PRINT(template, name, proto, args, print) \
|
||||
DEFINE_EVENT(template, name, PARAMS(proto), PARAMS(args))
|
||||
|
||||
#include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
|
||||
|
||||
/*
|
||||
@ -358,10 +478,10 @@ ftrace_define_fields_##call(struct ftrace_event_call *event_call) \
|
||||
__data_size += (len) * sizeof(type);
|
||||
|
||||
#undef __string
|
||||
#define __string(item, src) __dynamic_array(char, item, strlen(src) + 1) \
|
||||
#define __string(item, src) __dynamic_array(char, item, strlen(src) + 1)
|
||||
|
||||
#undef TRACE_EVENT
|
||||
#define TRACE_EVENT(call, proto, args, tstruct, assign, print) \
|
||||
#undef DECLARE_EVENT_CLASS
|
||||
#define DECLARE_EVENT_CLASS(call, proto, args, tstruct, assign, print) \
|
||||
static inline int ftrace_get_offsets_##call( \
|
||||
struct ftrace_data_offsets_##call *__data_offsets, proto) \
|
||||
{ \
|
||||
@ -373,6 +493,13 @@ static inline int ftrace_get_offsets_##call( \
|
||||
return __data_size; \
|
||||
}
|
||||
|
||||
#undef DEFINE_EVENT
|
||||
#define DEFINE_EVENT(template, name, proto, args)
|
||||
|
||||
#undef DEFINE_EVENT_PRINT
|
||||
#define DEFINE_EVENT_PRINT(template, name, proto, args, print) \
|
||||
DEFINE_EVENT(template, name, PARAMS(proto), PARAMS(args))
|
||||
|
||||
#include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
|
||||
|
||||
#ifdef CONFIG_EVENT_PROFILE
|
||||
@ -394,21 +521,28 @@ static inline int ftrace_get_offsets_##call( \
|
||||
*
|
||||
*/
|
||||
|
||||
#undef TRACE_EVENT
|
||||
#define TRACE_EVENT(call, proto, args, tstruct, assign, print) \
|
||||
#undef DECLARE_EVENT_CLASS
|
||||
#define DECLARE_EVENT_CLASS(call, proto, args, tstruct, assign, print)
|
||||
|
||||
#undef DEFINE_EVENT
|
||||
#define DEFINE_EVENT(template, name, proto, args) \
|
||||
\
|
||||
static void ftrace_profile_##call(proto); \
|
||||
static void ftrace_profile_##name(proto); \
|
||||
\
|
||||
static int ftrace_profile_enable_##call(void) \
|
||||
static int ftrace_profile_enable_##name(struct ftrace_event_call *unused)\
|
||||
{ \
|
||||
return register_trace_##call(ftrace_profile_##call); \
|
||||
return register_trace_##name(ftrace_profile_##name); \
|
||||
} \
|
||||
\
|
||||
static void ftrace_profile_disable_##call(void) \
|
||||
static void ftrace_profile_disable_##name(struct ftrace_event_call *unused)\
|
||||
{ \
|
||||
unregister_trace_##call(ftrace_profile_##call); \
|
||||
unregister_trace_##name(ftrace_profile_##name); \
|
||||
}
|
||||
|
||||
#undef DEFINE_EVENT_PRINT
|
||||
#define DEFINE_EVENT_PRINT(template, name, proto, args, print) \
|
||||
DEFINE_EVENT(template, name, PARAMS(proto), PARAMS(args))
|
||||
|
||||
#include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
|
||||
|
||||
#endif
|
||||
@ -423,7 +557,7 @@ static void ftrace_profile_disable_##call(void) \
|
||||
* event_trace_printk(_RET_IP_, "<call>: " <fmt>);
|
||||
* }
|
||||
*
|
||||
* static int ftrace_reg_event_<call>(void)
|
||||
* static int ftrace_reg_event_<call>(struct ftrace_event_call *unused)
|
||||
* {
|
||||
* int ret;
|
||||
*
|
||||
@ -434,7 +568,7 @@ static void ftrace_profile_disable_##call(void) \
|
||||
* return ret;
|
||||
* }
|
||||
*
|
||||
* static void ftrace_unreg_event_<call>(void)
|
||||
* static void ftrace_unreg_event_<call>(struct ftrace_event_call *unused)
|
||||
* {
|
||||
* unregister_trace_<call>(ftrace_event_<call>);
|
||||
* }
|
||||
@ -469,7 +603,7 @@ static void ftrace_profile_disable_##call(void) \
|
||||
* trace_current_buffer_unlock_commit(buffer, event, irq_flags, pc);
|
||||
* }
|
||||
*
|
||||
* static int ftrace_raw_reg_event_<call>(void)
|
||||
* static int ftrace_raw_reg_event_<call>(struct ftrace_event_call *unused)
|
||||
* {
|
||||
* int ret;
|
||||
*
|
||||
@ -480,7 +614,7 @@ static void ftrace_profile_disable_##call(void) \
|
||||
* return ret;
|
||||
* }
|
||||
*
|
||||
* static void ftrace_unreg_event_<call>(void)
|
||||
* static void ftrace_unreg_event_<call>(struct ftrace_event_call *unused)
|
||||
* {
|
||||
* unregister_trace_<call>(ftrace_raw_event_<call>);
|
||||
* }
|
||||
@ -489,7 +623,7 @@ static void ftrace_profile_disable_##call(void) \
|
||||
* .trace = ftrace_raw_output_<call>, <-- stage 2
|
||||
* };
|
||||
*
|
||||
* static int ftrace_raw_init_event_<call>(void)
|
||||
* static int ftrace_raw_init_event_<call>(struct ftrace_event_call *unused)
|
||||
* {
|
||||
* int id;
|
||||
*
|
||||
@ -547,15 +681,13 @@ static void ftrace_profile_disable_##call(void) \
|
||||
#define __assign_str(dst, src) \
|
||||
strcpy(__get_str(dst), src);
|
||||
|
||||
#undef TRACE_EVENT
|
||||
#define TRACE_EVENT(call, proto, args, tstruct, assign, print) \
|
||||
#undef DECLARE_EVENT_CLASS
|
||||
#define DECLARE_EVENT_CLASS(call, proto, args, tstruct, assign, print) \
|
||||
\
|
||||
static struct ftrace_event_call event_##call; \
|
||||
\
|
||||
static void ftrace_raw_event_##call(proto) \
|
||||
static void ftrace_raw_event_id_##call(struct ftrace_event_call *event_call, \
|
||||
proto) \
|
||||
{ \
|
||||
struct ftrace_data_offsets_##call __maybe_unused __data_offsets;\
|
||||
struct ftrace_event_call *event_call = &event_##call; \
|
||||
struct ring_buffer_event *event; \
|
||||
struct ftrace_raw_##call *entry; \
|
||||
struct ring_buffer *buffer; \
|
||||
@ -569,7 +701,7 @@ static void ftrace_raw_event_##call(proto) \
|
||||
__data_size = ftrace_get_offsets_##call(&__data_offsets, args); \
|
||||
\
|
||||
event = trace_current_buffer_lock_reserve(&buffer, \
|
||||
event_##call.id, \
|
||||
event_call->id, \
|
||||
sizeof(*entry) + __data_size, \
|
||||
irq_flags, pc); \
|
||||
if (!event) \
|
||||
@ -584,9 +716,17 @@ static void ftrace_raw_event_##call(proto) \
|
||||
if (!filter_current_check_discard(buffer, event_call, entry, event)) \
|
||||
trace_nowake_buffer_unlock_commit(buffer, \
|
||||
event, irq_flags, pc); \
|
||||
}
|
||||
|
||||
#undef DEFINE_EVENT
|
||||
#define DEFINE_EVENT(template, call, proto, args) \
|
||||
\
|
||||
static void ftrace_raw_event_##call(proto) \
|
||||
{ \
|
||||
ftrace_raw_event_id_##template(&event_##call, args); \
|
||||
} \
|
||||
\
|
||||
static int ftrace_raw_reg_event_##call(void *ptr) \
|
||||
static int ftrace_raw_reg_event_##call(struct ftrace_event_call *unused)\
|
||||
{ \
|
||||
int ret; \
|
||||
\
|
||||
@ -597,7 +737,7 @@ static int ftrace_raw_reg_event_##call(void *ptr) \
|
||||
return ret; \
|
||||
} \
|
||||
\
|
||||
static void ftrace_raw_unreg_event_##call(void *ptr) \
|
||||
static void ftrace_raw_unreg_event_##call(struct ftrace_event_call *unused)\
|
||||
{ \
|
||||
unregister_trace_##call(ftrace_raw_event_##call); \
|
||||
} \
|
||||
@ -606,7 +746,7 @@ static struct trace_event ftrace_event_type_##call = { \
|
||||
.trace = ftrace_raw_output_##call, \
|
||||
}; \
|
||||
\
|
||||
static int ftrace_raw_init_event_##call(void) \
|
||||
static int ftrace_raw_init_event_##call(struct ftrace_event_call *unused)\
|
||||
{ \
|
||||
int id; \
|
||||
\
|
||||
@ -616,7 +756,36 @@ static int ftrace_raw_init_event_##call(void) \
|
||||
event_##call.id = id; \
|
||||
INIT_LIST_HEAD(&event_##call.fields); \
|
||||
return 0; \
|
||||
} \
|
||||
}
|
||||
|
||||
#undef DEFINE_EVENT_PRINT
|
||||
#define DEFINE_EVENT_PRINT(template, name, proto, args, print) \
|
||||
DEFINE_EVENT(template, name, PARAMS(proto), PARAMS(args))
|
||||
|
||||
#include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
|
||||
|
||||
#undef DECLARE_EVENT_CLASS
|
||||
#define DECLARE_EVENT_CLASS(call, proto, args, tstruct, assign, print)
|
||||
|
||||
#undef DEFINE_EVENT
|
||||
#define DEFINE_EVENT(template, call, proto, args) \
|
||||
\
|
||||
static struct ftrace_event_call __used \
|
||||
__attribute__((__aligned__(4))) \
|
||||
__attribute__((section("_ftrace_events"))) event_##call = { \
|
||||
.name = #call, \
|
||||
.system = __stringify(TRACE_SYSTEM), \
|
||||
.event = &ftrace_event_type_##call, \
|
||||
.raw_init = ftrace_raw_init_event_##call, \
|
||||
.regfunc = ftrace_raw_reg_event_##call, \
|
||||
.unregfunc = ftrace_raw_unreg_event_##call, \
|
||||
.show_format = ftrace_format_##template, \
|
||||
.define_fields = ftrace_define_fields_##template, \
|
||||
_TRACE_PROFILE_INIT(call) \
|
||||
}
|
||||
|
||||
#undef DEFINE_EVENT_PRINT
|
||||
#define DEFINE_EVENT_PRINT(template, call, proto, args, print) \
|
||||
\
|
||||
static struct ftrace_event_call __used \
|
||||
__attribute__((__aligned__(4))) \
|
||||
@ -628,7 +797,7 @@ __attribute__((section("_ftrace_events"))) event_##call = { \
|
||||
.regfunc = ftrace_raw_reg_event_##call, \
|
||||
.unregfunc = ftrace_raw_unreg_event_##call, \
|
||||
.show_format = ftrace_format_##call, \
|
||||
.define_fields = ftrace_define_fields_##call, \
|
||||
.define_fields = ftrace_define_fields_##template, \
|
||||
_TRACE_PROFILE_INIT(call) \
|
||||
}
|
||||
|
||||
@ -646,6 +815,7 @@ __attribute__((section("_ftrace_events"))) event_##call = { \
|
||||
* struct ftrace_event_call *event_call = &event_<call>;
|
||||
* extern void perf_tp_event(int, u64, u64, void *, int);
|
||||
* struct ftrace_raw_##call *entry;
|
||||
* struct perf_trace_buf *trace_buf;
|
||||
* u64 __addr = 0, __count = 1;
|
||||
* unsigned long irq_flags;
|
||||
* struct trace_entry *ent;
|
||||
@ -670,14 +840,25 @@ __attribute__((section("_ftrace_events"))) event_##call = { \
|
||||
* __cpu = smp_processor_id();
|
||||
*
|
||||
* if (in_nmi())
|
||||
* raw_data = rcu_dereference(trace_profile_buf_nmi);
|
||||
* trace_buf = rcu_dereference(perf_trace_buf_nmi);
|
||||
* else
|
||||
* raw_data = rcu_dereference(trace_profile_buf);
|
||||
* trace_buf = rcu_dereference(perf_trace_buf);
|
||||
*
|
||||
* if (!raw_data)
|
||||
* if (!trace_buf)
|
||||
* goto end;
|
||||
*
|
||||
* raw_data = per_cpu_ptr(raw_data, __cpu);
|
||||
* trace_buf = per_cpu_ptr(trace_buf, __cpu);
|
||||
*
|
||||
* // Avoid recursion from perf that could mess up the buffer
|
||||
* if (trace_buf->recursion++)
|
||||
* goto end_recursion;
|
||||
*
|
||||
* raw_data = trace_buf->buf;
|
||||
*
|
||||
* // Make recursion update visible before entering perf_tp_event
|
||||
* // so that we protect from perf recursions.
|
||||
*
|
||||
* barrier();
|
||||
*
|
||||
* //zero dead bytes from alignment to avoid stack leak to userspace:
|
||||
* *(u64 *)(&raw_data[__entry_size - sizeof(u64)]) = 0ULL;
|
||||
@ -704,21 +885,26 @@ __attribute__((section("_ftrace_events"))) event_##call = { \
|
||||
#undef __perf_count
|
||||
#define __perf_count(c) __count = (c)
|
||||
|
||||
#undef TRACE_EVENT
|
||||
#define TRACE_EVENT(call, proto, args, tstruct, assign, print) \
|
||||
static void ftrace_profile_##call(proto) \
|
||||
#undef DECLARE_EVENT_CLASS
|
||||
#define DECLARE_EVENT_CLASS(call, proto, args, tstruct, assign, print) \
|
||||
static void \
|
||||
ftrace_profile_templ_##call(struct ftrace_event_call *event_call, \
|
||||
proto) \
|
||||
{ \
|
||||
struct ftrace_data_offsets_##call __maybe_unused __data_offsets;\
|
||||
struct ftrace_event_call *event_call = &event_##call; \
|
||||
extern void perf_tp_event(int, u64, u64, void *, int); \
|
||||
extern int perf_swevent_get_recursion_context(void); \
|
||||
extern void perf_swevent_put_recursion_context(int rctx); \
|
||||
extern void perf_tp_event(int, u64, u64, void *, int); \
|
||||
struct ftrace_raw_##call *entry; \
|
||||
u64 __addr = 0, __count = 1; \
|
||||
unsigned long irq_flags; \
|
||||
struct trace_entry *ent; \
|
||||
int __entry_size; \
|
||||
int __data_size; \
|
||||
char *trace_buf; \
|
||||
char *raw_data; \
|
||||
int __cpu; \
|
||||
int rctx; \
|
||||
int pc; \
|
||||
\
|
||||
pc = preempt_count(); \
|
||||
@ -733,17 +919,22 @@ static void ftrace_profile_##call(proto) \
|
||||
return; \
|
||||
\
|
||||
local_irq_save(irq_flags); \
|
||||
\
|
||||
rctx = perf_swevent_get_recursion_context(); \
|
||||
if (rctx < 0) \
|
||||
goto end_recursion; \
|
||||
\
|
||||
__cpu = smp_processor_id(); \
|
||||
\
|
||||
if (in_nmi()) \
|
||||
raw_data = rcu_dereference(trace_profile_buf_nmi); \
|
||||
trace_buf = rcu_dereference(perf_trace_buf_nmi); \
|
||||
else \
|
||||
raw_data = rcu_dereference(trace_profile_buf); \
|
||||
trace_buf = rcu_dereference(perf_trace_buf); \
|
||||
\
|
||||
if (!raw_data) \
|
||||
if (!trace_buf) \
|
||||
goto end; \
|
||||
\
|
||||
raw_data = per_cpu_ptr(raw_data, __cpu); \
|
||||
raw_data = per_cpu_ptr(trace_buf, __cpu); \
|
||||
\
|
||||
*(u64 *)(&raw_data[__entry_size - sizeof(u64)]) = 0ULL; \
|
||||
entry = (struct ftrace_raw_##call *)raw_data; \
|
||||
@ -759,10 +950,25 @@ static void ftrace_profile_##call(proto) \
|
||||
__entry_size); \
|
||||
\
|
||||
end: \
|
||||
perf_swevent_put_recursion_context(rctx); \
|
||||
end_recursion: \
|
||||
local_irq_restore(irq_flags); \
|
||||
\
|
||||
}
|
||||
|
||||
#undef DEFINE_EVENT
|
||||
#define DEFINE_EVENT(template, call, proto, args) \
|
||||
static void ftrace_profile_##call(proto) \
|
||||
{ \
|
||||
struct ftrace_event_call *event_call = &event_##call; \
|
||||
\
|
||||
ftrace_profile_templ_##template(event_call, args); \
|
||||
}
|
||||
|
||||
#undef DEFINE_EVENT_PRINT
|
||||
#define DEFINE_EVENT_PRINT(template, name, proto, args, print) \
|
||||
DEFINE_EVENT(template, name, PARAMS(proto), PARAMS(args))
|
||||
|
||||
#include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
|
||||
#endif /* CONFIG_EVENT_PROFILE */
|
||||
|
||||
|
Reference in New Issue
Block a user