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