]> git.ipfire.org Git - people/teissler/ipfire-2.x.git/blob - src/patches/suse-2.6.27.25/patches.trace/s390-utrace-enablement.patch
Updated xen patches taken from suse.
[people/teissler/ipfire-2.x.git] / src / patches / suse-2.6.27.25 / patches.trace / s390-utrace-enablement.patch
1 Subject: Backport s390 kernel components required for utrace enablement
2
3 From: Ananth N. Mavinakayanahalli <ananth@in.ibm.com>
4
5 References: bnc#442709
6
7 Acked-by: John Jolly <jjolly@novell.com>
8 ---
9 arch/s390/Kconfig | 1
10 arch/s390/include/asm/ptrace.h | 1
11 arch/s390/include/asm/syscall.h | 80 ++++++++++++++++++++++++++++++++++++
12 arch/s390/include/asm/thread_info.h | 2
13 arch/s390/kernel/entry.S | 50 ++++++++++++++++++----
14 arch/s390/kernel/entry64.S | 42 ++++++++++++++----
15 arch/s390/kernel/ptrace.c | 75 +++++++++++++++++++++------------
16 arch/s390/kernel/signal.c | 13 +++++
17 8 files changed, 216 insertions(+), 48 deletions(-)
18
19 --- a/arch/s390/include/asm/ptrace.h
20 +++ b/arch/s390/include/asm/ptrace.h
21 @@ -490,6 +490,7 @@ extern void user_disable_single_step(str
22
23 #define user_mode(regs) (((regs)->psw.mask & PSW_MASK_PSTATE) != 0)
24 #define instruction_pointer(regs) ((regs)->psw.addr & PSW_ADDR_INSN)
25 +#define user_stack_pointer(regs)((regs)->gprs[15])
26 #define regs_return_value(regs)((regs)->gprs[2])
27 #define profile_pc(regs) instruction_pointer(regs)
28 extern void show_regs(struct pt_regs * regs);
29 --- /dev/null
30 +++ b/arch/s390/include/asm/syscall.h
31 @@ -0,0 +1,80 @@
32 +/*
33 + * Access to user system call parameters and results
34 + *
35 + * Copyright IBM Corp. 2008
36 + * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com)
37 + *
38 + * This program is free software; you can redistribute it and/or modify
39 + * it under the terms of the GNU General Public License (version 2 only)
40 + * as published by the Free Software Foundation.
41 + */
42 +
43 +#ifndef _ASM_SYSCALL_H
44 +#define _ASM_SYSCALL_H 1
45 +
46 +#include <asm/ptrace.h>
47 +
48 +static inline long syscall_get_nr(struct task_struct *task,
49 + struct pt_regs *regs)
50 +{
51 + if (regs->trap != __LC_SVC_OLD_PSW)
52 + return -1;
53 + return regs->gprs[2];
54 +}
55 +
56 +static inline void syscall_rollback(struct task_struct *task,
57 + struct pt_regs *regs)
58 +{
59 + regs->gprs[2] = regs->orig_gpr2;
60 +}
61 +
62 +static inline long syscall_get_error(struct task_struct *task,
63 + struct pt_regs *regs)
64 +{
65 + return (regs->gprs[2] >= -4096UL) ? -regs->gprs[2] : 0;
66 +}
67 +
68 +static inline long syscall_get_return_value(struct task_struct *task,
69 + struct pt_regs *regs)
70 +{
71 + return regs->gprs[2];
72 +}
73 +
74 +static inline void syscall_set_return_value(struct task_struct *task,
75 + struct pt_regs *regs,
76 + int error, long val)
77 +{
78 + regs->gprs[2] = error ? -error : val;
79 +}
80 +
81 +static inline void syscall_get_arguments(struct task_struct *task,
82 + struct pt_regs *regs,
83 + unsigned int i, unsigned int n,
84 + unsigned long *args)
85 +{
86 + BUG_ON(i + n > 6);
87 +#ifdef CONFIG_COMPAT
88 + if (test_tsk_thread_flag(task, TIF_31BIT)) {
89 + if (i + n == 6)
90 + args[--n] = (u32) regs->args[0];
91 + while (n-- > 0)
92 + args[n] = (u32) regs->gprs[2 + i + n];
93 + }
94 +#endif
95 + if (i + n == 6)
96 + args[--n] = regs->args[0];
97 + memcpy(args, &regs->gprs[2 + i], n * sizeof(args[0]));
98 +}
99 +
100 +static inline void syscall_set_arguments(struct task_struct *task,
101 + struct pt_regs *regs,
102 + unsigned int i, unsigned int n,
103 + const unsigned long *args)
104 +{
105 + BUG_ON(i + n > 6);
106 + if (i + n == 6)
107 + regs->args[0] = args[--n];
108 + memcpy(&regs->gprs[2 + i], args, n * sizeof(args[0]));
109 +}
110 +
111 +#endif /* _ASM_SYSCALL_H */
112 --- a/arch/s390/include/asm/thread_info.h
113 +++ b/arch/s390/include/asm/thread_info.h
114 @@ -86,6 +86,7 @@ static inline struct thread_info *curren
115 * thread information flags bit numbers
116 */
117 #define TIF_SYSCALL_TRACE 0 /* syscall trace active */
118 +#define TIF_NOTIFY_RESUME 1 /* callback before returning to user */
119 #define TIF_SIGPENDING 2 /* signal pending */
120 #define TIF_NEED_RESCHED 3 /* rescheduling necessary */
121 #define TIF_RESTART_SVC 4 /* restart svc with new svc number */
122 @@ -101,6 +102,7 @@ static inline struct thread_info *curren
123 #define TIF_FREEZE 21
124
125 #define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE)
126 +#define _TIF_NOTIFY_RESUME (1<<TIF_NOTIFY_RESUME)
127 #define _TIF_RESTORE_SIGMASK (1<<TIF_RESTORE_SIGMASK)
128 #define _TIF_SIGPENDING (1<<TIF_SIGPENDING)
129 #define _TIF_NEED_RESCHED (1<<TIF_NEED_RESCHED)
130 --- a/arch/s390/Kconfig
131 +++ b/arch/s390/Kconfig
132 @@ -76,6 +76,7 @@ config S390
133 select HAVE_KPROBES
134 select HAVE_KRETPROBES
135 select HAVE_KVM if 64BIT
136 + select HAVE_ARCH_TRACEHOOK
137
138 source "init/Kconfig"
139
140 --- a/arch/s390/kernel/entry64.S
141 +++ b/arch/s390/kernel/entry64.S
142 @@ -52,9 +52,9 @@ SP_SIZE = STACK_FRAME_OVERHEAD + __
143 STACK_SHIFT = PAGE_SHIFT + THREAD_ORDER
144 STACK_SIZE = 1 << STACK_SHIFT
145
146 -_TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | \
147 +_TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED | \
148 _TIF_MCCK_PENDING | _TIF_RESTART_SVC | _TIF_SINGLE_STEP )
149 -_TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | \
150 +_TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED | \
151 _TIF_MCCK_PENDING)
152
153 #define BASED(name) name-system_call(%r13)
154 @@ -310,6 +310,8 @@ sysc_work:
155 jo sysc_reschedule
156 tm __TI_flags+7(%r9),_TIF_SIGPENDING
157 jnz sysc_sigpending
158 + tm __TI_flags+7(%r9),_TIF_NOTIFY_RESUME
159 + jnz sysc_notify_resume
160 tm __TI_flags+7(%r9),_TIF_RESTART_SVC
161 jo sysc_restart
162 tm __TI_flags+7(%r9),_TIF_SINGLE_STEP
163 @@ -345,6 +347,14 @@ sysc_sigpending:
164 j sysc_work_loop
165
166 #
167 +# _TIF_NOTIFY_RESUME is set, call do_notify_resume
168 +#
169 +sysc_notify_resume:
170 + la %r2,SP_PTREGS(%r15) # load pt_regs
171 + larl %r14,sysc_work_loop
172 + jg do_notify_resume # call do_notify_resume
173 +
174 +#
175 # _TIF_RESTART_SVC is set, set up registers and restart svc
176 #
177 sysc_restart:
178 @@ -367,20 +377,19 @@ sysc_singlestep:
179 jg do_single_step # branch to do_sigtrap
180
181 #
182 -# call syscall_trace before and after system call
183 -# special linkage: %r12 contains the return address for trace_svc
184 +# call tracehook_report_syscall_entry/tracehook_report_syscall_exit before
185 +# and after the system call
186 #
187 sysc_tracesys:
188 la %r2,SP_PTREGS(%r15) # load pt_regs
189 la %r3,0
190 srl %r7,2
191 stg %r7,SP_R2(%r15)
192 - brasl %r14,syscall_trace
193 + brasl %r14,do_syscall_trace_enter
194 lghi %r0,NR_syscalls
195 - clg %r0,SP_R2(%r15)
196 + clgr %r0,%r2
197 jnh sysc_tracenogo
198 - lg %r7,SP_R2(%r15) # strace might have changed the
199 - sll %r7,2 # system call
200 + slag %r7,%r2,2 # *4
201 lgf %r8,0(%r7,%r10)
202 sysc_tracego:
203 lmg %r3,%r6,SP_R3(%r15)
204 @@ -391,9 +400,8 @@ sysc_tracenogo:
205 tm __TI_flags+7(%r9),(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT)
206 jz sysc_return
207 la %r2,SP_PTREGS(%r15) # load pt_regs
208 - la %r3,1
209 larl %r14,sysc_return # return point is sysc_return
210 - jg syscall_trace
211 + jg do_syscall_trace_exit
212
213 #
214 # a new process exits the kernel with ret_from_fork
215 @@ -672,6 +680,8 @@ io_work_loop:
216 jo io_reschedule
217 tm __TI_flags+7(%r9),_TIF_SIGPENDING
218 jnz io_sigpending
219 + tm __TI_flags+7(%r9),_TIF_NOTIFY_RESUME
220 + jnz io_notify_resume
221 j io_restore
222 io_work_done:
223
224 @@ -712,6 +722,18 @@ io_sigpending:
225 TRACE_IRQS_OFF
226 j io_work_loop
227
228 +#
229 +# _TIF_NOTIFY_RESUME or is set, call do_notify_resume
230 +#
231 +io_notify_resume:
232 + TRACE_IRQS_ON
233 + stosm __SF_EMPTY(%r15),0x03 # reenable interrupts
234 + la %r2,SP_PTREGS(%r15) # load pt_regs
235 + brasl %r14,do_notify_resume # call do_notify_resume
236 + stnsm __SF_EMPTY(%r15),0xfc # disable I/O and ext. interrupts
237 + TRACE_IRQS_OFF
238 + j io_work_loop
239 +
240 /*
241 * External interrupt handler routine
242 */
243 --- a/arch/s390/kernel/entry.S
244 +++ b/arch/s390/kernel/entry.S
245 @@ -49,9 +49,9 @@ SP_ILC = STACK_FRAME_OVERHEAD + __P
246 SP_TRAP = STACK_FRAME_OVERHEAD + __PT_TRAP
247 SP_SIZE = STACK_FRAME_OVERHEAD + __PT_SIZE
248
249 -_TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | \
250 +_TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED | \
251 _TIF_MCCK_PENDING | _TIF_RESTART_SVC | _TIF_SINGLE_STEP )
252 -_TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | \
253 +_TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED | \
254 _TIF_MCCK_PENDING)
255
256 STACK_SHIFT = PAGE_SHIFT + THREAD_ORDER
257 @@ -318,6 +318,8 @@ sysc_work:
258 bo BASED(sysc_reschedule)
259 tm __TI_flags+3(%r9),_TIF_SIGPENDING
260 bnz BASED(sysc_sigpending)
261 + tm __TI_flags+3(%r9),_TIF_NOTIFY_RESUME
262 + bnz BASED(sysc_notify_resume)
263 tm __TI_flags+3(%r9),_TIF_RESTART_SVC
264 bo BASED(sysc_restart)
265 tm __TI_flags+3(%r9),_TIF_SINGLE_STEP
266 @@ -356,6 +358,16 @@ sysc_sigpending:
267 b BASED(sysc_work_loop)
268
269 #
270 +# _TIF_NOTIFY_RESUME is set, call do_notify_resume
271 +#
272 +sysc_notify_resume:
273 + la %r2,SP_PTREGS(%r15) # load pt_regs
274 + l %r1,BASED(.Ldo_notify_resume)
275 + la %r14,BASED(sysc_work_loop)
276 + br %r1 # call do_notify_resume
277 +
278 +
279 +#
280 # _TIF_RESTART_SVC is set, set up registers and restart svc
281 #
282 sysc_restart:
283 @@ -378,20 +390,21 @@ sysc_singlestep:
284 br %r1 # branch to do_single_step
285
286 #
287 -# call trace before and after sys_call
288 +# call tracehook_report_syscall_entry/tracehook_report_syscall_exit before
289 +# and after the system call
290 #
291 sysc_tracesys:
292 - l %r1,BASED(.Ltrace)
293 + l %r1,BASED(.Ltrace_entry)
294 la %r2,SP_PTREGS(%r15) # load pt_regs
295 la %r3,0
296 srl %r7,2
297 st %r7,SP_R2(%r15)
298 basr %r14,%r1
299 - clc SP_R2(4,%r15),BASED(.Lnr_syscalls)
300 + cl %r2,BASED(.Lnr_syscalls)
301 bnl BASED(sysc_tracenogo)
302 l %r8,BASED(.Lsysc_table)
303 - l %r7,SP_R2(%r15) # strace might have changed the
304 - sll %r7,2 # system call
305 + lr %r7,%r2
306 + sll %r7,2 # *4
307 l %r8,0(%r7,%r8)
308 sysc_tracego:
309 lm %r3,%r6,SP_R3(%r15)
310 @@ -401,9 +414,8 @@ sysc_tracego:
311 sysc_tracenogo:
312 tm __TI_flags+3(%r9),(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT)
313 bz BASED(sysc_return)
314 - l %r1,BASED(.Ltrace)
315 + l %r1,BASED(.Ltrace_exit)
316 la %r2,SP_PTREGS(%r15) # load pt_regs
317 - la %r3,1
318 la %r14,BASED(sysc_return)
319 br %r1
320
321 @@ -666,6 +678,8 @@ io_work_loop:
322 bo BASED(io_reschedule)
323 tm __TI_flags+3(%r9),_TIF_SIGPENDING
324 bnz BASED(io_sigpending)
325 + tm __TI_flags+3(%r9),_TIF_NOTIFY_RESUME
326 + bnz BASED(io_notify_resume)
327 b BASED(io_restore)
328 io_work_done:
329
330 @@ -704,6 +718,19 @@ io_sigpending:
331 TRACE_IRQS_OFF
332 b BASED(io_work_loop)
333
334 +#
335 +# _TIF_SIGPENDING is set, call do_signal
336 +#
337 +io_notify_resume:
338 + TRACE_IRQS_ON
339 + stosm __SF_EMPTY(%r15),0x03 # reenable interrupts
340 + la %r2,SP_PTREGS(%r15) # load pt_regs
341 + l %r1,BASED(.Ldo_notify_resume)
342 + basr %r14,%r1 # call do_signal
343 + stnsm __SF_EMPTY(%r15),0xfc # disable I/O and ext. interrupts
344 + TRACE_IRQS_OFF
345 + b BASED(io_work_loop)
346 +
347 /*
348 * External interrupt handler routine
349 */
350 @@ -1070,6 +1097,8 @@ cleanup_io_leave_insn:
351 .Ldo_IRQ: .long do_IRQ
352 .Ldo_extint: .long do_extint
353 .Ldo_signal: .long do_signal
354 +.Ldo_notify_resume:
355 + .long do_notify_resume
356 .Lhandle_per: .long do_single_step
357 .Ldo_execve: .long do_execve
358 .Lexecve_tail: .long execve_tail
359 @@ -1079,7 +1108,8 @@ cleanup_io_leave_insn:
360 .Lpreempt_schedule_irq:
361 .long preempt_schedule_irq
362 #endif
363 -.Ltrace: .long syscall_trace
364 +.Ltrace_entry: .long do_syscall_trace_enter
365 +.Ltrace_exit: .long do_syscall_trace_exit
366 .Lschedtail: .long schedule_tail
367 .Lsysc_table: .long sys_call_table
368 #ifdef CONFIG_TRACE_IRQFLAGS
369 --- a/arch/s390/kernel/ptrace.c
370 +++ b/arch/s390/kernel/ptrace.c
371 @@ -35,6 +35,7 @@
372 #include <linux/signal.h>
373 #include <linux/elf.h>
374 #include <linux/regset.h>
375 +#include <linux/tracehook.h>
376
377 #include <asm/segment.h>
378 #include <asm/page.h>
379 @@ -639,40 +640,58 @@ long compat_arch_ptrace(struct task_stru
380 }
381 #endif
382
383 -asmlinkage void
384 -syscall_trace(struct pt_regs *regs, int entryexit)
385 +asmlinkage long do_syscall_trace_enter(struct pt_regs *regs)
386 {
387 - if (unlikely(current->audit_context) && entryexit)
388 - audit_syscall_exit(AUDITSC_RESULT(regs->gprs[2]), regs->gprs[2]);
389 -
390 - if (!test_thread_flag(TIF_SYSCALL_TRACE))
391 - goto out;
392 - if (!(current->ptrace & PT_PTRACED))
393 - goto out;
394 - ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
395 - ? 0x80 : 0));
396 + long ret;
397
398 /*
399 - * If the debuffer has set an invalid system call number,
400 - * we prepare to skip the system call restart handling.
401 + * The sysc_tracesys code in entry.S stored the system
402 + * call number to gprs[2].
403 */
404 - if (!entryexit && regs->gprs[2] >= NR_syscalls)
405 +
406 + if (is_self_ptracing(regs->gprs[2])) {
407 + struct siginfo info;
408 +
409 + memset(&info, 0, sizeof(struct siginfo));
410 + info.si_signo = SIGSYS;
411 + info.si_code = SYS_SYSCALL;
412 + info.si_errno = regs->gprs[2];
413 + info.si_addr = (void *)regs->orig_gpr2;
414 + send_sig_info(SIGSYS, &info, current);
415 + regs->gprs[2] = -1;
416 + return -1L;
417 + }
418 +
419 + ret = regs->gprs[2];
420 + if (test_thread_flag(TIF_SYSCALL_TRACE) &&
421 + (tracehook_report_syscall_entry(regs) ||
422 + regs->gprs[2] >= NR_syscalls)) {
423 + /*
424 + * Tracing decided this syscall should not happen or the
425 + * debugger stored an invalid system call number. Skip
426 + * the system call and the system call restart handling.
427 + */
428 regs->trap = -1;
429 + ret = -1;
430 + }
431
432 - /*
433 - * this isn't the same as continuing with a signal, but it will do
434 - * for normal use. strace only continues with a signal if the
435 - * stopping signal is not SIGTRAP. -brl
436 - */
437 - if (current->exit_code) {
438 - send_sig(current->exit_code, current, 1);
439 - current->exit_code = 0;
440 - }
441 - out:
442 - if (unlikely(current->audit_context) && !entryexit)
443 - audit_syscall_entry(test_thread_flag(TIF_31BIT)?AUDIT_ARCH_S390:AUDIT_ARCH_S390X,
444 - regs->gprs[2], regs->orig_gpr2, regs->gprs[3],
445 - regs->gprs[4], regs->gprs[5]);
446 + if (unlikely(current->audit_context))
447 + audit_syscall_entry(test_thread_flag(TIF_31BIT) ?
448 + AUDIT_ARCH_S390 : AUDIT_ARCH_S390X,
449 + regs->gprs[2], regs->orig_gpr2,
450 + regs->gprs[3], regs->gprs[4],
451 + regs->gprs[5]);
452 + return ret;
453 +}
454 +
455 +asmlinkage void do_syscall_trace_exit(struct pt_regs *regs)
456 +{
457 + if (unlikely(current->audit_context))
458 + audit_syscall_exit(AUDITSC_RESULT(regs->gprs[2]),
459 + regs->gprs[2]);
460 +
461 + if (test_thread_flag(TIF_SYSCALL_TRACE))
462 + tracehook_report_syscall_exit(regs, 0);
463 }
464
465 /*
466 --- a/arch/s390/kernel/signal.c
467 +++ b/arch/s390/kernel/signal.c
468 @@ -25,6 +25,7 @@
469 #include <linux/personality.h>
470 #include <linux/binfmts.h>
471 #include <linux/syscalls.h>
472 +#include <linux/tracehook.h>
473 #include <asm/ucontext.h>
474 #include <asm/uaccess.h>
475 #include <asm/lowcore.h>
476 @@ -504,6 +505,12 @@ void do_signal(struct pt_regs *regs)
477 */
478 if (current->thread.per_info.single_step)
479 set_thread_flag(TIF_SINGLE_STEP);
480 +
481 + /*
482 + * Let tracing know that we've done the handler setup.
483 + */
484 + tracehook_signal_handler(signr, &info, &ka, regs,
485 + test_thread_flag(TIF_SINGLE_STEP));
486 }
487 return;
488 }
489 @@ -523,3 +530,9 @@ void do_signal(struct pt_regs *regs)
490 set_thread_flag(TIF_RESTART_SVC);
491 }
492 }
493 +
494 +void do_notify_resume(struct pt_regs *regs)
495 +{
496 + clear_thread_flag(TIF_NOTIFY_RESUME);
497 + tracehook_notify_resume(regs);
498 +}