Linux Audio

Check our new training course

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