diff options
author | Frederic Weisbecker <fweisbec@gmail.com> | 2009-11-26 22:55:54 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2009-11-27 00:22:59 -0500 |
commit | dd1853c3f493f6d22d9e5390b192a07b73d2ac0a (patch) | |
tree | af87226bcdc254ce2ab656530263e61f6552322b /kernel/trace/trace_ksym.c | |
parent | 5fa10b28e57f94a90535cfeafe89dcee9f47d540 (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.c | 42 |
1 files changed, 20 insertions, 22 deletions
diff --git a/kernel/trace/trace_ksym.c b/kernel/trace/trace_ksym.c index c538b15b95d6..ddfa0fd43bc0 100644 --- a/kernel/trace/trace_ksym.c +++ b/kernel/trace/trace_ksym.c | |||
@@ -42,9 +42,7 @@ | |||
42 | 42 | ||
43 | struct trace_ksym { | 43 | struct 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>"); |