aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Schwidefsky <schwidefsky@de.ibm.com>2007-04-27 10:01:40 -0400
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2007-04-27 10:01:42 -0400
commit03ff9a235a0602724fc54916469b6e0939c62c9b (patch)
tree86ab2236897eb59542be2ccd667d6ca221153a44
parentef99516c9646802c3d38c3eb83de302e05b3c1b5 (diff)
[S390] System call cleanup.
Remove system call glue for sys_clone, sys_fork, sys_vfork, sys_execve, sys_sigreturn, sys_rt_sigreturn and sys_sigaltstack. Call do_execve from kernel_execve directly, move pt_regs to the right place and branch to sysc_return to start the user space program. This removes the last in-kernel system call. Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com> Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com>
-rw-r--r--arch/s390/kernel/compat_linux.c60
-rw-r--r--arch/s390/kernel/compat_signal.c14
-rw-r--r--arch/s390/kernel/entry.S87
-rw-r--r--arch/s390/kernel/entry64.S100
-rw-r--r--arch/s390/kernel/process.c82
-rw-r--r--arch/s390/kernel/signal.c10
-rw-r--r--arch/s390/kernel/sys_s390.c20
-rw-r--r--arch/s390/kernel/syscalls.S14
8 files changed, 162 insertions, 225 deletions
diff --git a/arch/s390/kernel/compat_linux.c b/arch/s390/kernel/compat_linux.c
index 664c669b1856..5236fdb17fcb 100644
--- a/arch/s390/kernel/compat_linux.c
+++ b/arch/s390/kernel/compat_linux.c
@@ -495,29 +495,34 @@ sys32_rt_sigqueueinfo(int pid, int sig, compat_siginfo_t __user *uinfo)
495 * sys32_execve() executes a new program after the asm stub has set 495 * sys32_execve() executes a new program after the asm stub has set
496 * things up for us. This should basically do what I want it to. 496 * things up for us. This should basically do what I want it to.
497 */ 497 */
498asmlinkage long 498asmlinkage long sys32_execve(void)
499sys32_execve(struct pt_regs regs)
500{ 499{
501 int error; 500 struct pt_regs *regs = task_pt_regs(current);
502 char * filename; 501 char *filename;
502 unsigned long result;
503 int rc;
503 504
504 filename = getname(compat_ptr(regs.orig_gpr2)); 505 filename = getname(compat_ptr(regs->orig_gpr2));
505 error = PTR_ERR(filename); 506 if (IS_ERR(filename)) {
506 if (IS_ERR(filename)) 507 result = PTR_ERR(filename);
507 goto out; 508 goto out;
508 error = compat_do_execve(filename, compat_ptr(regs.gprs[3]),
509 compat_ptr(regs.gprs[4]), &regs);
510 if (error == 0)
511 {
512 task_lock(current);
513 current->ptrace &= ~PT_DTRACE;
514 task_unlock(current);
515 current->thread.fp_regs.fpc=0;
516 asm volatile("sfpc %0,0" : : "d" (0));
517 } 509 }
510 rc = compat_do_execve(filename, compat_ptr(regs->gprs[3]),
511 compat_ptr(regs->gprs[4]), regs);
512 if (rc) {
513 result = rc;
514 goto out_putname;
515 }
516 task_lock(current);
517 current->ptrace &= ~PT_DTRACE;
518 task_unlock(current);
519 current->thread.fp_regs.fpc=0;
520 asm volatile("sfpc %0,0" : : "d" (0));
521 result = regs->gprs[2];
522out_putname:
518 putname(filename); 523 putname(filename);
519out: 524out:
520 return error; 525 return result;
521} 526}
522 527
523 528
@@ -918,19 +923,20 @@ asmlinkage long sys32_write(unsigned int fd, char __user * buf, size_t count)
918 return sys_write(fd, buf, count); 923 return sys_write(fd, buf, count);
919} 924}
920 925
921asmlinkage long sys32_clone(struct pt_regs regs) 926asmlinkage long sys32_clone(void)
922{ 927{
923 unsigned long clone_flags; 928 struct pt_regs *regs = task_pt_regs(current);
924 unsigned long newsp; 929 unsigned long clone_flags;
930 unsigned long newsp;
925 int __user *parent_tidptr, *child_tidptr; 931 int __user *parent_tidptr, *child_tidptr;
926 932
927 clone_flags = regs.gprs[3] & 0xffffffffUL; 933 clone_flags = regs->gprs[3] & 0xffffffffUL;
928 newsp = regs.orig_gpr2 & 0x7fffffffUL; 934 newsp = regs->orig_gpr2 & 0x7fffffffUL;
929 parent_tidptr = compat_ptr(regs.gprs[4]); 935 parent_tidptr = compat_ptr(regs->gprs[4]);
930 child_tidptr = compat_ptr(regs.gprs[5]); 936 child_tidptr = compat_ptr(regs->gprs[5]);
931 if (!newsp) 937 if (!newsp)
932 newsp = regs.gprs[15]; 938 newsp = regs->gprs[15];
933 return do_fork(clone_flags, newsp, &regs, 0, 939 return do_fork(clone_flags, newsp, regs, 0,
934 parent_tidptr, child_tidptr); 940 parent_tidptr, child_tidptr);
935} 941}
936 942
diff --git a/arch/s390/kernel/compat_signal.c b/arch/s390/kernel/compat_signal.c
index 887a9881d0d0..80a54a0149ab 100644
--- a/arch/s390/kernel/compat_signal.c
+++ b/arch/s390/kernel/compat_signal.c
@@ -255,9 +255,9 @@ sys32_rt_sigaction(int sig, const struct sigaction32 __user *act,
255} 255}
256 256
257asmlinkage long 257asmlinkage long
258sys32_sigaltstack(const stack_t32 __user *uss, stack_t32 __user *uoss, 258sys32_sigaltstack(const stack_t32 __user *uss, stack_t32 __user *uoss)
259 struct pt_regs *regs)
260{ 259{
260 struct pt_regs *regs = task_pt_regs(current);
261 stack_t kss, koss; 261 stack_t kss, koss;
262 unsigned long ss_sp; 262 unsigned long ss_sp;
263 int ret, err = 0; 263 int ret, err = 0;
@@ -344,8 +344,9 @@ static int restore_sigregs32(struct pt_regs *regs,_sigregs32 __user *sregs)
344 return 0; 344 return 0;
345} 345}
346 346
347asmlinkage long sys32_sigreturn(struct pt_regs *regs) 347asmlinkage long sys32_sigreturn(void)
348{ 348{
349 struct pt_regs *regs = task_pt_regs(current);
349 sigframe32 __user *frame = (sigframe32 __user *)regs->gprs[15]; 350 sigframe32 __user *frame = (sigframe32 __user *)regs->gprs[15];
350 sigset_t set; 351 sigset_t set;
351 352
@@ -370,8 +371,9 @@ badframe:
370 return 0; 371 return 0;
371} 372}
372 373
373asmlinkage long sys32_rt_sigreturn(struct pt_regs *regs) 374asmlinkage long sys32_rt_sigreturn(void)
374{ 375{
376 struct pt_regs *regs = task_pt_regs(current);
375 rt_sigframe32 __user *frame = (rt_sigframe32 __user *)regs->gprs[15]; 377 rt_sigframe32 __user *frame = (rt_sigframe32 __user *)regs->gprs[15];
376 sigset_t set; 378 sigset_t set;
377 stack_t st; 379 stack_t st;
@@ -407,8 +409,8 @@ asmlinkage long sys32_rt_sigreturn(struct pt_regs *regs)
407 return regs->gprs[2]; 409 return regs->gprs[2];
408 410
409badframe: 411badframe:
410 force_sig(SIGSEGV, current); 412 force_sig(SIGSEGV, current);
411 return 0; 413 return 0;
412} 414}
413 415
414/* 416/*
diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S
index dddc3de30401..c8a2212014e0 100644
--- a/arch/s390/kernel/entry.S
+++ b/arch/s390/kernel/entry.S
@@ -249,8 +249,6 @@ sysc_do_restart:
249 bnz BASED(sysc_tracesys) 249 bnz BASED(sysc_tracesys)
250 basr %r14,%r8 # call sys_xxxx 250 basr %r14,%r8 # call sys_xxxx
251 st %r2,SP_R2(%r15) # store return value (change R2 on stack) 251 st %r2,SP_R2(%r15) # store return value (change R2 on stack)
252 # ATTENTION: check sys_execve_glue before
253 # changing anything here !!
254 252
255sysc_return: 253sysc_return:
256 tm SP_PSW+1(%r15),0x01 # returning to user ? 254 tm SP_PSW+1(%r15),0x01 # returning to user ?
@@ -381,50 +379,37 @@ ret_from_fork:
381 b BASED(sysc_return) 379 b BASED(sysc_return)
382 380
383# 381#
384# clone, fork, vfork, exec and sigreturn need glue, 382# kernel_execve function needs to deal with pt_regs that is not
385# because they all expect pt_regs as parameter, 383# at the usual place
386# but are called with different parameter.
387# return-address is set up above
388# 384#
389sys_clone_glue: 385 .globl kernel_execve
390 la %r2,SP_PTREGS(%r15) # load pt_regs 386kernel_execve:
391 l %r1,BASED(.Lclone) 387 stm %r12,%r15,48(%r15)
392 br %r1 # branch to sys_clone 388 lr %r14,%r15
393 389 l %r13,__LC_SVC_NEW_PSW+4
394sys_fork_glue: 390 s %r15,BASED(.Lc_spsize)
395 la %r2,SP_PTREGS(%r15) # load pt_regs 391 st %r14,__SF_BACKCHAIN(%r15)
396 l %r1,BASED(.Lfork) 392 la %r12,SP_PTREGS(%r15)
397 br %r1 # branch to sys_fork 393 xc 0(__PT_SIZE,%r12),0(%r12)
398 394 l %r1,BASED(.Ldo_execve)
399sys_vfork_glue: 395 lr %r5,%r12
400 la %r2,SP_PTREGS(%r15) # load pt_regs 396 basr %r14,%r1
401 l %r1,BASED(.Lvfork) 397 ltr %r2,%r2
402 br %r1 # branch to sys_vfork 398 be BASED(0f)
403 399 a %r15,BASED(.Lc_spsize)
404sys_execve_glue: 400 lm %r12,%r15,48(%r15)
405 la %r2,SP_PTREGS(%r15) # load pt_regs 401 br %r14
406 l %r1,BASED(.Lexecve) 402 # execve succeeded.
407 lr %r12,%r14 # save return address 4030: stnsm __SF_EMPTY(%r15),0xfc # disable interrupts
408 basr %r14,%r1 # call sys_execve 404 l %r15,__LC_KERNEL_STACK # load ksp
409 ltr %r2,%r2 # check if execve failed 405 s %r15,BASED(.Lc_spsize) # make room for registers & psw
410 bnz 0(%r12) # it did fail -> store result in gpr2 406 l %r9,__LC_THREAD_INFO
411 b 4(%r12) # SKIP ST 2,SP_R2(15) after BASR 14,8 407 mvc SP_PTREGS(__PT_SIZE,%r15),0(%r12) # copy pt_regs
412 # in system_call/sysc_tracesys 408 xc __SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15)
413 409 stosm __SF_EMPTY(%r15),0x03 # reenable interrupts
414sys_sigreturn_glue: 410 l %r1,BASED(.Lexecve_tail)
415 la %r2,SP_PTREGS(%r15) # load pt_regs as parameter 411 basr %r14,%r1
416 l %r1,BASED(.Lsigreturn) 412 b BASED(sysc_return)
417 br %r1 # branch to sys_sigreturn
418
419sys_rt_sigreturn_glue:
420 la %r2,SP_PTREGS(%r15) # load pt_regs as parameter
421 l %r1,BASED(.Lrt_sigreturn)
422 br %r1 # branch to sys_sigreturn
423
424sys_sigaltstack_glue:
425 la %r4,SP_PTREGS(%r15) # load pt_regs as parameter
426 l %r1,BASED(.Lsigaltstack)
427 br %r1 # branch to sys_sigreturn
428 413
429/* 414/*
430 * Program check handler routine 415 * Program check handler routine
@@ -1031,19 +1016,11 @@ cleanup_io_leave_insn:
1031.Ldo_extint: .long do_extint 1016.Ldo_extint: .long do_extint
1032.Ldo_signal: .long do_signal 1017.Ldo_signal: .long do_signal
1033.Lhandle_per: .long do_single_step 1018.Lhandle_per: .long do_single_step
1019.Ldo_execve: .long do_execve
1020.Lexecve_tail: .long execve_tail
1034.Ljump_table: .long pgm_check_table 1021.Ljump_table: .long pgm_check_table
1035.Lschedule: .long schedule 1022.Lschedule: .long schedule
1036.Lclone: .long sys_clone
1037.Lexecve: .long sys_execve
1038.Lfork: .long sys_fork
1039.Lrt_sigreturn: .long sys_rt_sigreturn
1040.Lrt_sigsuspend:
1041 .long sys_rt_sigsuspend
1042.Lsigreturn: .long sys_sigreturn
1043.Lsigsuspend: .long sys_sigsuspend
1044.Lsigaltstack: .long sys_sigaltstack
1045.Ltrace: .long syscall_trace 1023.Ltrace: .long syscall_trace
1046.Lvfork: .long sys_vfork
1047.Lschedtail: .long schedule_tail 1024.Lschedtail: .long schedule_tail
1048.Lsysc_table: .long sys_call_table 1025.Lsysc_table: .long sys_call_table
1049#ifdef CONFIG_TRACE_IRQFLAGS 1026#ifdef CONFIG_TRACE_IRQFLAGS
diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S
index 0f758c329a5d..93745fd8f555 100644
--- a/arch/s390/kernel/entry64.S
+++ b/arch/s390/kernel/entry64.S
@@ -244,8 +244,6 @@ sysc_noemu:
244 jnz sysc_tracesys 244 jnz sysc_tracesys
245 basr %r14,%r8 # call sys_xxxx 245 basr %r14,%r8 # call sys_xxxx
246 stg %r2,SP_R2(%r15) # store return value (change R2 on stack) 246 stg %r2,SP_R2(%r15) # store return value (change R2 on stack)
247 # ATTENTION: check sys_execve_glue before
248 # changing anything here !!
249 247
250sysc_return: 248sysc_return:
251 tm SP_PSW+1(%r15),0x01 # returning to user ? 249 tm SP_PSW+1(%r15),0x01 # returning to user ?
@@ -371,77 +369,35 @@ ret_from_fork:
371 j sysc_return 369 j sysc_return
372 370
373# 371#
374# clone, fork, vfork, exec and sigreturn need glue, 372# kernel_execve function needs to deal with pt_regs that is not
375# because they all expect pt_regs as parameter, 373# at the usual place
376# but are called with different parameter.
377# return-address is set up above
378# 374#
379sys_clone_glue: 375 .globl kernel_execve
380 la %r2,SP_PTREGS(%r15) # load pt_regs 376kernel_execve:
381 jg sys_clone # branch to sys_clone 377 stmg %r12,%r15,96(%r15)
382 378 lgr %r14,%r15
383#ifdef CONFIG_COMPAT 379 aghi %r15,-SP_SIZE
384sys32_clone_glue: 380 stg %r14,__SF_BACKCHAIN(%r15)
385 la %r2,SP_PTREGS(%r15) # load pt_regs 381 la %r12,SP_PTREGS(%r15)
386 jg sys32_clone # branch to sys32_clone 382 xc 0(__PT_SIZE,%r12),0(%r12)
387#endif 383 lgr %r5,%r12
388 384 brasl %r14,do_execve
389sys_fork_glue: 385 ltgfr %r2,%r2
390 la %r2,SP_PTREGS(%r15) # load pt_regs 386 je 0f
391 jg sys_fork # branch to sys_fork 387 aghi %r15,SP_SIZE
392 388 lmg %r12,%r15,96(%r15)
393sys_vfork_glue: 389 br %r14
394 la %r2,SP_PTREGS(%r15) # load pt_regs 390 # execve succeeded.
395 jg sys_vfork # branch to sys_vfork 3910: stnsm __SF_EMPTY(%r15),0xfc # disable interrupts
396 392 lg %r15,__LC_KERNEL_STACK # load ksp
397sys_execve_glue: 393 aghi %r15,-SP_SIZE # make room for registers & psw
398 la %r2,SP_PTREGS(%r15) # load pt_regs 394 lg %r13,__LC_SVC_NEW_PSW+8
399 lgr %r12,%r14 # save return address 395 lg %r9,__LC_THREAD_INFO
400 brasl %r14,sys_execve # call sys_execve 396 mvc SP_PTREGS(__PT_SIZE,%r15),0(%r12) # copy pt_regs
401 ltgr %r2,%r2 # check if execve failed 397 xc __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15)
402 bnz 0(%r12) # it did fail -> store result in gpr2 398 stosm __SF_EMPTY(%r15),0x03 # reenable interrupts
403 b 6(%r12) # SKIP STG 2,SP_R2(15) in 399 brasl %r14,execve_tail
404 # system_call/sysc_tracesys 400 j sysc_return
405#ifdef CONFIG_COMPAT
406sys32_execve_glue:
407 la %r2,SP_PTREGS(%r15) # load pt_regs
408 lgr %r12,%r14 # save return address
409 brasl %r14,sys32_execve # call sys32_execve
410 ltgr %r2,%r2 # check if execve failed
411 bnz 0(%r12) # it did fail -> store result in gpr2
412 b 6(%r12) # SKIP STG 2,SP_R2(15) in
413 # system_call/sysc_tracesys
414#endif
415
416sys_sigreturn_glue:
417 la %r2,SP_PTREGS(%r15) # load pt_regs as parameter
418 jg sys_sigreturn # branch to sys_sigreturn
419
420#ifdef CONFIG_COMPAT
421sys32_sigreturn_glue:
422 la %r2,SP_PTREGS(%r15) # load pt_regs as parameter
423 jg sys32_sigreturn # branch to sys32_sigreturn
424#endif
425
426sys_rt_sigreturn_glue:
427 la %r2,SP_PTREGS(%r15) # load pt_regs as parameter
428 jg sys_rt_sigreturn # branch to sys_sigreturn
429
430#ifdef CONFIG_COMPAT
431sys32_rt_sigreturn_glue:
432 la %r2,SP_PTREGS(%r15) # load pt_regs as parameter
433 jg sys32_rt_sigreturn # branch to sys32_sigreturn
434#endif
435
436sys_sigaltstack_glue:
437 la %r4,SP_PTREGS(%r15) # load pt_regs as parameter
438 jg sys_sigaltstack # branch to sys_sigreturn
439
440#ifdef CONFIG_COMPAT
441sys32_sigaltstack_glue:
442 la %r4,SP_PTREGS(%r15) # load pt_regs as parameter
443 jg sys32_sigaltstack_wrapper # branch to sys_sigreturn
444#endif
445 401
446/* 402/*
447 * Program check handler routine 403 * Program check handler routine
diff --git a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c
index 5acfac654f9d..11d9b0197626 100644
--- a/arch/s390/kernel/process.c
+++ b/arch/s390/kernel/process.c
@@ -280,24 +280,26 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long new_stackp,
280 return 0; 280 return 0;
281} 281}
282 282
283asmlinkage long sys_fork(struct pt_regs regs) 283asmlinkage long sys_fork(void)
284{ 284{
285 return do_fork(SIGCHLD, regs.gprs[15], &regs, 0, NULL, NULL); 285 struct pt_regs *regs = task_pt_regs(current);
286 return do_fork(SIGCHLD, regs->gprs[15], regs, 0, NULL, NULL);
286} 287}
287 288
288asmlinkage long sys_clone(struct pt_regs regs) 289asmlinkage long sys_clone(void)
289{ 290{
290 unsigned long clone_flags; 291 struct pt_regs *regs = task_pt_regs(current);
291 unsigned long newsp; 292 unsigned long clone_flags;
293 unsigned long newsp;
292 int __user *parent_tidptr, *child_tidptr; 294 int __user *parent_tidptr, *child_tidptr;
293 295
294 clone_flags = regs.gprs[3]; 296 clone_flags = regs->gprs[3];
295 newsp = regs.orig_gpr2; 297 newsp = regs->orig_gpr2;
296 parent_tidptr = (int __user *) regs.gprs[4]; 298 parent_tidptr = (int __user *) regs->gprs[4];
297 child_tidptr = (int __user *) regs.gprs[5]; 299 child_tidptr = (int __user *) regs->gprs[5];
298 if (!newsp) 300 if (!newsp)
299 newsp = regs.gprs[15]; 301 newsp = regs->gprs[15];
300 return do_fork(clone_flags, newsp, &regs, 0, 302 return do_fork(clone_flags, newsp, regs, 0,
301 parent_tidptr, child_tidptr); 303 parent_tidptr, child_tidptr);
302} 304}
303 305
@@ -311,40 +313,52 @@ asmlinkage long sys_clone(struct pt_regs regs)
311 * do not have enough call-clobbered registers to hold all 313 * do not have enough call-clobbered registers to hold all
312 * the information you need. 314 * the information you need.
313 */ 315 */
314asmlinkage long sys_vfork(struct pt_regs regs) 316asmlinkage long sys_vfork(void)
315{ 317{
318 struct pt_regs *regs = task_pt_regs(current);
316 return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, 319 return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD,
317 regs.gprs[15], &regs, 0, NULL, NULL); 320 regs->gprs[15], regs, 0, NULL, NULL);
321}
322
323asmlinkage void execve_tail(void)
324{
325 task_lock(current);
326 current->ptrace &= ~PT_DTRACE;
327 task_unlock(current);
328 current->thread.fp_regs.fpc = 0;
329 if (MACHINE_HAS_IEEE)
330 asm volatile("sfpc %0,%0" : : "d" (0));
318} 331}
319 332
320/* 333/*
321 * sys_execve() executes a new program. 334 * sys_execve() executes a new program.
322 */ 335 */
323asmlinkage long sys_execve(struct pt_regs regs) 336asmlinkage long sys_execve(void)
324{ 337{
325 int error; 338 struct pt_regs *regs = task_pt_regs(current);
326 char * filename; 339 char *filename;
327 340 unsigned long result;
328 filename = getname((char __user *) regs.orig_gpr2); 341 int rc;
329 error = PTR_ERR(filename); 342
330 if (IS_ERR(filename)) 343 filename = getname((char __user *) regs->orig_gpr2);
331 goto out; 344 if (IS_ERR(filename)) {
332 error = do_execve(filename, (char __user * __user *) regs.gprs[3], 345 result = PTR_ERR(filename);
333 (char __user * __user *) regs.gprs[4], &regs); 346 goto out;
334 if (error == 0) {
335 task_lock(current);
336 current->ptrace &= ~PT_DTRACE;
337 task_unlock(current);
338 current->thread.fp_regs.fpc = 0;
339 if (MACHINE_HAS_IEEE)
340 asm volatile("sfpc %0,%0" : : "d" (0));
341 } 347 }
342 putname(filename); 348 rc = do_execve(filename, (char __user * __user *) regs->gprs[3],
349 (char __user * __user *) regs->gprs[4], regs);
350 if (rc) {
351 result = rc;
352 goto out_putname;
353 }
354 execve_tail();
355 result = regs->gprs[2];
356out_putname:
357 putname(filename);
343out: 358out:
344 return error; 359 return result;
345} 360}
346 361
347
348/* 362/*
349 * fill in the FPU structure for a core dump. 363 * fill in the FPU structure for a core dump.
350 */ 364 */
diff --git a/arch/s390/kernel/signal.c b/arch/s390/kernel/signal.c
index 554f9cf7499c..3c41907799a1 100644
--- a/arch/s390/kernel/signal.c
+++ b/arch/s390/kernel/signal.c
@@ -102,9 +102,9 @@ sys_sigaction(int sig, const struct old_sigaction __user *act,
102} 102}
103 103
104asmlinkage long 104asmlinkage long
105sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, 105sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss)
106 struct pt_regs *regs)
107{ 106{
107 struct pt_regs *regs = task_pt_regs(current);
108 return do_sigaltstack(uss, uoss, regs->gprs[15]); 108 return do_sigaltstack(uss, uoss, regs->gprs[15]);
109} 109}
110 110
@@ -163,8 +163,9 @@ static int restore_sigregs(struct pt_regs *regs, _sigregs __user *sregs)
163 return 0; 163 return 0;
164} 164}
165 165
166asmlinkage long sys_sigreturn(struct pt_regs *regs) 166asmlinkage long sys_sigreturn(void)
167{ 167{
168 struct pt_regs *regs = task_pt_regs(current);
168 sigframe __user *frame = (sigframe __user *)regs->gprs[15]; 169 sigframe __user *frame = (sigframe __user *)regs->gprs[15];
169 sigset_t set; 170 sigset_t set;
170 171
@@ -189,8 +190,9 @@ badframe:
189 return 0; 190 return 0;
190} 191}
191 192
192asmlinkage long sys_rt_sigreturn(struct pt_regs *regs) 193asmlinkage long sys_rt_sigreturn(void)
193{ 194{
195 struct pt_regs *regs = task_pt_regs(current);
194 rt_sigframe __user *frame = (rt_sigframe __user *)regs->gprs[15]; 196 rt_sigframe __user *frame = (rt_sigframe __user *)regs->gprs[15];
195 sigset_t set; 197 sigset_t set;
196 198
diff --git a/arch/s390/kernel/sys_s390.c b/arch/s390/kernel/sys_s390.c
index 584ed95f3380..3a77c22cda78 100644
--- a/arch/s390/kernel/sys_s390.c
+++ b/arch/s390/kernel/sys_s390.c
@@ -266,23 +266,3 @@ s390_fadvise64_64(struct fadvise64_64_args __user *args)
266 return -EFAULT; 266 return -EFAULT;
267 return sys_fadvise64_64(a.fd, a.offset, a.len, a.advice); 267 return sys_fadvise64_64(a.fd, a.offset, a.len, a.advice);
268} 268}
269
270/*
271 * Do a system call from kernel instead of calling sys_execve so we
272 * end up with proper pt_regs.
273 */
274int kernel_execve(const char *filename, char *const argv[], char *const envp[])
275{
276 register const char *__arg1 asm("2") = filename;
277 register char *const*__arg2 asm("3") = argv;
278 register char *const*__arg3 asm("4") = envp;
279 register long __svcres asm("2");
280 asm volatile(
281 "svc %b1"
282 : "=d" (__svcres)
283 : "i" (__NR_execve),
284 "0" (__arg1),
285 "d" (__arg2),
286 "d" (__arg3) : "memory");
287 return __svcres;
288}
diff --git a/arch/s390/kernel/syscalls.S b/arch/s390/kernel/syscalls.S
index c774f1069e10..cd8d321cd0c2 100644
--- a/arch/s390/kernel/syscalls.S
+++ b/arch/s390/kernel/syscalls.S
@@ -10,7 +10,7 @@
10 10
11NI_SYSCALL /* 0 */ 11NI_SYSCALL /* 0 */
12SYSCALL(sys_exit,sys_exit,sys32_exit_wrapper) 12SYSCALL(sys_exit,sys_exit,sys32_exit_wrapper)
13SYSCALL(sys_fork_glue,sys_fork_glue,sys_fork_glue) 13SYSCALL(sys_fork,sys_fork,sys_fork)
14SYSCALL(sys_read,sys_read,sys32_read_wrapper) 14SYSCALL(sys_read,sys_read,sys32_read_wrapper)
15SYSCALL(sys_write,sys_write,sys32_write_wrapper) 15SYSCALL(sys_write,sys_write,sys32_write_wrapper)
16SYSCALL(sys_open,sys_open,sys32_open_wrapper) /* 5 */ 16SYSCALL(sys_open,sys_open,sys32_open_wrapper) /* 5 */
@@ -19,7 +19,7 @@ SYSCALL(sys_restart_syscall,sys_restart_syscall,sys_restart_syscall)
19SYSCALL(sys_creat,sys_creat,sys32_creat_wrapper) 19SYSCALL(sys_creat,sys_creat,sys32_creat_wrapper)
20SYSCALL(sys_link,sys_link,sys32_link_wrapper) 20SYSCALL(sys_link,sys_link,sys32_link_wrapper)
21SYSCALL(sys_unlink,sys_unlink,sys32_unlink_wrapper) /* 10 */ 21SYSCALL(sys_unlink,sys_unlink,sys32_unlink_wrapper) /* 10 */
22SYSCALL(sys_execve_glue,sys_execve_glue,sys32_execve_glue) 22SYSCALL(sys_execve,sys_execve,sys32_execve)
23SYSCALL(sys_chdir,sys_chdir,sys32_chdir_wrapper) 23SYSCALL(sys_chdir,sys_chdir,sys32_chdir_wrapper)
24SYSCALL(sys_time,sys_ni_syscall,sys32_time_wrapper) /* old time syscall */ 24SYSCALL(sys_time,sys_ni_syscall,sys32_time_wrapper) /* old time syscall */
25SYSCALL(sys_mknod,sys_mknod,sys32_mknod_wrapper) 25SYSCALL(sys_mknod,sys_mknod,sys32_mknod_wrapper)
@@ -127,8 +127,8 @@ SYSCALL(sys_swapoff,sys_swapoff,sys32_swapoff_wrapper) /* 115 */
127SYSCALL(sys_sysinfo,sys_sysinfo,compat_sys_sysinfo_wrapper) 127SYSCALL(sys_sysinfo,sys_sysinfo,compat_sys_sysinfo_wrapper)
128SYSCALL(sys_ipc,sys_ipc,sys32_ipc_wrapper) 128SYSCALL(sys_ipc,sys_ipc,sys32_ipc_wrapper)
129SYSCALL(sys_fsync,sys_fsync,sys32_fsync_wrapper) 129SYSCALL(sys_fsync,sys_fsync,sys32_fsync_wrapper)
130SYSCALL(sys_sigreturn_glue,sys_sigreturn_glue,sys32_sigreturn_glue) 130SYSCALL(sys_sigreturn,sys_sigreturn,sys32_sigreturn)
131SYSCALL(sys_clone_glue,sys_clone_glue,sys32_clone_glue) /* 120 */ 131SYSCALL(sys_clone,sys_clone,sys32_clone) /* 120 */
132SYSCALL(sys_setdomainname,sys_setdomainname,sys32_setdomainname_wrapper) 132SYSCALL(sys_setdomainname,sys_setdomainname,sys32_setdomainname_wrapper)
133SYSCALL(sys_newuname,s390x_newuname,sys32_newuname_wrapper) 133SYSCALL(sys_newuname,s390x_newuname,sys32_newuname_wrapper)
134NI_SYSCALL /* modify_ldt for i386 */ 134NI_SYSCALL /* modify_ldt for i386 */
@@ -181,7 +181,7 @@ SYSCALL(sys_nfsservctl,sys_nfsservctl,compat_sys_nfsservctl_wrapper)
181SYSCALL(sys_setresgid16,sys_ni_syscall,sys32_setresgid16_wrapper) /* 170 old setresgid16 syscall */ 181SYSCALL(sys_setresgid16,sys_ni_syscall,sys32_setresgid16_wrapper) /* 170 old setresgid16 syscall */
182SYSCALL(sys_getresgid16,sys_ni_syscall,sys32_getresgid16_wrapper) /* old getresgid16 syscall */ 182SYSCALL(sys_getresgid16,sys_ni_syscall,sys32_getresgid16_wrapper) /* old getresgid16 syscall */
183SYSCALL(sys_prctl,sys_prctl,sys32_prctl_wrapper) 183SYSCALL(sys_prctl,sys_prctl,sys32_prctl_wrapper)
184SYSCALL(sys_rt_sigreturn_glue,sys_rt_sigreturn_glue,sys32_rt_sigreturn_glue) 184SYSCALL(sys_rt_sigreturn,sys_rt_sigreturn,sys32_rt_sigreturn)
185SYSCALL(sys_rt_sigaction,sys_rt_sigaction,sys32_rt_sigaction_wrapper) 185SYSCALL(sys_rt_sigaction,sys_rt_sigaction,sys32_rt_sigaction_wrapper)
186SYSCALL(sys_rt_sigprocmask,sys_rt_sigprocmask,sys32_rt_sigprocmask_wrapper) /* 175 */ 186SYSCALL(sys_rt_sigprocmask,sys_rt_sigprocmask,sys32_rt_sigprocmask_wrapper) /* 175 */
187SYSCALL(sys_rt_sigpending,sys_rt_sigpending,sys32_rt_sigpending_wrapper) 187SYSCALL(sys_rt_sigpending,sys_rt_sigpending,sys32_rt_sigpending_wrapper)
@@ -194,11 +194,11 @@ SYSCALL(sys_chown16,sys_ni_syscall,sys32_chown16_wrapper) /* old chown16 syscall
194SYSCALL(sys_getcwd,sys_getcwd,sys32_getcwd_wrapper) 194SYSCALL(sys_getcwd,sys_getcwd,sys32_getcwd_wrapper)
195SYSCALL(sys_capget,sys_capget,sys32_capget_wrapper) 195SYSCALL(sys_capget,sys_capget,sys32_capget_wrapper)
196SYSCALL(sys_capset,sys_capset,sys32_capset_wrapper) /* 185 */ 196SYSCALL(sys_capset,sys_capset,sys32_capset_wrapper) /* 185 */
197SYSCALL(sys_sigaltstack_glue,sys_sigaltstack_glue,sys32_sigaltstack_glue) 197SYSCALL(sys_sigaltstack,sys_sigaltstack,sys32_sigaltstack)
198SYSCALL(sys_sendfile,sys_sendfile64,sys32_sendfile_wrapper) 198SYSCALL(sys_sendfile,sys_sendfile64,sys32_sendfile_wrapper)
199NI_SYSCALL /* streams1 */ 199NI_SYSCALL /* streams1 */
200NI_SYSCALL /* streams2 */ 200NI_SYSCALL /* streams2 */
201SYSCALL(sys_vfork_glue,sys_vfork_glue,sys_vfork_glue) /* 190 */ 201SYSCALL(sys_vfork,sys_vfork,sys_vfork) /* 190 */
202SYSCALL(sys_getrlimit,sys_getrlimit,compat_sys_getrlimit_wrapper) 202SYSCALL(sys_getrlimit,sys_getrlimit,compat_sys_getrlimit_wrapper)
203SYSCALL(sys_mmap2,sys_mmap2,sys32_mmap2_wrapper) 203SYSCALL(sys_mmap2,sys_mmap2,sys32_mmap2_wrapper)
204SYSCALL(sys_truncate64,sys_ni_syscall,sys32_truncate64_wrapper) 204SYSCALL(sys_truncate64,sys_ni_syscall,sys32_truncate64_wrapper)