Blackfin: fix single stepping over system calls
authorMike Frysinger <vapier@gentoo.org>
Wed, 17 Feb 2010 10:44:22 +0000 (10:44 +0000)
committerMike Frysinger <vapier@gentoo.org>
Tue, 9 Mar 2010 05:30:51 +0000 (00:30 -0500)
On Blackfin systems, the hardware single step exception triggers before
the system call exception, so we need to save this info to process it
later on.  Otherwise, single stepping in userspace misses a few insns
right after the system call.

This is based a bit on the SuperH code added in commit 4b505db9c4c72dbd.

Reported-by: Roland McGrath <roland@redhat.com>
Signed-off-by: Mike Frysinger <vapier@gentoo.org>
arch/blackfin/include/asm/thread_info.h
arch/blackfin/kernel/ptrace.c
arch/blackfin/kernel/signal.c
arch/blackfin/mach-common/entry.S

index 0149c92ceeb04ddd853b28ecd58958d4b501110b..e9a5614cdbb15abb2a78412661c364e4af9f5e12 100644 (file)
@@ -103,6 +103,7 @@ static inline struct thread_info *current_thread_info(void)
 #define TIF_FREEZE             6       /* is freezing for suspend */
 #define TIF_IRQ_SYNC           7       /* sync pipeline stage */
 #define TIF_NOTIFY_RESUME      8       /* callback before returning to user */
+#define TIF_SINGLESTEP         9
 
 /* as above, but as bit values */
 #define _TIF_SYSCALL_TRACE     (1<<TIF_SYSCALL_TRACE)
@@ -113,6 +114,7 @@ static inline struct thread_info *current_thread_info(void)
 #define _TIF_FREEZE            (1<<TIF_FREEZE)
 #define _TIF_IRQ_SYNC          (1<<TIF_IRQ_SYNC)
 #define _TIF_NOTIFY_RESUME     (1<<TIF_NOTIFY_RESUME)
+#define _TIF_SINGLESTEP                (1<<TIF_SINGLESTEP)
 
 #define _TIF_WORK_MASK         0x0000FFFE      /* work to do on interrupt/exception return */
 
index 0618b8287e34e54305c5a5ae385d1b839c27834e..43eb969405d1657bd0aba85b2528e9d28296bd55 100644 (file)
@@ -220,12 +220,16 @@ void user_enable_single_step(struct task_struct *child)
 {
        struct pt_regs *regs = task_pt_regs(child);
        regs->syscfg |= SYSCFG_SSSTEP;
+
+       set_tsk_thread_flag(child, TIF_SINGLESTEP);
 }
 
 void user_disable_single_step(struct task_struct *child)
 {
        struct pt_regs *regs = task_pt_regs(child);
        regs->syscfg &= ~SYSCFG_SSSTEP;
+
+       clear_tsk_thread_flag(child, TIF_SINGLESTEP);
 }
 
 long arch_ptrace(struct task_struct *child, long request, long addr, long data)
@@ -401,6 +405,9 @@ asmlinkage int syscall_trace_enter(struct pt_regs *regs)
 
 asmlinkage void syscall_trace_leave(struct pt_regs *regs)
 {
-       if (test_thread_flag(TIF_SYSCALL_TRACE))
-               tracehook_report_syscall_exit(regs, 0);
+       int step;
+
+       step = test_thread_flag(TIF_SINGLESTEP);
+       if (step || test_thread_flag(TIF_SYSCALL_TRACE))
+               tracehook_report_syscall_exit(regs, step);
 }
index e60990c0a1f01ef91cf85d5dd693ad98e018a4b8..28d6f28c058c41ea90940fc90cc060df8aaac6ea 100644 (file)
@@ -306,7 +306,8 @@ asmlinkage void do_signal(struct pt_regs *regs)
                        if (test_thread_flag(TIF_RESTORE_SIGMASK))
                                clear_thread_flag(TIF_RESTORE_SIGMASK);
 
-                       tracehook_signal_handler(signr, &info, &ka, regs, 1);
+                       tracehook_signal_handler(signr, &info, &ka, regs,
+                               test_thread_flag(TIF_SINGLESTEP));
                }
 
                return;
index 0df5b834d34eee62b9966afe6527218d5a061e3f..0a9e458d0f7e197f66e599c925a9ac6d81e73c5b 100644 (file)
@@ -642,6 +642,8 @@ ENTRY(_system_call)
        r7 = [p2+TI_FLAGS];
        CC = BITTST(r7,TIF_SYSCALL_TRACE);
        if CC JUMP _sys_trace;
+       CC = BITTST(r7,TIF_SINGLESTEP);
+       if CC JUMP _sys_trace;
 
        /* Execute the appropriate system call */