Modify the ptrace code to use the hardware breakpoint interfaces for user-space.

Signed-off-by: K.Prasad <pra...@linux.vnet.ibm.com>
---
 arch/powerpc/kernel/ptrace.c             |   48 +++++
Index: linux-2.6-tip.hbkpt/arch/powerpc/kernel/ptrace.c
===================================================================
--- linux-2.6-tip.hbkpt.orig/arch/powerpc/kernel/ptrace.c
+++ linux-2.6-tip.hbkpt/arch/powerpc/kernel/ptrace.c
@@ -37,6 +37,9 @@
 #include <asm/page.h>
 #include <asm/pgtable.h>
 #include <asm/system.h>
+#ifdef CONFIG_PPC64
+#include <asm/hw_breakpoint.h>
+#endif
 
 /*
  * does not yet catch signals sent when the child dies.
@@ -735,9 +738,22 @@ void user_disable_single_step(struct tas
        clear_tsk_thread_flag(task, TIF_SINGLESTEP);
 }
 
+static void ptrace_triggered(struct hw_breakpoint *bp, struct pt_regs *regs)
+{
+       /*
+        * The SIGTRAP signal is generated automatically for us in do_dabr().
+        * We don't have to do anything here
+        */
+}
+
 int ptrace_set_debugreg(struct task_struct *task, unsigned long addr,
                               unsigned long data)
 {
+#ifdef CONFIG_PPC64
+       struct thread_struct *thread = &(task->thread);
+       struct hw_breakpoint *bp;
+       int ret;
+#endif
        /* For ppc64 we support one DABR and no IABR's at the moment (ppc64).
         *  For embedded processors we support one DAC and no IAC's at the
         *  moment.
@@ -767,6 +783,38 @@ int ptrace_set_debugreg(struct task_stru
        if (data && !(data & DABR_TRANSLATION))
                return -EIO;
 
+#ifdef CONFIG_PPC64
+       bp = thread->hbp[0];
+       if ((data & ~HW_BREAKPOINT_ALIGN) == 0) {
+               if (bp) {
+                       unregister_user_hw_breakpoint(task, bp);
+                       kfree(bp);
+                       thread->hbp[0] = NULL;
+               }
+               return 0;
+       }
+
+       if (bp) {
+               bp->info.type = data & DABR_DATA_RW;
+               task->thread.dabr = bp->info.address =
+                                               (data & ~HW_BREAKPOINT_ALIGN);
+               return modify_user_hw_breakpoint(task, bp);
+       }
+       bp = kzalloc(sizeof(struct hw_breakpoint), GFP_KERNEL);
+       if (!bp)
+               return -ENOMEM;
+
+       /* Store the type of breakpoint */
+       bp->info.type = data & DABR_DATA_RW;
+       bp->triggered = ptrace_triggered;
+       task->thread.dabr = bp->info.address = (data & ~HW_BREAKPOINT_ALIGN);
+
+       ret = register_user_hw_breakpoint(task, bp);
+       if (ret)
+               return ret;
+       set_tsk_thread_flag(task, TIF_DEBUG);
+#endif /* CONFIG_PPC64 */
+
        /* Move contents to the DABR register */
        task->thread.dabr = data;

_______________________________________________
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev

Reply via email to