linux/arch/sparc/kernel/process.c
<<
>>
Prefs
   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}
 111