/*
  * Construct an arch_hw_breakpoint from a perf_event.
  */
-static int arch_build_bp_info(struct perf_event *bp)
+static int arch_build_bp_info(struct perf_event *bp,
+                             const struct perf_event_attr *attr,
+                             struct arch_hw_breakpoint *hw)
 {
-       struct arch_hw_breakpoint *info = counter_arch_bp(bp);
-
        /* Type */
-       switch (bp->attr.bp_type) {
+       switch (attr->bp_type) {
        case HW_BREAKPOINT_X:
-               info->ctrl.type = ARM_BREAKPOINT_EXECUTE;
+               hw->ctrl.type = ARM_BREAKPOINT_EXECUTE;
                break;
        case HW_BREAKPOINT_R:
-               info->ctrl.type = ARM_BREAKPOINT_LOAD;
+               hw->ctrl.type = ARM_BREAKPOINT_LOAD;
                break;
        case HW_BREAKPOINT_W:
-               info->ctrl.type = ARM_BREAKPOINT_STORE;
+               hw->ctrl.type = ARM_BREAKPOINT_STORE;
                break;
        case HW_BREAKPOINT_RW:
-               info->ctrl.type = ARM_BREAKPOINT_LOAD | ARM_BREAKPOINT_STORE;
+               hw->ctrl.type = ARM_BREAKPOINT_LOAD | ARM_BREAKPOINT_STORE;
                break;
        default:
                return -EINVAL;
        }
 
        /* Len */
-       switch (bp->attr.bp_len) {
+       switch (attr->bp_len) {
        case HW_BREAKPOINT_LEN_1:
-               info->ctrl.len = ARM_BREAKPOINT_LEN_1;
+               hw->ctrl.len = ARM_BREAKPOINT_LEN_1;
                break;
        case HW_BREAKPOINT_LEN_2:
-               info->ctrl.len = ARM_BREAKPOINT_LEN_2;
+               hw->ctrl.len = ARM_BREAKPOINT_LEN_2;
                break;
        case HW_BREAKPOINT_LEN_4:
-               info->ctrl.len = ARM_BREAKPOINT_LEN_4;
+               hw->ctrl.len = ARM_BREAKPOINT_LEN_4;
                break;
        case HW_BREAKPOINT_LEN_8:
-               info->ctrl.len = ARM_BREAKPOINT_LEN_8;
-               if ((info->ctrl.type != ARM_BREAKPOINT_EXECUTE)
+               hw->ctrl.len = ARM_BREAKPOINT_LEN_8;
+               if ((hw->ctrl.type != ARM_BREAKPOINT_EXECUTE)
                        && max_watchpoint_len >= 8)
                        break;
        default:
         * by the hardware and must be aligned to the appropriate number of
         * bytes.
         */
-       if (info->ctrl.type == ARM_BREAKPOINT_EXECUTE &&
-           info->ctrl.len != ARM_BREAKPOINT_LEN_2 &&
-           info->ctrl.len != ARM_BREAKPOINT_LEN_4)
+       if (hw->ctrl.type == ARM_BREAKPOINT_EXECUTE &&
+           hw->ctrl.len != ARM_BREAKPOINT_LEN_2 &&
+           hw->ctrl.len != ARM_BREAKPOINT_LEN_4)
                return -EINVAL;
 
        /* Address */
-       info->address = bp->attr.bp_addr;
+       hw->address = attr->bp_addr;
 
        /* Privilege */
-       info->ctrl.privilege = ARM_BREAKPOINT_USER;
-       if (arch_check_bp_in_kernelspace(info))
-               info->ctrl.privilege |= ARM_BREAKPOINT_PRIV;
+       hw->ctrl.privilege = ARM_BREAKPOINT_USER;
+       if (arch_check_bp_in_kernelspace(hw))
+               hw->ctrl.privilege |= ARM_BREAKPOINT_PRIV;
 
        /* Enabled? */
-       info->ctrl.enabled = !bp->attr.disabled;
+       hw->ctrl.enabled = !attr->disabled;
 
        /* Mismatch */
-       info->ctrl.mismatch = 0;
+       hw->ctrl.mismatch = 0;
 
        return 0;
 }
 /*
  * Validate the arch-specific HW Breakpoint register settings.
  */
-int arch_validate_hwbkpt_settings(struct perf_event *bp)
+int hw_breakpoint_arch_parse(struct perf_event *bp,
+                            const struct perf_event_attr *attr,
+                            struct arch_hw_breakpoint *hw)
 {
-       struct arch_hw_breakpoint *info = counter_arch_bp(bp);
        int ret = 0;
        u32 offset, alignment_mask = 0x3;
 
                return -ENODEV;
 
        /* Build the arch_hw_breakpoint. */
-       ret = arch_build_bp_info(bp);
+       ret = arch_build_bp_info(bp, attr, hw);
        if (ret)
                goto out;
 
        /* Check address alignment. */
-       if (info->ctrl.len == ARM_BREAKPOINT_LEN_8)
+       if (hw->ctrl.len == ARM_BREAKPOINT_LEN_8)
                alignment_mask = 0x7;
-       offset = info->address & alignment_mask;
+       offset = hw->address & alignment_mask;
        switch (offset) {
        case 0:
                /* Aligned */
        case 1:
        case 2:
                /* Allow halfword watchpoints and breakpoints. */
-               if (info->ctrl.len == ARM_BREAKPOINT_LEN_2)
+               if (hw->ctrl.len == ARM_BREAKPOINT_LEN_2)
                        break;
        case 3:
                /* Allow single byte watchpoint. */
-               if (info->ctrl.len == ARM_BREAKPOINT_LEN_1)
+               if (hw->ctrl.len == ARM_BREAKPOINT_LEN_1)
                        break;
        default:
                ret = -EINVAL;
                goto out;
        }
 
-       info->address &= ~alignment_mask;
-       info->ctrl.len <<= offset;
+       hw->address &= ~alignment_mask;
+       hw->ctrl.len <<= offset;
 
        if (is_default_overflow_handler(bp)) {
                /*
                        return -EINVAL;
 
                /* We don't allow mismatch breakpoints in kernel space. */
-               if (arch_check_bp_in_kernelspace(info))
+               if (arch_check_bp_in_kernelspace(hw))
                        return -EPERM;
 
                /*
                 * reports them.
                 */
                if (!debug_exception_updates_fsr() &&
-                   (info->ctrl.type == ARM_BREAKPOINT_LOAD ||
-                    info->ctrl.type == ARM_BREAKPOINT_STORE))
+                   (hw->ctrl.type == ARM_BREAKPOINT_LOAD ||
+                    hw->ctrl.type == ARM_BREAKPOINT_STORE))
                        return -EINVAL;
        }