aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/trace/kprobetrace.txt4
-rw-r--r--kernel/trace/trace_kprobe.c110
2 files changed, 111 insertions, 3 deletions
diff --git a/Documentation/trace/kprobetrace.txt b/Documentation/trace/kprobetrace.txt
index db5531865648..8f882ebd1368 100644
--- a/Documentation/trace/kprobetrace.txt
+++ b/Documentation/trace/kprobetrace.txt
@@ -62,13 +62,15 @@ enabled:
62 You can enable/disable the probe by writing 1 or 0 on it. 62 You can enable/disable the probe by writing 1 or 0 on it.
63 63
64format: 64format:
65 It shows the format of this probe event. It also shows aliases of arguments 65 This shows the format of this probe event. It also shows aliases of arguments
66 which you specified to kprobe_events. 66 which you specified to kprobe_events.
67 67
68filter: 68filter:
69 You can write filtering rules of this event. And you can use both of aliase 69 You can write filtering rules of this event. And you can use both of aliase
70 names and field names for describing filters. 70 names and field names for describing filters.
71 71
72id:
73 This shows the id of this probe event.
72 74
73Event Profiling 75Event Profiling
74--------------- 76---------------
diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c
index 4ce728ca1b18..730e992d28da 100644
--- a/kernel/trace/trace_kprobe.c
+++ b/kernel/trace/trace_kprobe.c
@@ -28,6 +28,7 @@
28#include <linux/string.h> 28#include <linux/string.h>
29#include <linux/ctype.h> 29#include <linux/ctype.h>
30#include <linux/ptrace.h> 30#include <linux/ptrace.h>
31#include <linux/perf_counter.h>
31 32
32#include "trace.h" 33#include "trace.h"
33#include "trace_output.h" 34#include "trace_output.h"
@@ -280,6 +281,7 @@ static struct trace_probe *alloc_trace_probe(const char *event,
280 } else 281 } else
281 tp->rp.kp.addr = addr; 282 tp->rp.kp.addr = addr;
282 283
284 /* Set handler here for checking whether this probe is return or not. */
283 if (is_return) 285 if (is_return)
284 tp->rp.handler = kretprobe_trace_func; 286 tp->rp.handler = kretprobe_trace_func;
285 else 287 else
@@ -929,10 +931,13 @@ static int probe_event_enable(struct ftrace_event_call *call)
929{ 931{
930 struct trace_probe *tp = (struct trace_probe *)call->data; 932 struct trace_probe *tp = (struct trace_probe *)call->data;
931 933
932 if (probe_is_return(tp)) 934 if (probe_is_return(tp)) {
935 tp->rp.handler = kretprobe_trace_func;
933 return enable_kretprobe(&tp->rp); 936 return enable_kretprobe(&tp->rp);
934 else 937 } else {
938 tp->rp.kp.pre_handler = kprobe_trace_func;
935 return enable_kprobe(&tp->rp.kp); 939 return enable_kprobe(&tp->rp.kp);
940 }
936} 941}
937 942
938static void probe_event_disable(struct ftrace_event_call *call) 943static void probe_event_disable(struct ftrace_event_call *call)
@@ -1105,6 +1110,101 @@ static int kretprobe_event_show_format(struct ftrace_event_call *call,
1105 "func, ret_ip"); 1110 "func, ret_ip");
1106} 1111}
1107 1112
1113#ifdef CONFIG_EVENT_PROFILE
1114
1115/* Kprobe profile handler */
1116static __kprobes int kprobe_profile_func(struct kprobe *kp,
1117 struct pt_regs *regs)
1118{
1119 struct trace_probe *tp = container_of(kp, struct trace_probe, rp.kp);
1120 struct ftrace_event_call *call = &tp->call;
1121 struct kprobe_trace_entry *entry;
1122 int size, i, pc;
1123 unsigned long irq_flags;
1124
1125 local_save_flags(irq_flags);
1126 pc = preempt_count();
1127
1128 size = SIZEOF_KPROBE_TRACE_ENTRY(tp->nr_args);
1129
1130 do {
1131 char raw_data[size];
1132 struct trace_entry *ent;
1133
1134 *(u64 *)(&raw_data[size - sizeof(u64)]) = 0ULL;
1135 entry = (struct kprobe_trace_entry *)raw_data;
1136 ent = &entry->ent;
1137
1138 tracing_generic_entry_update(ent, irq_flags, pc);
1139 ent->type = call->id;
1140 entry->nargs = tp->nr_args;
1141 entry->ip = (unsigned long)kp->addr;
1142 for (i = 0; i < tp->nr_args; i++)
1143 entry->args[i] = call_fetch(&tp->args[i], regs);
1144 perf_tpcounter_event(call->id, entry->ip, 1, entry, size);
1145 } while (0);
1146 return 0;
1147}
1148
1149/* Kretprobe profile handler */
1150static __kprobes int kretprobe_profile_func(struct kretprobe_instance *ri,
1151 struct pt_regs *regs)
1152{
1153 struct trace_probe *tp = container_of(ri->rp, struct trace_probe, rp);
1154 struct ftrace_event_call *call = &tp->call;
1155 struct kretprobe_trace_entry *entry;
1156 int size, i, pc;
1157 unsigned long irq_flags;
1158
1159 local_save_flags(irq_flags);
1160 pc = preempt_count();
1161
1162 size = SIZEOF_KRETPROBE_TRACE_ENTRY(tp->nr_args);
1163
1164 do {
1165 char raw_data[size];
1166 struct trace_entry *ent;
1167
1168 *(u64 *)(&raw_data[size - sizeof(u64)]) = 0ULL;
1169 entry = (struct kretprobe_trace_entry *)raw_data;
1170 ent = &entry->ent;
1171
1172 tracing_generic_entry_update(ent, irq_flags, pc);
1173 ent->type = call->id;
1174 entry->nargs = tp->nr_args;
1175 entry->func = (unsigned long)tp->rp.kp.addr;
1176 entry->ret_ip = (unsigned long)ri->ret_addr;
1177 for (i = 0; i < tp->nr_args; i++)
1178 entry->args[i] = call_fetch(&tp->args[i], regs);
1179 perf_tpcounter_event(call->id, entry->ret_ip, 1, entry, size);
1180 } while (0);
1181 return 0;
1182}
1183
1184static int probe_profile_enable(struct ftrace_event_call *call)
1185{
1186 struct trace_probe *tp = (struct trace_probe *)call->data;
1187
1188 if (atomic_inc_return(&call->profile_count))
1189 return 0;
1190
1191 if (probe_is_return(tp)) {
1192 tp->rp.handler = kretprobe_profile_func;
1193 return enable_kretprobe(&tp->rp);
1194 } else {
1195 tp->rp.kp.pre_handler = kprobe_profile_func;
1196 return enable_kprobe(&tp->rp.kp);
1197 }
1198}
1199
1200static void probe_profile_disable(struct ftrace_event_call *call)
1201{
1202 if (atomic_add_negative(-1, &call->profile_count))
1203 probe_event_disable(call);
1204}
1205
1206#endif /* CONFIG_EVENT_PROFILE */
1207
1108static int register_probe_event(struct trace_probe *tp) 1208static int register_probe_event(struct trace_probe *tp)
1109{ 1209{
1110 struct ftrace_event_call *call = &tp->call; 1210 struct ftrace_event_call *call = &tp->call;
@@ -1130,6 +1230,12 @@ static int register_probe_event(struct trace_probe *tp)
1130 call->enabled = 1; 1230 call->enabled = 1;
1131 call->regfunc = probe_event_enable; 1231 call->regfunc = probe_event_enable;
1132 call->unregfunc = probe_event_disable; 1232 call->unregfunc = probe_event_disable;
1233
1234#ifdef CONFIG_EVENT_PROFILE
1235 atomic_set(&call->profile_count, -1);
1236 call->profile_enable = probe_profile_enable;
1237 call->profile_disable = probe_profile_disable;
1238#endif
1133 call->data = tp; 1239 call->data = tp;
1134 ret = trace_add_event_call(call); 1240 ret = trace_add_event_call(call);
1135 if (ret) { 1241 if (ret) {