aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/trace/trace_kprobe.c
diff options
context:
space:
mode:
authorMasami Hiramatsu <mhiramat@redhat.com>2009-09-14 16:49:20 -0400
committerFrederic Weisbecker <fweisbec@gmail.com>2009-09-16 22:03:54 -0400
commit50d780560785b068c358675c5f0bf6c83b5c373e (patch)
tree23baa2c37e12207778a7104e9b9e0d7fec5bee62 /kernel/trace/trace_kprobe.c
parent4fead8e46fded93cc0d432ced774d9a3a8d21bad (diff)
tracing/kprobes: Add probe handler dispatcher to support perf and ftrace concurrent use
Add kprobe_dispatcher and kretprobe_dispatcher to dispatch event in both profile and tracing handlers. This allows simultaneous kprobe uses by ftrace and perf. Signed-off-by: Masami Hiramatsu <mhiramat@redhat.com> Acked-by: Steven Rostedt <rostedt@goodmis.org> Cc: Jim Keniston <jkenisto@us.ibm.com> Cc: Ananth N Mavinakayanahalli <ananth@in.ibm.com> Cc: Andi Kleen <ak@linux.intel.com> Cc: Christoph Hellwig <hch@infradead.org> Cc: Frank Ch. Eigler <fche@redhat.com> Cc: H. Peter Anvin <hpa@zytor.com> Cc: Ingo Molnar <mingo@elte.hu> Cc: Jason Baron <jbaron@redhat.com> Cc: K.Prasad <prasad@linux.vnet.ibm.com> Cc: Lai Jiangshan <laijs@cn.fujitsu.com> Cc: Li Zefan <lizf@cn.fujitsu.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Srikar Dronamraju <srikar@linux.vnet.ibm.com> Cc: Tom Zanussi <tzanussi@gmail.com> LKML-Reference: <20090914204920.18779.57555.stgit@dhcp-100-2-132.bos.redhat.com> Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com>
Diffstat (limited to 'kernel/trace/trace_kprobe.c')
-rw-r--r--kernel/trace/trace_kprobe.c85
1 files changed, 63 insertions, 22 deletions
diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c
index ea0db8eee570..70b632c3bd08 100644
--- a/kernel/trace/trace_kprobe.c
+++ b/kernel/trace/trace_kprobe.c
@@ -185,10 +185,15 @@ struct probe_arg {
185 const char *name; 185 const char *name;
186}; 186};
187 187
188/* Flags for trace_probe */
189#define TP_FLAG_TRACE 1
190#define TP_FLAG_PROFILE 2
191
188struct trace_probe { 192struct trace_probe {
189 struct list_head list; 193 struct list_head list;
190 struct kretprobe rp; /* Use rp.kp for kprobe use */ 194 struct kretprobe rp; /* Use rp.kp for kprobe use */
191 unsigned long nhit; 195 unsigned long nhit;
196 unsigned int flags; /* For TP_FLAG_* */
192 const char *symbol; /* symbol name */ 197 const char *symbol; /* symbol name */
193 struct ftrace_event_call call; 198 struct ftrace_event_call call;
194 struct trace_event event; 199 struct trace_event event;
@@ -200,10 +205,6 @@ struct trace_probe {
200 (offsetof(struct trace_probe, args) + \ 205 (offsetof(struct trace_probe, args) + \
201 (sizeof(struct probe_arg) * (n))) 206 (sizeof(struct probe_arg) * (n)))
202 207
203static int kprobe_trace_func(struct kprobe *kp, struct pt_regs *regs);
204static int kretprobe_trace_func(struct kretprobe_instance *ri,
205 struct pt_regs *regs);
206
207static __kprobes int probe_is_return(struct trace_probe *tp) 208static __kprobes int probe_is_return(struct trace_probe *tp)
208{ 209{
209 return tp->rp.handler != NULL; 210 return tp->rp.handler != NULL;
@@ -263,6 +264,10 @@ static void unregister_probe_event(struct trace_probe *tp);
263static DEFINE_MUTEX(probe_lock); 264static DEFINE_MUTEX(probe_lock);
264static LIST_HEAD(probe_list); 265static LIST_HEAD(probe_list);
265 266
267static int kprobe_dispatcher(struct kprobe *kp, struct pt_regs *regs);
268static int kretprobe_dispatcher(struct kretprobe_instance *ri,
269 struct pt_regs *regs);
270
266/* 271/*
267 * Allocate new trace_probe and initialize it (including kprobes). 272 * Allocate new trace_probe and initialize it (including kprobes).
268 */ 273 */
@@ -288,11 +293,10 @@ static struct trace_probe *alloc_trace_probe(const char *group,
288 } else 293 } else
289 tp->rp.kp.addr = addr; 294 tp->rp.kp.addr = addr;
290 295
291 /* Set handler here for checking whether this probe is return or not. */
292 if (is_return) 296 if (is_return)
293 tp->rp.handler = kretprobe_trace_func; 297 tp->rp.handler = kretprobe_dispatcher;
294 else 298 else
295 tp->rp.kp.pre_handler = kprobe_trace_func; 299 tp->rp.kp.pre_handler = kprobe_dispatcher;
296 300
297 if (!event) 301 if (!event)
298 goto error; 302 goto error;
@@ -379,6 +383,7 @@ static int register_trace_probe(struct trace_probe *tp)
379 goto end; 383 goto end;
380 } 384 }
381 385
386 tp->flags = TP_FLAG_TRACE;
382 if (probe_is_return(tp)) 387 if (probe_is_return(tp))
383 ret = register_kretprobe(&tp->rp); 388 ret = register_kretprobe(&tp->rp);
384 else 389 else
@@ -987,23 +992,24 @@ static int probe_event_enable(struct ftrace_event_call *call)
987{ 992{
988 struct trace_probe *tp = (struct trace_probe *)call->data; 993 struct trace_probe *tp = (struct trace_probe *)call->data;
989 994
990 if (probe_is_return(tp)) { 995 tp->flags |= TP_FLAG_TRACE;
991 tp->rp.handler = kretprobe_trace_func; 996 if (probe_is_return(tp))
992 return enable_kretprobe(&tp->rp); 997 return enable_kretprobe(&tp->rp);
993 } else { 998 else
994 tp->rp.kp.pre_handler = kprobe_trace_func;
995 return enable_kprobe(&tp->rp.kp); 999 return enable_kprobe(&tp->rp.kp);
996 }
997} 1000}
998 1001
999static void probe_event_disable(struct ftrace_event_call *call) 1002static void probe_event_disable(struct ftrace_event_call *call)
1000{ 1003{
1001 struct trace_probe *tp = (struct trace_probe *)call->data; 1004 struct trace_probe *tp = (struct trace_probe *)call->data;
1002 1005
1003 if (probe_is_return(tp)) 1006 tp->flags &= ~TP_FLAG_TRACE;
1004 disable_kretprobe(&tp->rp); 1007 if (!(tp->flags & (TP_FLAG_TRACE | TP_FLAG_PROFILE))) {
1005 else 1008 if (probe_is_return(tp))
1006 disable_kprobe(&tp->rp.kp); 1009 disable_kretprobe(&tp->rp);
1010 else
1011 disable_kprobe(&tp->rp.kp);
1012 }
1007} 1013}
1008 1014
1009static int probe_event_raw_init(struct ftrace_event_call *event_call) 1015static int probe_event_raw_init(struct ftrace_event_call *event_call)
@@ -1212,22 +1218,57 @@ static int probe_profile_enable(struct ftrace_event_call *call)
1212 if (atomic_inc_return(&call->profile_count)) 1218 if (atomic_inc_return(&call->profile_count))
1213 return 0; 1219 return 0;
1214 1220
1215 if (probe_is_return(tp)) { 1221 tp->flags |= TP_FLAG_PROFILE;
1216 tp->rp.handler = kretprobe_profile_func; 1222 if (probe_is_return(tp))
1217 return enable_kretprobe(&tp->rp); 1223 return enable_kretprobe(&tp->rp);
1218 } else { 1224 else
1219 tp->rp.kp.pre_handler = kprobe_profile_func;
1220 return enable_kprobe(&tp->rp.kp); 1225 return enable_kprobe(&tp->rp.kp);
1221 }
1222} 1226}
1223 1227
1224static void probe_profile_disable(struct ftrace_event_call *call) 1228static void probe_profile_disable(struct ftrace_event_call *call)
1225{ 1229{
1230 struct trace_probe *tp = (struct trace_probe *)call->data;
1231
1226 if (atomic_add_negative(-1, &call->profile_count)) 1232 if (atomic_add_negative(-1, &call->profile_count))
1227 probe_event_disable(call); 1233 tp->flags &= ~TP_FLAG_PROFILE;
1234
1235 if (!(tp->flags & (TP_FLAG_TRACE | TP_FLAG_PROFILE))) {
1236 if (probe_is_return(tp))
1237 disable_kretprobe(&tp->rp);
1238 else
1239 disable_kprobe(&tp->rp.kp);
1240 }
1228} 1241}
1242#endif /* CONFIG_EVENT_PROFILE */
1243
1244
1245static __kprobes
1246int kprobe_dispatcher(struct kprobe *kp, struct pt_regs *regs)
1247{
1248 struct trace_probe *tp = container_of(kp, struct trace_probe, rp.kp);
1229 1249
1250 if (tp->flags & TP_FLAG_TRACE)
1251 kprobe_trace_func(kp, regs);
1252#ifdef CONFIG_EVENT_PROFILE
1253 if (tp->flags & TP_FLAG_PROFILE)
1254 kprobe_profile_func(kp, regs);
1230#endif /* CONFIG_EVENT_PROFILE */ 1255#endif /* CONFIG_EVENT_PROFILE */
1256 return 0; /* We don't tweek kernel, so just return 0 */
1257}
1258
1259static __kprobes
1260int kretprobe_dispatcher(struct kretprobe_instance *ri, struct pt_regs *regs)
1261{
1262 struct trace_probe *tp = container_of(ri->rp, struct trace_probe, rp);
1263
1264 if (tp->flags & TP_FLAG_TRACE)
1265 kretprobe_trace_func(ri, regs);
1266#ifdef CONFIG_EVENT_PROFILE
1267 if (tp->flags & TP_FLAG_PROFILE)
1268 kretprobe_profile_func(ri, regs);
1269#endif /* CONFIG_EVENT_PROFILE */
1270 return 0; /* We don't tweek kernel, so just return 0 */
1271}
1231 1272
1232static int register_probe_event(struct trace_probe *tp) 1273static int register_probe_event(struct trace_probe *tp)
1233{ 1274{