#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;
#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;
#ifdef CONFIG_EVENT_PROFILE
/*
- * Generate the functions needed for tracepoint perf_counter support.
+ * Generate the functions needed for tracepoint perf_event support.
*
* NOTE: The insertion profile callback (ftrace_profile_<call>) is defined later
*
\
static void ftrace_profile_##call(proto); \
\
-static int ftrace_profile_enable_##call(void) \
+static int ftrace_profile_enable_##call(struct ftrace_event_call *unused)\
{ \
return register_trace_##call(ftrace_profile_##call); \
} \
\
-static void ftrace_profile_disable_##call(void) \
+static void ftrace_profile_disable_##call(struct ftrace_event_call *unused)\
{ \
unregister_trace_##call(ftrace_profile_##call); \
}
* 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;
*
* 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>);
* }
* 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;
*
* 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>);
* }
* .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;
*
event, irq_flags, pc); \
} \
\
-static int ftrace_raw_reg_event_##call(void *ptr) \
+static int ftrace_raw_reg_event_##call(struct ftrace_event_call *unused)\
{ \
int ret; \
\
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); \
} \
.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; \
\
* {
* struct ftrace_data_offsets_<call> __maybe_unused __data_offsets;
* struct ftrace_event_call *event_call = &event_<call>;
- * extern void perf_tpcounter_event(int, u64, u64, void *, int);
+ * 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;
* __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;
*
* <assign> <- affect our values
*
- * perf_tpcounter_event(event_call->id, __addr, __count, entry,
+ * perf_tp_event(event_call->id, __addr, __count, entry,
* __entry_size); <- submit them to perf counter
*
* }
{ \
struct ftrace_data_offsets_##call __maybe_unused __data_offsets;\
struct ftrace_event_call *event_call = &event_##call; \
- extern void perf_tpcounter_event(int, u64, u64, void *, int); \
+ 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; \
__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); \
+ if (trace_buf->recursion++) \
+ goto end_recursion; \
+ \
+ barrier(); \
+ \
+ raw_data = trace_buf->buf; \
\
*(u64 *)(&raw_data[__entry_size - sizeof(u64)]) = 0ULL; \
entry = (struct ftrace_raw_##call *)raw_data; \
\
{ assign; } \
\
- perf_tpcounter_event(event_call->id, __addr, __count, entry, \
+ perf_tp_event(event_call->id, __addr, __count, entry, \
__entry_size); \
\
+end_recursion: \
+ trace_buf->recursion--; \
end: \
local_irq_restore(irq_flags); \
\