Loading arch/s390/Kconfig +1 −0 Original line number Diff line number Diff line Loading @@ -141,6 +141,7 @@ config S390 select GENERIC_KERNEL_EXECVE select HAVE_MOD_ARCH_SPECIFIC select MODULES_USE_ELF_RELA select CLONE_BACKWARDS2 config SCHED_OMIT_FRAME_POINTER def_bool y Loading arch/s390/include/asm/unistd.h +3 −0 Original line number Diff line number Diff line Loading @@ -54,6 +54,9 @@ # define __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND # endif #define __ARCH_WANT_SYS_EXECVE #define __ARCH_WANT_SYS_FORK #define __ARCH_WANT_SYS_VFORK #define __ARCH_WANT_SYS_CLONE /* * "Conditional" syscalls Loading arch/s390/kernel/process.c +10 −42 Original line number Diff line number Diff line Loading @@ -118,7 +118,7 @@ void release_thread(struct task_struct *dead_task) int copy_thread(unsigned long clone_flags, unsigned long new_stackp, unsigned long arg, struct task_struct *p, struct pt_regs *regs) struct task_struct *p, struct pt_regs *unused) { struct thread_info *ti; struct fake_frame Loading Loading @@ -150,7 +150,7 @@ int copy_thread(unsigned long clone_flags, unsigned long new_stackp, frame->sf.gprs[9] = (unsigned long) frame; /* Store access registers to kernel stack of new process. */ if (unlikely(!regs)) { if (unlikely(p->flags & PF_KTHREAD)) { /* kernel thread */ memset(&frame->childregs, 0, sizeof(struct pt_regs)); frame->childregs.psw.mask = psw_kernel_bits | PSW_MASK_DAT | Loading @@ -164,8 +164,9 @@ int copy_thread(unsigned long clone_flags, unsigned long new_stackp, return 0; } frame->childregs = *regs; frame->childregs = *current_pt_regs(); frame->childregs.gprs[2] = 0; /* child returns 0 on fork. */ if (new_stackp) frame->childregs.gprs[15] = new_stackp; /* Don't copy runtime instrumentation info */ Loading @@ -183,57 +184,24 @@ int copy_thread(unsigned long clone_flags, unsigned long new_stackp, sizeof(s390_fp_regs)); /* Set a new TLS ? */ if (clone_flags & CLONE_SETTLS) p->thread.acrs[0] = regs->gprs[6]; p->thread.acrs[0] = frame->childregs.gprs[6]; #else /* CONFIG_64BIT */ /* Save the fpu registers to new thread structure. */ save_fp_regs(&p->thread.fp_regs); /* Set a new TLS ? */ if (clone_flags & CLONE_SETTLS) { unsigned long tls = frame->childregs.gprs[6]; if (is_compat_task()) { p->thread.acrs[0] = (unsigned int) regs->gprs[6]; p->thread.acrs[0] = (unsigned int)tls; } else { p->thread.acrs[0] = (unsigned int)(regs->gprs[6] >> 32); p->thread.acrs[1] = (unsigned int) regs->gprs[6]; p->thread.acrs[0] = (unsigned int)(tls >> 32); p->thread.acrs[1] = (unsigned int)tls; } } #endif /* CONFIG_64BIT */ return 0; } SYSCALL_DEFINE0(fork) { struct pt_regs *regs = task_pt_regs(current); return do_fork(SIGCHLD, regs->gprs[15], regs, 0, NULL, NULL); } SYSCALL_DEFINE4(clone, unsigned long, newsp, unsigned long, clone_flags, int __user *, parent_tidptr, int __user *, child_tidptr) { struct pt_regs *regs = task_pt_regs(current); if (!newsp) newsp = regs->gprs[15]; return do_fork(clone_flags, newsp, regs, 0, parent_tidptr, child_tidptr); } /* * This is trivial, and on the face of it looks like it * could equally well be done in user mode. * * Not so, for quite unobvious reasons - register pressure. * In user mode vfork() cannot have a stack frame, and if * done by calling the "clone()" system call directly, you * do not have enough call-clobbered registers to hold all * the information you need. */ SYSCALL_DEFINE0(vfork) { struct pt_regs *regs = task_pt_regs(current); return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->gprs[15], regs, 0, NULL, NULL); } asmlinkage void execve_tail(void) { current->thread.fp_regs.fpc = 0; Loading Loading
arch/s390/Kconfig +1 −0 Original line number Diff line number Diff line Loading @@ -141,6 +141,7 @@ config S390 select GENERIC_KERNEL_EXECVE select HAVE_MOD_ARCH_SPECIFIC select MODULES_USE_ELF_RELA select CLONE_BACKWARDS2 config SCHED_OMIT_FRAME_POINTER def_bool y Loading
arch/s390/include/asm/unistd.h +3 −0 Original line number Diff line number Diff line Loading @@ -54,6 +54,9 @@ # define __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND # endif #define __ARCH_WANT_SYS_EXECVE #define __ARCH_WANT_SYS_FORK #define __ARCH_WANT_SYS_VFORK #define __ARCH_WANT_SYS_CLONE /* * "Conditional" syscalls Loading
arch/s390/kernel/process.c +10 −42 Original line number Diff line number Diff line Loading @@ -118,7 +118,7 @@ void release_thread(struct task_struct *dead_task) int copy_thread(unsigned long clone_flags, unsigned long new_stackp, unsigned long arg, struct task_struct *p, struct pt_regs *regs) struct task_struct *p, struct pt_regs *unused) { struct thread_info *ti; struct fake_frame Loading Loading @@ -150,7 +150,7 @@ int copy_thread(unsigned long clone_flags, unsigned long new_stackp, frame->sf.gprs[9] = (unsigned long) frame; /* Store access registers to kernel stack of new process. */ if (unlikely(!regs)) { if (unlikely(p->flags & PF_KTHREAD)) { /* kernel thread */ memset(&frame->childregs, 0, sizeof(struct pt_regs)); frame->childregs.psw.mask = psw_kernel_bits | PSW_MASK_DAT | Loading @@ -164,8 +164,9 @@ int copy_thread(unsigned long clone_flags, unsigned long new_stackp, return 0; } frame->childregs = *regs; frame->childregs = *current_pt_regs(); frame->childregs.gprs[2] = 0; /* child returns 0 on fork. */ if (new_stackp) frame->childregs.gprs[15] = new_stackp; /* Don't copy runtime instrumentation info */ Loading @@ -183,57 +184,24 @@ int copy_thread(unsigned long clone_flags, unsigned long new_stackp, sizeof(s390_fp_regs)); /* Set a new TLS ? */ if (clone_flags & CLONE_SETTLS) p->thread.acrs[0] = regs->gprs[6]; p->thread.acrs[0] = frame->childregs.gprs[6]; #else /* CONFIG_64BIT */ /* Save the fpu registers to new thread structure. */ save_fp_regs(&p->thread.fp_regs); /* Set a new TLS ? */ if (clone_flags & CLONE_SETTLS) { unsigned long tls = frame->childregs.gprs[6]; if (is_compat_task()) { p->thread.acrs[0] = (unsigned int) regs->gprs[6]; p->thread.acrs[0] = (unsigned int)tls; } else { p->thread.acrs[0] = (unsigned int)(regs->gprs[6] >> 32); p->thread.acrs[1] = (unsigned int) regs->gprs[6]; p->thread.acrs[0] = (unsigned int)(tls >> 32); p->thread.acrs[1] = (unsigned int)tls; } } #endif /* CONFIG_64BIT */ return 0; } SYSCALL_DEFINE0(fork) { struct pt_regs *regs = task_pt_regs(current); return do_fork(SIGCHLD, regs->gprs[15], regs, 0, NULL, NULL); } SYSCALL_DEFINE4(clone, unsigned long, newsp, unsigned long, clone_flags, int __user *, parent_tidptr, int __user *, child_tidptr) { struct pt_regs *regs = task_pt_regs(current); if (!newsp) newsp = regs->gprs[15]; return do_fork(clone_flags, newsp, regs, 0, parent_tidptr, child_tidptr); } /* * This is trivial, and on the face of it looks like it * could equally well be done in user mode. * * Not so, for quite unobvious reasons - register pressure. * In user mode vfork() cannot have a stack frame, and if * done by calling the "clone()" system call directly, you * do not have enough call-clobbered registers to hold all * the information you need. */ SYSCALL_DEFINE0(vfork) { struct pt_regs *regs = task_pt_regs(current); return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->gprs[15], regs, 0, NULL, NULL); } asmlinkage void execve_tail(void) { current->thread.fp_regs.fpc = 0; Loading