On Mon, May 24, 2010 at 09:32:25AM +0530, K.Prasad wrote:
> Implement perf-events based hw-breakpoint interfaces for PowerPC Book III S
> processors. These interfaces help arbitrate requests from various users and
> schedules them as appropriate.
> 
<snipped>
> +/*
> + * Handle debug exception notifications.
> + */
> +int __kprobes hw_breakpoint_handler(struct die_args *args)
> +{
> +     bool is_kernel, is_ptrace_bp = false;
> +     int rc = NOTIFY_STOP;
> +     struct perf_event *bp;
> +     struct pt_regs *regs = args->regs;
> +     unsigned long dar = regs->dar;
> +     int stepped = 1;
> +     struct arch_hw_breakpoint *info;
> +
> +     /* Disable breakpoints during exception handling */
> +     set_dabr(0);
> +     /*
> +      * The counter may be concurrently released but that can only
> +      * occur from a call_rcu() path. We can then safely fetch
> +      * the breakpoint, use its callback, touch its counter
> +      * while we are in an rcu_read_lock() path.
> +      */
> +     rcu_read_lock();
> +
> +     bp = __get_cpu_var(bp_per_reg);
> +     if (!bp)
> +             goto out;
> +     info = counter_arch_bp(bp);
> +     is_kernel = is_kernel_addr(bp->attr.bp_addr);
> +     is_ptrace_bp = (bp->overflow_handler == ptrace_triggered) ?
> +                     true : false;
> +
> +     /*
> +      * Verify if dar lies within the address range occupied by the symbol
> +      * being watched to filter extraneous exceptions.
> +      */
> +     if (!((bp->attr.bp_addr <= dar) &&
> +         (dar <= (bp->attr.bp_addr + bp->attr.bp_len))) &&
> +         (!is_ptrace_bp))
> +             /*
> +              * This exception is triggered not because of a memory access on
> +              * the monitored variable but in the double-word address range
> +              * in which it is contained. We will consume this exception,
> +              * considering it as 'noise'.
> +              */
> +             goto restore_bp;
> +
> +     /*
> +      * Return early after invoking user-callback function without restoring
> +      * DABR if the breakpoint is from ptrace which always operates in
> +      * one-shot mode. The ptrace-ed process will receive the SIGTRAP signal
> +      * generated in do_dabr().
> +      */
> +     if (is_ptrace_bp) {
> +             perf_bp_event(bp, regs);
> +             rc = NOTIFY_DONE;
> +             goto out;
> +     }
> +
> +     /*
> +      * Do not emulate user-space instructions from kernel-space,
> +      * instead single-step them.
> +      */
> +     if (!is_kernel) {
> +             bp->ctx->task->thread.last_hit_ubp = bp;
> +             regs->msr |= MSR_SE;
> +             goto out;
> +     }
> +
> +     stepped = emulate_step(regs, regs->nip);
> +     /* emulate_step() could not execute it, single-step them */
> +     if (stepped == 0) {

As I was responding to one of the previous mails, I realised that I
had not made changes here as Paul Mackerras had suggested
(reference linuxppc-dev message-id:
[email protected]) i.e. uninstall breakpoint
if single-stepping failed.

I'll quickly send out a revised patch as a reply to this one. Regrets
for the confusion caused.

Thanks,
K.Prasad

> +             regs->msr |= MSR_SE;
> +             __get_cpu_var(last_hit_bp) = bp;
> +             goto out;
> +     }
> +     /*
> +      * As a policy, the callback is invoked in a 'trigger-after-execute'
> +      * fashion
> +      */
> +     perf_bp_event(bp, regs);
> +
> +restore_bp:
> +     set_dabr(info->address | info->type | DABR_TRANSLATION);
> +out:
> +     rcu_read_unlock();
> +     return rc;
> +}
_______________________________________________
Linuxppc-dev mailing list
[email protected]
https://lists.ozlabs.org/listinfo/linuxppc-dev

Reply via email to