diff options
author | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2007-04-27 10:01:40 -0400 |
---|---|---|
committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2007-04-27 10:01:42 -0400 |
commit | 03ff9a235a0602724fc54916469b6e0939c62c9b (patch) | |
tree | 86ab2236897eb59542be2ccd667d6ca221153a44 /arch/s390 | |
parent | ef99516c9646802c3d38c3eb83de302e05b3c1b5 (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>
Diffstat (limited to 'arch/s390')
-rw-r--r-- | arch/s390/kernel/compat_linux.c | 60 | ||||
-rw-r--r-- | arch/s390/kernel/compat_signal.c | 14 | ||||
-rw-r--r-- | arch/s390/kernel/entry.S | 87 | ||||
-rw-r--r-- | arch/s390/kernel/entry64.S | 100 | ||||
-rw-r--r-- | arch/s390/kernel/process.c | 82 | ||||
-rw-r--r-- | arch/s390/kernel/signal.c | 10 | ||||
-rw-r--r-- | arch/s390/kernel/sys_s390.c | 20 | ||||
-rw-r--r-- | arch/s390/kernel/syscalls.S | 14 |
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 | */ |
498 | asmlinkage long | 498 | asmlinkage long sys32_execve(void) |
499 | sys32_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]), ®s); | ||
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]; | ||
522 | out_putname: | ||
518 | putname(filename); | 523 | putname(filename); |
519 | out: | 524 | out: |
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 | ||
921 | asmlinkage long sys32_clone(struct pt_regs regs) | 926 | asmlinkage 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, ®s, 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 | ||
257 | asmlinkage long | 257 | asmlinkage long |
258 | sys32_sigaltstack(const stack_t32 __user *uss, stack_t32 __user *uoss, | 258 | sys32_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 | ||
347 | asmlinkage long sys32_sigreturn(struct pt_regs *regs) | 347 | asmlinkage 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 | ||
373 | asmlinkage long sys32_rt_sigreturn(struct pt_regs *regs) | 374 | asmlinkage 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 | ||
409 | badframe: | 411 | badframe: |
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 | ||
255 | sysc_return: | 253 | sysc_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 | # |
389 | sys_clone_glue: | 385 | .globl kernel_execve |
390 | la %r2,SP_PTREGS(%r15) # load pt_regs | 386 | kernel_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 | |
394 | sys_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) | |
399 | sys_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) | |
404 | sys_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 | 403 | 0: 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 | |
414 | sys_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 | |||
419 | sys_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 | |||
424 | sys_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 | ||
250 | sysc_return: | 248 | sysc_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 | # |
379 | sys_clone_glue: | 375 | .globl kernel_execve |
380 | la %r2,SP_PTREGS(%r15) # load pt_regs | 376 | kernel_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 |
384 | sys32_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 | |
389 | sys_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) | |
393 | sys_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 | 391 | 0: stnsm __SF_EMPTY(%r15),0xfc # disable interrupts |
396 | 392 | lg %r15,__LC_KERNEL_STACK # load ksp | |
397 | sys_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 | ||
406 | sys32_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 | |||
416 | sys_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 | ||
421 | sys32_sigreturn_glue: | ||
422 | la %r2,SP_PTREGS(%r15) # load pt_regs as parameter | ||
423 | jg sys32_sigreturn # branch to sys32_sigreturn | ||
424 | #endif | ||
425 | |||
426 | sys_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 | ||
431 | sys32_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 | |||
436 | sys_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 | ||
441 | sys32_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 | ||
283 | asmlinkage long sys_fork(struct pt_regs regs) | 283 | asmlinkage long sys_fork(void) |
284 | { | 284 | { |
285 | return do_fork(SIGCHLD, regs.gprs[15], ®s, 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 | ||
288 | asmlinkage long sys_clone(struct pt_regs regs) | 289 | asmlinkage 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, ®s, 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 | */ |
314 | asmlinkage long sys_vfork(struct pt_regs regs) | 316 | asmlinkage 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], ®s, 0, NULL, NULL); | 320 | regs->gprs[15], regs, 0, NULL, NULL); |
321 | } | ||
322 | |||
323 | asmlinkage 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 | */ |
323 | asmlinkage long sys_execve(struct pt_regs regs) | 336 | asmlinkage 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], ®s); | 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]; | ||
356 | out_putname: | ||
357 | putname(filename); | ||
343 | out: | 358 | out: |
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 | ||
104 | asmlinkage long | 104 | asmlinkage long |
105 | sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, | 105 | sys_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 | ||
166 | asmlinkage long sys_sigreturn(struct pt_regs *regs) | 166 | asmlinkage 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 | ||
192 | asmlinkage long sys_rt_sigreturn(struct pt_regs *regs) | 193 | asmlinkage 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 | */ | ||
274 | int 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 | ||
11 | NI_SYSCALL /* 0 */ | 11 | NI_SYSCALL /* 0 */ |
12 | SYSCALL(sys_exit,sys_exit,sys32_exit_wrapper) | 12 | SYSCALL(sys_exit,sys_exit,sys32_exit_wrapper) |
13 | SYSCALL(sys_fork_glue,sys_fork_glue,sys_fork_glue) | 13 | SYSCALL(sys_fork,sys_fork,sys_fork) |
14 | SYSCALL(sys_read,sys_read,sys32_read_wrapper) | 14 | SYSCALL(sys_read,sys_read,sys32_read_wrapper) |
15 | SYSCALL(sys_write,sys_write,sys32_write_wrapper) | 15 | SYSCALL(sys_write,sys_write,sys32_write_wrapper) |
16 | SYSCALL(sys_open,sys_open,sys32_open_wrapper) /* 5 */ | 16 | SYSCALL(sys_open,sys_open,sys32_open_wrapper) /* 5 */ |
@@ -19,7 +19,7 @@ SYSCALL(sys_restart_syscall,sys_restart_syscall,sys_restart_syscall) | |||
19 | SYSCALL(sys_creat,sys_creat,sys32_creat_wrapper) | 19 | SYSCALL(sys_creat,sys_creat,sys32_creat_wrapper) |
20 | SYSCALL(sys_link,sys_link,sys32_link_wrapper) | 20 | SYSCALL(sys_link,sys_link,sys32_link_wrapper) |
21 | SYSCALL(sys_unlink,sys_unlink,sys32_unlink_wrapper) /* 10 */ | 21 | SYSCALL(sys_unlink,sys_unlink,sys32_unlink_wrapper) /* 10 */ |
22 | SYSCALL(sys_execve_glue,sys_execve_glue,sys32_execve_glue) | 22 | SYSCALL(sys_execve,sys_execve,sys32_execve) |
23 | SYSCALL(sys_chdir,sys_chdir,sys32_chdir_wrapper) | 23 | SYSCALL(sys_chdir,sys_chdir,sys32_chdir_wrapper) |
24 | SYSCALL(sys_time,sys_ni_syscall,sys32_time_wrapper) /* old time syscall */ | 24 | SYSCALL(sys_time,sys_ni_syscall,sys32_time_wrapper) /* old time syscall */ |
25 | SYSCALL(sys_mknod,sys_mknod,sys32_mknod_wrapper) | 25 | SYSCALL(sys_mknod,sys_mknod,sys32_mknod_wrapper) |
@@ -127,8 +127,8 @@ SYSCALL(sys_swapoff,sys_swapoff,sys32_swapoff_wrapper) /* 115 */ | |||
127 | SYSCALL(sys_sysinfo,sys_sysinfo,compat_sys_sysinfo_wrapper) | 127 | SYSCALL(sys_sysinfo,sys_sysinfo,compat_sys_sysinfo_wrapper) |
128 | SYSCALL(sys_ipc,sys_ipc,sys32_ipc_wrapper) | 128 | SYSCALL(sys_ipc,sys_ipc,sys32_ipc_wrapper) |
129 | SYSCALL(sys_fsync,sys_fsync,sys32_fsync_wrapper) | 129 | SYSCALL(sys_fsync,sys_fsync,sys32_fsync_wrapper) |
130 | SYSCALL(sys_sigreturn_glue,sys_sigreturn_glue,sys32_sigreturn_glue) | 130 | SYSCALL(sys_sigreturn,sys_sigreturn,sys32_sigreturn) |
131 | SYSCALL(sys_clone_glue,sys_clone_glue,sys32_clone_glue) /* 120 */ | 131 | SYSCALL(sys_clone,sys_clone,sys32_clone) /* 120 */ |
132 | SYSCALL(sys_setdomainname,sys_setdomainname,sys32_setdomainname_wrapper) | 132 | SYSCALL(sys_setdomainname,sys_setdomainname,sys32_setdomainname_wrapper) |
133 | SYSCALL(sys_newuname,s390x_newuname,sys32_newuname_wrapper) | 133 | SYSCALL(sys_newuname,s390x_newuname,sys32_newuname_wrapper) |
134 | NI_SYSCALL /* modify_ldt for i386 */ | 134 | NI_SYSCALL /* modify_ldt for i386 */ |
@@ -181,7 +181,7 @@ SYSCALL(sys_nfsservctl,sys_nfsservctl,compat_sys_nfsservctl_wrapper) | |||
181 | SYSCALL(sys_setresgid16,sys_ni_syscall,sys32_setresgid16_wrapper) /* 170 old setresgid16 syscall */ | 181 | SYSCALL(sys_setresgid16,sys_ni_syscall,sys32_setresgid16_wrapper) /* 170 old setresgid16 syscall */ |
182 | SYSCALL(sys_getresgid16,sys_ni_syscall,sys32_getresgid16_wrapper) /* old getresgid16 syscall */ | 182 | SYSCALL(sys_getresgid16,sys_ni_syscall,sys32_getresgid16_wrapper) /* old getresgid16 syscall */ |
183 | SYSCALL(sys_prctl,sys_prctl,sys32_prctl_wrapper) | 183 | SYSCALL(sys_prctl,sys_prctl,sys32_prctl_wrapper) |
184 | SYSCALL(sys_rt_sigreturn_glue,sys_rt_sigreturn_glue,sys32_rt_sigreturn_glue) | 184 | SYSCALL(sys_rt_sigreturn,sys_rt_sigreturn,sys32_rt_sigreturn) |
185 | SYSCALL(sys_rt_sigaction,sys_rt_sigaction,sys32_rt_sigaction_wrapper) | 185 | SYSCALL(sys_rt_sigaction,sys_rt_sigaction,sys32_rt_sigaction_wrapper) |
186 | SYSCALL(sys_rt_sigprocmask,sys_rt_sigprocmask,sys32_rt_sigprocmask_wrapper) /* 175 */ | 186 | SYSCALL(sys_rt_sigprocmask,sys_rt_sigprocmask,sys32_rt_sigprocmask_wrapper) /* 175 */ |
187 | SYSCALL(sys_rt_sigpending,sys_rt_sigpending,sys32_rt_sigpending_wrapper) | 187 | SYSCALL(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 | |||
194 | SYSCALL(sys_getcwd,sys_getcwd,sys32_getcwd_wrapper) | 194 | SYSCALL(sys_getcwd,sys_getcwd,sys32_getcwd_wrapper) |
195 | SYSCALL(sys_capget,sys_capget,sys32_capget_wrapper) | 195 | SYSCALL(sys_capget,sys_capget,sys32_capget_wrapper) |
196 | SYSCALL(sys_capset,sys_capset,sys32_capset_wrapper) /* 185 */ | 196 | SYSCALL(sys_capset,sys_capset,sys32_capset_wrapper) /* 185 */ |
197 | SYSCALL(sys_sigaltstack_glue,sys_sigaltstack_glue,sys32_sigaltstack_glue) | 197 | SYSCALL(sys_sigaltstack,sys_sigaltstack,sys32_sigaltstack) |
198 | SYSCALL(sys_sendfile,sys_sendfile64,sys32_sendfile_wrapper) | 198 | SYSCALL(sys_sendfile,sys_sendfile64,sys32_sendfile_wrapper) |
199 | NI_SYSCALL /* streams1 */ | 199 | NI_SYSCALL /* streams1 */ |
200 | NI_SYSCALL /* streams2 */ | 200 | NI_SYSCALL /* streams2 */ |
201 | SYSCALL(sys_vfork_glue,sys_vfork_glue,sys_vfork_glue) /* 190 */ | 201 | SYSCALL(sys_vfork,sys_vfork,sys_vfork) /* 190 */ |
202 | SYSCALL(sys_getrlimit,sys_getrlimit,compat_sys_getrlimit_wrapper) | 202 | SYSCALL(sys_getrlimit,sys_getrlimit,compat_sys_getrlimit_wrapper) |
203 | SYSCALL(sys_mmap2,sys_mmap2,sys32_mmap2_wrapper) | 203 | SYSCALL(sys_mmap2,sys_mmap2,sys32_mmap2_wrapper) |
204 | SYSCALL(sys_truncate64,sys_ni_syscall,sys32_truncate64_wrapper) | 204 | SYSCALL(sys_truncate64,sys_ni_syscall,sys32_truncate64_wrapper) |