aboutsummaryrefslogtreecommitdiffstats
path: root/arch/blackfin
diff options
context:
space:
mode:
authorMike Frysinger <vapier@gentoo.org>2010-02-17 05:44:22 -0500
committerMike Frysinger <vapier@gentoo.org>2010-03-09 00:30:51 -0500
commit600482c13d3d3612d71f39d8aaec47f63aafa801 (patch)
tree87b347917f743a493de71d9655f7f336f4e92c73 /arch/blackfin
parente8f263dfd32a784a816fe68956e564f8ede4a9fc (diff)
Blackfin: fix single stepping over system calls
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>
Diffstat (limited to 'arch/blackfin')
-rw-r--r--arch/blackfin/include/asm/thread_info.h2
-rw-r--r--arch/blackfin/kernel/ptrace.c11
-rw-r--r--arch/blackfin/kernel/signal.c3
-rw-r--r--arch/blackfin/mach-common/entry.S2
4 files changed, 15 insertions, 3 deletions
diff --git a/arch/blackfin/include/asm/thread_info.h b/arch/blackfin/include/asm/thread_info.h
index 0149c92ceeb0..e9a5614cdbb1 100644
--- a/arch/blackfin/include/asm/thread_info.h
+++ b/arch/blackfin/include/asm/thread_info.h
@@ -103,6 +103,7 @@ static inline struct thread_info *current_thread_info(void)
103#define TIF_FREEZE 6 /* is freezing for suspend */ 103#define TIF_FREEZE 6 /* is freezing for suspend */
104#define TIF_IRQ_SYNC 7 /* sync pipeline stage */ 104#define TIF_IRQ_SYNC 7 /* sync pipeline stage */
105#define TIF_NOTIFY_RESUME 8 /* callback before returning to user */ 105#define TIF_NOTIFY_RESUME 8 /* callback before returning to user */
106#define TIF_SINGLESTEP 9
106 107
107/* as above, but as bit values */ 108/* as above, but as bit values */
108#define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE) 109#define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE)
@@ -113,6 +114,7 @@ static inline struct thread_info *current_thread_info(void)
113#define _TIF_FREEZE (1<<TIF_FREEZE) 114#define _TIF_FREEZE (1<<TIF_FREEZE)
114#define _TIF_IRQ_SYNC (1<<TIF_IRQ_SYNC) 115#define _TIF_IRQ_SYNC (1<<TIF_IRQ_SYNC)
115#define _TIF_NOTIFY_RESUME (1<<TIF_NOTIFY_RESUME) 116#define _TIF_NOTIFY_RESUME (1<<TIF_NOTIFY_RESUME)
117#define _TIF_SINGLESTEP (1<<TIF_SINGLESTEP)
116 118
117#define _TIF_WORK_MASK 0x0000FFFE /* work to do on interrupt/exception return */ 119#define _TIF_WORK_MASK 0x0000FFFE /* work to do on interrupt/exception return */
118 120
diff --git a/arch/blackfin/kernel/ptrace.c b/arch/blackfin/kernel/ptrace.c
index 0618b8287e34..43eb969405d1 100644
--- a/arch/blackfin/kernel/ptrace.c
+++ b/arch/blackfin/kernel/ptrace.c
@@ -220,12 +220,16 @@ void user_enable_single_step(struct task_struct *child)
220{ 220{
221 struct pt_regs *regs = task_pt_regs(child); 221 struct pt_regs *regs = task_pt_regs(child);
222 regs->syscfg |= SYSCFG_SSSTEP; 222 regs->syscfg |= SYSCFG_SSSTEP;
223
224 set_tsk_thread_flag(child, TIF_SINGLESTEP);
223} 225}
224 226
225void user_disable_single_step(struct task_struct *child) 227void user_disable_single_step(struct task_struct *child)
226{ 228{
227 struct pt_regs *regs = task_pt_regs(child); 229 struct pt_regs *regs = task_pt_regs(child);
228 regs->syscfg &= ~SYSCFG_SSSTEP; 230 regs->syscfg &= ~SYSCFG_SSSTEP;
231
232 clear_tsk_thread_flag(child, TIF_SINGLESTEP);
229} 233}
230 234
231long arch_ptrace(struct task_struct *child, long request, long addr, long data) 235long 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)
401 405
402asmlinkage void syscall_trace_leave(struct pt_regs *regs) 406asmlinkage void syscall_trace_leave(struct pt_regs *regs)
403{ 407{
404 if (test_thread_flag(TIF_SYSCALL_TRACE)) 408 int step;
405 tracehook_report_syscall_exit(regs, 0); 409
410 step = test_thread_flag(TIF_SINGLESTEP);
411 if (step || test_thread_flag(TIF_SYSCALL_TRACE))
412 tracehook_report_syscall_exit(regs, step);
406} 413}
diff --git a/arch/blackfin/kernel/signal.c b/arch/blackfin/kernel/signal.c
index e60990c0a1f0..28d6f28c058c 100644
--- a/arch/blackfin/kernel/signal.c
+++ b/arch/blackfin/kernel/signal.c
@@ -306,7 +306,8 @@ asmlinkage void do_signal(struct pt_regs *regs)
306 if (test_thread_flag(TIF_RESTORE_SIGMASK)) 306 if (test_thread_flag(TIF_RESTORE_SIGMASK))
307 clear_thread_flag(TIF_RESTORE_SIGMASK); 307 clear_thread_flag(TIF_RESTORE_SIGMASK);
308 308
309 tracehook_signal_handler(signr, &info, &ka, regs, 1); 309 tracehook_signal_handler(signr, &info, &ka, regs,
310 test_thread_flag(TIF_SINGLESTEP));
310 } 311 }
311 312
312 return; 313 return;
diff --git a/arch/blackfin/mach-common/entry.S b/arch/blackfin/mach-common/entry.S
index 0df5b834d34e..0a9e458d0f7e 100644
--- a/arch/blackfin/mach-common/entry.S
+++ b/arch/blackfin/mach-common/entry.S
@@ -642,6 +642,8 @@ ENTRY(_system_call)
642 r7 = [p2+TI_FLAGS]; 642 r7 = [p2+TI_FLAGS];
643 CC = BITTST(r7,TIF_SYSCALL_TRACE); 643 CC = BITTST(r7,TIF_SYSCALL_TRACE);
644 if CC JUMP _sys_trace; 644 if CC JUMP _sys_trace;
645 CC = BITTST(r7,TIF_SINGLESTEP);
646 if CC JUMP _sys_trace;
645 647
646 /* Execute the appropriate system call */ 648 /* Execute the appropriate system call */
647 649