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