hw_breakpoint :watchpointhandler

    static void watchpoint_handler(unsigned long addr, unsigned int fsr,
                               struct pt_regs *regs)
{
        int i, access;
        u32 val, ctrl_reg, alignment_mask;
        struct perf_event *wp, **slots;
        struct arch_hw_breakpoint *info;
        struct arch_hw_breakpoint_ctrl ctrl;

        slots = (struct perf_event **)__get_cpu_var(wp_on_reg);

        for (i = 0; i < core_num_wrps; ++i) {
                rcu_read_lock();

                wp = slots[i];

                if (wp == NULL)
                   goto unlock;

                info = counter_arch_bp(wp);
                /*
                 * The DFAR is an unknown value on debug architectures prior
                 * to 7.1. Since we only allow a single watchpoint on these
                 * older CPUs, we can set the trigger to the lowest possible
                 * faulting address.
                 */
                if (debug_arch < ARM_DEBUG_ARCH_V7_1) {
                        BUG_ON(i > 0);
                        info->trigger = wp->attr.bp_addr;
                } else {
                        if (info->ctrl.len == ARM_BREAKPOINT_LEN_8)
                                alignment_mask = 0x7;
                        else
                                alignment_mask = 0x3;

                        /* Check if the watchpoint value matches. */
                        val = read_wb_reg(ARM_BASE_WVR + i);
                        if (val != (addr & ~alignment_mask))
                                goto unlock;

                        /* Possible match, check the byte address select. */
                        ctrl_reg = read_wb_reg(ARM_BASE_WCR + i);
                        decode_ctrl_reg(ctrl_reg, &ctrl);
                        if (!((1 << (addr & alignment_mask)) & ctrl.len))
                                goto unlock;

                        /* Check that the access type matches. */
                        access = (fsr & ARM_FSR_ACCESS_MASK) ? HW_BREAKPOINT_W :
                                 HW_BREAKPOINT_R;
                        if (!(access & hw_breakpoint_type(wp)))
                                goto unlock;

                        /* We have a winner. */
                        info->trigger = addr;
                }

                pr_debug("watchpoint fired: address = 0x%x\n", info->trigger);

                perf_bp_event(wp, regs);

       /*
                 * If no overflow handler is present, insert a temporary
                 * mismatch breakpoint so we can single-step over the
                 * watchpoint trigger.
                 */
                if (!wp->overflow_handler)
                        enable_single_step(wp, instruction_pointer(regs));

unlock:
                rcu_read_unlock();
        }
}



你可能感兴趣的:(代码)