[RFC Patch 2/5] PPC64-HWBKPT: Implement hw-breakpoints for PowerPC Book III S
K.Prasad
prasad at linux.vnet.ibm.com
Mon May 24 14:38:12 EST 2010
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:
20100520131003.GB29903 at brick.ozlabs.ibm.com) 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;
> +}
More information about the Linuxppc-dev
mailing list