diff options
| -rw-r--r-- | arch/sparc/kernel/process.c | 20 | ||||
| -rw-r--r-- | arch/sparc64/kernel/process.c | 18 |
2 files changed, 31 insertions, 7 deletions
diff --git a/arch/sparc/kernel/process.c b/arch/sparc/kernel/process.c index e7f35198ae34..36431f377dee 100644 --- a/arch/sparc/kernel/process.c +++ b/arch/sparc/kernel/process.c | |||
| @@ -419,14 +419,26 @@ asmlinkage int sparc_do_fork(unsigned long clone_flags, | |||
| 419 | unsigned long stack_size) | 419 | unsigned long stack_size) |
| 420 | { | 420 | { |
| 421 | unsigned long parent_tid_ptr, child_tid_ptr; | 421 | unsigned long parent_tid_ptr, child_tid_ptr; |
| 422 | unsigned long orig_i1 = regs->u_regs[UREG_I1]; | ||
| 423 | long ret; | ||
| 422 | 424 | ||
| 423 | parent_tid_ptr = regs->u_regs[UREG_I2]; | 425 | parent_tid_ptr = regs->u_regs[UREG_I2]; |
| 424 | child_tid_ptr = regs->u_regs[UREG_I4]; | 426 | child_tid_ptr = regs->u_regs[UREG_I4]; |
| 425 | 427 | ||
| 426 | return do_fork(clone_flags, stack_start, | 428 | ret = do_fork(clone_flags, stack_start, |
| 427 | regs, stack_size, | 429 | regs, stack_size, |
| 428 | (int __user *) parent_tid_ptr, | 430 | (int __user *) parent_tid_ptr, |
| 429 | (int __user *) child_tid_ptr); | 431 | (int __user *) child_tid_ptr); |
| 432 | |||
| 433 | /* If we get an error and potentially restart the system | ||
| 434 | * call, we're screwed because copy_thread() clobbered | ||
| 435 | * the parent's %o1. So detect that case and restore it | ||
| 436 | * here. | ||
| 437 | */ | ||
| 438 | if ((unsigned long)ret >= -ERESTART_RESTARTBLOCK) | ||
| 439 | regs->u_regs[UREG_I1] = orig_i1; | ||
| 440 | |||
| 441 | return ret; | ||
| 430 | } | 442 | } |
| 431 | 443 | ||
| 432 | /* Copy a Sparc thread. The fork() return value conventions | 444 | /* Copy a Sparc thread. The fork() return value conventions |
diff --git a/arch/sparc64/kernel/process.c b/arch/sparc64/kernel/process.c index 500ac6d483a0..4129c0449856 100644 --- a/arch/sparc64/kernel/process.c +++ b/arch/sparc64/kernel/process.c | |||
| @@ -503,6 +503,8 @@ asmlinkage long sparc_do_fork(unsigned long clone_flags, | |||
| 503 | unsigned long stack_size) | 503 | unsigned long stack_size) |
| 504 | { | 504 | { |
| 505 | int __user *parent_tid_ptr, *child_tid_ptr; | 505 | int __user *parent_tid_ptr, *child_tid_ptr; |
| 506 | unsigned long orig_i1 = regs->u_regs[UREG_I1]; | ||
| 507 | long ret; | ||
| 506 | 508 | ||
| 507 | #ifdef CONFIG_COMPAT | 509 | #ifdef CONFIG_COMPAT |
| 508 | if (test_thread_flag(TIF_32BIT)) { | 510 | if (test_thread_flag(TIF_32BIT)) { |
| @@ -515,9 +517,19 @@ asmlinkage long sparc_do_fork(unsigned long clone_flags, | |||
| 515 | child_tid_ptr = (int __user *) regs->u_regs[UREG_I4]; | 517 | child_tid_ptr = (int __user *) regs->u_regs[UREG_I4]; |
| 516 | } | 518 | } |
| 517 | 519 | ||
| 518 | return do_fork(clone_flags, stack_start, | 520 | ret = do_fork(clone_flags, stack_start, |
| 519 | regs, stack_size, | 521 | regs, stack_size, |
| 520 | parent_tid_ptr, child_tid_ptr); | 522 | parent_tid_ptr, child_tid_ptr); |
| 523 | |||
| 524 | /* If we get an error and potentially restart the system | ||
| 525 | * call, we're screwed because copy_thread() clobbered | ||
| 526 | * the parent's %o1. So detect that case and restore it | ||
| 527 | * here. | ||
| 528 | */ | ||
| 529 | if ((unsigned long)ret >= -ERESTART_RESTARTBLOCK) | ||
| 530 | regs->u_regs[UREG_I1] = orig_i1; | ||
| 531 | |||
| 532 | return ret; | ||
| 521 | } | 533 | } |
| 522 | 534 | ||
| 523 | /* Copy a Sparc thread. The fork() return value conventions | 535 | /* Copy a Sparc thread. The fork() return value conventions |
