diff options
-rw-r--r-- | arch/s390/Kconfig | 1 | ||||
-rw-r--r-- | arch/s390/include/asm/ptrace.h | 1 | ||||
-rw-r--r-- | arch/s390/include/asm/syscall.h | 80 | ||||
-rw-r--r-- | arch/s390/include/asm/thread_info.h | 2 | ||||
-rw-r--r-- | arch/s390/kernel/entry.S | 50 | ||||
-rw-r--r-- | arch/s390/kernel/entry64.S | 42 | ||||
-rw-r--r-- | arch/s390/kernel/ptrace.c | 61 | ||||
-rw-r--r-- | arch/s390/kernel/signal.c | 13 |
8 files changed, 202 insertions, 48 deletions
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index 8d41908e2513..4c03049e7db9 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig | |||
@@ -74,6 +74,7 @@ config S390 | |||
74 | select HAVE_KPROBES | 74 | select HAVE_KPROBES |
75 | select HAVE_KRETPROBES | 75 | select HAVE_KRETPROBES |
76 | select HAVE_KVM if 64BIT | 76 | select HAVE_KVM if 64BIT |
77 | select HAVE_ARCH_TRACEHOOK | ||
77 | 78 | ||
78 | source "init/Kconfig" | 79 | source "init/Kconfig" |
79 | 80 | ||
diff --git a/arch/s390/include/asm/ptrace.h b/arch/s390/include/asm/ptrace.h index af2c9ac28a07..a7226f8143fb 100644 --- a/arch/s390/include/asm/ptrace.h +++ b/arch/s390/include/asm/ptrace.h | |||
@@ -490,6 +490,7 @@ extern void user_disable_single_step(struct task_struct *); | |||
490 | 490 | ||
491 | #define user_mode(regs) (((regs)->psw.mask & PSW_MASK_PSTATE) != 0) | 491 | #define user_mode(regs) (((regs)->psw.mask & PSW_MASK_PSTATE) != 0) |
492 | #define instruction_pointer(regs) ((regs)->psw.addr & PSW_ADDR_INSN) | 492 | #define instruction_pointer(regs) ((regs)->psw.addr & PSW_ADDR_INSN) |
493 | #define user_stack_pointer(regs)((regs)->gprs[15]) | ||
493 | #define regs_return_value(regs)((regs)->gprs[2]) | 494 | #define regs_return_value(regs)((regs)->gprs[2]) |
494 | #define profile_pc(regs) instruction_pointer(regs) | 495 | #define profile_pc(regs) instruction_pointer(regs) |
495 | extern void show_regs(struct pt_regs * regs); | 496 | extern void show_regs(struct pt_regs * regs); |
diff --git a/arch/s390/include/asm/syscall.h b/arch/s390/include/asm/syscall.h new file mode 100644 index 000000000000..6e623971fbb9 --- /dev/null +++ b/arch/s390/include/asm/syscall.h | |||
@@ -0,0 +1,80 @@ | |||
1 | /* | ||
2 | * Access to user system call parameters and results | ||
3 | * | ||
4 | * Copyright IBM Corp. 2008 | ||
5 | * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com) | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License (version 2 only) | ||
9 | * as published by the Free Software Foundation. | ||
10 | */ | ||
11 | |||
12 | #ifndef _ASM_SYSCALL_H | ||
13 | #define _ASM_SYSCALL_H 1 | ||
14 | |||
15 | #include <asm/ptrace.h> | ||
16 | |||
17 | static inline long syscall_get_nr(struct task_struct *task, | ||
18 | struct pt_regs *regs) | ||
19 | { | ||
20 | if (regs->trap != __LC_SVC_OLD_PSW) | ||
21 | return -1; | ||
22 | return regs->gprs[2]; | ||
23 | } | ||
24 | |||
25 | static inline void syscall_rollback(struct task_struct *task, | ||
26 | struct pt_regs *regs) | ||
27 | { | ||
28 | regs->gprs[2] = regs->orig_gpr2; | ||
29 | } | ||
30 | |||
31 | static inline long syscall_get_error(struct task_struct *task, | ||
32 | struct pt_regs *regs) | ||
33 | { | ||
34 | return (regs->gprs[2] >= -4096UL) ? -regs->gprs[2] : 0; | ||
35 | } | ||
36 | |||
37 | static inline long syscall_get_return_value(struct task_struct *task, | ||
38 | struct pt_regs *regs) | ||
39 | { | ||
40 | return regs->gprs[2]; | ||
41 | } | ||
42 | |||
43 | static inline void syscall_set_return_value(struct task_struct *task, | ||
44 | struct pt_regs *regs, | ||
45 | int error, long val) | ||
46 | { | ||
47 | regs->gprs[2] = error ? -error : val; | ||
48 | } | ||
49 | |||
50 | static inline void syscall_get_arguments(struct task_struct *task, | ||
51 | struct pt_regs *regs, | ||
52 | unsigned int i, unsigned int n, | ||
53 | unsigned long *args) | ||
54 | { | ||
55 | BUG_ON(i + n > 6); | ||
56 | #ifdef CONFIG_COMPAT | ||
57 | if (test_tsk_thread_flag(task, TIF_31BIT)) { | ||
58 | if (i + n == 6) | ||
59 | args[--n] = (u32) regs->args[0]; | ||
60 | while (n-- > 0) | ||
61 | args[n] = (u32) regs->gprs[2 + i + n]; | ||
62 | } | ||
63 | #endif | ||
64 | if (i + n == 6) | ||
65 | args[--n] = regs->args[0]; | ||
66 | memcpy(args, ®s->gprs[2 + i], n * sizeof(args[0])); | ||
67 | } | ||
68 | |||
69 | static inline void syscall_set_arguments(struct task_struct *task, | ||
70 | struct pt_regs *regs, | ||
71 | unsigned int i, unsigned int n, | ||
72 | const unsigned long *args) | ||
73 | { | ||
74 | BUG_ON(i + n > 6); | ||
75 | if (i + n == 6) | ||
76 | regs->args[0] = args[--n]; | ||
77 | memcpy(®s->gprs[2 + i], args, n * sizeof(args[0])); | ||
78 | } | ||
79 | |||
80 | #endif /* _ASM_SYSCALL_H */ | ||
diff --git a/arch/s390/include/asm/thread_info.h b/arch/s390/include/asm/thread_info.h index 91a8f93ad355..ea40a9d690fc 100644 --- a/arch/s390/include/asm/thread_info.h +++ b/arch/s390/include/asm/thread_info.h | |||
@@ -86,6 +86,7 @@ static inline struct thread_info *current_thread_info(void) | |||
86 | * thread information flags bit numbers | 86 | * thread information flags bit numbers |
87 | */ | 87 | */ |
88 | #define TIF_SYSCALL_TRACE 0 /* syscall trace active */ | 88 | #define TIF_SYSCALL_TRACE 0 /* syscall trace active */ |
89 | #define TIF_NOTIFY_RESUME 1 /* callback before returning to user */ | ||
89 | #define TIF_SIGPENDING 2 /* signal pending */ | 90 | #define TIF_SIGPENDING 2 /* signal pending */ |
90 | #define TIF_NEED_RESCHED 3 /* rescheduling necessary */ | 91 | #define TIF_NEED_RESCHED 3 /* rescheduling necessary */ |
91 | #define TIF_RESTART_SVC 4 /* restart svc with new svc number */ | 92 | #define TIF_RESTART_SVC 4 /* restart svc with new svc number */ |
@@ -100,6 +101,7 @@ static inline struct thread_info *current_thread_info(void) | |||
100 | #define TIF_RESTORE_SIGMASK 20 /* restore signal mask in do_signal() */ | 101 | #define TIF_RESTORE_SIGMASK 20 /* restore signal mask in do_signal() */ |
101 | 102 | ||
102 | #define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE) | 103 | #define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE) |
104 | #define _TIF_NOTIFY_RESUME (1<<TIF_NOTIFY_RESUME) | ||
103 | #define _TIF_RESTORE_SIGMASK (1<<TIF_RESTORE_SIGMASK) | 105 | #define _TIF_RESTORE_SIGMASK (1<<TIF_RESTORE_SIGMASK) |
104 | #define _TIF_SIGPENDING (1<<TIF_SIGPENDING) | 106 | #define _TIF_SIGPENDING (1<<TIF_SIGPENDING) |
105 | #define _TIF_NEED_RESCHED (1<<TIF_NEED_RESCHED) | 107 | #define _TIF_NEED_RESCHED (1<<TIF_NEED_RESCHED) |
diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S index 708cf9cf9a35..ed500ef799b7 100644 --- a/arch/s390/kernel/entry.S +++ b/arch/s390/kernel/entry.S | |||
@@ -49,9 +49,9 @@ SP_ILC = STACK_FRAME_OVERHEAD + __PT_ILC | |||
49 | SP_TRAP = STACK_FRAME_OVERHEAD + __PT_TRAP | 49 | SP_TRAP = STACK_FRAME_OVERHEAD + __PT_TRAP |
50 | SP_SIZE = STACK_FRAME_OVERHEAD + __PT_SIZE | 50 | SP_SIZE = STACK_FRAME_OVERHEAD + __PT_SIZE |
51 | 51 | ||
52 | _TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | \ | 52 | _TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED | \ |
53 | _TIF_MCCK_PENDING | _TIF_RESTART_SVC | _TIF_SINGLE_STEP ) | 53 | _TIF_MCCK_PENDING | _TIF_RESTART_SVC | _TIF_SINGLE_STEP ) |
54 | _TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | \ | 54 | _TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED | \ |
55 | _TIF_MCCK_PENDING) | 55 | _TIF_MCCK_PENDING) |
56 | 56 | ||
57 | STACK_SHIFT = PAGE_SHIFT + THREAD_ORDER | 57 | STACK_SHIFT = PAGE_SHIFT + THREAD_ORDER |
@@ -318,6 +318,8 @@ sysc_work: | |||
318 | bo BASED(sysc_reschedule) | 318 | bo BASED(sysc_reschedule) |
319 | tm __TI_flags+3(%r9),_TIF_SIGPENDING | 319 | tm __TI_flags+3(%r9),_TIF_SIGPENDING |
320 | bnz BASED(sysc_sigpending) | 320 | bnz BASED(sysc_sigpending) |
321 | tm __TI_flags+3(%r9),_TIF_NOTIFY_RESUME | ||
322 | bnz BASED(sysc_notify_resume) | ||
321 | tm __TI_flags+3(%r9),_TIF_RESTART_SVC | 323 | tm __TI_flags+3(%r9),_TIF_RESTART_SVC |
322 | bo BASED(sysc_restart) | 324 | bo BASED(sysc_restart) |
323 | tm __TI_flags+3(%r9),_TIF_SINGLE_STEP | 325 | tm __TI_flags+3(%r9),_TIF_SINGLE_STEP |
@@ -356,6 +358,16 @@ sysc_sigpending: | |||
356 | b BASED(sysc_work_loop) | 358 | b BASED(sysc_work_loop) |
357 | 359 | ||
358 | # | 360 | # |
361 | # _TIF_NOTIFY_RESUME is set, call do_notify_resume | ||
362 | # | ||
363 | sysc_notify_resume: | ||
364 | la %r2,SP_PTREGS(%r15) # load pt_regs | ||
365 | l %r1,BASED(.Ldo_notify_resume) | ||
366 | la %r14,BASED(sysc_work_loop) | ||
367 | br %r1 # call do_notify_resume | ||
368 | |||
369 | |||
370 | # | ||
359 | # _TIF_RESTART_SVC is set, set up registers and restart svc | 371 | # _TIF_RESTART_SVC is set, set up registers and restart svc |
360 | # | 372 | # |
361 | sysc_restart: | 373 | sysc_restart: |
@@ -378,20 +390,21 @@ sysc_singlestep: | |||
378 | br %r1 # branch to do_single_step | 390 | br %r1 # branch to do_single_step |
379 | 391 | ||
380 | # | 392 | # |
381 | # call trace before and after sys_call | 393 | # call tracehook_report_syscall_entry/tracehook_report_syscall_exit before |
394 | # and after the system call | ||
382 | # | 395 | # |
383 | sysc_tracesys: | 396 | sysc_tracesys: |
384 | l %r1,BASED(.Ltrace) | 397 | l %r1,BASED(.Ltrace_entry) |
385 | la %r2,SP_PTREGS(%r15) # load pt_regs | 398 | la %r2,SP_PTREGS(%r15) # load pt_regs |
386 | la %r3,0 | 399 | la %r3,0 |
387 | srl %r7,2 | 400 | srl %r7,2 |
388 | st %r7,SP_R2(%r15) | 401 | st %r7,SP_R2(%r15) |
389 | basr %r14,%r1 | 402 | basr %r14,%r1 |
390 | clc SP_R2(4,%r15),BASED(.Lnr_syscalls) | 403 | cl %r2,BASED(.Lnr_syscalls) |
391 | bnl BASED(sysc_tracenogo) | 404 | bnl BASED(sysc_tracenogo) |
392 | l %r8,BASED(.Lsysc_table) | 405 | l %r8,BASED(.Lsysc_table) |
393 | l %r7,SP_R2(%r15) # strace might have changed the | 406 | lr %r7,%r2 |
394 | sll %r7,2 # system call | 407 | sll %r7,2 # *4 |
395 | l %r8,0(%r7,%r8) | 408 | l %r8,0(%r7,%r8) |
396 | sysc_tracego: | 409 | sysc_tracego: |
397 | lm %r3,%r6,SP_R3(%r15) | 410 | lm %r3,%r6,SP_R3(%r15) |
@@ -401,9 +414,8 @@ sysc_tracego: | |||
401 | sysc_tracenogo: | 414 | sysc_tracenogo: |
402 | tm __TI_flags+3(%r9),(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT) | 415 | tm __TI_flags+3(%r9),(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT) |
403 | bz BASED(sysc_return) | 416 | bz BASED(sysc_return) |
404 | l %r1,BASED(.Ltrace) | 417 | l %r1,BASED(.Ltrace_exit) |
405 | la %r2,SP_PTREGS(%r15) # load pt_regs | 418 | la %r2,SP_PTREGS(%r15) # load pt_regs |
406 | la %r3,1 | ||
407 | la %r14,BASED(sysc_return) | 419 | la %r14,BASED(sysc_return) |
408 | br %r1 | 420 | br %r1 |
409 | 421 | ||
@@ -666,6 +678,8 @@ io_work_loop: | |||
666 | bo BASED(io_reschedule) | 678 | bo BASED(io_reschedule) |
667 | tm __TI_flags+3(%r9),_TIF_SIGPENDING | 679 | tm __TI_flags+3(%r9),_TIF_SIGPENDING |
668 | bnz BASED(io_sigpending) | 680 | bnz BASED(io_sigpending) |
681 | tm __TI_flags+3(%r9),_TIF_NOTIFY_RESUME | ||
682 | bnz BASED(io_notify_resume) | ||
669 | b BASED(io_restore) | 683 | b BASED(io_restore) |
670 | io_work_done: | 684 | io_work_done: |
671 | 685 | ||
@@ -704,6 +718,19 @@ io_sigpending: | |||
704 | TRACE_IRQS_OFF | 718 | TRACE_IRQS_OFF |
705 | b BASED(io_work_loop) | 719 | b BASED(io_work_loop) |
706 | 720 | ||
721 | # | ||
722 | # _TIF_SIGPENDING is set, call do_signal | ||
723 | # | ||
724 | io_notify_resume: | ||
725 | TRACE_IRQS_ON | ||
726 | stosm __SF_EMPTY(%r15),0x03 # reenable interrupts | ||
727 | la %r2,SP_PTREGS(%r15) # load pt_regs | ||
728 | l %r1,BASED(.Ldo_notify_resume) | ||
729 | basr %r14,%r1 # call do_signal | ||
730 | stnsm __SF_EMPTY(%r15),0xfc # disable I/O and ext. interrupts | ||
731 | TRACE_IRQS_OFF | ||
732 | b BASED(io_work_loop) | ||
733 | |||
707 | /* | 734 | /* |
708 | * External interrupt handler routine | 735 | * External interrupt handler routine |
709 | */ | 736 | */ |
@@ -1070,6 +1097,8 @@ cleanup_io_leave_insn: | |||
1070 | .Ldo_IRQ: .long do_IRQ | 1097 | .Ldo_IRQ: .long do_IRQ |
1071 | .Ldo_extint: .long do_extint | 1098 | .Ldo_extint: .long do_extint |
1072 | .Ldo_signal: .long do_signal | 1099 | .Ldo_signal: .long do_signal |
1100 | .Ldo_notify_resume: | ||
1101 | .long do_notify_resume | ||
1073 | .Lhandle_per: .long do_single_step | 1102 | .Lhandle_per: .long do_single_step |
1074 | .Ldo_execve: .long do_execve | 1103 | .Ldo_execve: .long do_execve |
1075 | .Lexecve_tail: .long execve_tail | 1104 | .Lexecve_tail: .long execve_tail |
@@ -1079,7 +1108,8 @@ cleanup_io_leave_insn: | |||
1079 | .Lpreempt_schedule_irq: | 1108 | .Lpreempt_schedule_irq: |
1080 | .long preempt_schedule_irq | 1109 | .long preempt_schedule_irq |
1081 | #endif | 1110 | #endif |
1082 | .Ltrace: .long syscall_trace | 1111 | .Ltrace_entry: .long do_syscall_trace_enter |
1112 | .Ltrace_exit: .long do_syscall_trace_exit | ||
1083 | .Lschedtail: .long schedule_tail | 1113 | .Lschedtail: .long schedule_tail |
1084 | .Lsysc_table: .long sys_call_table | 1114 | .Lsysc_table: .long sys_call_table |
1085 | #ifdef CONFIG_TRACE_IRQFLAGS | 1115 | #ifdef CONFIG_TRACE_IRQFLAGS |
diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S index fee10177dbfc..d7ce150453f2 100644 --- a/arch/s390/kernel/entry64.S +++ b/arch/s390/kernel/entry64.S | |||
@@ -52,9 +52,9 @@ SP_SIZE = STACK_FRAME_OVERHEAD + __PT_SIZE | |||
52 | STACK_SHIFT = PAGE_SHIFT + THREAD_ORDER | 52 | STACK_SHIFT = PAGE_SHIFT + THREAD_ORDER |
53 | STACK_SIZE = 1 << STACK_SHIFT | 53 | STACK_SIZE = 1 << STACK_SHIFT |
54 | 54 | ||
55 | _TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | \ | 55 | _TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED | \ |
56 | _TIF_MCCK_PENDING | _TIF_RESTART_SVC | _TIF_SINGLE_STEP ) | 56 | _TIF_MCCK_PENDING | _TIF_RESTART_SVC | _TIF_SINGLE_STEP ) |
57 | _TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | \ | 57 | _TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED | \ |
58 | _TIF_MCCK_PENDING) | 58 | _TIF_MCCK_PENDING) |
59 | 59 | ||
60 | #define BASED(name) name-system_call(%r13) | 60 | #define BASED(name) name-system_call(%r13) |
@@ -310,6 +310,8 @@ sysc_work: | |||
310 | jo sysc_reschedule | 310 | jo sysc_reschedule |
311 | tm __TI_flags+7(%r9),_TIF_SIGPENDING | 311 | tm __TI_flags+7(%r9),_TIF_SIGPENDING |
312 | jnz sysc_sigpending | 312 | jnz sysc_sigpending |
313 | tm __TI_flags+7(%r9),_TIF_NOTIFY_RESUME | ||
314 | jnz sysc_notify_resume | ||
313 | tm __TI_flags+7(%r9),_TIF_RESTART_SVC | 315 | tm __TI_flags+7(%r9),_TIF_RESTART_SVC |
314 | jo sysc_restart | 316 | jo sysc_restart |
315 | tm __TI_flags+7(%r9),_TIF_SINGLE_STEP | 317 | tm __TI_flags+7(%r9),_TIF_SINGLE_STEP |
@@ -345,6 +347,14 @@ sysc_sigpending: | |||
345 | j sysc_work_loop | 347 | j sysc_work_loop |
346 | 348 | ||
347 | # | 349 | # |
350 | # _TIF_NOTIFY_RESUME is set, call do_notify_resume | ||
351 | # | ||
352 | sysc_notify_resume: | ||
353 | la %r2,SP_PTREGS(%r15) # load pt_regs | ||
354 | larl %r14,sysc_work_loop | ||
355 | jg do_notify_resume # call do_notify_resume | ||
356 | |||
357 | # | ||
348 | # _TIF_RESTART_SVC is set, set up registers and restart svc | 358 | # _TIF_RESTART_SVC is set, set up registers and restart svc |
349 | # | 359 | # |
350 | sysc_restart: | 360 | sysc_restart: |
@@ -367,20 +377,19 @@ sysc_singlestep: | |||
367 | jg do_single_step # branch to do_sigtrap | 377 | jg do_single_step # branch to do_sigtrap |
368 | 378 | ||
369 | # | 379 | # |
370 | # call syscall_trace before and after system call | 380 | # call tracehook_report_syscall_entry/tracehook_report_syscall_exit before |
371 | # special linkage: %r12 contains the return address for trace_svc | 381 | # and after the system call |
372 | # | 382 | # |
373 | sysc_tracesys: | 383 | sysc_tracesys: |
374 | la %r2,SP_PTREGS(%r15) # load pt_regs | 384 | la %r2,SP_PTREGS(%r15) # load pt_regs |
375 | la %r3,0 | 385 | la %r3,0 |
376 | srl %r7,2 | 386 | srl %r7,2 |
377 | stg %r7,SP_R2(%r15) | 387 | stg %r7,SP_R2(%r15) |
378 | brasl %r14,syscall_trace | 388 | brasl %r14,do_syscall_trace_enter |
379 | lghi %r0,NR_syscalls | 389 | lghi %r0,NR_syscalls |
380 | clg %r0,SP_R2(%r15) | 390 | clgr %r0,%r2 |
381 | jnh sysc_tracenogo | 391 | jnh sysc_tracenogo |
382 | lg %r7,SP_R2(%r15) # strace might have changed the | 392 | slag %r7,%r2,2 # *4 |
383 | sll %r7,2 # system call | ||
384 | lgf %r8,0(%r7,%r10) | 393 | lgf %r8,0(%r7,%r10) |
385 | sysc_tracego: | 394 | sysc_tracego: |
386 | lmg %r3,%r6,SP_R3(%r15) | 395 | lmg %r3,%r6,SP_R3(%r15) |
@@ -391,9 +400,8 @@ sysc_tracenogo: | |||
391 | tm __TI_flags+7(%r9),(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT) | 400 | tm __TI_flags+7(%r9),(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT) |
392 | jz sysc_return | 401 | jz sysc_return |
393 | la %r2,SP_PTREGS(%r15) # load pt_regs | 402 | la %r2,SP_PTREGS(%r15) # load pt_regs |
394 | la %r3,1 | ||
395 | larl %r14,sysc_return # return point is sysc_return | 403 | larl %r14,sysc_return # return point is sysc_return |
396 | jg syscall_trace | 404 | jg do_syscall_trace_exit |
397 | 405 | ||
398 | # | 406 | # |
399 | # a new process exits the kernel with ret_from_fork | 407 | # a new process exits the kernel with ret_from_fork |
@@ -672,6 +680,8 @@ io_work_loop: | |||
672 | jo io_reschedule | 680 | jo io_reschedule |
673 | tm __TI_flags+7(%r9),_TIF_SIGPENDING | 681 | tm __TI_flags+7(%r9),_TIF_SIGPENDING |
674 | jnz io_sigpending | 682 | jnz io_sigpending |
683 | tm __TI_flags+7(%r9),_TIF_NOTIFY_RESUME | ||
684 | jnz io_notify_resume | ||
675 | j io_restore | 685 | j io_restore |
676 | io_work_done: | 686 | io_work_done: |
677 | 687 | ||
@@ -712,6 +722,18 @@ io_sigpending: | |||
712 | TRACE_IRQS_OFF | 722 | TRACE_IRQS_OFF |
713 | j io_work_loop | 723 | j io_work_loop |
714 | 724 | ||
725 | # | ||
726 | # _TIF_NOTIFY_RESUME or is set, call do_notify_resume | ||
727 | # | ||
728 | io_notify_resume: | ||
729 | TRACE_IRQS_ON | ||
730 | stosm __SF_EMPTY(%r15),0x03 # reenable interrupts | ||
731 | la %r2,SP_PTREGS(%r15) # load pt_regs | ||
732 | brasl %r14,do_notify_resume # call do_notify_resume | ||
733 | stnsm __SF_EMPTY(%r15),0xfc # disable I/O and ext. interrupts | ||
734 | TRACE_IRQS_OFF | ||
735 | j io_work_loop | ||
736 | |||
715 | /* | 737 | /* |
716 | * External interrupt handler routine | 738 | * External interrupt handler routine |
717 | */ | 739 | */ |
diff --git a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c index c8b08289eb87..1f31be1ecc4b 100644 --- a/arch/s390/kernel/ptrace.c +++ b/arch/s390/kernel/ptrace.c | |||
@@ -35,6 +35,7 @@ | |||
35 | #include <linux/signal.h> | 35 | #include <linux/signal.h> |
36 | #include <linux/elf.h> | 36 | #include <linux/elf.h> |
37 | #include <linux/regset.h> | 37 | #include <linux/regset.h> |
38 | #include <linux/tracehook.h> | ||
38 | 39 | ||
39 | #include <asm/segment.h> | 40 | #include <asm/segment.h> |
40 | #include <asm/page.h> | 41 | #include <asm/page.h> |
@@ -639,40 +640,44 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request, | |||
639 | } | 640 | } |
640 | #endif | 641 | #endif |
641 | 642 | ||
642 | asmlinkage void | 643 | asmlinkage long do_syscall_trace_enter(struct pt_regs *regs) |
643 | syscall_trace(struct pt_regs *regs, int entryexit) | ||
644 | { | 644 | { |
645 | if (unlikely(current->audit_context) && entryexit) | 645 | long ret; |
646 | audit_syscall_exit(AUDITSC_RESULT(regs->gprs[2]), regs->gprs[2]); | ||
647 | |||
648 | if (!test_thread_flag(TIF_SYSCALL_TRACE)) | ||
649 | goto out; | ||
650 | if (!(current->ptrace & PT_PTRACED)) | ||
651 | goto out; | ||
652 | ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) | ||
653 | ? 0x80 : 0)); | ||
654 | 646 | ||
655 | /* | 647 | /* |
656 | * If the debuffer has set an invalid system call number, | 648 | * The sysc_tracesys code in entry.S stored the system |
657 | * we prepare to skip the system call restart handling. | 649 | * call number to gprs[2]. |
658 | */ | 650 | */ |
659 | if (!entryexit && regs->gprs[2] >= NR_syscalls) | 651 | ret = regs->gprs[2]; |
652 | if (test_thread_flag(TIF_SYSCALL_TRACE) && | ||
653 | (tracehook_report_syscall_entry(regs) || | ||
654 | regs->gprs[2] >= NR_syscalls)) { | ||
655 | /* | ||
656 | * Tracing decided this syscall should not happen or the | ||
657 | * debugger stored an invalid system call number. Skip | ||
658 | * the system call and the system call restart handling. | ||
659 | */ | ||
660 | regs->trap = -1; | 660 | regs->trap = -1; |
661 | 661 | ret = -1; | |
662 | /* | ||
663 | * this isn't the same as continuing with a signal, but it will do | ||
664 | * for normal use. strace only continues with a signal if the | ||
665 | * stopping signal is not SIGTRAP. -brl | ||
666 | */ | ||
667 | if (current->exit_code) { | ||
668 | send_sig(current->exit_code, current, 1); | ||
669 | current->exit_code = 0; | ||
670 | } | 662 | } |
671 | out: | 663 | |
672 | if (unlikely(current->audit_context) && !entryexit) | 664 | if (unlikely(current->audit_context)) |
673 | audit_syscall_entry(test_thread_flag(TIF_31BIT)?AUDIT_ARCH_S390:AUDIT_ARCH_S390X, | 665 | audit_syscall_entry(test_thread_flag(TIF_31BIT) ? |
674 | regs->gprs[2], regs->orig_gpr2, regs->gprs[3], | 666 | AUDIT_ARCH_S390 : AUDIT_ARCH_S390X, |
675 | regs->gprs[4], regs->gprs[5]); | 667 | regs->gprs[2], regs->orig_gpr2, |
668 | regs->gprs[3], regs->gprs[4], | ||
669 | regs->gprs[5]); | ||
670 | return ret; | ||
671 | } | ||
672 | |||
673 | asmlinkage void do_syscall_trace_exit(struct pt_regs *regs) | ||
674 | { | ||
675 | if (unlikely(current->audit_context)) | ||
676 | audit_syscall_exit(AUDITSC_RESULT(regs->gprs[2]), | ||
677 | regs->gprs[2]); | ||
678 | |||
679 | if (test_thread_flag(TIF_SYSCALL_TRACE)) | ||
680 | tracehook_report_syscall_exit(regs, 0); | ||
676 | } | 681 | } |
677 | 682 | ||
678 | /* | 683 | /* |
diff --git a/arch/s390/kernel/signal.c b/arch/s390/kernel/signal.c index b97682040215..4f7fc3059a8e 100644 --- a/arch/s390/kernel/signal.c +++ b/arch/s390/kernel/signal.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <linux/tty.h> | 24 | #include <linux/tty.h> |
25 | #include <linux/personality.h> | 25 | #include <linux/personality.h> |
26 | #include <linux/binfmts.h> | 26 | #include <linux/binfmts.h> |
27 | #include <linux/tracehook.h> | ||
27 | #include <asm/ucontext.h> | 28 | #include <asm/ucontext.h> |
28 | #include <asm/uaccess.h> | 29 | #include <asm/uaccess.h> |
29 | #include <asm/lowcore.h> | 30 | #include <asm/lowcore.h> |
@@ -507,6 +508,12 @@ void do_signal(struct pt_regs *regs) | |||
507 | */ | 508 | */ |
508 | if (current->thread.per_info.single_step) | 509 | if (current->thread.per_info.single_step) |
509 | set_thread_flag(TIF_SINGLE_STEP); | 510 | set_thread_flag(TIF_SINGLE_STEP); |
511 | |||
512 | /* | ||
513 | * Let tracing know that we've done the handler setup. | ||
514 | */ | ||
515 | tracehook_signal_handler(signr, &info, &ka, regs, | ||
516 | test_thread_flag(TIF_SINGLE_STEP)); | ||
510 | } | 517 | } |
511 | return; | 518 | return; |
512 | } | 519 | } |
@@ -526,3 +533,9 @@ void do_signal(struct pt_regs *regs) | |||
526 | set_thread_flag(TIF_RESTART_SVC); | 533 | set_thread_flag(TIF_RESTART_SVC); |
527 | } | 534 | } |
528 | } | 535 | } |
536 | |||
537 | void do_notify_resume(struct pt_regs *regs) | ||
538 | { | ||
539 | clear_thread_flag(TIF_NOTIFY_RESUME); | ||
540 | tracehook_notify_resume(regs); | ||
541 | } | ||