aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/kernel/ptrace.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/s390/kernel/ptrace.c')
-rw-r--r--arch/s390/kernel/ptrace.c51
1 files changed, 50 insertions, 1 deletions
diff --git a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c
index ae0e14b8880..bae1cc49fe9 100644
--- a/arch/s390/kernel/ptrace.c
+++ b/arch/s390/kernel/ptrace.c
@@ -42,6 +42,7 @@ enum s390_regset {
42 REGSET_GENERAL, 42 REGSET_GENERAL,
43 REGSET_FP, 43 REGSET_FP,
44 REGSET_LAST_BREAK, 44 REGSET_LAST_BREAK,
45 REGSET_SYSTEM_CALL,
45 REGSET_GENERAL_EXTENDED, 46 REGSET_GENERAL_EXTENDED,
46}; 47};
47 48
@@ -303,6 +304,13 @@ static int __poke_user(struct task_struct *child, addr_t addr, addr_t data)
303 high order bit but older gdb's rely on it */ 304 high order bit but older gdb's rely on it */
304 data |= PSW_ADDR_AMODE; 305 data |= PSW_ADDR_AMODE;
305#endif 306#endif
307 if (addr == (addr_t) &dummy->regs.psw.addr)
308 /*
309 * The debugger changed the instruction address,
310 * reset system call restart, see signal.c:do_signal
311 */
312 task_thread_info(child)->system_call = 0;
313
306 *(addr_t *)((addr_t) &task_pt_regs(child)->psw + addr) = data; 314 *(addr_t *)((addr_t) &task_pt_regs(child)->psw + addr) = data;
307 315
308 } else if (addr < (addr_t) (&dummy->regs.orig_gpr2)) { 316 } else if (addr < (addr_t) (&dummy->regs.orig_gpr2)) {
@@ -610,6 +618,11 @@ static int __poke_user_compat(struct task_struct *child,
610 /* Build a 64 bit psw address from 31 bit address. */ 618 /* Build a 64 bit psw address from 31 bit address. */
611 task_pt_regs(child)->psw.addr = 619 task_pt_regs(child)->psw.addr =
612 (__u64) tmp & PSW32_ADDR_INSN; 620 (__u64) tmp & PSW32_ADDR_INSN;
621 /*
622 * The debugger changed the instruction address,
623 * reset system call restart, see signal.c:do_signal
624 */
625 task_thread_info(child)->system_call = 0;
613 } else { 626 } else {
614 /* gpr 0-15 */ 627 /* gpr 0-15 */
615 *(__u32*)((addr_t) &task_pt_regs(child)->psw 628 *(__u32*)((addr_t) &task_pt_regs(child)->psw
@@ -737,7 +750,7 @@ asmlinkage long do_syscall_trace_enter(struct pt_regs *regs)
737 * debugger stored an invalid system call number. Skip 750 * debugger stored an invalid system call number. Skip
738 * the system call and the system call restart handling. 751 * the system call and the system call restart handling.
739 */ 752 */
740 regs->svcnr = 0; 753 regs->svc_code = 0;
741 ret = -1; 754 ret = -1;
742 } 755 }
743 756
@@ -899,6 +912,26 @@ static int s390_last_break_get(struct task_struct *target,
899 912
900#endif 913#endif
901 914
915static int s390_system_call_get(struct task_struct *target,
916 const struct user_regset *regset,
917 unsigned int pos, unsigned int count,
918 void *kbuf, void __user *ubuf)
919{
920 unsigned int *data = &task_thread_info(target)->system_call;
921 return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
922 data, 0, sizeof(unsigned int));
923}
924
925static int s390_system_call_set(struct task_struct *target,
926 const struct user_regset *regset,
927 unsigned int pos, unsigned int count,
928 const void *kbuf, const void __user *ubuf)
929{
930 unsigned int *data = &task_thread_info(target)->system_call;
931 return user_regset_copyin(&pos, &count, &kbuf, &ubuf,
932 data, 0, sizeof(unsigned int));
933}
934
902static const struct user_regset s390_regsets[] = { 935static const struct user_regset s390_regsets[] = {
903 [REGSET_GENERAL] = { 936 [REGSET_GENERAL] = {
904 .core_note_type = NT_PRSTATUS, 937 .core_note_type = NT_PRSTATUS,
@@ -925,6 +958,14 @@ static const struct user_regset s390_regsets[] = {
925 .get = s390_last_break_get, 958 .get = s390_last_break_get,
926 }, 959 },
927#endif 960#endif
961 [REGSET_SYSTEM_CALL] = {
962 .core_note_type = NT_S390_SYSTEM_CALL,
963 .n = 1,
964 .size = sizeof(unsigned int),
965 .align = sizeof(unsigned int),
966 .get = s390_system_call_get,
967 .set = s390_system_call_set,
968 },
928}; 969};
929 970
930static const struct user_regset_view user_s390_view = { 971static const struct user_regset_view user_s390_view = {
@@ -1104,6 +1145,14 @@ static const struct user_regset s390_compat_regsets[] = {
1104 .align = sizeof(long), 1145 .align = sizeof(long),
1105 .get = s390_compat_last_break_get, 1146 .get = s390_compat_last_break_get,
1106 }, 1147 },
1148 [REGSET_SYSTEM_CALL] = {
1149 .core_note_type = NT_S390_SYSTEM_CALL,
1150 .n = 1,
1151 .size = sizeof(compat_uint_t),
1152 .align = sizeof(compat_uint_t),
1153 .get = s390_system_call_get,
1154 .set = s390_system_call_set,
1155 },
1107 [REGSET_GENERAL_EXTENDED] = { 1156 [REGSET_GENERAL_EXTENDED] = {
1108 .core_note_type = NT_S390_HIGH_GPRS, 1157 .core_note_type = NT_S390_HIGH_GPRS,
1109 .n = sizeof(s390_compat_regs_high) / sizeof(compat_long_t), 1158 .n = sizeof(s390_compat_regs_high) / sizeof(compat_long_t),