You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/signal
Pull big execve/kernel_thread/fork unification series from Al Viro:
"All architectures are converted to new model. Quite a bit of that
stuff is actually shared with architecture trees; in such cases it's
literally shared branch pulled by both, not a cherry-pick.
A lot of ugliness and black magic is gone (-3KLoC total in this one):
- kernel_thread()/kernel_execve()/sys_execve() redesign.
We don't do syscalls from kernel anymore for either kernel_thread()
or kernel_execve():
kernel_thread() is essentially clone(2) with callback run before we
return to userland, the callbacks either never return or do
successful do_execve() before returning.
kernel_execve() is a wrapper for do_execve() - it doesn't need to
do transition to user mode anymore.
As a result kernel_thread() and kernel_execve() are
arch-independent now - they live in kernel/fork.c and fs/exec.c
resp. sys_execve() is also in fs/exec.c and it's completely
architecture-independent.
- daemonize() is gone, along with its parts in fs/*.c
- struct pt_regs * is no longer passed to do_fork/copy_process/
copy_thread/do_execve/search_binary_handler/->load_binary/do_coredump.
- sys_fork()/sys_vfork()/sys_clone() unified; some architectures
still need wrappers (ones with callee-saved registers not saved in
pt_regs on syscall entry), but the main part of those suckers is in
kernel/fork.c now."
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/signal: (113 commits)
do_coredump(): get rid of pt_regs argument
print_fatal_signal(): get rid of pt_regs argument
ptrace_signal(): get rid of unused arguments
get rid of ptrace_signal_deliver() arguments
new helper: signal_pt_regs()
unify default ptrace_signal_deliver
flagday: kill pt_regs argument of do_fork()
death to idle_regs()
don't pass regs to copy_process()
flagday: don't pass regs to copy_thread()
bfin: switch to generic vfork, get rid of pointless wrappers
xtensa: switch to generic clone()
openrisc: switch to use of generic fork and clone
unicore32: switch to generic clone(2)
score: switch to generic fork/vfork/clone
c6x: sanitize copy_thread(), get rid of clone(2) wrapper, switch to generic clone()
take sys_fork/sys_vfork/sys_clone prototypes to linux/syscalls.h
mn10300: switch to generic fork/vfork/clone
h8300: switch to generic fork/vfork/clone
tile: switch to generic clone()
...
Conflicts:
arch/microblaze/include/asm/Kbuild
This commit is contained in:
@@ -342,4 +342,18 @@ config MODULES_USE_ELF_REL
|
|||||||
Modules only use ELF REL relocations. Modules with ELF RELA
|
Modules only use ELF REL relocations. Modules with ELF RELA
|
||||||
relocations will give an error.
|
relocations will give an error.
|
||||||
|
|
||||||
|
#
|
||||||
|
# ABI hall of shame
|
||||||
|
#
|
||||||
|
config CLONE_BACKWARDS
|
||||||
|
bool
|
||||||
|
help
|
||||||
|
Architecture has tls passed as the 4th argument of clone(2),
|
||||||
|
not the 5th one.
|
||||||
|
|
||||||
|
config CLONE_BACKWARDS2
|
||||||
|
bool
|
||||||
|
help
|
||||||
|
Architecture has the first two arguments of clone(2) swapped.
|
||||||
|
|
||||||
source "kernel/gcov/Kconfig"
|
source "kernel/gcov/Kconfig"
|
||||||
|
|||||||
@@ -78,6 +78,7 @@ struct switch_stack {
|
|||||||
|
|
||||||
#define current_pt_regs() \
|
#define current_pt_regs() \
|
||||||
((struct pt_regs *) ((char *)current_thread_info() + 2*PAGE_SIZE) - 1)
|
((struct pt_regs *) ((char *)current_thread_info() + 2*PAGE_SIZE) - 1)
|
||||||
|
#define signal_pt_regs current_pt_regs
|
||||||
|
|
||||||
#define force_successful_syscall_return() (current_pt_regs()->r0 = 0)
|
#define force_successful_syscall_return() (current_pt_regs()->r0 = 0)
|
||||||
|
|
||||||
|
|||||||
@@ -164,9 +164,6 @@ struct sigstack {
|
|||||||
|
|
||||||
#ifdef __KERNEL__
|
#ifdef __KERNEL__
|
||||||
#include <asm/sigcontext.h>
|
#include <asm/sigcontext.h>
|
||||||
|
|
||||||
#define ptrace_signal_deliver(regs, cookie) do { } while (0)
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -482,6 +482,9 @@
|
|||||||
#define __ARCH_WANT_SYS_SIGPENDING
|
#define __ARCH_WANT_SYS_SIGPENDING
|
||||||
#define __ARCH_WANT_SYS_RT_SIGSUSPEND
|
#define __ARCH_WANT_SYS_RT_SIGSUSPEND
|
||||||
#define __ARCH_WANT_SYS_EXECVE
|
#define __ARCH_WANT_SYS_EXECVE
|
||||||
|
#define __ARCH_WANT_SYS_FORK
|
||||||
|
#define __ARCH_WANT_SYS_VFORK
|
||||||
|
#define __ARCH_WANT_SYS_CLONE
|
||||||
|
|
||||||
/* "Conditional" syscalls. What we want is
|
/* "Conditional" syscalls. What we want is
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
#include <linux/binfmts.h>
|
#include <linux/binfmts.h>
|
||||||
#include <linux/a.out.h>
|
#include <linux/a.out.h>
|
||||||
|
|
||||||
static int load_binary(struct linux_binprm *bprm, struct pt_regs *regs)
|
static int load_binary(struct linux_binprm *bprm)
|
||||||
{
|
{
|
||||||
struct exec *eh = (struct exec *)bprm->buf;
|
struct exec *eh = (struct exec *)bprm->buf;
|
||||||
unsigned long loader;
|
unsigned long loader;
|
||||||
@@ -37,7 +37,7 @@ static int load_binary(struct linux_binprm *bprm, struct pt_regs *regs)
|
|||||||
retval = prepare_binprm(bprm);
|
retval = prepare_binprm(bprm);
|
||||||
if (retval < 0)
|
if (retval < 0)
|
||||||
return retval;
|
return retval;
|
||||||
return search_binary_handler(bprm,regs);
|
return search_binary_handler(bprm);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct linux_binfmt loader_format = {
|
static struct linux_binfmt loader_format = {
|
||||||
|
|||||||
+12
-39
@@ -612,47 +612,24 @@ ret_from_kernel_thread:
|
|||||||
* Special system calls. Most of these are special in that they either
|
* Special system calls. Most of these are special in that they either
|
||||||
* have to play switch_stack games or in some way use the pt_regs struct.
|
* have to play switch_stack games or in some way use the pt_regs struct.
|
||||||
*/
|
*/
|
||||||
.align 4
|
|
||||||
.globl sys_fork
|
|
||||||
.ent sys_fork
|
|
||||||
sys_fork:
|
|
||||||
.prologue 0
|
|
||||||
mov $sp, $21
|
|
||||||
bsr $1, do_switch_stack
|
|
||||||
bis $31, SIGCHLD, $16
|
|
||||||
mov $31, $17
|
|
||||||
mov $31, $18
|
|
||||||
mov $31, $19
|
|
||||||
mov $31, $20
|
|
||||||
jsr $26, alpha_clone
|
|
||||||
bsr $1, undo_switch_stack
|
|
||||||
ret
|
|
||||||
.end sys_fork
|
|
||||||
|
|
||||||
|
.macro fork_like name
|
||||||
.align 4
|
.align 4
|
||||||
.globl sys_clone
|
.globl alpha_\name
|
||||||
.ent sys_clone
|
.ent alpha_\name
|
||||||
sys_clone:
|
alpha_\name:
|
||||||
.prologue 0
|
.prologue 0
|
||||||
mov $sp, $21
|
|
||||||
bsr $1, do_switch_stack
|
bsr $1, do_switch_stack
|
||||||
/* $16, $17, $18, $19, $20 come from the user. */
|
jsr $26, sys_\name
|
||||||
jsr $26, alpha_clone
|
ldq $26, 56($sp)
|
||||||
bsr $1, undo_switch_stack
|
lda $sp, SWITCH_STACK_SIZE($sp)
|
||||||
ret
|
ret
|
||||||
.end sys_clone
|
.end alpha_\name
|
||||||
|
.endm
|
||||||
|
|
||||||
.align 4
|
fork_like fork
|
||||||
.globl sys_vfork
|
fork_like vfork
|
||||||
.ent sys_vfork
|
fork_like clone
|
||||||
sys_vfork:
|
|
||||||
.prologue 0
|
|
||||||
mov $sp, $16
|
|
||||||
bsr $1, do_switch_stack
|
|
||||||
jsr $26, alpha_vfork
|
|
||||||
bsr $1, undo_switch_stack
|
|
||||||
ret
|
|
||||||
.end sys_vfork
|
|
||||||
|
|
||||||
.align 4
|
.align 4
|
||||||
.globl sys_sigreturn
|
.globl sys_sigreturn
|
||||||
@@ -661,8 +638,6 @@ sys_sigreturn:
|
|||||||
.prologue 0
|
.prologue 0
|
||||||
lda $9, ret_from_straced
|
lda $9, ret_from_straced
|
||||||
cmpult $26, $9, $9
|
cmpult $26, $9, $9
|
||||||
mov $sp, $17
|
|
||||||
lda $18, -SWITCH_STACK_SIZE($sp)
|
|
||||||
lda $sp, -SWITCH_STACK_SIZE($sp)
|
lda $sp, -SWITCH_STACK_SIZE($sp)
|
||||||
jsr $26, do_sigreturn
|
jsr $26, do_sigreturn
|
||||||
bne $9, 1f
|
bne $9, 1f
|
||||||
@@ -678,8 +653,6 @@ sys_rt_sigreturn:
|
|||||||
.prologue 0
|
.prologue 0
|
||||||
lda $9, ret_from_straced
|
lda $9, ret_from_straced
|
||||||
cmpult $26, $9, $9
|
cmpult $26, $9, $9
|
||||||
mov $sp, $17
|
|
||||||
lda $18, -SWITCH_STACK_SIZE($sp)
|
|
||||||
lda $sp, -SWITCH_STACK_SIZE($sp)
|
lda $sp, -SWITCH_STACK_SIZE($sp)
|
||||||
jsr $26, do_rt_sigreturn
|
jsr $26, do_rt_sigreturn
|
||||||
bne $9, 1f
|
bne $9, 1f
|
||||||
|
|||||||
+14
-48
@@ -234,33 +234,6 @@ release_thread(struct task_struct *dead_task)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* "alpha_clone()".. By the time we get here, the
|
|
||||||
* non-volatile registers have also been saved on the
|
|
||||||
* stack. We do some ugly pointer stuff here.. (see
|
|
||||||
* also copy_thread)
|
|
||||||
*
|
|
||||||
* Notice that "fork()" is implemented in terms of clone,
|
|
||||||
* with parameters (SIGCHLD, 0).
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
alpha_clone(unsigned long clone_flags, unsigned long usp,
|
|
||||||
int __user *parent_tid, int __user *child_tid,
|
|
||||||
unsigned long tls_value, struct pt_regs *regs)
|
|
||||||
{
|
|
||||||
if (!usp)
|
|
||||||
usp = rdusp();
|
|
||||||
|
|
||||||
return do_fork(clone_flags, usp, regs, 0, parent_tid, child_tid);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
alpha_vfork(struct pt_regs *regs)
|
|
||||||
{
|
|
||||||
return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, rdusp(),
|
|
||||||
regs, 0, NULL, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copy an alpha thread..
|
* Copy an alpha thread..
|
||||||
*/
|
*/
|
||||||
@@ -268,18 +241,22 @@ alpha_vfork(struct pt_regs *regs)
|
|||||||
int
|
int
|
||||||
copy_thread(unsigned long clone_flags, unsigned long usp,
|
copy_thread(unsigned long clone_flags, unsigned long usp,
|
||||||
unsigned long arg,
|
unsigned long arg,
|
||||||
struct task_struct * p, struct pt_regs * regs)
|
struct task_struct *p)
|
||||||
{
|
{
|
||||||
extern void ret_from_fork(void);
|
extern void ret_from_fork(void);
|
||||||
extern void ret_from_kernel_thread(void);
|
extern void ret_from_kernel_thread(void);
|
||||||
|
|
||||||
struct thread_info *childti = task_thread_info(p);
|
struct thread_info *childti = task_thread_info(p);
|
||||||
struct pt_regs *childregs = task_pt_regs(p);
|
struct pt_regs *childregs = task_pt_regs(p);
|
||||||
|
struct pt_regs *regs = current_pt_regs();
|
||||||
struct switch_stack *childstack, *stack;
|
struct switch_stack *childstack, *stack;
|
||||||
unsigned long settls;
|
unsigned long settls;
|
||||||
|
|
||||||
childstack = ((struct switch_stack *) childregs) - 1;
|
childstack = ((struct switch_stack *) childregs) - 1;
|
||||||
if (unlikely(!regs)) {
|
childti->pcb.ksp = (unsigned long) childstack;
|
||||||
|
childti->pcb.flags = 1; /* set FEN, clear everything else */
|
||||||
|
|
||||||
|
if (unlikely(p->flags & PF_KTHREAD)) {
|
||||||
/* kernel thread */
|
/* kernel thread */
|
||||||
memset(childstack, 0,
|
memset(childstack, 0,
|
||||||
sizeof(struct switch_stack) + sizeof(struct pt_regs));
|
sizeof(struct switch_stack) + sizeof(struct pt_regs));
|
||||||
@@ -288,12 +265,17 @@ copy_thread(unsigned long clone_flags, unsigned long usp,
|
|||||||
childstack->r10 = arg;
|
childstack->r10 = arg;
|
||||||
childregs->hae = alpha_mv.hae_cache,
|
childregs->hae = alpha_mv.hae_cache,
|
||||||
childti->pcb.usp = 0;
|
childti->pcb.usp = 0;
|
||||||
childti->pcb.ksp = (unsigned long) childstack;
|
|
||||||
childti->pcb.flags = 1; /* set FEN, clear everything else */
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
/* Note: if CLONE_SETTLS is not set, then we must inherit the
|
||||||
|
value from the parent, which will have been set by the block
|
||||||
|
copy in dup_task_struct. This is non-intuitive, but is
|
||||||
|
required for proper operation in the case of a threaded
|
||||||
|
application calling fork. */
|
||||||
|
if (clone_flags & CLONE_SETTLS)
|
||||||
|
childti->pcb.unique = regs->r20;
|
||||||
|
childti->pcb.usp = usp ?: rdusp();
|
||||||
*childregs = *regs;
|
*childregs = *regs;
|
||||||
settls = regs->r20;
|
|
||||||
childregs->r0 = 0;
|
childregs->r0 = 0;
|
||||||
childregs->r19 = 0;
|
childregs->r19 = 0;
|
||||||
childregs->r20 = 1; /* OSF/1 has some strange fork() semantics. */
|
childregs->r20 = 1; /* OSF/1 has some strange fork() semantics. */
|
||||||
@@ -301,22 +283,6 @@ copy_thread(unsigned long clone_flags, unsigned long usp,
|
|||||||
stack = ((struct switch_stack *) regs) - 1;
|
stack = ((struct switch_stack *) regs) - 1;
|
||||||
*childstack = *stack;
|
*childstack = *stack;
|
||||||
childstack->r26 = (unsigned long) ret_from_fork;
|
childstack->r26 = (unsigned long) ret_from_fork;
|
||||||
childti->pcb.usp = usp;
|
|
||||||
childti->pcb.ksp = (unsigned long) childstack;
|
|
||||||
childti->pcb.flags = 1; /* set FEN, clear everything else */
|
|
||||||
|
|
||||||
/* Set a new TLS for the child thread? Peek back into the
|
|
||||||
syscall arguments that we saved on syscall entry. Oops,
|
|
||||||
except we'd have clobbered it with the parent/child set
|
|
||||||
of r20. Read the saved copy. */
|
|
||||||
/* Note: if CLONE_SETTLS is not set, then we must inherit the
|
|
||||||
value from the parent, which will have been set by the block
|
|
||||||
copy in dup_task_struct. This is non-intuitive, but is
|
|
||||||
required for proper operation in the case of a threaded
|
|
||||||
application calling fork. */
|
|
||||||
if (clone_flags & CLONE_SETTLS)
|
|
||||||
childti->pcb.unique = settls;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -160,10 +160,10 @@ extern char compile_time_assert
|
|||||||
#define INSN_CALLSYS 0x00000083
|
#define INSN_CALLSYS 0x00000083
|
||||||
|
|
||||||
static long
|
static long
|
||||||
restore_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs,
|
restore_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs)
|
||||||
struct switch_stack *sw)
|
|
||||||
{
|
{
|
||||||
unsigned long usp;
|
unsigned long usp;
|
||||||
|
struct switch_stack *sw = (struct switch_stack *)regs - 1;
|
||||||
long i, err = __get_user(regs->pc, &sc->sc_pc);
|
long i, err = __get_user(regs->pc, &sc->sc_pc);
|
||||||
|
|
||||||
current_thread_info()->restart_block.fn = do_no_restart_syscall;
|
current_thread_info()->restart_block.fn = do_no_restart_syscall;
|
||||||
@@ -215,9 +215,9 @@ restore_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs,
|
|||||||
registers and transfer control from userland. */
|
registers and transfer control from userland. */
|
||||||
|
|
||||||
asmlinkage void
|
asmlinkage void
|
||||||
do_sigreturn(struct sigcontext __user *sc, struct pt_regs *regs,
|
do_sigreturn(struct sigcontext __user *sc)
|
||||||
struct switch_stack *sw)
|
|
||||||
{
|
{
|
||||||
|
struct pt_regs *regs = current_pt_regs();
|
||||||
sigset_t set;
|
sigset_t set;
|
||||||
|
|
||||||
/* Verify that it's a good sigcontext before using it */
|
/* Verify that it's a good sigcontext before using it */
|
||||||
@@ -228,7 +228,7 @@ do_sigreturn(struct sigcontext __user *sc, struct pt_regs *regs,
|
|||||||
|
|
||||||
set_current_blocked(&set);
|
set_current_blocked(&set);
|
||||||
|
|
||||||
if (restore_sigcontext(sc, regs, sw))
|
if (restore_sigcontext(sc, regs))
|
||||||
goto give_sigsegv;
|
goto give_sigsegv;
|
||||||
|
|
||||||
/* Send SIGTRAP if we're single-stepping: */
|
/* Send SIGTRAP if we're single-stepping: */
|
||||||
@@ -249,9 +249,9 @@ give_sigsegv:
|
|||||||
}
|
}
|
||||||
|
|
||||||
asmlinkage void
|
asmlinkage void
|
||||||
do_rt_sigreturn(struct rt_sigframe __user *frame, struct pt_regs *regs,
|
do_rt_sigreturn(struct rt_sigframe __user *frame)
|
||||||
struct switch_stack *sw)
|
|
||||||
{
|
{
|
||||||
|
struct pt_regs *regs = current_pt_regs();
|
||||||
sigset_t set;
|
sigset_t set;
|
||||||
|
|
||||||
/* Verify that it's a good ucontext_t before using it */
|
/* Verify that it's a good ucontext_t before using it */
|
||||||
@@ -262,7 +262,7 @@ do_rt_sigreturn(struct rt_sigframe __user *frame, struct pt_regs *regs,
|
|||||||
|
|
||||||
set_current_blocked(&set);
|
set_current_blocked(&set);
|
||||||
|
|
||||||
if (restore_sigcontext(&frame->uc.uc_mcontext, regs, sw))
|
if (restore_sigcontext(&frame->uc.uc_mcontext, regs))
|
||||||
goto give_sigsegv;
|
goto give_sigsegv;
|
||||||
|
|
||||||
/* Send SIGTRAP if we're single-stepping: */
|
/* Send SIGTRAP if we're single-stepping: */
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
sys_call_table:
|
sys_call_table:
|
||||||
.quad alpha_ni_syscall /* 0 */
|
.quad alpha_ni_syscall /* 0 */
|
||||||
.quad sys_exit
|
.quad sys_exit
|
||||||
.quad sys_fork
|
.quad alpha_fork
|
||||||
.quad sys_read
|
.quad sys_read
|
||||||
.quad sys_write
|
.quad sys_write
|
||||||
.quad alpha_ni_syscall /* 5 */
|
.quad alpha_ni_syscall /* 5 */
|
||||||
@@ -76,7 +76,7 @@ sys_call_table:
|
|||||||
.quad sys_getpgrp
|
.quad sys_getpgrp
|
||||||
.quad sys_getpagesize
|
.quad sys_getpagesize
|
||||||
.quad alpha_ni_syscall /* 65 */
|
.quad alpha_ni_syscall /* 65 */
|
||||||
.quad sys_vfork
|
.quad alpha_vfork
|
||||||
.quad sys_newstat
|
.quad sys_newstat
|
||||||
.quad sys_newlstat
|
.quad sys_newlstat
|
||||||
.quad alpha_ni_syscall
|
.quad alpha_ni_syscall
|
||||||
@@ -330,7 +330,7 @@ sys_call_table:
|
|||||||
.quad sys_ni_syscall /* 309: old get_kernel_syms */
|
.quad sys_ni_syscall /* 309: old get_kernel_syms */
|
||||||
.quad sys_syslog /* 310 */
|
.quad sys_syslog /* 310 */
|
||||||
.quad sys_reboot
|
.quad sys_reboot
|
||||||
.quad sys_clone
|
.quad alpha_clone
|
||||||
.quad sys_uselib
|
.quad sys_uselib
|
||||||
.quad sys_mlock
|
.quad sys_mlock
|
||||||
.quad sys_munlock /* 315 */
|
.quad sys_munlock /* 315 */
|
||||||
|
|||||||
@@ -57,6 +57,7 @@ config ARM
|
|||||||
select SYS_SUPPORTS_APM_EMULATION
|
select SYS_SUPPORTS_APM_EMULATION
|
||||||
select HAVE_MOD_ARCH_SPECIFIC if ARM_UNWIND
|
select HAVE_MOD_ARCH_SPECIFIC if ARM_UNWIND
|
||||||
select MODULES_USE_ELF_REL
|
select MODULES_USE_ELF_REL
|
||||||
|
select CLONE_BACKWARDS
|
||||||
help
|
help
|
||||||
The ARM series is a line of low-power-consumption RISC chip designs
|
The ARM series is a line of low-power-consumption RISC chip designs
|
||||||
licensed by ARM Ltd and targeted at embedded applications and
|
licensed by ARM Ltd and targeted at embedded applications and
|
||||||
|
|||||||
@@ -35,5 +35,4 @@ struct k_sigaction {
|
|||||||
};
|
};
|
||||||
|
|
||||||
#include <asm/sigcontext.h>
|
#include <asm/sigcontext.h>
|
||||||
#define ptrace_signal_deliver(regs, cookie) do { } while (0)
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -42,6 +42,9 @@
|
|||||||
#define __ARCH_WANT_SYS_SOCKETCALL
|
#define __ARCH_WANT_SYS_SOCKETCALL
|
||||||
#endif
|
#endif
|
||||||
#define __ARCH_WANT_SYS_EXECVE
|
#define __ARCH_WANT_SYS_EXECVE
|
||||||
|
#define __ARCH_WANT_SYS_FORK
|
||||||
|
#define __ARCH_WANT_SYS_VFORK
|
||||||
|
#define __ARCH_WANT_SYS_CLONE
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* "Conditional" syscalls
|
* "Conditional" syscalls
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
*/
|
*/
|
||||||
/* 0 */ CALL(sys_restart_syscall)
|
/* 0 */ CALL(sys_restart_syscall)
|
||||||
CALL(sys_exit)
|
CALL(sys_exit)
|
||||||
CALL(sys_fork_wrapper)
|
CALL(sys_fork)
|
||||||
CALL(sys_read)
|
CALL(sys_read)
|
||||||
CALL(sys_write)
|
CALL(sys_write)
|
||||||
/* 5 */ CALL(sys_open)
|
/* 5 */ CALL(sys_open)
|
||||||
@@ -129,7 +129,7 @@
|
|||||||
CALL(OBSOLETE(ABI(sys_ipc, sys_oabi_ipc)))
|
CALL(OBSOLETE(ABI(sys_ipc, sys_oabi_ipc)))
|
||||||
CALL(sys_fsync)
|
CALL(sys_fsync)
|
||||||
CALL(sys_sigreturn_wrapper)
|
CALL(sys_sigreturn_wrapper)
|
||||||
/* 120 */ CALL(sys_clone_wrapper)
|
/* 120 */ CALL(sys_clone)
|
||||||
CALL(sys_setdomainname)
|
CALL(sys_setdomainname)
|
||||||
CALL(sys_newuname)
|
CALL(sys_newuname)
|
||||||
CALL(sys_ni_syscall) /* modify_ldt */
|
CALL(sys_ni_syscall) /* modify_ldt */
|
||||||
@@ -199,7 +199,7 @@
|
|||||||
CALL(sys_sendfile)
|
CALL(sys_sendfile)
|
||||||
CALL(sys_ni_syscall) /* getpmsg */
|
CALL(sys_ni_syscall) /* getpmsg */
|
||||||
CALL(sys_ni_syscall) /* putpmsg */
|
CALL(sys_ni_syscall) /* putpmsg */
|
||||||
/* 190 */ CALL(sys_vfork_wrapper)
|
/* 190 */ CALL(sys_vfork)
|
||||||
CALL(sys_getrlimit)
|
CALL(sys_getrlimit)
|
||||||
CALL(sys_mmap2)
|
CALL(sys_mmap2)
|
||||||
CALL(ABI(sys_truncate64, sys_oabi_truncate64))
|
CALL(ABI(sys_truncate64, sys_oabi_truncate64))
|
||||||
|
|||||||
@@ -502,22 +502,6 @@ sys_syscall:
|
|||||||
b sys_ni_syscall
|
b sys_ni_syscall
|
||||||
ENDPROC(sys_syscall)
|
ENDPROC(sys_syscall)
|
||||||
|
|
||||||
sys_fork_wrapper:
|
|
||||||
add r0, sp, #S_OFF
|
|
||||||
b sys_fork
|
|
||||||
ENDPROC(sys_fork_wrapper)
|
|
||||||
|
|
||||||
sys_vfork_wrapper:
|
|
||||||
add r0, sp, #S_OFF
|
|
||||||
b sys_vfork
|
|
||||||
ENDPROC(sys_vfork_wrapper)
|
|
||||||
|
|
||||||
sys_clone_wrapper:
|
|
||||||
add ip, sp, #S_OFF
|
|
||||||
str ip, [sp, #4]
|
|
||||||
b sys_clone
|
|
||||||
ENDPROC(sys_clone_wrapper)
|
|
||||||
|
|
||||||
sys_sigreturn_wrapper:
|
sys_sigreturn_wrapper:
|
||||||
add r0, sp, #S_OFF
|
add r0, sp, #S_OFF
|
||||||
mov why, #0 @ prevent syscall restart handling
|
mov why, #0 @ prevent syscall restart handling
|
||||||
|
|||||||
@@ -376,17 +376,18 @@ asmlinkage void ret_from_fork(void) __asm__("ret_from_fork");
|
|||||||
|
|
||||||
int
|
int
|
||||||
copy_thread(unsigned long clone_flags, unsigned long stack_start,
|
copy_thread(unsigned long clone_flags, unsigned long stack_start,
|
||||||
unsigned long stk_sz, struct task_struct *p, struct pt_regs *regs)
|
unsigned long stk_sz, struct task_struct *p)
|
||||||
{
|
{
|
||||||
struct thread_info *thread = task_thread_info(p);
|
struct thread_info *thread = task_thread_info(p);
|
||||||
struct pt_regs *childregs = task_pt_regs(p);
|
struct pt_regs *childregs = task_pt_regs(p);
|
||||||
|
|
||||||
memset(&thread->cpu_context, 0, sizeof(struct cpu_context_save));
|
memset(&thread->cpu_context, 0, sizeof(struct cpu_context_save));
|
||||||
|
|
||||||
if (likely(regs)) {
|
if (likely(!(p->flags & PF_KTHREAD))) {
|
||||||
*childregs = *regs;
|
*childregs = *current_pt_regs();
|
||||||
childregs->ARM_r0 = 0;
|
childregs->ARM_r0 = 0;
|
||||||
childregs->ARM_sp = stack_start;
|
if (stack_start)
|
||||||
|
childregs->ARM_sp = stack_start;
|
||||||
} else {
|
} else {
|
||||||
memset(childregs, 0, sizeof(struct pt_regs));
|
memset(childregs, 0, sizeof(struct pt_regs));
|
||||||
thread->cpu_context.r4 = stk_sz;
|
thread->cpu_context.r4 = stk_sz;
|
||||||
@@ -399,7 +400,7 @@ copy_thread(unsigned long clone_flags, unsigned long stack_start,
|
|||||||
clear_ptrace_hw_breakpoint(p);
|
clear_ptrace_hw_breakpoint(p);
|
||||||
|
|
||||||
if (clone_flags & CLONE_SETTLS)
|
if (clone_flags & CLONE_SETTLS)
|
||||||
thread->tp_value = regs->ARM_r3;
|
thread->tp_value = childregs->ARM_r3;
|
||||||
|
|
||||||
thread_notify(THREAD_NOTIFY_COPY, thread);
|
thread_notify(THREAD_NOTIFY_COPY, thread);
|
||||||
|
|
||||||
|
|||||||
@@ -28,37 +28,6 @@
|
|||||||
#include <linux/uaccess.h>
|
#include <linux/uaccess.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
|
|
||||||
/* Fork a new task - this creates a new program thread.
|
|
||||||
* This is called indirectly via a small wrapper
|
|
||||||
*/
|
|
||||||
asmlinkage int sys_fork(struct pt_regs *regs)
|
|
||||||
{
|
|
||||||
#ifdef CONFIG_MMU
|
|
||||||
return do_fork(SIGCHLD, regs->ARM_sp, regs, 0, NULL, NULL);
|
|
||||||
#else
|
|
||||||
/* can not support in nommu mode */
|
|
||||||
return(-EINVAL);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Clone a task - this clones the calling program thread.
|
|
||||||
* This is called indirectly via a small wrapper
|
|
||||||
*/
|
|
||||||
asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp,
|
|
||||||
int __user *parent_tidptr, int tls_val,
|
|
||||||
int __user *child_tidptr, struct pt_regs *regs)
|
|
||||||
{
|
|
||||||
if (!newsp)
|
|
||||||
newsp = regs->ARM_sp;
|
|
||||||
|
|
||||||
return do_fork(clone_flags, newsp, regs, 0, parent_tidptr, child_tidptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
asmlinkage int sys_vfork(struct pt_regs *regs)
|
|
||||||
{
|
|
||||||
return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->ARM_sp, regs, 0, NULL, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Since loff_t is a 64 bit type we avoid a lot of ABI hassle
|
* Since loff_t is a 64 bit type we avoid a lot of ABI hassle
|
||||||
* with a different argument ordering.
|
* with a different argument ordering.
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ config ARM64
|
|||||||
select RTC_LIB
|
select RTC_LIB
|
||||||
select SPARSE_IRQ
|
select SPARSE_IRQ
|
||||||
select SYSCTL_EXCEPTION_TRACE
|
select SYSCTL_EXCEPTION_TRACE
|
||||||
|
select CLONE_BACKWARDS
|
||||||
help
|
help
|
||||||
ARM 64-bit (AArch64) Linux support.
|
ARM 64-bit (AArch64) Linux support.
|
||||||
|
|
||||||
|
|||||||
@@ -27,12 +27,6 @@ asmlinkage long sys_rt_sigreturn_wrapper(void);
|
|||||||
asmlinkage long sys_sigaltstack_wrapper(const stack_t __user *uss,
|
asmlinkage long sys_sigaltstack_wrapper(const stack_t __user *uss,
|
||||||
stack_t __user *uoss);
|
stack_t __user *uoss);
|
||||||
|
|
||||||
/*
|
|
||||||
* AArch64 sys_clone implementation has a different prototype than the generic
|
|
||||||
* one (additional TLS value argument).
|
|
||||||
*/
|
|
||||||
#define sys_clone sys_clone
|
|
||||||
|
|
||||||
#include <asm-generic/syscalls.h>
|
#include <asm-generic/syscalls.h>
|
||||||
|
|
||||||
#endif /* __ASM_SYSCALLS_H */
|
#endif /* __ASM_SYSCALLS_H */
|
||||||
|
|||||||
@@ -24,6 +24,9 @@
|
|||||||
#define __ARCH_WANT_SYS_SIGPROCMASK
|
#define __ARCH_WANT_SYS_SIGPROCMASK
|
||||||
#define __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND
|
#define __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND
|
||||||
#define __ARCH_WANT_COMPAT_SYS_SENDFILE
|
#define __ARCH_WANT_COMPAT_SYS_SENDFILE
|
||||||
|
#define __ARCH_WANT_SYS_FORK
|
||||||
|
#define __ARCH_WANT_SYS_VFORK
|
||||||
#endif
|
#endif
|
||||||
#define __ARCH_WANT_SYS_EXECVE
|
#define __ARCH_WANT_SYS_EXECVE
|
||||||
|
#define __ARCH_WANT_SYS_CLONE
|
||||||
#include <uapi/asm/unistd.h>
|
#include <uapi/asm/unistd.h>
|
||||||
|
|||||||
@@ -23,7 +23,7 @@
|
|||||||
|
|
||||||
__SYSCALL(0, sys_restart_syscall)
|
__SYSCALL(0, sys_restart_syscall)
|
||||||
__SYSCALL(1, sys_exit)
|
__SYSCALL(1, sys_exit)
|
||||||
__SYSCALL(2, compat_sys_fork)
|
__SYSCALL(2, sys_fork)
|
||||||
__SYSCALL(3, sys_read)
|
__SYSCALL(3, sys_read)
|
||||||
__SYSCALL(4, sys_write)
|
__SYSCALL(4, sys_write)
|
||||||
__SYSCALL(5, compat_sys_open)
|
__SYSCALL(5, compat_sys_open)
|
||||||
@@ -211,7 +211,7 @@ __SYSCALL(186, compat_sys_sigaltstack_wrapper)
|
|||||||
__SYSCALL(187, compat_sys_sendfile)
|
__SYSCALL(187, compat_sys_sendfile)
|
||||||
__SYSCALL(188, sys_ni_syscall) /* 188 reserved */
|
__SYSCALL(188, sys_ni_syscall) /* 188 reserved */
|
||||||
__SYSCALL(189, sys_ni_syscall) /* 189 reserved */
|
__SYSCALL(189, sys_ni_syscall) /* 189 reserved */
|
||||||
__SYSCALL(190, compat_sys_vfork)
|
__SYSCALL(190, sys_vfork)
|
||||||
__SYSCALL(191, compat_sys_getrlimit) /* SuS compliant getrlimit */
|
__SYSCALL(191, compat_sys_getrlimit) /* SuS compliant getrlimit */
|
||||||
__SYSCALL(192, sys_mmap_pgoff)
|
__SYSCALL(192, sys_mmap_pgoff)
|
||||||
__SYSCALL(193, compat_sys_truncate64_wrapper)
|
__SYSCALL(193, compat_sys_truncate64_wrapper)
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user