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>
diff --git a/kernel/trace/trace_ksym.c b/kernel/trace/trace_ksym.c
index c538b15..ddfa0fd 100644
--- a/kernel/trace/trace_ksym.c
+++ b/kernel/trace/trace_ksym.c
@@ -42,9 +42,7 @@
struct trace_ksym {
struct perf_event **ksym_hbp;
- unsigned long ksym_addr;
- int type;
- int len;
+ struct perf_event_attr attr;
#ifdef CONFIG_PROFILE_KSYM_TRACER
unsigned long counter;
#endif
@@ -71,7 +69,7 @@
rcu_read_lock();
hlist_for_each_entry_rcu(entry, node, &ksym_filter_head, ksym_hlist) {
- if ((entry->ksym_addr == hbp_hit_addr) &&
+ if ((entry->attr.bp_addr == hbp_hit_addr) &&
(entry->counter <= MAX_UL_INT)) {
entry->counter++;
break;
@@ -192,14 +190,15 @@
if (!entry)
return -ENOMEM;
- entry->type = op;
- entry->ksym_addr = addr;
- entry->len = HW_BREAKPOINT_LEN_4;
+ hw_breakpoint_init(&entry->attr);
+
+ entry->attr.bp_type = op;
+ entry->attr.bp_addr = addr;
+ entry->attr.bp_len = HW_BREAKPOINT_LEN_4;
ret = -EAGAIN;
- entry->ksym_hbp = register_wide_hw_breakpoint(entry->ksym_addr,
- entry->len, entry->type,
- ksym_hbp_handler, true);
+ entry->ksym_hbp = register_wide_hw_breakpoint(&entry->attr,
+ ksym_hbp_handler);
if (IS_ERR(entry->ksym_hbp)) {
ret = PTR_ERR(entry->ksym_hbp);
@@ -236,12 +235,12 @@
mutex_lock(&ksym_tracer_mutex);
hlist_for_each_entry(entry, node, &ksym_filter_head, ksym_hlist) {
- ret = trace_seq_printf(s, "%pS:", (void *)entry->ksym_addr);
- if (entry->type == HW_BREAKPOINT_R)
+ ret = trace_seq_printf(s, "%pS:", (void *)entry->attr.bp_addr);
+ if (entry->attr.bp_type == HW_BREAKPOINT_R)
ret = trace_seq_puts(s, "r--\n");
- else if (entry->type == HW_BREAKPOINT_W)
+ else if (entry->attr.bp_type == HW_BREAKPOINT_W)
ret = trace_seq_puts(s, "-w-\n");
- else if (entry->type == (HW_BREAKPOINT_W | HW_BREAKPOINT_R))
+ else if (entry->attr.bp_type == (HW_BREAKPOINT_W | HW_BREAKPOINT_R))
ret = trace_seq_puts(s, "rw-\n");
WARN_ON_ONCE(!ret);
}
@@ -317,9 +316,9 @@
ret = -EINVAL;
hlist_for_each_entry(entry, node, &ksym_filter_head, ksym_hlist) {
- if (entry->ksym_addr == ksym_addr) {
+ if (entry->attr.bp_addr == ksym_addr) {
/* Check for malformed request: (6) */
- if (entry->type != op)
+ if (entry->attr.bp_type != op)
changed = 1;
else
goto out;
@@ -328,13 +327,12 @@
}
if (changed) {
unregister_wide_hw_breakpoint(entry->ksym_hbp);
- entry->type = op;
+ entry->attr.bp_type = op;
ret = 0;
if (op > 0) {
entry->ksym_hbp =
- register_wide_hw_breakpoint(entry->ksym_addr,
- entry->len, entry->type,
- ksym_hbp_handler, true);
+ register_wide_hw_breakpoint(&entry->attr,
+ ksym_hbp_handler);
if (IS_ERR(entry->ksym_hbp))
ret = PTR_ERR(entry->ksym_hbp);
else
@@ -489,7 +487,7 @@
entry = hlist_entry(stat, struct trace_ksym, ksym_hlist);
- access_type = entry->type;
+ access_type = entry->attr.bp_type;
switch (access_type) {
case HW_BREAKPOINT_R:
@@ -505,7 +503,7 @@
seq_puts(m, " NA ");
}
- if (lookup_symbol_name(entry->ksym_addr, fn_name) >= 0)
+ if (lookup_symbol_name(entry->attr.bp_addr, fn_name) >= 0)
seq_printf(m, " %-36s", fn_name);
else
seq_printf(m, " %-36s", "<NA>");