diff options
Diffstat (limited to 'arch/ia64/kernel/process.c')
-rw-r--r-- | arch/ia64/kernel/process.c | 161 |
1 files changed, 60 insertions, 101 deletions
diff --git a/arch/ia64/kernel/process.c b/arch/ia64/kernel/process.c index 35e106f2ed13..31360cbbd5f8 100644 --- a/arch/ia64/kernel/process.c +++ b/arch/ia64/kernel/process.c | |||
@@ -393,72 +393,24 @@ ia64_load_extra (struct task_struct *task) | |||
393 | int | 393 | int |
394 | copy_thread(unsigned long clone_flags, | 394 | copy_thread(unsigned long clone_flags, |
395 | unsigned long user_stack_base, unsigned long user_stack_size, | 395 | unsigned long user_stack_base, unsigned long user_stack_size, |
396 | struct task_struct *p, struct pt_regs *regs) | 396 | struct task_struct *p) |
397 | { | 397 | { |
398 | extern char ia64_ret_from_clone; | 398 | extern char ia64_ret_from_clone; |
399 | struct switch_stack *child_stack, *stack; | 399 | struct switch_stack *child_stack, *stack; |
400 | unsigned long rbs, child_rbs, rbs_size; | 400 | unsigned long rbs, child_rbs, rbs_size; |
401 | struct pt_regs *child_ptregs; | 401 | struct pt_regs *child_ptregs; |
402 | struct pt_regs *regs = current_pt_regs(); | ||
402 | int retval = 0; | 403 | int retval = 0; |
403 | 404 | ||
404 | #ifdef CONFIG_SMP | ||
405 | /* | ||
406 | * For SMP idle threads, fork_by_hand() calls do_fork with | ||
407 | * NULL regs. | ||
408 | */ | ||
409 | if (!regs) | ||
410 | return 0; | ||
411 | #endif | ||
412 | |||
413 | stack = ((struct switch_stack *) regs) - 1; | ||
414 | |||
415 | child_ptregs = (struct pt_regs *) ((unsigned long) p + IA64_STK_OFFSET) - 1; | 405 | child_ptregs = (struct pt_regs *) ((unsigned long) p + IA64_STK_OFFSET) - 1; |
416 | child_stack = (struct switch_stack *) child_ptregs - 1; | 406 | child_stack = (struct switch_stack *) child_ptregs - 1; |
417 | 407 | ||
418 | /* copy parent's switch_stack & pt_regs to child: */ | ||
419 | memcpy(child_stack, stack, sizeof(*child_ptregs) + sizeof(*child_stack)); | ||
420 | |||
421 | rbs = (unsigned long) current + IA64_RBS_OFFSET; | 408 | rbs = (unsigned long) current + IA64_RBS_OFFSET; |
422 | child_rbs = (unsigned long) p + IA64_RBS_OFFSET; | 409 | child_rbs = (unsigned long) p + IA64_RBS_OFFSET; |
423 | rbs_size = stack->ar_bspstore - rbs; | ||
424 | |||
425 | /* copy the parent's register backing store to the child: */ | ||
426 | memcpy((void *) child_rbs, (void *) rbs, rbs_size); | ||
427 | |||
428 | if (likely(user_mode(child_ptregs))) { | ||
429 | if (clone_flags & CLONE_SETTLS) | ||
430 | child_ptregs->r13 = regs->r16; /* see sys_clone2() in entry.S */ | ||
431 | if (user_stack_base) { | ||
432 | child_ptregs->r12 = user_stack_base + user_stack_size - 16; | ||
433 | child_ptregs->ar_bspstore = user_stack_base; | ||
434 | child_ptregs->ar_rnat = 0; | ||
435 | child_ptregs->loadrs = 0; | ||
436 | } | ||
437 | } else { | ||
438 | /* | ||
439 | * Note: we simply preserve the relative position of | ||
440 | * the stack pointer here. There is no need to | ||
441 | * allocate a scratch area here, since that will have | ||
442 | * been taken care of by the caller of sys_clone() | ||
443 | * already. | ||
444 | */ | ||
445 | child_ptregs->r12 = (unsigned long) child_ptregs - 16; /* kernel sp */ | ||
446 | child_ptregs->r13 = (unsigned long) p; /* set `current' pointer */ | ||
447 | } | ||
448 | child_stack->ar_bspstore = child_rbs + rbs_size; | ||
449 | child_stack->b0 = (unsigned long) &ia64_ret_from_clone; | ||
450 | 410 | ||
451 | /* copy parts of thread_struct: */ | 411 | /* copy parts of thread_struct: */ |
452 | p->thread.ksp = (unsigned long) child_stack - 16; | 412 | p->thread.ksp = (unsigned long) child_stack - 16; |
453 | 413 | ||
454 | /* stop some PSR bits from being inherited. | ||
455 | * the psr.up/psr.pp bits must be cleared on fork but inherited on execve() | ||
456 | * therefore we must specify them explicitly here and not include them in | ||
457 | * IA64_PSR_BITS_TO_CLEAR. | ||
458 | */ | ||
459 | child_ptregs->cr_ipsr = ((child_ptregs->cr_ipsr | IA64_PSR_BITS_TO_SET) | ||
460 | & ~(IA64_PSR_BITS_TO_CLEAR | IA64_PSR_PP | IA64_PSR_UP)); | ||
461 | |||
462 | /* | 414 | /* |
463 | * NOTE: The calling convention considers all floating point | 415 | * NOTE: The calling convention considers all floating point |
464 | * registers in the high partition (fph) to be scratch. Since | 416 | * registers in the high partition (fph) to be scratch. Since |
@@ -480,8 +432,66 @@ copy_thread(unsigned long clone_flags, | |||
480 | # define THREAD_FLAGS_TO_SET 0 | 432 | # define THREAD_FLAGS_TO_SET 0 |
481 | p->thread.flags = ((current->thread.flags & ~THREAD_FLAGS_TO_CLEAR) | 433 | p->thread.flags = ((current->thread.flags & ~THREAD_FLAGS_TO_CLEAR) |
482 | | THREAD_FLAGS_TO_SET); | 434 | | THREAD_FLAGS_TO_SET); |
435 | |||
483 | ia64_drop_fpu(p); /* don't pick up stale state from a CPU's fph */ | 436 | ia64_drop_fpu(p); /* don't pick up stale state from a CPU's fph */ |
484 | 437 | ||
438 | if (unlikely(p->flags & PF_KTHREAD)) { | ||
439 | if (unlikely(!user_stack_base)) { | ||
440 | /* fork_idle() called us */ | ||
441 | return 0; | ||
442 | } | ||
443 | memset(child_stack, 0, sizeof(*child_ptregs) + sizeof(*child_stack)); | ||
444 | child_stack->r4 = user_stack_base; /* payload */ | ||
445 | child_stack->r5 = user_stack_size; /* argument */ | ||
446 | /* | ||
447 | * Preserve PSR bits, except for bits 32-34 and 37-45, | ||
448 | * which we can't read. | ||
449 | */ | ||
450 | child_ptregs->cr_ipsr = ia64_getreg(_IA64_REG_PSR) | IA64_PSR_BN; | ||
451 | /* mark as valid, empty frame */ | ||
452 | child_ptregs->cr_ifs = 1UL << 63; | ||
453 | child_stack->ar_fpsr = child_ptregs->ar_fpsr | ||
454 | = ia64_getreg(_IA64_REG_AR_FPSR); | ||
455 | child_stack->pr = (1 << PRED_KERNEL_STACK); | ||
456 | child_stack->ar_bspstore = child_rbs; | ||
457 | child_stack->b0 = (unsigned long) &ia64_ret_from_clone; | ||
458 | |||
459 | /* stop some PSR bits from being inherited. | ||
460 | * the psr.up/psr.pp bits must be cleared on fork but inherited on execve() | ||
461 | * therefore we must specify them explicitly here and not include them in | ||
462 | * IA64_PSR_BITS_TO_CLEAR. | ||
463 | */ | ||
464 | child_ptregs->cr_ipsr = ((child_ptregs->cr_ipsr | IA64_PSR_BITS_TO_SET) | ||
465 | & ~(IA64_PSR_BITS_TO_CLEAR | IA64_PSR_PP | IA64_PSR_UP)); | ||
466 | |||
467 | return 0; | ||
468 | } | ||
469 | stack = ((struct switch_stack *) regs) - 1; | ||
470 | /* copy parent's switch_stack & pt_regs to child: */ | ||
471 | memcpy(child_stack, stack, sizeof(*child_ptregs) + sizeof(*child_stack)); | ||
472 | |||
473 | /* copy the parent's register backing store to the child: */ | ||
474 | rbs_size = stack->ar_bspstore - rbs; | ||
475 | memcpy((void *) child_rbs, (void *) rbs, rbs_size); | ||
476 | if (clone_flags & CLONE_SETTLS) | ||
477 | child_ptregs->r13 = regs->r16; /* see sys_clone2() in entry.S */ | ||
478 | if (user_stack_base) { | ||
479 | child_ptregs->r12 = user_stack_base + user_stack_size - 16; | ||
480 | child_ptregs->ar_bspstore = user_stack_base; | ||
481 | child_ptregs->ar_rnat = 0; | ||
482 | child_ptregs->loadrs = 0; | ||
483 | } | ||
484 | child_stack->ar_bspstore = child_rbs + rbs_size; | ||
485 | child_stack->b0 = (unsigned long) &ia64_ret_from_clone; | ||
486 | |||
487 | /* stop some PSR bits from being inherited. | ||
488 | * the psr.up/psr.pp bits must be cleared on fork but inherited on execve() | ||
489 | * therefore we must specify them explicitly here and not include them in | ||
490 | * IA64_PSR_BITS_TO_CLEAR. | ||
491 | */ | ||
492 | child_ptregs->cr_ipsr = ((child_ptregs->cr_ipsr | IA64_PSR_BITS_TO_SET) | ||
493 | & ~(IA64_PSR_BITS_TO_CLEAR | IA64_PSR_PP | IA64_PSR_UP)); | ||
494 | |||
485 | #ifdef CONFIG_PERFMON | 495 | #ifdef CONFIG_PERFMON |
486 | if (current->thread.pfm_context) | 496 | if (current->thread.pfm_context) |
487 | pfm_inherit(p, child_ptregs); | 497 | pfm_inherit(p, child_ptregs); |
@@ -608,57 +618,6 @@ dump_fpu (struct pt_regs *pt, elf_fpregset_t dst) | |||
608 | return 1; /* f0-f31 are always valid so we always return 1 */ | 618 | return 1; /* f0-f31 are always valid so we always return 1 */ |
609 | } | 619 | } |
610 | 620 | ||
611 | long | ||
612 | sys_execve (const char __user *filename, | ||
613 | const char __user *const __user *argv, | ||
614 | const char __user *const __user *envp, | ||
615 | struct pt_regs *regs) | ||
616 | { | ||
617 | struct filename *fname; | ||
618 | int error; | ||
619 | |||
620 | fname = getname(filename); | ||
621 | error = PTR_ERR(fname); | ||
622 | if (IS_ERR(fname)) | ||
623 | goto out; | ||
624 | error = do_execve(fname->name, argv, envp, regs); | ||
625 | putname(fname); | ||
626 | out: | ||
627 | return error; | ||
628 | } | ||
629 | |||
630 | pid_t | ||
631 | kernel_thread (int (*fn)(void *), void *arg, unsigned long flags) | ||
632 | { | ||
633 | extern void start_kernel_thread (void); | ||
634 | unsigned long *helper_fptr = (unsigned long *) &start_kernel_thread; | ||
635 | struct { | ||
636 | struct switch_stack sw; | ||
637 | struct pt_regs pt; | ||
638 | } regs; | ||
639 | |||
640 | memset(®s, 0, sizeof(regs)); | ||
641 | regs.pt.cr_iip = helper_fptr[0]; /* set entry point (IP) */ | ||
642 | regs.pt.r1 = helper_fptr[1]; /* set GP */ | ||
643 | regs.pt.r9 = (unsigned long) fn; /* 1st argument */ | ||
644 | regs.pt.r11 = (unsigned long) arg; /* 2nd argument */ | ||
645 | /* Preserve PSR bits, except for bits 32-34 and 37-45, which we can't read. */ | ||
646 | regs.pt.cr_ipsr = ia64_getreg(_IA64_REG_PSR) | IA64_PSR_BN; | ||
647 | regs.pt.cr_ifs = 1UL << 63; /* mark as valid, empty frame */ | ||
648 | regs.sw.ar_fpsr = regs.pt.ar_fpsr = ia64_getreg(_IA64_REG_AR_FPSR); | ||
649 | regs.sw.ar_bspstore = (unsigned long) current + IA64_RBS_OFFSET; | ||
650 | regs.sw.pr = (1 << PRED_KERNEL_STACK); | ||
651 | return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, ®s.pt, 0, NULL, NULL); | ||
652 | } | ||
653 | EXPORT_SYMBOL(kernel_thread); | ||
654 | |||
655 | /* This gets called from kernel_thread() via ia64_invoke_thread_helper(). */ | ||
656 | int | ||
657 | kernel_thread_helper (int (*fn)(void *), void *arg) | ||
658 | { | ||
659 | return (*fn)(arg); | ||
660 | } | ||
661 | |||
662 | /* | 621 | /* |
663 | * Flush thread state. This is called when a thread does an execve(). | 622 | * Flush thread state. This is called when a thread does an execve(). |
664 | */ | 623 | */ |