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
Este cometimento está contido em:
@@ -42,6 +42,8 @@ config IA64
|
||||
select GENERIC_TIME_VSYSCALL_OLD
|
||||
select HAVE_MOD_ARCH_SPECIFIC
|
||||
select MODULES_USE_ELF_RELA
|
||||
select GENERIC_KERNEL_THREAD
|
||||
select GENERIC_KERNEL_EXECVE
|
||||
default y
|
||||
help
|
||||
The Itanium Processor Family is Intel's 64-bit successor to
|
||||
|
@@ -340,22 +340,6 @@ struct task_struct;
|
||||
*/
|
||||
#define release_thread(dead_task)
|
||||
|
||||
/*
|
||||
* This is the mechanism for creating a new kernel thread.
|
||||
*
|
||||
* NOTE 1: Only a kernel-only process (ie the swapper or direct
|
||||
* descendants who haven't done an "execve()") should use this: it
|
||||
* will work within a system call from a "real" process, but the
|
||||
* process memory space will not be free'd until both the parent and
|
||||
* the child have exited.
|
||||
*
|
||||
* NOTE 2: This MUST NOT be an inlined function. Otherwise, we get
|
||||
* into trouble in init/main.c when the child thread returns to
|
||||
* do_basic_setup() and the timing is such that free_initmem() has
|
||||
* been called already.
|
||||
*/
|
||||
extern pid_t kernel_thread (int (*fn)(void *), void *arg, unsigned long flags);
|
||||
|
||||
/* Get wait channel for task P. */
|
||||
extern unsigned long get_wchan (struct task_struct *p);
|
||||
|
||||
|
@@ -38,7 +38,5 @@ struct k_sigaction {
|
||||
|
||||
# include <asm/sigcontext.h>
|
||||
|
||||
#define ptrace_signal_deliver(regs, cookie) do { } while (0)
|
||||
|
||||
# endif /* !__ASSEMBLY__ */
|
||||
#endif /* _ASM_IA64_SIGNAL_H */
|
||||
|
@@ -29,6 +29,7 @@
|
||||
|
||||
#define __ARCH_WANT_SYS_RT_SIGACTION
|
||||
#define __ARCH_WANT_SYS_RT_SIGSUSPEND
|
||||
#define __ARCH_WANT_SYS_EXECVE
|
||||
|
||||
#if !defined(__ASSEMBLY__) && !defined(ASSEMBLER)
|
||||
|
||||
|
@@ -61,14 +61,13 @@ ENTRY(ia64_execve)
|
||||
* Allocate 8 input registers since ptrace() may clobber them
|
||||
*/
|
||||
.prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(8)
|
||||
alloc loc1=ar.pfs,8,2,4,0
|
||||
alloc loc1=ar.pfs,8,2,3,0
|
||||
mov loc0=rp
|
||||
.body
|
||||
mov out0=in0 // filename
|
||||
;; // stop bit between alloc and call
|
||||
mov out1=in1 // argv
|
||||
mov out2=in2 // envp
|
||||
add out3=16,sp // regs
|
||||
br.call.sptk.many rp=sys_execve
|
||||
.ret0:
|
||||
cmp4.ge p6,p7=r8,r0
|
||||
@@ -76,7 +75,6 @@ ENTRY(ia64_execve)
|
||||
sxt4 r8=r8 // return 64-bit result
|
||||
;;
|
||||
stf.spill [sp]=f0
|
||||
(p6) cmp.ne pKStk,pUStk=r0,r0 // a successful execve() lands us in user-mode...
|
||||
mov rp=loc0
|
||||
(p6) mov ar.pfs=r0 // clear ar.pfs on success
|
||||
(p7) br.ret.sptk.many rp
|
||||
@@ -118,13 +116,12 @@ GLOBAL_ENTRY(sys_clone2)
|
||||
mov loc1=r16 // save ar.pfs across do_fork
|
||||
.body
|
||||
mov out1=in1
|
||||
mov out3=in2
|
||||
mov out2=in2
|
||||
tbit.nz p6,p0=in0,CLONE_SETTLS_BIT
|
||||
mov out4=in3 // parent_tidptr: valid only w/CLONE_PARENT_SETTID
|
||||
mov out3=in3 // parent_tidptr: valid only w/CLONE_PARENT_SETTID
|
||||
;;
|
||||
(p6) st8 [r2]=in5 // store TLS in r16 for copy_thread()
|
||||
mov out5=in4 // child_tidptr: valid only w/CLONE_CHILD_SETTID or CLONE_CHILD_CLEARTID
|
||||
adds out2=IA64_SWITCH_STACK_SIZE+16,sp // out2 = ®s
|
||||
mov out4=in4 // child_tidptr: valid only w/CLONE_CHILD_SETTID or CLONE_CHILD_CLEARTID
|
||||
mov out0=in0 // out0 = clone_flags
|
||||
br.call.sptk.many rp=do_fork
|
||||
.ret1: .restore sp
|
||||
@@ -150,13 +147,12 @@ GLOBAL_ENTRY(sys_clone)
|
||||
mov loc1=r16 // save ar.pfs across do_fork
|
||||
.body
|
||||
mov out1=in1
|
||||
mov out3=16 // stacksize (compensates for 16-byte scratch area)
|
||||
mov out2=16 // stacksize (compensates for 16-byte scratch area)
|
||||
tbit.nz p6,p0=in0,CLONE_SETTLS_BIT
|
||||
mov out4=in2 // parent_tidptr: valid only w/CLONE_PARENT_SETTID
|
||||
mov out3=in2 // parent_tidptr: valid only w/CLONE_PARENT_SETTID
|
||||
;;
|
||||
(p6) st8 [r2]=in4 // store TLS in r13 (tp)
|
||||
mov out5=in3 // child_tidptr: valid only w/CLONE_CHILD_SETTID or CLONE_CHILD_CLEARTID
|
||||
adds out2=IA64_SWITCH_STACK_SIZE+16,sp // out2 = ®s
|
||||
mov out4=in3 // child_tidptr: valid only w/CLONE_CHILD_SETTID or CLONE_CHILD_CLEARTID
|
||||
mov out0=in0 // out0 = clone_flags
|
||||
br.call.sptk.many rp=do_fork
|
||||
.ret2: .restore sp
|
||||
@@ -484,19 +480,6 @@ GLOBAL_ENTRY(prefetch_stack)
|
||||
br.ret.sptk.many rp
|
||||
END(prefetch_stack)
|
||||
|
||||
GLOBAL_ENTRY(kernel_execve)
|
||||
rum psr.ac
|
||||
mov r15=__NR_execve // put syscall number in place
|
||||
break __BREAK_SYSCALL
|
||||
br.ret.sptk.many rp
|
||||
END(kernel_execve)
|
||||
|
||||
GLOBAL_ENTRY(clone)
|
||||
mov r15=__NR_clone // put syscall number in place
|
||||
break __BREAK_SYSCALL
|
||||
br.ret.sptk.many rp
|
||||
END(clone)
|
||||
|
||||
/*
|
||||
* Invoke a system call, but do some tracing before and after the call.
|
||||
* We MUST preserve the current register frame throughout this routine
|
||||
@@ -600,6 +583,27 @@ GLOBAL_ENTRY(ia64_strace_leave_kernel)
|
||||
.ret4: br.cond.sptk ia64_leave_kernel
|
||||
END(ia64_strace_leave_kernel)
|
||||
|
||||
ENTRY(call_payload)
|
||||
.prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(0)
|
||||
/* call the kernel_thread payload; fn is in r4, arg - in r5 */
|
||||
alloc loc1=ar.pfs,0,3,1,0
|
||||
mov loc0=rp
|
||||
mov loc2=gp
|
||||
mov out0=r5 // arg
|
||||
ld8 r14 = [r4], 8 // fn.address
|
||||
;;
|
||||
mov b6 = r14
|
||||
ld8 gp = [r4] // fn.gp
|
||||
;;
|
||||
br.call.sptk.many rp=b6 // fn(arg)
|
||||
.ret12: mov gp=loc2
|
||||
mov rp=loc0
|
||||
mov ar.pfs=loc1
|
||||
/* ... and if it has returned, we are going to userland */
|
||||
cmp.ne pKStk,pUStk=r0,r0
|
||||
br.ret.sptk.many rp
|
||||
END(call_payload)
|
||||
|
||||
GLOBAL_ENTRY(ia64_ret_from_clone)
|
||||
PT_REGS_UNWIND_INFO(0)
|
||||
{ /*
|
||||
@@ -616,6 +620,7 @@ GLOBAL_ENTRY(ia64_ret_from_clone)
|
||||
br.call.sptk.many rp=ia64_invoke_schedule_tail
|
||||
}
|
||||
.ret8:
|
||||
(pKStk) br.call.sptk.many rp=call_payload
|
||||
adds r2=TI_FLAGS+IA64_TASK_SIZE,r13
|
||||
;;
|
||||
ld4 r2=[r2]
|
||||
|
@@ -1093,19 +1093,6 @@ GLOBAL_ENTRY(cycle_to_cputime)
|
||||
END(cycle_to_cputime)
|
||||
#endif /* CONFIG_VIRT_CPU_ACCOUNTING */
|
||||
|
||||
GLOBAL_ENTRY(start_kernel_thread)
|
||||
.prologue
|
||||
.save rp, r0 // this is the end of the call-chain
|
||||
.body
|
||||
alloc r2 = ar.pfs, 0, 0, 2, 0
|
||||
mov out0 = r9
|
||||
mov out1 = r11;;
|
||||
br.call.sptk.many rp = kernel_thread_helper;;
|
||||
mov out0 = r8
|
||||
br.call.sptk.many rp = sys_exit;;
|
||||
1: br.sptk.few 1b // not reached
|
||||
END(start_kernel_thread)
|
||||
|
||||
#ifdef CONFIG_IA64_BRL_EMU
|
||||
|
||||
/*
|
||||
|
@@ -393,72 +393,24 @@ ia64_load_extra (struct task_struct *task)
|
||||
int
|
||||
copy_thread(unsigned long clone_flags,
|
||||
unsigned long user_stack_base, unsigned long user_stack_size,
|
||||
struct task_struct *p, struct pt_regs *regs)
|
||||
struct task_struct *p)
|
||||
{
|
||||
extern char ia64_ret_from_clone;
|
||||
struct switch_stack *child_stack, *stack;
|
||||
unsigned long rbs, child_rbs, rbs_size;
|
||||
struct pt_regs *child_ptregs;
|
||||
struct pt_regs *regs = current_pt_regs();
|
||||
int retval = 0;
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
/*
|
||||
* For SMP idle threads, fork_by_hand() calls do_fork with
|
||||
* NULL regs.
|
||||
*/
|
||||
if (!regs)
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
stack = ((struct switch_stack *) regs) - 1;
|
||||
|
||||
child_ptregs = (struct pt_regs *) ((unsigned long) p + IA64_STK_OFFSET) - 1;
|
||||
child_stack = (struct switch_stack *) child_ptregs - 1;
|
||||
|
||||
/* copy parent's switch_stack & pt_regs to child: */
|
||||
memcpy(child_stack, stack, sizeof(*child_ptregs) + sizeof(*child_stack));
|
||||
|
||||
rbs = (unsigned long) current + IA64_RBS_OFFSET;
|
||||
child_rbs = (unsigned long) p + IA64_RBS_OFFSET;
|
||||
rbs_size = stack->ar_bspstore - rbs;
|
||||
|
||||
/* copy the parent's register backing store to the child: */
|
||||
memcpy((void *) child_rbs, (void *) rbs, rbs_size);
|
||||
|
||||
if (likely(user_mode(child_ptregs))) {
|
||||
if (clone_flags & CLONE_SETTLS)
|
||||
child_ptregs->r13 = regs->r16; /* see sys_clone2() in entry.S */
|
||||
if (user_stack_base) {
|
||||
child_ptregs->r12 = user_stack_base + user_stack_size - 16;
|
||||
child_ptregs->ar_bspstore = user_stack_base;
|
||||
child_ptregs->ar_rnat = 0;
|
||||
child_ptregs->loadrs = 0;
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* Note: we simply preserve the relative position of
|
||||
* the stack pointer here. There is no need to
|
||||
* allocate a scratch area here, since that will have
|
||||
* been taken care of by the caller of sys_clone()
|
||||
* already.
|
||||
*/
|
||||
child_ptregs->r12 = (unsigned long) child_ptregs - 16; /* kernel sp */
|
||||
child_ptregs->r13 = (unsigned long) p; /* set `current' pointer */
|
||||
}
|
||||
child_stack->ar_bspstore = child_rbs + rbs_size;
|
||||
child_stack->b0 = (unsigned long) &ia64_ret_from_clone;
|
||||
|
||||
/* copy parts of thread_struct: */
|
||||
p->thread.ksp = (unsigned long) child_stack - 16;
|
||||
|
||||
/* stop some PSR bits from being inherited.
|
||||
* the psr.up/psr.pp bits must be cleared on fork but inherited on execve()
|
||||
* therefore we must specify them explicitly here and not include them in
|
||||
* IA64_PSR_BITS_TO_CLEAR.
|
||||
*/
|
||||
child_ptregs->cr_ipsr = ((child_ptregs->cr_ipsr | IA64_PSR_BITS_TO_SET)
|
||||
& ~(IA64_PSR_BITS_TO_CLEAR | IA64_PSR_PP | IA64_PSR_UP));
|
||||
|
||||
/*
|
||||
* NOTE: The calling convention considers all floating point
|
||||
* registers in the high partition (fph) to be scratch. Since
|
||||
@@ -480,8 +432,66 @@ copy_thread(unsigned long clone_flags,
|
||||
# define THREAD_FLAGS_TO_SET 0
|
||||
p->thread.flags = ((current->thread.flags & ~THREAD_FLAGS_TO_CLEAR)
|
||||
| THREAD_FLAGS_TO_SET);
|
||||
|
||||
ia64_drop_fpu(p); /* don't pick up stale state from a CPU's fph */
|
||||
|
||||
if (unlikely(p->flags & PF_KTHREAD)) {
|
||||
if (unlikely(!user_stack_base)) {
|
||||
/* fork_idle() called us */
|
||||
return 0;
|
||||
}
|
||||
memset(child_stack, 0, sizeof(*child_ptregs) + sizeof(*child_stack));
|
||||
child_stack->r4 = user_stack_base; /* payload */
|
||||
child_stack->r5 = user_stack_size; /* argument */
|
||||
/*
|
||||
* Preserve PSR bits, except for bits 32-34 and 37-45,
|
||||
* which we can't read.
|
||||
*/
|
||||
child_ptregs->cr_ipsr = ia64_getreg(_IA64_REG_PSR) | IA64_PSR_BN;
|
||||
/* mark as valid, empty frame */
|
||||
child_ptregs->cr_ifs = 1UL << 63;
|
||||
child_stack->ar_fpsr = child_ptregs->ar_fpsr
|
||||
= ia64_getreg(_IA64_REG_AR_FPSR);
|
||||
child_stack->pr = (1 << PRED_KERNEL_STACK);
|
||||
child_stack->ar_bspstore = child_rbs;
|
||||
child_stack->b0 = (unsigned long) &ia64_ret_from_clone;
|
||||
|
||||
/* stop some PSR bits from being inherited.
|
||||
* the psr.up/psr.pp bits must be cleared on fork but inherited on execve()
|
||||
* therefore we must specify them explicitly here and not include them in
|
||||
* IA64_PSR_BITS_TO_CLEAR.
|
||||
*/
|
||||
child_ptregs->cr_ipsr = ((child_ptregs->cr_ipsr | IA64_PSR_BITS_TO_SET)
|
||||
& ~(IA64_PSR_BITS_TO_CLEAR | IA64_PSR_PP | IA64_PSR_UP));
|
||||
|
||||
return 0;
|
||||
}
|
||||
stack = ((struct switch_stack *) regs) - 1;
|
||||
/* copy parent's switch_stack & pt_regs to child: */
|
||||
memcpy(child_stack, stack, sizeof(*child_ptregs) + sizeof(*child_stack));
|
||||
|
||||
/* copy the parent's register backing store to the child: */
|
||||
rbs_size = stack->ar_bspstore - rbs;
|
||||
memcpy((void *) child_rbs, (void *) rbs, rbs_size);
|
||||
if (clone_flags & CLONE_SETTLS)
|
||||
child_ptregs->r13 = regs->r16; /* see sys_clone2() in entry.S */
|
||||
if (user_stack_base) {
|
||||
child_ptregs->r12 = user_stack_base + user_stack_size - 16;
|
||||
child_ptregs->ar_bspstore = user_stack_base;
|
||||
child_ptregs->ar_rnat = 0;
|
||||
child_ptregs->loadrs = 0;
|
||||
}
|
||||
child_stack->ar_bspstore = child_rbs + rbs_size;
|
||||
child_stack->b0 = (unsigned long) &ia64_ret_from_clone;
|
||||
|
||||
/* stop some PSR bits from being inherited.
|
||||
* the psr.up/psr.pp bits must be cleared on fork but inherited on execve()
|
||||
* therefore we must specify them explicitly here and not include them in
|
||||
* IA64_PSR_BITS_TO_CLEAR.
|
||||
*/
|
||||
child_ptregs->cr_ipsr = ((child_ptregs->cr_ipsr | IA64_PSR_BITS_TO_SET)
|
||||
& ~(IA64_PSR_BITS_TO_CLEAR | IA64_PSR_PP | IA64_PSR_UP));
|
||||
|
||||
#ifdef CONFIG_PERFMON
|
||||
if (current->thread.pfm_context)
|
||||
pfm_inherit(p, child_ptregs);
|
||||
@@ -608,57 +618,6 @@ dump_fpu (struct pt_regs *pt, elf_fpregset_t dst)
|
||||
return 1; /* f0-f31 are always valid so we always return 1 */
|
||||
}
|
||||
|
||||
long
|
||||
sys_execve (const char __user *filename,
|
||||
const char __user *const __user *argv,
|
||||
const char __user *const __user *envp,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
struct filename *fname;
|
||||
int error;
|
||||
|
||||
fname = getname(filename);
|
||||
error = PTR_ERR(fname);
|
||||
if (IS_ERR(fname))
|
||||
goto out;
|
||||
error = do_execve(fname->name, argv, envp, regs);
|
||||
putname(fname);
|
||||
out:
|
||||
return error;
|
||||
}
|
||||
|
||||
pid_t
|
||||
kernel_thread (int (*fn)(void *), void *arg, unsigned long flags)
|
||||
{
|
||||
extern void start_kernel_thread (void);
|
||||
unsigned long *helper_fptr = (unsigned long *) &start_kernel_thread;
|
||||
struct {
|
||||
struct switch_stack sw;
|
||||
struct pt_regs pt;
|
||||
} regs;
|
||||
|
||||
memset(®s, 0, sizeof(regs));
|
||||
regs.pt.cr_iip = helper_fptr[0]; /* set entry point (IP) */
|
||||
regs.pt.r1 = helper_fptr[1]; /* set GP */
|
||||
regs.pt.r9 = (unsigned long) fn; /* 1st argument */
|
||||
regs.pt.r11 = (unsigned long) arg; /* 2nd argument */
|
||||
/* Preserve PSR bits, except for bits 32-34 and 37-45, which we can't read. */
|
||||
regs.pt.cr_ipsr = ia64_getreg(_IA64_REG_PSR) | IA64_PSR_BN;
|
||||
regs.pt.cr_ifs = 1UL << 63; /* mark as valid, empty frame */
|
||||
regs.sw.ar_fpsr = regs.pt.ar_fpsr = ia64_getreg(_IA64_REG_AR_FPSR);
|
||||
regs.sw.ar_bspstore = (unsigned long) current + IA64_RBS_OFFSET;
|
||||
regs.sw.pr = (1 << PRED_KERNEL_STACK);
|
||||
return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, ®s.pt, 0, NULL, NULL);
|
||||
}
|
||||
EXPORT_SYMBOL(kernel_thread);
|
||||
|
||||
/* This gets called from kernel_thread() via ia64_invoke_thread_helper(). */
|
||||
int
|
||||
kernel_thread_helper (int (*fn)(void *), void *arg)
|
||||
{
|
||||
return (*fn)(arg);
|
||||
}
|
||||
|
||||
/*
|
||||
* Flush thread state. This is called when a thread does an execve().
|
||||
*/
|
||||
|
@@ -460,11 +460,6 @@ start_secondary (void *unused)
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct pt_regs * __cpuinit idle_regs(struct pt_regs *regs)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int __cpuinit
|
||||
do_boot_cpu (int sapicid, int cpu, struct task_struct *idle)
|
||||
{
|
||||
|
Criar uma nova questão referindo esta
Bloquear um utilizador