aboutsummaryrefslogtreecommitdiffstats
path: root/arch/ia64/kernel/process.c
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2012-10-14 15:43:06 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2012-10-19 14:28:09 -0400
commit54d496c3915a10b5e46c5dd9de1a6d301ceb32bd (patch)
treed55abe04fe72f9c348256cd64917d2bcfde76965 /arch/ia64/kernel/process.c
parentc19e6d67e4be16e20ff90f0baa98b16d926d23a5 (diff)
ia64: switch to generic kernel_thread()/kernel_execve()
Acked-by: Tony Luck <tony.luck@intel.com> Tested-by: Tony Luck <tony.luck@intel.com> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'arch/ia64/kernel/process.c')
-rw-r--r--arch/ia64/kernel/process.c129
1 files changed, 58 insertions, 71 deletions
diff --git a/arch/ia64/kernel/process.c b/arch/ia64/kernel/process.c
index 6a48775d9363..37686dbfd264 100644
--- a/arch/ia64/kernel/process.c
+++ b/arch/ia64/kernel/process.c
@@ -401,55 +401,15 @@ copy_thread(unsigned long clone_flags,
401 struct pt_regs *child_ptregs; 401 struct pt_regs *child_ptregs;
402 int retval = 0; 402 int retval = 0;
403 403
404 stack = ((struct switch_stack *) regs) - 1;
405
406 child_ptregs = (struct pt_regs *) ((unsigned long) p + IA64_STK_OFFSET) - 1; 404 child_ptregs = (struct pt_regs *) ((unsigned long) p + IA64_STK_OFFSET) - 1;
407 child_stack = (struct switch_stack *) child_ptregs - 1; 405 child_stack = (struct switch_stack *) child_ptregs - 1;
408 406
409 /* copy parent's switch_stack & pt_regs to child: */
410 memcpy(child_stack, stack, sizeof(*child_ptregs) + sizeof(*child_stack));
411
412 rbs = (unsigned long) current + IA64_RBS_OFFSET; 407 rbs = (unsigned long) current + IA64_RBS_OFFSET;
413 child_rbs = (unsigned long) p + IA64_RBS_OFFSET; 408 child_rbs = (unsigned long) p + IA64_RBS_OFFSET;
414 409
415 if (likely(user_mode(child_ptregs))) {
416 /* copy the parent's register backing store to the child: */
417 rbs_size = stack->ar_bspstore - rbs;
418 memcpy((void *) child_rbs, (void *) rbs, rbs_size);
419 if (clone_flags & CLONE_SETTLS)
420 child_ptregs->r13 = regs->r16; /* see sys_clone2() in entry.S */
421 if (user_stack_base) {
422 child_ptregs->r12 = user_stack_base + user_stack_size - 16;
423 child_ptregs->ar_bspstore = user_stack_base;
424 child_ptregs->ar_rnat = 0;
425 child_ptregs->loadrs = 0;
426 }
427 } else {
428 /*
429 * Note: we simply preserve the relative position of
430 * the stack pointer here. There is no need to
431 * allocate a scratch area here, since that will have
432 * been taken care of by the caller of sys_clone()
433 * already.
434 */
435 rbs_size = 0;
436 child_ptregs->r12 = (unsigned long) child_ptregs - 16; /* kernel sp */
437 child_ptregs->r13 = (unsigned long) p; /* set `current' pointer */
438 }
439 child_stack->ar_bspstore = child_rbs + rbs_size;
440 child_stack->b0 = (unsigned long) &ia64_ret_from_clone;
441
442 /* copy parts of thread_struct: */ 410 /* copy parts of thread_struct: */
443 p->thread.ksp = (unsigned long) child_stack - 16; 411 p->thread.ksp = (unsigned long) child_stack - 16;
444 412
445 /* stop some PSR bits from being inherited.
446 * the psr.up/psr.pp bits must be cleared on fork but inherited on execve()
447 * therefore we must specify them explicitly here and not include them in
448 * IA64_PSR_BITS_TO_CLEAR.
449 */
450 child_ptregs->cr_ipsr = ((child_ptregs->cr_ipsr | IA64_PSR_BITS_TO_SET)
451 & ~(IA64_PSR_BITS_TO_CLEAR | IA64_PSR_PP | IA64_PSR_UP));
452
453 /* 413 /*
454 * NOTE: The calling convention considers all floating point 414 * NOTE: The calling convention considers all floating point
455 * registers in the high partition (fph) to be scratch. Since 415 * registers in the high partition (fph) to be scratch. Since
@@ -471,8 +431,66 @@ copy_thread(unsigned long clone_flags,
471# define THREAD_FLAGS_TO_SET 0 431# define THREAD_FLAGS_TO_SET 0
472 p->thread.flags = ((current->thread.flags & ~THREAD_FLAGS_TO_CLEAR) 432 p->thread.flags = ((current->thread.flags & ~THREAD_FLAGS_TO_CLEAR)
473 | THREAD_FLAGS_TO_SET); 433 | THREAD_FLAGS_TO_SET);
434
474 ia64_drop_fpu(p); /* don't pick up stale state from a CPU's fph */ 435 ia64_drop_fpu(p); /* don't pick up stale state from a CPU's fph */
475 436
437 if (unlikely(p->flags & PF_KTHREAD)) {
438 if (unlikely(!user_stack_base)) {
439 /* fork_idle() called us */
440 return 0;
441 }
442 memset(child_stack, 0, sizeof(*child_ptregs) + sizeof(*child_stack));
443 child_stack->r4 = user_stack_base; /* payload */
444 child_stack->r5 = user_stack_size; /* argument */
445 /*
446 * Preserve PSR bits, except for bits 32-34 and 37-45,
447 * which we can't read.
448 */
449 child_ptregs->cr_ipsr = ia64_getreg(_IA64_REG_PSR) | IA64_PSR_BN;
450 /* mark as valid, empty frame */
451 child_ptregs->cr_ifs = 1UL << 63;
452 child_stack->ar_fpsr = child_ptregs->ar_fpsr
453 = ia64_getreg(_IA64_REG_AR_FPSR);
454 child_stack->pr = (1 << PRED_KERNEL_STACK);
455 child_stack->ar_bspstore = child_rbs;
456 child_stack->b0 = (unsigned long) &ia64_ret_from_clone;
457
458 /* stop some PSR bits from being inherited.
459 * the psr.up/psr.pp bits must be cleared on fork but inherited on execve()
460 * therefore we must specify them explicitly here and not include them in
461 * IA64_PSR_BITS_TO_CLEAR.
462 */
463 child_ptregs->cr_ipsr = ((child_ptregs->cr_ipsr | IA64_PSR_BITS_TO_SET)
464 & ~(IA64_PSR_BITS_TO_CLEAR | IA64_PSR_PP | IA64_PSR_UP));
465
466 return 0;
467 }
468 stack = ((struct switch_stack *) regs) - 1;
469 /* copy parent's switch_stack & pt_regs to child: */
470 memcpy(child_stack, stack, sizeof(*child_ptregs) + sizeof(*child_stack));
471
472 /* copy the parent's register backing store to the child: */
473 rbs_size = stack->ar_bspstore - rbs;
474 memcpy((void *) child_rbs, (void *) rbs, rbs_size);
475 if (clone_flags & CLONE_SETTLS)
476 child_ptregs->r13 = regs->r16; /* see sys_clone2() in entry.S */
477 if (user_stack_base) {
478 child_ptregs->r12 = user_stack_base + user_stack_size - 16;
479 child_ptregs->ar_bspstore = user_stack_base;
480 child_ptregs->ar_rnat = 0;
481 child_ptregs->loadrs = 0;
482 }
483 child_stack->ar_bspstore = child_rbs + rbs_size;
484 child_stack->b0 = (unsigned long) &ia64_ret_from_clone;
485
486 /* stop some PSR bits from being inherited.
487 * the psr.up/psr.pp bits must be cleared on fork but inherited on execve()
488 * therefore we must specify them explicitly here and not include them in
489 * IA64_PSR_BITS_TO_CLEAR.
490 */
491 child_ptregs->cr_ipsr = ((child_ptregs->cr_ipsr | IA64_PSR_BITS_TO_SET)
492 & ~(IA64_PSR_BITS_TO_CLEAR | IA64_PSR_PP | IA64_PSR_UP));
493
476#ifdef CONFIG_PERFMON 494#ifdef CONFIG_PERFMON
477 if (current->thread.pfm_context) 495 if (current->thread.pfm_context)
478 pfm_inherit(p, child_ptregs); 496 pfm_inherit(p, child_ptregs);
@@ -618,37 +636,6 @@ out:
618 return error; 636 return error;
619} 637}
620 638
621pid_t
622kernel_thread (int (*fn)(void *), void *arg, unsigned long flags)
623{
624 extern void start_kernel_thread (void);
625 unsigned long *helper_fptr = (unsigned long *) &start_kernel_thread;
626 struct {
627 struct switch_stack sw;
628 struct pt_regs pt;
629 } regs;
630
631 memset(&regs, 0, sizeof(regs));
632 regs.pt.cr_iip = helper_fptr[0]; /* set entry point (IP) */
633 regs.pt.r1 = helper_fptr[1]; /* set GP */
634 regs.pt.r9 = (unsigned long) fn; /* 1st argument */
635 regs.pt.r11 = (unsigned long) arg; /* 2nd argument */
636 /* Preserve PSR bits, except for bits 32-34 and 37-45, which we can't read. */
637 regs.pt.cr_ipsr = ia64_getreg(_IA64_REG_PSR) | IA64_PSR_BN;
638 regs.pt.cr_ifs = 1UL << 63; /* mark as valid, empty frame */
639 regs.sw.ar_fpsr = regs.pt.ar_fpsr = ia64_getreg(_IA64_REG_AR_FPSR);
640 regs.sw.pr = (1 << PRED_KERNEL_STACK);
641 return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, &regs.pt, 0, NULL, NULL);
642}
643EXPORT_SYMBOL(kernel_thread);
644
645/* This gets called from kernel_thread() via ia64_invoke_thread_helper(). */
646int
647kernel_thread_helper (int (*fn)(void *), void *arg)
648{
649 return (*fn)(arg);
650}
651
652/* 639/*
653 * Flush thread state. This is called when a thread does an execve(). 640 * Flush thread state. This is called when a thread does an execve().
654 */ 641 */