aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/trace/trace_ksym.c
diff options
context:
space:
mode:
authorFrederic Weisbecker <fweisbec@gmail.com>2009-11-26 22:55:54 -0500
committerIngo Molnar <mingo@elte.hu>2009-11-27 00:22:59 -0500
commitdd1853c3f493f6d22d9e5390b192a07b73d2ac0a (patch)
treeaf87226bcdc254ce2ab656530263e61f6552322b /kernel/trace/trace_ksym.c
parent5fa10b28e57f94a90535cfeafe89dcee9f47d540 (diff)
hw-breakpoints: Use struct perf_event_attr to define kernel breakpoints
Kernel breakpoints are created using functions in which we pass breakpoint parameters as individual variables: address, length and type. Although it fits well for x86, this just does not scale across architectures that may support this api later as these may have more or different needs. Pass in a perf_event_attr structure instead because it is meant to evolve as much as possible into a generic hardware breakpoint parameter structure. Reported-by: K.Prasad <prasad@linux.vnet.ibm.com> Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com> LKML-Reference: <1259294154-5197-2-git-send-regression-fweisbec@gmail.com> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'kernel/trace/trace_ksym.c')
-rw-r--r--kernel/trace/trace_ksym.c42
1 files changed, 20 insertions, 22 deletions
diff --git a/kernel/trace/trace_ksym.c b/kernel/trace/trace_ksym.c
index c538b15b95d..ddfa0fd43bc 100644
--- a/kernel/trace/trace_ksym.c
+++ b/kernel/trace/trace_ksym.c
@@ -42,9 +42,7 @@
42 42
43struct trace_ksym { 43struct trace_ksym {
44 struct perf_event **ksym_hbp; 44 struct perf_event **ksym_hbp;
45 unsigned long ksym_addr; 45 struct perf_event_attr attr;
46 int type;
47 int len;
48#ifdef CONFIG_PROFILE_KSYM_TRACER 46#ifdef CONFIG_PROFILE_KSYM_TRACER
49 unsigned long counter; 47 unsigned long counter;
50#endif 48#endif
@@ -71,7 +69,7 @@ void ksym_collect_stats(unsigned long hbp_hit_addr)
71 69
72 rcu_read_lock(); 70 rcu_read_lock();
73 hlist_for_each_entry_rcu(entry, node, &ksym_filter_head, ksym_hlist) { 71 hlist_for_each_entry_rcu(entry, node, &ksym_filter_head, ksym_hlist) {
74 if ((entry->ksym_addr == hbp_hit_addr) && 72 if ((entry->attr.bp_addr == hbp_hit_addr) &&
75 (entry->counter <= MAX_UL_INT)) { 73 (entry->counter <= MAX_UL_INT)) {
76 entry->counter++; 74 entry->counter++;
77 break; 75 break;
@@ -192,14 +190,15 @@ int process_new_ksym_entry(char *ksymname, int op, unsigned long addr)
192 if (!entry) 190 if (!entry)
193 return -ENOMEM; 191 return -ENOMEM;
194 192
195 entry->type = op; 193 hw_breakpoint_init(&entry->attr);
196 entry->ksym_addr = addr; 194
197 entry->len = HW_BREAKPOINT_LEN_4; 195 entry->attr.bp_type = op;
196 entry->attr.bp_addr = addr;
197 entry->attr.bp_len = HW_BREAKPOINT_LEN_4;
198 198
199 ret = -EAGAIN; 199 ret = -EAGAIN;
200 entry->ksym_hbp = register_wide_hw_breakpoint(entry->ksym_addr, 200 entry->ksym_hbp = register_wide_hw_breakpoint(&entry->attr,
201 entry->len, entry->type, 201 ksym_hbp_handler);
202 ksym_hbp_handler, true);
203 202
204 if (IS_ERR(entry->ksym_hbp)) { 203 if (IS_ERR(entry->ksym_hbp)) {
205 ret = PTR_ERR(entry->ksym_hbp); 204 ret = PTR_ERR(entry->ksym_hbp);
@@ -236,12 +235,12 @@ static ssize_t ksym_trace_filter_read(struct file *filp, char __user *ubuf,
236 mutex_lock(&ksym_tracer_mutex); 235 mutex_lock(&ksym_tracer_mutex);
237 236
238 hlist_for_each_entry(entry, node, &ksym_filter_head, ksym_hlist) { 237 hlist_for_each_entry(entry, node, &ksym_filter_head, ksym_hlist) {
239 ret = trace_seq_printf(s, "%pS:", (void *)entry->ksym_addr); 238 ret = trace_seq_printf(s, "%pS:", (void *)entry->attr.bp_addr);
240 if (entry->type == HW_BREAKPOINT_R) 239 if (entry->attr.bp_type == HW_BREAKPOINT_R)
241 ret = trace_seq_puts(s, "r--\n"); 240 ret = trace_seq_puts(s, "r--\n");
242 else if (entry->type == HW_BREAKPOINT_W) 241 else if (entry->attr.bp_type == HW_BREAKPOINT_W)
243 ret = trace_seq_puts(s, "-w-\n"); 242 ret = trace_seq_puts(s, "-w-\n");
244 else if (entry->type == (HW_BREAKPOINT_W | HW_BREAKPOINT_R)) 243 else if (entry->attr.bp_type == (HW_BREAKPOINT_W | HW_BREAKPOINT_R))
245 ret = trace_seq_puts(s, "rw-\n"); 244 ret = trace_seq_puts(s, "rw-\n");
246 WARN_ON_ONCE(!ret); 245 WARN_ON_ONCE(!ret);
247 } 246 }
@@ -317,9 +316,9 @@ static ssize_t ksym_trace_filter_write(struct file *file,
317 316
318 ret = -EINVAL; 317 ret = -EINVAL;
319 hlist_for_each_entry(entry, node, &ksym_filter_head, ksym_hlist) { 318 hlist_for_each_entry(entry, node, &ksym_filter_head, ksym_hlist) {
320 if (entry->ksym_addr == ksym_addr) { 319 if (entry->attr.bp_addr == ksym_addr) {
321 /* Check for malformed request: (6) */ 320 /* Check for malformed request: (6) */
322 if (entry->type != op) 321 if (entry->attr.bp_type != op)
323 changed = 1; 322 changed = 1;
324 else 323 else
325 goto out; 324 goto out;
@@ -328,13 +327,12 @@ static ssize_t ksym_trace_filter_write(struct file *file,
328 } 327 }
329 if (changed) { 328 if (changed) {
330 unregister_wide_hw_breakpoint(entry->ksym_hbp); 329 unregister_wide_hw_breakpoint(entry->ksym_hbp);
331 entry->type = op; 330 entry->attr.bp_type = op;
332 ret = 0; 331 ret = 0;
333 if (op > 0) { 332 if (op > 0) {
334 entry->ksym_hbp = 333 entry->ksym_hbp =
335 register_wide_hw_breakpoint(entry->ksym_addr, 334 register_wide_hw_breakpoint(&entry->attr,
336 entry->len, entry->type, 335 ksym_hbp_handler);
337 ksym_hbp_handler, true);
338 if (IS_ERR(entry->ksym_hbp)) 336 if (IS_ERR(entry->ksym_hbp))
339 ret = PTR_ERR(entry->ksym_hbp); 337 ret = PTR_ERR(entry->ksym_hbp);
340 else 338 else
@@ -489,7 +487,7 @@ static int ksym_tracer_stat_show(struct seq_file *m, void *v)
489 487
490 entry = hlist_entry(stat, struct trace_ksym, ksym_hlist); 488 entry = hlist_entry(stat, struct trace_ksym, ksym_hlist);
491 489
492 access_type = entry->type; 490 access_type = entry->attr.bp_type;
493 491
494 switch (access_type) { 492 switch (access_type) {
495 case HW_BREAKPOINT_R: 493 case HW_BREAKPOINT_R:
@@ -505,7 +503,7 @@ static int ksym_tracer_stat_show(struct seq_file *m, void *v)
505 seq_puts(m, " NA "); 503 seq_puts(m, " NA ");
506 } 504 }
507 505
508 if (lookup_symbol_name(entry->ksym_addr, fn_name) >= 0) 506 if (lookup_symbol_name(entry->attr.bp_addr, fn_name) >= 0)
509 seq_printf(m, " %-36s", fn_name); 507 seq_printf(m, " %-36s", fn_name);
510 else 508 else
511 seq_printf(m, " %-36s", "<NA>"); 509 seq_printf(m, " %-36s", "<NA>");