.pinned = 1,                    \
 };
 
+static inline void hw_breakpoint_init(struct perf_event_attr *attr)
+{
+       attr->type = PERF_TYPE_BREAKPOINT;
+       attr->size = sizeof(*attr);
+       attr->pinned = 1;
+}
+
 static inline unsigned long hw_breakpoint_addr(struct perf_event *bp)
 {
        return bp->attr.bp_addr;
  * Kernel breakpoints are not associated with any particular thread.
  */
 extern struct perf_event *
-register_wide_hw_breakpoint_cpu(unsigned long addr,
-                               int len,
-                               int type,
+register_wide_hw_breakpoint_cpu(struct perf_event_attr *attr,
                                perf_callback_t triggered,
-                               int cpu,
-                               bool active);
+                               int cpu);
 
 extern struct perf_event **
-register_wide_hw_breakpoint(unsigned long addr,
-                           int len,
-                           int type,
-                           perf_callback_t triggered,
-                           bool active);
+register_wide_hw_breakpoint(struct perf_event_attr *attr,
+                           perf_callback_t triggered);
 
 extern int register_perf_hw_breakpoint(struct perf_event *bp);
 extern int __register_perf_hw_breakpoint(struct perf_event *bp);
                          perf_callback_t triggered,
                          struct task_struct *tsk)      { return NULL; }
 static inline struct perf_event *
-register_wide_hw_breakpoint_cpu(unsigned long addr,
-                               int len,
-                               int type,
+register_wide_hw_breakpoint_cpu(struct perf_event_attr *attr,
                                perf_callback_t triggered,
-                               int cpu,
-                               bool active)            { return NULL; }
+                               int cpu)                { return NULL; }
 static inline struct perf_event **
-register_wide_hw_breakpoint(unsigned long addr,
-                           int len,
-                           int type,
-                           perf_callback_t triggered,
-                           bool active)                { return NULL; }
+register_wide_hw_breakpoint(struct perf_event_attr *attr,
+                           perf_callback_t triggered)  { return NULL; }
 static inline int
 register_perf_hw_breakpoint(struct perf_event *bp)     { return -ENOSYS; }
 static inline int
 
 }
 EXPORT_SYMBOL_GPL(unregister_hw_breakpoint);
 
-static struct perf_event *
-register_kernel_hw_breakpoint_cpu(unsigned long addr,
-                                 int len,
-                                 int type,
-                                 perf_callback_t triggered,
-                                 int cpu,
-                                 bool active)
-{
-       DEFINE_BREAKPOINT_ATTR(attr);
-
-       attr.bp_addr = addr;
-       attr.bp_len = len;
-       attr.bp_type = type;
-
-       if (!active)
-               attr.disabled = 1;
-
-       return perf_event_create_kernel_counter(&attr, cpu, -1, triggered);
-}
-
 /**
  * register_wide_hw_breakpoint - register a wide breakpoint in the kernel
- * @addr: is the memory address that triggers the breakpoint
- * @len: the length of the access to the memory (1 byte, 2 bytes etc...)
- * @type: the type of the access to the memory (read/write/exec)
+ * @attr: breakpoint attributes
  * @triggered: callback to trigger when we hit the breakpoint
- * @active: should we activate it while registering it
  *
  * @return a set of per_cpu pointers to perf events
  */
 struct perf_event **
-register_wide_hw_breakpoint(unsigned long addr,
-                           int len,
-                           int type,
-                           perf_callback_t triggered,
-                           bool active)
+register_wide_hw_breakpoint(struct perf_event_attr *attr,
+                           perf_callback_t triggered)
 {
        struct perf_event **cpu_events, **pevent, *bp;
        long err;
 
        for_each_possible_cpu(cpu) {
                pevent = per_cpu_ptr(cpu_events, cpu);
-               bp = register_kernel_hw_breakpoint_cpu(addr, len, type,
-                                       triggered, cpu, active);
+               bp = perf_event_create_kernel_counter(attr, cpu, -1, triggered);
 
                *pevent = bp;
 
 
 
 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
 
        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;
        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);
        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);
        }
 
        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;
        }
        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
 
        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:
                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>");
 
 static int __init hw_break_module_init(void)
 {
        int ret;
-       unsigned long addr;
+       DEFINE_BREAKPOINT_ATTR(attr);
 
-       addr = kallsyms_lookup_name(ksym_name);
+       attr.bp_addr = kallsyms_lookup_name(ksym_name);
+       attr.bp_len = HW_BREAKPOINT_LEN_4;
+       attr.bp_type = HW_BREAKPOINT_W | HW_BREAKPOINT_R;
 
-       sample_hbp = register_wide_hw_breakpoint(addr, HW_BREAKPOINT_LEN_4,
-                                                HW_BREAKPOINT_W | HW_BREAKPOINT_R,
-                                                sample_hbp_handler, true);
+       sample_hbp = register_wide_hw_breakpoint(&attr, sample_hbp_handler);
        if (IS_ERR(sample_hbp)) {
                ret = PTR_ERR(sample_hbp);
                goto fail;