aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/s390/include/asm/ptrace.h5
-rw-r--r--arch/s390/include/asm/syscall.h5
-rw-r--r--arch/s390/include/asm/thread_info.h1
-rw-r--r--arch/s390/kernel/asm-offsets.c3
-rw-r--r--arch/s390/kernel/compat_signal.c2
-rw-r--r--arch/s390/kernel/entry.S28
-rw-r--r--arch/s390/kernel/entry64.S30
-rw-r--r--arch/s390/kernel/ptrace.c51
-rw-r--r--arch/s390/kernel/signal.c107
-rw-r--r--include/linux/elf.h1
10 files changed, 142 insertions, 91 deletions
diff --git a/arch/s390/include/asm/ptrace.h b/arch/s390/include/asm/ptrace.h
index 62fd80c9e98c..93c907b4776f 100644
--- a/arch/s390/include/asm/ptrace.h
+++ b/arch/s390/include/asm/ptrace.h
@@ -328,8 +328,7 @@ struct pt_regs
328 psw_t psw; 328 psw_t psw;
329 unsigned long gprs[NUM_GPRS]; 329 unsigned long gprs[NUM_GPRS];
330 unsigned long orig_gpr2; 330 unsigned long orig_gpr2;
331 unsigned short ilc; 331 unsigned int svc_code;
332 unsigned short svcnr;
333}; 332};
334 333
335/* 334/*
@@ -487,6 +486,8 @@ typedef struct
487#define PTRACE_POKETEXT_AREA 0x5004 486#define PTRACE_POKETEXT_AREA 0x5004
488#define PTRACE_POKEDATA_AREA 0x5005 487#define PTRACE_POKEDATA_AREA 0x5005
489#define PTRACE_GET_LAST_BREAK 0x5006 488#define PTRACE_GET_LAST_BREAK 0x5006
489#define PTRACE_PEEK_SYSTEM_CALL 0x5007
490#define PTRACE_POKE_SYSTEM_CALL 0x5008
490 491
491/* 492/*
492 * PT_PROT definition is loosely based on hppa bsd definition in 493 * PT_PROT definition is loosely based on hppa bsd definition in
diff --git a/arch/s390/include/asm/syscall.h b/arch/s390/include/asm/syscall.h
index 5c0246b955d8..614267f60713 100644
--- a/arch/s390/include/asm/syscall.h
+++ b/arch/s390/include/asm/syscall.h
@@ -13,6 +13,7 @@
13#define _ASM_SYSCALL_H 1 13#define _ASM_SYSCALL_H 1
14 14
15#include <linux/sched.h> 15#include <linux/sched.h>
16#include <linux/err.h>
16#include <asm/ptrace.h> 17#include <asm/ptrace.h>
17 18
18/* 19/*
@@ -25,7 +26,7 @@ extern const unsigned int sys_call_table[];
25static inline long syscall_get_nr(struct task_struct *task, 26static inline long syscall_get_nr(struct task_struct *task,
26 struct pt_regs *regs) 27 struct pt_regs *regs)
27{ 28{
28 return regs->svcnr ? regs->svcnr : -1; 29 return regs->svc_code ? (regs->svc_code & 0xffff) : -1;
29} 30}
30 31
31static inline void syscall_rollback(struct task_struct *task, 32static inline void syscall_rollback(struct task_struct *task,
@@ -37,7 +38,7 @@ static inline void syscall_rollback(struct task_struct *task,
37static inline long syscall_get_error(struct task_struct *task, 38static inline long syscall_get_error(struct task_struct *task,
38 struct pt_regs *regs) 39 struct pt_regs *regs)
39{ 40{
40 return (regs->gprs[2] >= -4096UL) ? -regs->gprs[2] : 0; 41 return IS_ERR_VALUE(regs->gprs[2]) ? regs->gprs[2] : 0;
41} 42}
42 43
43static inline long syscall_get_return_value(struct task_struct *task, 44static inline long syscall_get_return_value(struct task_struct *task,
diff --git a/arch/s390/include/asm/thread_info.h b/arch/s390/include/asm/thread_info.h
index f9a9a10979c9..0c4788eb5a65 100644
--- a/arch/s390/include/asm/thread_info.h
+++ b/arch/s390/include/asm/thread_info.h
@@ -48,6 +48,7 @@ struct thread_info {
48 unsigned int cpu; /* current CPU */ 48 unsigned int cpu; /* current CPU */
49 int preempt_count; /* 0 => preemptable, <0 => BUG */ 49 int preempt_count; /* 0 => preemptable, <0 => BUG */
50 struct restart_block restart_block; 50 struct restart_block restart_block;
51 unsigned int system_call;
51 __u64 user_timer; 52 __u64 user_timer;
52 __u64 system_timer; 53 __u64 system_timer;
53 unsigned long last_break; /* last breaking-event-address. */ 54 unsigned long last_break; /* last breaking-event-address. */
diff --git a/arch/s390/kernel/asm-offsets.c b/arch/s390/kernel/asm-offsets.c
index 1140035b1cd8..751318765e2e 100644
--- a/arch/s390/kernel/asm-offsets.c
+++ b/arch/s390/kernel/asm-offsets.c
@@ -45,8 +45,7 @@ int main(void)
45 DEFINE(__PT_PSW, offsetof(struct pt_regs, psw)); 45 DEFINE(__PT_PSW, offsetof(struct pt_regs, psw));
46 DEFINE(__PT_GPRS, offsetof(struct pt_regs, gprs)); 46 DEFINE(__PT_GPRS, offsetof(struct pt_regs, gprs));
47 DEFINE(__PT_ORIG_GPR2, offsetof(struct pt_regs, orig_gpr2)); 47 DEFINE(__PT_ORIG_GPR2, offsetof(struct pt_regs, orig_gpr2));
48 DEFINE(__PT_ILC, offsetof(struct pt_regs, ilc)); 48 DEFINE(__PT_SVC_CODE, offsetof(struct pt_regs, svc_code));
49 DEFINE(__PT_SVCNR, offsetof(struct pt_regs, svcnr));
50 DEFINE(__PT_SIZE, sizeof(struct pt_regs)); 49 DEFINE(__PT_SIZE, sizeof(struct pt_regs));
51 BLANK(); 50 BLANK();
52 DEFINE(__SF_BACKCHAIN, offsetof(struct stack_frame, back_chain)); 51 DEFINE(__SF_BACKCHAIN, offsetof(struct stack_frame, back_chain));
diff --git a/arch/s390/kernel/compat_signal.c b/arch/s390/kernel/compat_signal.c
index a9a285b8c4ad..d7c8e54c32e7 100644
--- a/arch/s390/kernel/compat_signal.c
+++ b/arch/s390/kernel/compat_signal.c
@@ -342,7 +342,7 @@ static int restore_sigregs32(struct pt_regs *regs,_sigregs32 __user *sregs)
342 return err; 342 return err;
343 343
344 restore_fp_regs(&current->thread.fp_regs); 344 restore_fp_regs(&current->thread.fp_regs);
345 regs->svcnr = 0; /* disable syscall checks */ 345 regs->svc_code = 0; /* disable syscall checks */
346 return 0; 346 return 0;
347} 347}
348 348
diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S
index 195387ab7c98..afe3685d30e7 100644
--- a/arch/s390/kernel/entry.S
+++ b/arch/s390/kernel/entry.S
@@ -43,8 +43,7 @@ SP_R13 = STACK_FRAME_OVERHEAD + __PT_GPRS + 52
43SP_R14 = STACK_FRAME_OVERHEAD + __PT_GPRS + 56 43SP_R14 = STACK_FRAME_OVERHEAD + __PT_GPRS + 56
44SP_R15 = STACK_FRAME_OVERHEAD + __PT_GPRS + 60 44SP_R15 = STACK_FRAME_OVERHEAD + __PT_GPRS + 60
45SP_ORIG_R2 = STACK_FRAME_OVERHEAD + __PT_ORIG_GPR2 45SP_ORIG_R2 = STACK_FRAME_OVERHEAD + __PT_ORIG_GPR2
46SP_ILC = STACK_FRAME_OVERHEAD + __PT_ILC 46SP_SVC_CODE = STACK_FRAME_OVERHEAD + __PT_SVC_CODE
47SP_SVCNR = STACK_FRAME_OVERHEAD + __PT_SVCNR
48SP_SIZE = STACK_FRAME_OVERHEAD + __PT_SIZE 47SP_SIZE = STACK_FRAME_OVERHEAD + __PT_SIZE
49 48
50_TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED | \ 49_TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED | \
@@ -229,7 +228,7 @@ sysc_saveall:
229 SAVE_ALL_SVC __LC_SVC_OLD_PSW,__LC_SAVE_AREA 228 SAVE_ALL_SVC __LC_SVC_OLD_PSW,__LC_SAVE_AREA
230 CREATE_STACK_FRAME __LC_SAVE_AREA 229 CREATE_STACK_FRAME __LC_SAVE_AREA
231 mvc SP_PSW(8,%r15),__LC_SVC_OLD_PSW 230 mvc SP_PSW(8,%r15),__LC_SVC_OLD_PSW
232 mvc SP_ILC(4,%r15),__LC_SVC_ILC 231 mvc SP_SVC_CODE(4,%r15),__LC_SVC_ILC
233 l %r12,__LC_THREAD_INFO # load pointer to thread_info struct 232 l %r12,__LC_THREAD_INFO # load pointer to thread_info struct
234sysc_vtime: 233sysc_vtime:
235 UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER 234 UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER
@@ -239,12 +238,12 @@ sysc_update:
239 mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER 238 mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER
240sysc_do_svc: 239sysc_do_svc:
241 xr %r7,%r7 240 xr %r7,%r7
242 icm %r7,3,SP_SVCNR(%r15) # load svc number and test for svc 0 241 icm %r7,3,SP_SVC_CODE+2(%r15)# load svc number and test for svc 0
243 bnz BASED(sysc_nr_ok) # svc number > 0 242 bnz BASED(sysc_nr_ok) # svc number > 0
244 # svc 0: system call number in %r1 243 # svc 0: system call number in %r1
245 cl %r1,BASED(.Lnr_syscalls) 244 cl %r1,BASED(.Lnr_syscalls)
246 bnl BASED(sysc_nr_ok) 245 bnl BASED(sysc_nr_ok)
247 sth %r1,SP_SVCNR(%r15) 246 sth %r1,SP_SVC_CODE+2(%r15)
248 lr %r7,%r1 # copy svc number to %r7 247 lr %r7,%r1 # copy svc number to %r7
249sysc_nr_ok: 248sysc_nr_ok:
250 sll %r7,2 # svc number *4 249 sll %r7,2 # svc number *4
@@ -335,10 +334,11 @@ sysc_notify_resume:
335# 334#
336sysc_restart: 335sysc_restart:
337 ni __TI_flags+3(%r12),255-_TIF_RESTART_SVC # clear TIF_RESTART_SVC 336 ni __TI_flags+3(%r12),255-_TIF_RESTART_SVC # clear TIF_RESTART_SVC
338 l %r7,SP_R2(%r15) # load new svc number
339 mvc SP_R2(4,%r15),SP_ORIG_R2(%r15) # restore first argument
340 lm %r2,%r6,SP_R2(%r15) # load svc arguments 337 lm %r2,%r6,SP_R2(%r15) # load svc arguments
341 sth %r7,SP_SVCNR(%r15) 338 xr %r7,%r7 # svc 0 returns -ENOSYS
339 clc SP_SVC_CODE+2(%r15),BASED(.Lnr_syscalls+2)
340 bnl BASED(sysc_nr_ok) # invalid svc number -> do svc 0
341 icm %r7,3,SP_SVC_CODE+2(%r15)# load new svc number
342 b BASED(sysc_nr_ok) # restart svc 342 b BASED(sysc_nr_ok) # restart svc
343 343
344# 344#
@@ -346,7 +346,7 @@ sysc_restart:
346# 346#
347sysc_singlestep: 347sysc_singlestep:
348 ni __TI_flags+3(%r12),255-_TIF_PER_TRAP # clear TIF_PER_TRAP 348 ni __TI_flags+3(%r12),255-_TIF_PER_TRAP # clear TIF_PER_TRAP
349 xc SP_SVCNR(2,%r15),SP_SVCNR(%r15) # clear svc number 349 xc SP_SVC_CODE(4,%r15),SP_SVC_CODE(%r15) # clear svc code
350 la %r2,SP_PTREGS(%r15) # address of register-save area 350 la %r2,SP_PTREGS(%r15) # address of register-save area
351 l %r1,BASED(.Lhandle_per) # load adr. of per handler 351 l %r1,BASED(.Lhandle_per) # load adr. of per handler
352 la %r14,BASED(sysc_return) # load adr. of system return 352 la %r14,BASED(sysc_return) # load adr. of system return
@@ -361,7 +361,7 @@ sysc_tracesys:
361 la %r2,SP_PTREGS(%r15) # load pt_regs 361 la %r2,SP_PTREGS(%r15) # load pt_regs
362 la %r3,0 362 la %r3,0
363 xr %r0,%r0 363 xr %r0,%r0
364 icm %r0,3,SP_SVCNR(%r15) 364 icm %r0,3,SP_SVC_CODE(%r15)
365 st %r0,SP_R2(%r15) 365 st %r0,SP_R2(%r15)
366 basr %r14,%r1 366 basr %r14,%r1
367 cl %r2,BASED(.Lnr_syscalls) 367 cl %r2,BASED(.Lnr_syscalls)
@@ -454,7 +454,7 @@ ENTRY(pgm_check_handler)
454 bnz BASED(pgm_per) # got per exception -> special case 454 bnz BASED(pgm_per) # got per exception -> special case
455 SAVE_ALL_PGM __LC_PGM_OLD_PSW,__LC_SAVE_AREA 455 SAVE_ALL_PGM __LC_PGM_OLD_PSW,__LC_SAVE_AREA
456 CREATE_STACK_FRAME __LC_SAVE_AREA 456 CREATE_STACK_FRAME __LC_SAVE_AREA
457 xc SP_ILC(4,%r15),SP_ILC(%r15) 457 xc SP_SVC_CODE(4,%r15),SP_SVC_CODE(%r15)
458 mvc SP_PSW(8,%r15),__LC_PGM_OLD_PSW 458 mvc SP_PSW(8,%r15),__LC_PGM_OLD_PSW
459 l %r12,__LC_THREAD_INFO # load pointer to thread_info struct 459 l %r12,__LC_THREAD_INFO # load pointer to thread_info struct
460 tm SP_PSW+1(%r15),0x01 # interrupting from user ? 460 tm SP_PSW+1(%r15),0x01 # interrupting from user ?
@@ -531,7 +531,7 @@ pgm_svcper:
531 SAVE_ALL_PGM __LC_SVC_OLD_PSW,__LC_SAVE_AREA 531 SAVE_ALL_PGM __LC_SVC_OLD_PSW,__LC_SAVE_AREA
532 CREATE_STACK_FRAME __LC_SAVE_AREA 532 CREATE_STACK_FRAME __LC_SAVE_AREA
533 mvc SP_PSW(8,%r15),__LC_SVC_OLD_PSW 533 mvc SP_PSW(8,%r15),__LC_SVC_OLD_PSW
534 mvc SP_ILC(4,%r15),__LC_SVC_ILC 534 mvc SP_SVC_CODE(4,%r15),__LC_SVC_ILC
535 l %r12,__LC_THREAD_INFO # load pointer to thread_info struct 535 l %r12,__LC_THREAD_INFO # load pointer to thread_info struct
536 UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER 536 UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER
537 UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER 537 UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER
@@ -550,7 +550,7 @@ pgm_svcper:
550# 550#
551kernel_per: 551kernel_per:
552 REENABLE_IRQS 552 REENABLE_IRQS
553 xc SP_SVCNR(2,%r15),SP_SVCNR(%r15) 553 xc SP_SVC_CODE(4,%r15),SP_SVC_CODE(%r15)
554 la %r2,SP_PTREGS(%r15) # address of register-save area 554 la %r2,SP_PTREGS(%r15) # address of register-save area
555 l %r1,BASED(.Lhandle_per) # load adr. of per handler 555 l %r1,BASED(.Lhandle_per) # load adr. of per handler
556 basr %r14,%r1 # branch to do_single_step 556 basr %r14,%r1 # branch to do_single_step
@@ -966,7 +966,7 @@ cleanup_system_call:
966 st %r15,12(%r12) 966 st %r15,12(%r12)
967 CREATE_STACK_FRAME __LC_SAVE_AREA 967 CREATE_STACK_FRAME __LC_SAVE_AREA
968 mvc SP_PSW(8,%r15),__LC_SVC_OLD_PSW 968 mvc SP_PSW(8,%r15),__LC_SVC_OLD_PSW
969 mvc SP_ILC(4,%r15),__LC_SVC_ILC 969 mvc SP_SVC_CODE(4,%r15),__LC_SVC_ILC
970 mvc 0(4,%r12),__LC_THREAD_INFO 970 mvc 0(4,%r12),__LC_THREAD_INFO
971cleanup_vtime: 971cleanup_vtime:
972 clc __LC_RETURN_PSW+4(4),BASED(cleanup_system_call_insn+12) 972 clc __LC_RETURN_PSW+4(4),BASED(cleanup_system_call_insn+12)
diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S
index 3257f7f55551..7ff07d3a29c1 100644
--- a/arch/s390/kernel/entry64.S
+++ b/arch/s390/kernel/entry64.S
@@ -43,8 +43,7 @@ SP_R13 = STACK_FRAME_OVERHEAD + __PT_GPRS + 104
43SP_R14 = STACK_FRAME_OVERHEAD + __PT_GPRS + 112 43SP_R14 = STACK_FRAME_OVERHEAD + __PT_GPRS + 112
44SP_R15 = STACK_FRAME_OVERHEAD + __PT_GPRS + 120 44SP_R15 = STACK_FRAME_OVERHEAD + __PT_GPRS + 120
45SP_ORIG_R2 = STACK_FRAME_OVERHEAD + __PT_ORIG_GPR2 45SP_ORIG_R2 = STACK_FRAME_OVERHEAD + __PT_ORIG_GPR2
46SP_ILC = STACK_FRAME_OVERHEAD + __PT_ILC 46SP_SVC_CODE = STACK_FRAME_OVERHEAD + __PT_SVC_CODE
47SP_SVCNR = STACK_FRAME_OVERHEAD + __PT_SVCNR
48SP_SIZE = STACK_FRAME_OVERHEAD + __PT_SIZE 47SP_SIZE = STACK_FRAME_OVERHEAD + __PT_SIZE
49 48
50STACK_SHIFT = PAGE_SHIFT + THREAD_ORDER 49STACK_SHIFT = PAGE_SHIFT + THREAD_ORDER
@@ -250,7 +249,7 @@ sysc_saveall:
250 SAVE_ALL_SVC __LC_SVC_OLD_PSW,__LC_SAVE_AREA 249 SAVE_ALL_SVC __LC_SVC_OLD_PSW,__LC_SAVE_AREA
251 CREATE_STACK_FRAME __LC_SAVE_AREA 250 CREATE_STACK_FRAME __LC_SAVE_AREA
252 mvc SP_PSW(16,%r15),__LC_SVC_OLD_PSW 251 mvc SP_PSW(16,%r15),__LC_SVC_OLD_PSW
253 mvc SP_ILC(4,%r15),__LC_SVC_ILC 252 mvc SP_SVC_CODE(4,%r15),__LC_SVC_ILC
254 lg %r12,__LC_THREAD_INFO # load pointer to thread_info struct 253 lg %r12,__LC_THREAD_INFO # load pointer to thread_info struct
255sysc_vtime: 254sysc_vtime:
256 UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER 255 UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER
@@ -260,14 +259,14 @@ sysc_update:
260 mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER 259 mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER
261 LAST_BREAK 260 LAST_BREAK
262sysc_do_svc: 261sysc_do_svc:
263 llgh %r7,SP_SVCNR(%r15) 262 llgh %r7,SP_SVC_CODE+2(%r15)
264 slag %r7,%r7,2 # shift and test for svc 0 263 slag %r7,%r7,2 # shift and test for svc 0
265 jnz sysc_nr_ok 264 jnz sysc_nr_ok
266 # svc 0: system call number in %r1 265 # svc 0: system call number in %r1
267 llgfr %r1,%r1 # clear high word in r1 266 llgfr %r1,%r1 # clear high word in r1
268 cghi %r1,NR_syscalls 267 cghi %r1,NR_syscalls
269 jnl sysc_nr_ok 268 jnl sysc_nr_ok
270 sth %r1,SP_SVCNR(%r15) 269 sth %r1,SP_SVC_CODE+2(%r15)
271 slag %r7,%r1,2 # shift and test for svc 0 270 slag %r7,%r1,2 # shift and test for svc 0
272sysc_nr_ok: 271sysc_nr_ok:
273 larl %r10,sys_call_table 272 larl %r10,sys_call_table
@@ -358,11 +357,12 @@ sysc_notify_resume:
358# 357#
359sysc_restart: 358sysc_restart:
360 ni __TI_flags+7(%r12),255-_TIF_RESTART_SVC # clear TIF_RESTART_SVC 359 ni __TI_flags+7(%r12),255-_TIF_RESTART_SVC # clear TIF_RESTART_SVC
361 lg %r7,SP_R2(%r15) # load new svc number
362 mvc SP_R2(8,%r15),SP_ORIG_R2(%r15) # restore first argument
363 lmg %r2,%r6,SP_R2(%r15) # load svc arguments 360 lmg %r2,%r6,SP_R2(%r15) # load svc arguments
364 sth %r7,SP_SVCNR(%r15) 361 lghi %r7,0 # svc 0 returns -ENOSYS
365 slag %r7,%r7,2 362 lh %r1,SP_SVC_CODE+2(%r15) # load new svc number
363 cghi %r1,NR_syscalls
364 jnl sysc_nr_ok # invalid svc number -> do svc 0
365 slag %r7,%r1,2
366 j sysc_nr_ok # restart svc 366 j sysc_nr_ok # restart svc
367 367
368# 368#
@@ -370,7 +370,7 @@ sysc_restart:
370# 370#
371sysc_singlestep: 371sysc_singlestep:
372 ni __TI_flags+7(%r12),255-_TIF_PER_TRAP # clear TIF_PER_TRAP 372 ni __TI_flags+7(%r12),255-_TIF_PER_TRAP # clear TIF_PER_TRAP
373 xc SP_SVCNR(2,%r15),SP_SVCNR(%r15) # clear svc number 373 xc SP_SVC_CODE(4,%r15),SP_SVC_CODE(%r15) # clear svc code
374 la %r2,SP_PTREGS(%r15) # address of register-save area 374 la %r2,SP_PTREGS(%r15) # address of register-save area
375 larl %r14,sysc_return # load adr. of system return 375 larl %r14,sysc_return # load adr. of system return
376 jg do_per_trap 376 jg do_per_trap
@@ -382,7 +382,7 @@ sysc_singlestep:
382sysc_tracesys: 382sysc_tracesys:
383 la %r2,SP_PTREGS(%r15) # load pt_regs 383 la %r2,SP_PTREGS(%r15) # load pt_regs
384 la %r3,0 384 la %r3,0
385 llgh %r0,SP_SVCNR(%r15) 385 llgh %r0,SP_SVC_CODE+2(%r15)
386 stg %r0,SP_R2(%r15) 386 stg %r0,SP_R2(%r15)
387 brasl %r14,do_syscall_trace_enter 387 brasl %r14,do_syscall_trace_enter
388 lghi %r0,NR_syscalls 388 lghi %r0,NR_syscalls
@@ -470,7 +470,7 @@ ENTRY(pgm_check_handler)
470 jnz pgm_per # got per exception -> special case 470 jnz pgm_per # got per exception -> special case
471 SAVE_ALL_PGM __LC_PGM_OLD_PSW,__LC_SAVE_AREA 471 SAVE_ALL_PGM __LC_PGM_OLD_PSW,__LC_SAVE_AREA
472 CREATE_STACK_FRAME __LC_SAVE_AREA 472 CREATE_STACK_FRAME __LC_SAVE_AREA
473 xc SP_ILC(4,%r15),SP_ILC(%r15) 473 xc SP_SVC_CODE(4,%r15),SP_SVC_CODE(%r15)
474 mvc SP_PSW(16,%r15),__LC_PGM_OLD_PSW 474 mvc SP_PSW(16,%r15),__LC_PGM_OLD_PSW
475 lg %r12,__LC_THREAD_INFO # load pointer to thread_info struct 475 lg %r12,__LC_THREAD_INFO # load pointer to thread_info struct
476 HANDLE_SIE_INTERCEPT 476 HANDLE_SIE_INTERCEPT
@@ -551,7 +551,7 @@ pgm_svcper:
551 SAVE_ALL_PGM __LC_SVC_OLD_PSW,__LC_SAVE_AREA 551 SAVE_ALL_PGM __LC_SVC_OLD_PSW,__LC_SAVE_AREA
552 CREATE_STACK_FRAME __LC_SAVE_AREA 552 CREATE_STACK_FRAME __LC_SAVE_AREA
553 mvc SP_PSW(16,%r15),__LC_SVC_OLD_PSW 553 mvc SP_PSW(16,%r15),__LC_SVC_OLD_PSW
554 mvc SP_ILC(4,%r15),__LC_SVC_ILC 554 mvc SP_SVC_CODE(4,%r15),__LC_SVC_ILC
555 lg %r12,__LC_THREAD_INFO # load pointer to thread_info struct 555 lg %r12,__LC_THREAD_INFO # load pointer to thread_info struct
556 UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER 556 UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER
557 UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER 557 UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER
@@ -571,7 +571,7 @@ pgm_svcper:
571# 571#
572kernel_per: 572kernel_per:
573 REENABLE_IRQS 573 REENABLE_IRQS
574 xc SP_SVCNR(2,%r15),SP_SVCNR(%r15) # clear svc number 574 xc SP_SVC_CODE(4,%r15),SP_SVC_CODE(%r15) # clear svc number
575 la %r2,SP_PTREGS(%r15) # address of register-save area 575 la %r2,SP_PTREGS(%r15) # address of register-save area
576 brasl %r14,do_per_trap 576 brasl %r14,do_per_trap
577 j pgm_exit 577 j pgm_exit
@@ -973,7 +973,7 @@ cleanup_system_call:
973 stg %r11,0(%r12) 973 stg %r11,0(%r12)
974 CREATE_STACK_FRAME __LC_SAVE_AREA 974 CREATE_STACK_FRAME __LC_SAVE_AREA
975 mvc SP_PSW(16,%r15),__LC_SVC_OLD_PSW 975 mvc SP_PSW(16,%r15),__LC_SVC_OLD_PSW
976 mvc SP_ILC(4,%r15),__LC_SVC_ILC 976 mvc SP_SVC_CODE(4,%r15),__LC_SVC_ILC
977 mvc 8(8,%r12),__LC_THREAD_INFO 977 mvc 8(8,%r12),__LC_THREAD_INFO
978cleanup_vtime: 978cleanup_vtime:
979 clc __LC_RETURN_PSW+8(8),BASED(cleanup_system_call_insn+24) 979 clc __LC_RETURN_PSW+8(8),BASED(cleanup_system_call_insn+24)
diff --git a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c
index ae0e14b8880c..bae1cc49fe96 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),
diff --git a/arch/s390/kernel/signal.c b/arch/s390/kernel/signal.c
index 9a40e1cc5ec3..e751cab80e04 100644
--- a/arch/s390/kernel/signal.c
+++ b/arch/s390/kernel/signal.c
@@ -30,6 +30,7 @@
30#include <asm/ucontext.h> 30#include <asm/ucontext.h>
31#include <asm/uaccess.h> 31#include <asm/uaccess.h>
32#include <asm/lowcore.h> 32#include <asm/lowcore.h>
33#include <asm/compat.h>
33#include "entry.h" 34#include "entry.h"
34 35
35#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) 36#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
@@ -156,7 +157,7 @@ static int restore_sigregs(struct pt_regs *regs, _sigregs __user *sregs)
156 current->thread.fp_regs.fpc &= FPC_VALID_MASK; 157 current->thread.fp_regs.fpc &= FPC_VALID_MASK;
157 158
158 restore_fp_regs(&current->thread.fp_regs); 159 restore_fp_regs(&current->thread.fp_regs);
159 regs->svcnr = 0; /* disable syscall checks */ 160 regs->svc_code = 0; /* disable syscall checks */
160 return 0; 161 return 0;
161} 162}
162 163
@@ -401,7 +402,6 @@ static int handle_signal(unsigned long sig, struct k_sigaction *ka,
401 */ 402 */
402void do_signal(struct pt_regs *regs) 403void do_signal(struct pt_regs *regs)
403{ 404{
404 unsigned long retval = 0, continue_addr = 0, restart_addr = 0;
405 siginfo_t info; 405 siginfo_t info;
406 int signr; 406 int signr;
407 struct k_sigaction ka; 407 struct k_sigaction ka;
@@ -421,54 +421,43 @@ void do_signal(struct pt_regs *regs)
421 else 421 else
422 oldset = &current->blocked; 422 oldset = &current->blocked;
423 423
424 /* Are we from a system call? */ 424 /*
425 if (regs->svcnr) { 425 * Get signal to deliver. When running under ptrace, at this point
426 continue_addr = regs->psw.addr; 426 * the debugger may change all our registers, including the system
427 restart_addr = continue_addr - regs->ilc; 427 * call information.
428 retval = regs->gprs[2]; 428 */
429 429 current_thread_info()->system_call = regs->svc_code;
430 /* Prepare for system call restart. We do this here so that a
431 debugger will see the already changed PSW. */
432 switch (retval) {
433 case -ERESTARTNOHAND:
434 case -ERESTARTSYS:
435 case -ERESTARTNOINTR:
436 regs->gprs[2] = regs->orig_gpr2;
437 regs->psw.addr = restart_addr;
438 break;
439 case -ERESTART_RESTARTBLOCK:
440 regs->gprs[2] = -EINTR;
441 }
442 regs->svcnr = 0; /* Don't deal with this again. */
443 }
444
445 /* Get signal to deliver. When running under ptrace, at this point
446 the debugger may change all our registers ... */
447 signr = get_signal_to_deliver(&info, &ka, regs, NULL); 430 signr = get_signal_to_deliver(&info, &ka, regs, NULL);
448 431 regs->svc_code = current_thread_info()->system_call;
449 /* Depending on the signal settings we may need to revert the
450 decision to restart the system call. */
451 if (signr > 0 && regs->psw.addr == restart_addr) {
452 if (retval == -ERESTARTNOHAND
453 || (retval == -ERESTARTSYS
454 && !(current->sighand->action[signr-1].sa.sa_flags
455 & SA_RESTART))) {
456 regs->gprs[2] = -EINTR;
457 regs->psw.addr = continue_addr;
458 }
459 }
460 432
461 if (signr > 0) { 433 if (signr > 0) {
462 /* Whee! Actually deliver the signal. */ 434 /* Whee! Actually deliver the signal. */
463 int ret; 435 if (regs->svc_code > 0) {
464#ifdef CONFIG_COMPAT 436 /* Check for system call restarting. */
465 if (is_compat_task()) { 437 switch (regs->gprs[2]) {
466 ret = handle_signal32(signr, &ka, &info, oldset, regs); 438 case -ERESTART_RESTARTBLOCK:
467 } 439 case -ERESTARTNOHAND:
468 else 440 regs->gprs[2] = -EINTR;
469#endif 441 break;
470 ret = handle_signal(signr, &ka, &info, oldset, regs); 442 case -ERESTARTSYS:
471 if (!ret) { 443 if (!(ka.sa.sa_flags & SA_RESTART)) {
444 regs->gprs[2] = -EINTR;
445 break;
446 }
447 /* fallthrough */
448 case -ERESTARTNOINTR:
449 regs->gprs[2] = regs->orig_gpr2;
450 regs->psw.addr = regs->psw.addr -
451 (regs->svc_code >> 16);
452 break;
453 }
454 /* No longer in a system call */
455 regs->svc_code = 0;
456 }
457
458 if ((is_compat_task() ?
459 handle_signal32(signr, &ka, &info, oldset, regs) :
460 handle_signal(signr, &ka, &info, oldset, regs)) == 0) {
472 /* 461 /*
473 * A signal was successfully delivered; the saved 462 * A signal was successfully delivered; the saved
474 * sigmask will have been stored in the signal frame, 463 * sigmask will have been stored in the signal frame,
@@ -482,11 +471,28 @@ void do_signal(struct pt_regs *regs)
482 * Let tracing know that we've done the handler setup. 471 * Let tracing know that we've done the handler setup.
483 */ 472 */
484 tracehook_signal_handler(signr, &info, &ka, regs, 473 tracehook_signal_handler(signr, &info, &ka, regs,
485 test_thread_flag(TIF_SINGLE_STEP)); 474 test_thread_flag(TIF_SINGLE_STEP));
486 } 475 }
487 return; 476 return;
488 } 477 }
489 478
479 /* No handlers present - check for system call restart */
480 if (regs->svc_code > 0) {
481 switch (regs->gprs[2]) {
482 case -ERESTART_RESTARTBLOCK:
483 /* Restart with sys_restart_syscall */
484 regs->svc_code = __NR_restart_syscall;
485 /* fallthrough */
486 case -ERESTARTNOHAND:
487 case -ERESTARTSYS:
488 case -ERESTARTNOINTR:
489 /* Restart system call with magic TIF bit. */
490 regs->gprs[2] = regs->orig_gpr2;
491 set_thread_flag(TIF_RESTART_SVC);
492 break;
493 }
494 }
495
490 /* 496 /*
491 * If there's no signal to deliver, we just put the saved sigmask back. 497 * If there's no signal to deliver, we just put the saved sigmask back.
492 */ 498 */
@@ -494,13 +500,6 @@ void do_signal(struct pt_regs *regs)
494 clear_thread_flag(TIF_RESTORE_SIGMASK); 500 clear_thread_flag(TIF_RESTORE_SIGMASK);
495 sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL); 501 sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
496 } 502 }
497
498 /* Restart a different system call. */
499 if (retval == -ERESTART_RESTARTBLOCK
500 && regs->psw.addr == continue_addr) {
501 regs->gprs[2] = __NR_restart_syscall;
502 set_thread_flag(TIF_RESTART_SVC);
503 }
504} 503}
505 504
506void do_notify_resume(struct pt_regs *regs) 505void do_notify_resume(struct pt_regs *regs)
diff --git a/include/linux/elf.h b/include/linux/elf.h
index 110821cb6ea5..31f0508d7da7 100644
--- a/include/linux/elf.h
+++ b/include/linux/elf.h
@@ -395,6 +395,7 @@ typedef struct elf64_shdr {
395#define NT_S390_CTRS 0x304 /* s390 control registers */ 395#define NT_S390_CTRS 0x304 /* s390 control registers */
396#define NT_S390_PREFIX 0x305 /* s390 prefix register */ 396#define NT_S390_PREFIX 0x305 /* s390 prefix register */
397#define NT_S390_LAST_BREAK 0x306 /* s390 breaking event address */ 397#define NT_S390_LAST_BREAK 0x306 /* s390 breaking event address */
398#define NT_S390_SYSTEM_CALL 0x307 /* s390 system call restart data */
398#define NT_ARM_VFP 0x400 /* ARM VFP/NEON registers */ 399#define NT_ARM_VFP 0x400 /* ARM VFP/NEON registers */
399 400
400 401