diff options
-rw-r--r-- | arch/s390/kernel/ptrace.c | 15 | ||||
-rw-r--r-- | arch/s390/kernel/signal.c | 20 | ||||
-rw-r--r-- | include/asm-s390/ptrace.h | 8 |
3 files changed, 27 insertions, 16 deletions
diff --git a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c index 1d81bf9488ae..6e036bae9875 100644 --- a/arch/s390/kernel/ptrace.c +++ b/arch/s390/kernel/ptrace.c | |||
@@ -86,13 +86,13 @@ FixPerRegisters(struct task_struct *task) | |||
86 | per_info->control_regs.bits.storage_alt_space_ctl = 0; | 86 | per_info->control_regs.bits.storage_alt_space_ctl = 0; |
87 | } | 87 | } |
88 | 88 | ||
89 | static void set_single_step(struct task_struct *task) | 89 | void user_enable_single_step(struct task_struct *task) |
90 | { | 90 | { |
91 | task->thread.per_info.single_step = 1; | 91 | task->thread.per_info.single_step = 1; |
92 | FixPerRegisters(task); | 92 | FixPerRegisters(task); |
93 | } | 93 | } |
94 | 94 | ||
95 | static void clear_single_step(struct task_struct *task) | 95 | void user_disable_single_step(struct task_struct *task) |
96 | { | 96 | { |
97 | task->thread.per_info.single_step = 0; | 97 | task->thread.per_info.single_step = 0; |
98 | FixPerRegisters(task); | 98 | FixPerRegisters(task); |
@@ -107,7 +107,7 @@ void | |||
107 | ptrace_disable(struct task_struct *child) | 107 | ptrace_disable(struct task_struct *child) |
108 | { | 108 | { |
109 | /* make sure the single step bit is not set. */ | 109 | /* make sure the single step bit is not set. */ |
110 | clear_single_step(child); | 110 | user_disable_single_step(child); |
111 | } | 111 | } |
112 | 112 | ||
113 | #ifndef CONFIG_64BIT | 113 | #ifndef CONFIG_64BIT |
@@ -651,7 +651,7 @@ do_ptrace(struct task_struct *child, long request, long addr, long data) | |||
651 | clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); | 651 | clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); |
652 | child->exit_code = data; | 652 | child->exit_code = data; |
653 | /* make sure the single step bit is not set. */ | 653 | /* make sure the single step bit is not set. */ |
654 | clear_single_step(child); | 654 | user_disable_single_step(child); |
655 | wake_up_process(child); | 655 | wake_up_process(child); |
656 | return 0; | 656 | return 0; |
657 | 657 | ||
@@ -665,7 +665,7 @@ do_ptrace(struct task_struct *child, long request, long addr, long data) | |||
665 | return 0; | 665 | return 0; |
666 | child->exit_code = SIGKILL; | 666 | child->exit_code = SIGKILL; |
667 | /* make sure the single step bit is not set. */ | 667 | /* make sure the single step bit is not set. */ |
668 | clear_single_step(child); | 668 | user_disable_single_step(child); |
669 | wake_up_process(child); | 669 | wake_up_process(child); |
670 | return 0; | 670 | return 0; |
671 | 671 | ||
@@ -675,10 +675,7 @@ do_ptrace(struct task_struct *child, long request, long addr, long data) | |||
675 | return -EIO; | 675 | return -EIO; |
676 | clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); | 676 | clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); |
677 | child->exit_code = data; | 677 | child->exit_code = data; |
678 | if (data) | 678 | user_enable_single_step(child); |
679 | set_tsk_thread_flag(child, TIF_SINGLE_STEP); | ||
680 | else | ||
681 | set_single_step(child); | ||
682 | /* give it a chance to run. */ | 679 | /* give it a chance to run. */ |
683 | wake_up_process(child); | 680 | wake_up_process(child); |
684 | return 0; | 681 | return 0; |
diff --git a/arch/s390/kernel/signal.c b/arch/s390/kernel/signal.c index d264671c1b71..4449bf32cbf1 100644 --- a/arch/s390/kernel/signal.c +++ b/arch/s390/kernel/signal.c | |||
@@ -471,6 +471,7 @@ void do_signal(struct pt_regs *regs) | |||
471 | 471 | ||
472 | if (signr > 0) { | 472 | if (signr > 0) { |
473 | /* Whee! Actually deliver the signal. */ | 473 | /* Whee! Actually deliver the signal. */ |
474 | int ret; | ||
474 | #ifdef CONFIG_COMPAT | 475 | #ifdef CONFIG_COMPAT |
475 | if (test_thread_flag(TIF_31BIT)) { | 476 | if (test_thread_flag(TIF_31BIT)) { |
476 | extern int handle_signal32(unsigned long sig, | 477 | extern int handle_signal32(unsigned long sig, |
@@ -478,15 +479,12 @@ void do_signal(struct pt_regs *regs) | |||
478 | siginfo_t *info, | 479 | siginfo_t *info, |
479 | sigset_t *oldset, | 480 | sigset_t *oldset, |
480 | struct pt_regs *regs); | 481 | struct pt_regs *regs); |
481 | if (handle_signal32( | 482 | ret = handle_signal32(signr, &ka, &info, oldset, regs); |
482 | signr, &ka, &info, oldset, regs) == 0) { | ||
483 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) | ||
484 | clear_thread_flag(TIF_RESTORE_SIGMASK); | ||
485 | } | ||
486 | return; | ||
487 | } | 483 | } |
484 | else | ||
488 | #endif | 485 | #endif |
489 | if (handle_signal(signr, &ka, &info, oldset, regs) == 0) { | 486 | ret = handle_signal(signr, &ka, &info, oldset, regs); |
487 | if (!ret) { | ||
490 | /* | 488 | /* |
491 | * A signal was successfully delivered; the saved | 489 | * A signal was successfully delivered; the saved |
492 | * sigmask will have been stored in the signal frame, | 490 | * sigmask will have been stored in the signal frame, |
@@ -495,6 +493,14 @@ void do_signal(struct pt_regs *regs) | |||
495 | */ | 493 | */ |
496 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) | 494 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) |
497 | clear_thread_flag(TIF_RESTORE_SIGMASK); | 495 | clear_thread_flag(TIF_RESTORE_SIGMASK); |
496 | |||
497 | /* | ||
498 | * If we would have taken a single-step trap | ||
499 | * for a normal instruction, act like we took | ||
500 | * one for the handler setup. | ||
501 | */ | ||
502 | if (current->thread.per_info.single_step) | ||
503 | set_thread_flag(TIF_SINGLE_STEP); | ||
498 | } | 504 | } |
499 | return; | 505 | return; |
500 | } | 506 | } |
diff --git a/include/asm-s390/ptrace.h b/include/asm-s390/ptrace.h index 332ee73688fc..61f6952f2e35 100644 --- a/include/asm-s390/ptrace.h +++ b/include/asm-s390/ptrace.h | |||
@@ -465,6 +465,14 @@ struct user_regs_struct | |||
465 | #ifdef __KERNEL__ | 465 | #ifdef __KERNEL__ |
466 | #define __ARCH_SYS_PTRACE 1 | 466 | #define __ARCH_SYS_PTRACE 1 |
467 | 467 | ||
468 | /* | ||
469 | * These are defined as per linux/ptrace.h, which see. | ||
470 | */ | ||
471 | #define arch_has_single_step() (1) | ||
472 | struct task_struct; | ||
473 | extern void user_enable_single_step(struct task_struct *); | ||
474 | extern void user_disable_single_step(struct task_struct *); | ||
475 | |||
468 | #define user_mode(regs) (((regs)->psw.mask & PSW_MASK_PSTATE) != 0) | 476 | #define user_mode(regs) (((regs)->psw.mask & PSW_MASK_PSTATE) != 0) |
469 | #define instruction_pointer(regs) ((regs)->psw.addr & PSW_ADDR_INSN) | 477 | #define instruction_pointer(regs) ((regs)->psw.addr & PSW_ADDR_INSN) |
470 | #define regs_return_value(regs)((regs)->gprs[2]) | 478 | #define regs_return_value(regs)((regs)->gprs[2]) |