process.c 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * This file handles the architecture independent parts of process handling..
  4. */
  5. #include <linux/compat.h>
  6. #include <linux/errno.h>
  7. #include <linux/kernel.h>
  8. #include <linux/ptrace.h>
  9. #include <linux/sched.h>
  10. #include <linux/sched/task.h>
  11. #include <linux/sched/task_stack.h>
  12. #include <linux/signal.h>
  13. #include "kernel.h"
  14. asmlinkage long sparc_fork(struct pt_regs *regs)
  15. {
  16. unsigned long orig_i1 = regs->u_regs[UREG_I1];
  17. long ret;
  18. struct kernel_clone_args args = {
  19. .exit_signal = SIGCHLD,
  20. /* Reuse the parent's stack for the child. */
  21. .stack = regs->u_regs[UREG_FP],
  22. };
  23. ret = kernel_clone(&args);
  24. /* If we get an error and potentially restart the system
  25. * call, we're screwed because copy_thread() clobbered
  26. * the parent's %o1. So detect that case and restore it
  27. * here.
  28. */
  29. if ((unsigned long)ret >= -ERESTART_RESTARTBLOCK)
  30. regs->u_regs[UREG_I1] = orig_i1;
  31. return ret;
  32. }
  33. asmlinkage long sparc_vfork(struct pt_regs *regs)
  34. {
  35. unsigned long orig_i1 = regs->u_regs[UREG_I1];
  36. long ret;
  37. struct kernel_clone_args args = {
  38. .flags = CLONE_VFORK | CLONE_VM,
  39. .exit_signal = SIGCHLD,
  40. /* Reuse the parent's stack for the child. */
  41. .stack = regs->u_regs[UREG_FP],
  42. };
  43. ret = kernel_clone(&args);
  44. /* If we get an error and potentially restart the system
  45. * call, we're screwed because copy_thread() clobbered
  46. * the parent's %o1. So detect that case and restore it
  47. * here.
  48. */
  49. if ((unsigned long)ret >= -ERESTART_RESTARTBLOCK)
  50. regs->u_regs[UREG_I1] = orig_i1;
  51. return ret;
  52. }
  53. asmlinkage long sparc_clone(struct pt_regs *regs)
  54. {
  55. unsigned long orig_i1 = regs->u_regs[UREG_I1];
  56. unsigned int flags = lower_32_bits(regs->u_regs[UREG_I0]);
  57. long ret;
  58. struct kernel_clone_args args = {
  59. .flags = (flags & ~CSIGNAL),
  60. .exit_signal = (flags & CSIGNAL),
  61. .tls = regs->u_regs[UREG_I3],
  62. };
  63. #ifdef CONFIG_COMPAT
  64. if (test_thread_flag(TIF_32BIT)) {
  65. args.pidfd = compat_ptr(regs->u_regs[UREG_I2]);
  66. args.child_tid = compat_ptr(regs->u_regs[UREG_I4]);
  67. args.parent_tid = compat_ptr(regs->u_regs[UREG_I2]);
  68. } else
  69. #endif
  70. {
  71. args.pidfd = (int __user *)regs->u_regs[UREG_I2];
  72. args.child_tid = (int __user *)regs->u_regs[UREG_I4];
  73. args.parent_tid = (int __user *)regs->u_regs[UREG_I2];
  74. }
  75. /* Did userspace give setup a separate stack for the child or are we
  76. * reusing the parent's?
  77. */
  78. if (regs->u_regs[UREG_I1])
  79. args.stack = regs->u_regs[UREG_I1];
  80. else
  81. args.stack = regs->u_regs[UREG_FP];
  82. ret = kernel_clone(&args);
  83. /* If we get an error and potentially restart the system
  84. * call, we're screwed because copy_thread() clobbered
  85. * the parent's %o1. So detect that case and restore it
  86. * here.
  87. */
  88. if ((unsigned long)ret >= -ERESTART_RESTARTBLOCK)
  89. regs->u_regs[UREG_I1] = orig_i1;
  90. return ret;
  91. }