Skip to content

Commit

Permalink
Revert "powerpc/hw-breakpoint: Use generic hw-breakpoint interfaces f…
Browse files Browse the repository at this point in the history
…or new PPC ptrace flags"

This reverts commit 1b78840.

It causes oopses when passed incorrect arguments and has a
design fault using IPIs with interrupts disabled.

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
  • Loading branch information
Benjamin Herrenschmidt committed May 22, 2012
1 parent 933b90a commit 6749ef0
Show file tree
Hide file tree
Showing 2 changed files with 6 additions and 87 deletions.
16 changes: 0 additions & 16 deletions Documentation/powerpc/ptrace.txt
Original file line number Diff line number Diff line change
Expand Up @@ -127,22 +127,6 @@ Some examples of using the structure to:
p.addr2 = (uint64_t) end_range;
p.condition_value = 0;

- set a watchpoint in server processors (BookS)

p.version = 1;
p.trigger_type = PPC_BREAKPOINT_TRIGGER_RW;
p.addr_mode = PPC_BREAKPOINT_MODE_RANGE_INCLUSIVE;
or
p.addr_mode = PPC_BREAKPOINT_MODE_EXACT;

p.condition_mode = PPC_BREAKPOINT_CONDITION_NONE;
p.addr = (uint64_t) begin_range;
/* For PPC_BREAKPOINT_MODE_RANGE_INCLUSIVE addr2 needs to be specified, where
* addr2 - addr <= 8 Bytes.
*/
p.addr2 = (uint64_t) end_range;
p.condition_value = 0;

3. PTRACE_DELHWDEBUG

Takes an integer which identifies an existing breakpoint or watchpoint
Expand Down
77 changes: 6 additions & 71 deletions arch/powerpc/kernel/ptrace.c
Original file line number Diff line number Diff line change
Expand Up @@ -1336,12 +1336,6 @@ static int set_dac_range(struct task_struct *child,
static long ppc_set_hwdebug(struct task_struct *child,
struct ppc_hw_breakpoint *bp_info)
{
#ifdef CONFIG_HAVE_HW_BREAKPOINT
int len = 0;
struct thread_struct *thread = &(child->thread);
struct perf_event *bp;
struct perf_event_attr attr;
#endif /* CONFIG_HAVE_HW_BREAKPOINT */
#ifndef CONFIG_PPC_ADV_DEBUG_REGS
unsigned long dabr;
#endif
Expand Down Expand Up @@ -1385,9 +1379,13 @@ static long ppc_set_hwdebug(struct task_struct *child,
*/
if ((bp_info->trigger_type & PPC_BREAKPOINT_TRIGGER_RW) == 0 ||
(bp_info->trigger_type & ~PPC_BREAKPOINT_TRIGGER_RW) != 0 ||
bp_info->addr_mode != PPC_BREAKPOINT_MODE_EXACT ||
bp_info->condition_mode != PPC_BREAKPOINT_CONDITION_NONE)
return -EINVAL;

if (child->thread.dabr)
return -ENOSPC;

if ((unsigned long)bp_info->addr >= TASK_SIZE)
return -EIO;

Expand All @@ -1397,63 +1395,15 @@ static long ppc_set_hwdebug(struct task_struct *child,
dabr |= DABR_DATA_READ;
if (bp_info->trigger_type & PPC_BREAKPOINT_TRIGGER_WRITE)
dabr |= DABR_DATA_WRITE;
#ifdef CONFIG_HAVE_HW_BREAKPOINT
if (ptrace_get_breakpoints(child) < 0)
return -ESRCH;

/*
* Check if the request is for 'range' breakpoints. We can
* support it if range < 8 bytes.
*/
if (bp_info->addr_mode == PPC_BREAKPOINT_MODE_RANGE_INCLUSIVE) {
len = bp_info->addr2 - bp_info->addr;
} else if (bp_info->addr_mode != PPC_BREAKPOINT_MODE_EXACT) {
ptrace_put_breakpoints(child);
return -EINVAL;
}
bp = thread->ptrace_bps[0];
if (bp) {
ptrace_put_breakpoints(child);
return -ENOSPC;
}

/* Create a new breakpoint request if one doesn't exist already */
hw_breakpoint_init(&attr);
attr.bp_addr = (unsigned long)bp_info->addr & ~HW_BREAKPOINT_ALIGN;
attr.bp_len = len;
arch_bp_generic_fields(dabr & (DABR_DATA_WRITE | DABR_DATA_READ),
&attr.bp_type);

thread->ptrace_bps[0] = bp = register_user_hw_breakpoint(&attr,
ptrace_triggered, NULL, child);
if (IS_ERR(bp)) {
thread->ptrace_bps[0] = NULL;
ptrace_put_breakpoints(child);
return PTR_ERR(bp);
}

ptrace_put_breakpoints(child);
return 1;
#endif /* CONFIG_HAVE_HW_BREAKPOINT */

if (bp_info->addr_mode != PPC_BREAKPOINT_MODE_EXACT)
return -EINVAL;

if (child->thread.dabr)
return -ENOSPC;

child->thread.dabr = dabr;

return 1;
#endif /* !CONFIG_PPC_ADV_DEBUG_DVCS */
}

static long ppc_del_hwdebug(struct task_struct *child, long addr, long data)
{
#ifdef CONFIG_HAVE_HW_BREAKPOINT
int ret = 0;
struct thread_struct *thread = &(child->thread);
struct perf_event *bp;
#endif /* CONFIG_HAVE_HW_BREAKPOINT */
#ifdef CONFIG_PPC_ADV_DEBUG_REGS
int rc;

Expand All @@ -1473,25 +1423,10 @@ static long ppc_del_hwdebug(struct task_struct *child, long addr, long data)
#else
if (data != 1)
return -EINVAL;

#ifdef CONFIG_HAVE_HW_BREAKPOINT
if (ptrace_get_breakpoints(child) < 0)
return -ESRCH;

bp = thread->ptrace_bps[0];
if (bp) {
unregister_hw_breakpoint(bp);
thread->ptrace_bps[0] = NULL;
} else
ret = -ENOENT;
ptrace_put_breakpoints(child);
return ret;
#else /* CONFIG_HAVE_HW_BREAKPOINT */
if (child->thread.dabr == 0)
return -ENOENT;

child->thread.dabr = 0;
#endif /* CONFIG_HAVE_HW_BREAKPOINT */

return 0;
#endif
Expand Down Expand Up @@ -1598,7 +1533,7 @@ long arch_ptrace(struct task_struct *child, long request,
dbginfo.data_bp_alignment = 4;
#endif
dbginfo.sizeof_condition = 0;
dbginfo.features = PPC_DEBUG_FEATURE_DATA_BP_RANGE;
dbginfo.features = 0;
#endif /* CONFIG_PPC_ADV_DEBUG_REGS */

if (!access_ok(VERIFY_WRITE, datavp,
Expand Down

0 comments on commit 6749ef0

Please sign in to comment.