Revert "powerpc/hw-breakpoint: Use generic hw-breakpoint interfaces for new PPC ptrac...
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>
Mon, 21 May 2012 00:44:12 +0000 (10:44 +1000)
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>
Tue, 22 May 2012 04:37:24 +0000 (14:37 +1000)
This reverts commit 1b788400bbcbfe25280dc0b8000d2142bfe3be3b.

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>
---

Documentation/powerpc/ptrace.txt
arch/powerpc/kernel/ptrace.c

index f2a7a39..f4a5499 100644 (file)
@@ -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
index 8643ac8..ac3cb00 100644 (file)
@@ -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
@@ -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;
 
@@ -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;
 
@@ -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
@@ -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,