[S390] single-step cleanup
authorRoland McGrath <roland@redhat.com>
Sat, 26 Jan 2008 13:11:22 +0000 (14:11 +0100)
committerMartin Schwidefsky <schwidefsky@de.ibm.com>
Sat, 26 Jan 2008 13:11:27 +0000 (14:11 +0100)
Signed-off-by: Roland McGrath <roland@redhat.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
arch/s390/kernel/ptrace.c
arch/s390/kernel/signal.c
include/asm-s390/ptrace.h

index 1d81bf9488aec20b968e305b2acf57fcd6d0bd85..6e036bae987534d0c46e05159e6de1f310cc41bd 100644 (file)
@@ -86,13 +86,13 @@ FixPerRegisters(struct task_struct *task)
                per_info->control_regs.bits.storage_alt_space_ctl = 0;
 }
 
-static void set_single_step(struct task_struct *task)
+void user_enable_single_step(struct task_struct *task)
 {
        task->thread.per_info.single_step = 1;
        FixPerRegisters(task);
 }
 
-static void clear_single_step(struct task_struct *task)
+void user_disable_single_step(struct task_struct *task)
 {
        task->thread.per_info.single_step = 0;
        FixPerRegisters(task);
@@ -107,7 +107,7 @@ void
 ptrace_disable(struct task_struct *child)
 {
        /* make sure the single step bit is not set. */
-       clear_single_step(child);
+       user_disable_single_step(child);
 }
 
 #ifndef CONFIG_64BIT
@@ -651,7 +651,7 @@ do_ptrace(struct task_struct *child, long request, long addr, long data)
                        clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
                child->exit_code = data;
                /* make sure the single step bit is not set. */
-               clear_single_step(child);
+               user_disable_single_step(child);
                wake_up_process(child);
                return 0;
 
@@ -665,7 +665,7 @@ do_ptrace(struct task_struct *child, long request, long addr, long data)
                        return 0;
                child->exit_code = SIGKILL;
                /* make sure the single step bit is not set. */
-               clear_single_step(child);
+               user_disable_single_step(child);
                wake_up_process(child);
                return 0;
 
@@ -675,10 +675,7 @@ do_ptrace(struct task_struct *child, long request, long addr, long data)
                        return -EIO;
                clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
                child->exit_code = data;
-               if (data)
-                       set_tsk_thread_flag(child, TIF_SINGLE_STEP);
-               else
-                       set_single_step(child);
+               user_enable_single_step(child);
                /* give it a chance to run. */
                wake_up_process(child);
                return 0;
index d264671c1b71e996b38563a398e7109cb9946028..4449bf32cbf1e976e414518cee77998587ba18a3 100644 (file)
@@ -471,6 +471,7 @@ void do_signal(struct pt_regs *regs)
 
        if (signr > 0) {
                /* Whee!  Actually deliver the signal.  */
+               int ret;
 #ifdef CONFIG_COMPAT
                if (test_thread_flag(TIF_31BIT)) {
                        extern int handle_signal32(unsigned long sig,
@@ -478,15 +479,12 @@ void do_signal(struct pt_regs *regs)
                                                   siginfo_t *info,
                                                   sigset_t *oldset,
                                                   struct pt_regs *regs);
-                       if (handle_signal32(
-                                   signr, &ka, &info, oldset, regs) == 0) {
-                               if (test_thread_flag(TIF_RESTORE_SIGMASK))
-                                       clear_thread_flag(TIF_RESTORE_SIGMASK);
-                       }
-                       return;
+                       ret = handle_signal32(signr, &ka, &info, oldset, regs);
                }
+               else
 #endif
-               if (handle_signal(signr, &ka, &info, oldset, regs) == 0) {
+                       ret = handle_signal(signr, &ka, &info, oldset, regs);
+               if (!ret) {
                        /*
                         * A signal was successfully delivered; the saved
                         * sigmask will have been stored in the signal frame,
@@ -495,6 +493,14 @@ void do_signal(struct pt_regs *regs)
                         */
                        if (test_thread_flag(TIF_RESTORE_SIGMASK))
                                clear_thread_flag(TIF_RESTORE_SIGMASK);
+
+                       /*
+                        * If we would have taken a single-step trap
+                        * for a normal instruction, act like we took
+                        * one for the handler setup.
+                        */
+                       if (current->thread.per_info.single_step)
+                               set_thread_flag(TIF_SINGLE_STEP);
                }
                return;
        }
index 332ee73688fc183ab5fbd60cd722a90b5b3ed50a..61f6952f2e357e2b76f442994b91aa55c55e596f 100644 (file)
@@ -465,6 +465,14 @@ struct user_regs_struct
 #ifdef __KERNEL__
 #define __ARCH_SYS_PTRACE      1
 
+/*
+ * These are defined as per linux/ptrace.h, which see.
+ */
+#define arch_has_single_step() (1)
+struct task_struct;
+extern void user_enable_single_step(struct task_struct *);
+extern void user_disable_single_step(struct task_struct *);
+
 #define user_mode(regs) (((regs)->psw.mask & PSW_MASK_PSTATE) != 0)
 #define instruction_pointer(regs) ((regs)->psw.addr & PSW_ADDR_INSN)
 #define regs_return_value(regs)((regs)->gprs[2])