process.c 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. /*
  2. * arch/v850/kernel/process.c -- Arch-dependent process handling
  3. *
  4. * Copyright (C) 2001,02,03 NEC Electronics Corporation
  5. * Copyright (C) 2001,02,03 Miles Bader <miles@gnu.org>
  6. *
  7. * This file is subject to the terms and conditions of the GNU General
  8. * Public License. See the file COPYING in the main directory of this
  9. * archive for more details.
  10. *
  11. * Written by Miles Bader <miles@gnu.org>
  12. */
  13. #include <linux/config.h>
  14. #include <linux/errno.h>
  15. #include <linux/sched.h>
  16. #include <linux/kernel.h>
  17. #include <linux/mm.h>
  18. #include <linux/smp.h>
  19. #include <linux/smp_lock.h>
  20. #include <linux/stddef.h>
  21. #include <linux/unistd.h>
  22. #include <linux/ptrace.h>
  23. #include <linux/slab.h>
  24. #include <linux/user.h>
  25. #include <linux/a.out.h>
  26. #include <linux/reboot.h>
  27. #include <asm/uaccess.h>
  28. #include <asm/system.h>
  29. #include <asm/pgtable.h>
  30. extern void ret_from_fork (void);
  31. /* The idle loop. */
  32. void default_idle (void)
  33. {
  34. while (1) {
  35. while (! need_resched ())
  36. asm ("halt; nop; nop; nop; nop; nop" ::: "cc");
  37. schedule ();
  38. }
  39. }
  40. void (*idle)(void) = default_idle;
  41. /*
  42. * The idle thread. There's no useful work to be
  43. * done, so just try to conserve power and have a
  44. * low exit latency (ie sit in a loop waiting for
  45. * somebody to say that they'd like to reschedule)
  46. */
  47. void cpu_idle (void)
  48. {
  49. /* endless idle loop with no priority at all */
  50. (*idle) ();
  51. }
  52. /*
  53. * This is the mechanism for creating a new kernel thread.
  54. *
  55. * NOTE! Only a kernel-only process (ie the swapper or direct descendants who
  56. * haven't done an "execve()") should use this: it will work within a system
  57. * call from a "real" process, but the process memory space will not be free'd
  58. * until both the parent and the child have exited.
  59. */
  60. int kernel_thread (int (*fn)(void *), void *arg, unsigned long flags)
  61. {
  62. register mm_segment_t fs = get_fs ();
  63. register unsigned long syscall asm (SYSCALL_NUM);
  64. register unsigned long arg0 asm (SYSCALL_ARG0);
  65. register unsigned long ret asm (SYSCALL_RET);
  66. set_fs (KERNEL_DS);
  67. /* Clone this thread. Note that we don't pass the clone syscall's
  68. second argument -- it's ignored for calls from kernel mode (the
  69. child's SP is always set to the top of the kernel stack). */
  70. arg0 = flags | CLONE_VM;
  71. syscall = __NR_clone;
  72. asm volatile ("trap " SYSCALL_SHORT_TRAP
  73. : "=r" (ret), "=r" (syscall)
  74. : "1" (syscall), "r" (arg0)
  75. : SYSCALL_SHORT_CLOBBERS);
  76. if (ret == 0) {
  77. /* In child thread, call FN and exit. */
  78. arg0 = (*fn) (arg);
  79. syscall = __NR_exit;
  80. asm volatile ("trap " SYSCALL_SHORT_TRAP
  81. : "=r" (ret), "=r" (syscall)
  82. : "1" (syscall), "r" (arg0)
  83. : SYSCALL_SHORT_CLOBBERS);
  84. }
  85. /* In parent. */
  86. set_fs (fs);
  87. return ret;
  88. }
  89. void flush_thread (void)
  90. {
  91. set_fs (USER_DS);
  92. }
  93. int copy_thread (int nr, unsigned long clone_flags,
  94. unsigned long stack_start, unsigned long stack_size,
  95. struct task_struct *p, struct pt_regs *regs)
  96. {
  97. /* Start pushing stuff from the top of the child's kernel stack. */
  98. unsigned long orig_ksp = (unsigned long)p->thread_info + THREAD_SIZE;
  99. unsigned long ksp = orig_ksp;
  100. /* We push two `state save' stack fames (see entry.S) on the new
  101. kernel stack:
  102. 1) The innermost one is what switch_thread would have
  103. pushed, and is used when we context switch to the child
  104. thread for the first time. It's set up to return to
  105. ret_from_fork in entry.S.
  106. 2) The outermost one (nearest the top) is what a syscall
  107. trap would have pushed, and is set up to return to the
  108. same location as the parent thread, but with a return
  109. value of 0. */
  110. struct pt_regs *child_switch_regs, *child_trap_regs;
  111. /* Trap frame. */
  112. ksp -= STATE_SAVE_SIZE;
  113. child_trap_regs = (struct pt_regs *)(ksp + STATE_SAVE_PT_OFFSET);
  114. /* Switch frame. */
  115. ksp -= STATE_SAVE_SIZE;
  116. child_switch_regs = (struct pt_regs *)(ksp + STATE_SAVE_PT_OFFSET);
  117. /* First copy parent's register state to child. */
  118. *child_switch_regs = *regs;
  119. *child_trap_regs = *regs;
  120. /* switch_thread returns to the restored value of the lp
  121. register (r31), so we make that the place where we want to
  122. jump when the child thread begins running. */
  123. child_switch_regs->gpr[GPR_LP] = (v850_reg_t)ret_from_fork;
  124. if (regs->kernel_mode)
  125. /* Since we're returning to kernel-mode, make sure the child's
  126. stored kernel stack pointer agrees with what the actual
  127. stack pointer will be at that point (the trap return code
  128. always restores the SP, even when returning to
  129. kernel-mode). */
  130. child_trap_regs->gpr[GPR_SP] = orig_ksp;
  131. else
  132. /* Set the child's user-mode stack-pointer (the name
  133. `stack_start' is a misnomer, it's just the initial SP
  134. value). */
  135. child_trap_regs->gpr[GPR_SP] = stack_start;
  136. /* Thread state for the child (everything else is on the stack). */
  137. p->thread.ksp = ksp;
  138. return 0;
  139. }
  140. /*
  141. * fill in the user structure for a core dump..
  142. */
  143. void dump_thread (struct pt_regs *regs, struct user *dump)
  144. {
  145. #if 0 /* Later. XXX */
  146. dump->magic = CMAGIC;
  147. dump->start_code = 0;
  148. dump->start_stack = regs->gpr[GPR_SP];
  149. dump->u_tsize = ((unsigned long) current->mm->end_code) >> PAGE_SHIFT;
  150. dump->u_dsize = ((unsigned long) (current->mm->brk +
  151. (PAGE_SIZE-1))) >> PAGE_SHIFT;
  152. dump->u_dsize -= dump->u_tsize;
  153. dump->u_ssize = 0;
  154. if (dump->start_stack < TASK_SIZE)
  155. dump->u_ssize = ((unsigned long) (TASK_SIZE - dump->start_stack)) >> PAGE_SHIFT;
  156. dump->u_ar0 = (struct user_regs_struct *)((int)&dump->regs - (int)dump);
  157. dump->regs = *regs;
  158. dump->u_fpvalid = 0;
  159. #endif
  160. }
  161. /*
  162. * sys_execve() executes a new program.
  163. */
  164. int sys_execve (char *name, char **argv, char **envp, struct pt_regs *regs)
  165. {
  166. char *filename = getname (name);
  167. int error = PTR_ERR (filename);
  168. if (! IS_ERR (filename)) {
  169. error = do_execve (filename, argv, envp, regs);
  170. putname (filename);
  171. }
  172. return error;
  173. }
  174. /*
  175. * These bracket the sleeping functions..
  176. */
  177. #define first_sched ((unsigned long)__sched_text_start)
  178. #define last_sched ((unsigned long)__sched_text_end)
  179. unsigned long get_wchan (struct task_struct *p)
  180. {
  181. #if 0 /* Barf. Figure out the stack-layout later. XXX */
  182. unsigned long fp, pc;
  183. int count = 0;
  184. if (!p || p == current || p->state == TASK_RUNNING)
  185. return 0;
  186. pc = thread_saved_pc (p);
  187. /* This quite disgusting function walks up the stack, following
  188. saved return address, until it something that's out of bounds
  189. (as defined by `first_sched' and `last_sched'). It then
  190. returns the last PC that was in-bounds. */
  191. do {
  192. if (fp < stack_page + sizeof (struct task_struct) ||
  193. fp >= 8184+stack_page)
  194. return 0;
  195. pc = ((unsigned long *)fp)[1];
  196. if (pc < first_sched || pc >= last_sched)
  197. return pc;
  198. fp = *(unsigned long *) fp;
  199. } while (count++ < 16);
  200. #endif
  201. return 0;
  202. }