aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mn10300/kernel/process.c
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2008-02-08 07:19:31 -0500
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2008-02-08 12:22:30 -0500
commitb920de1b77b72ca9432ac3f97edb26541e65e5dd (patch)
tree40fa9be1470e929c47927dea7eddf184c0204229 /arch/mn10300/kernel/process.c
parentef3d534754f31fed9c3b976fee1ece1b3bc38282 (diff)
mn10300: add the MN10300/AM33 architecture to the kernel
Add architecture support for the MN10300/AM33 CPUs produced by MEI to the kernel. This patch also adds board support for the ASB2303 with the ASB2308 daughter board, and the ASB2305. The only processor supported is the MN103E010, which is an AM33v2 core plus on-chip devices. [akpm@linux-foundation.org: nuke cvs control strings] Signed-off-by: Masakazu Urade <urade.masakazu@jp.panasonic.com> Signed-off-by: Koichi Yasutake <yasutake.koichi@jp.panasonic.com> Signed-off-by: David Howells <dhowells@redhat.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'arch/mn10300/kernel/process.c')
-rw-r--r--arch/mn10300/kernel/process.c297
1 files changed, 297 insertions, 0 deletions
diff --git a/arch/mn10300/kernel/process.c b/arch/mn10300/kernel/process.c
new file mode 100644
index 000000000000..3b0d579fc15d
--- /dev/null
+++ b/arch/mn10300/kernel/process.c
@@ -0,0 +1,297 @@
1/* MN10300 Process handling code
2 *
3 * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public Licence
8 * as published by the Free Software Foundation; either version
9 * 2 of the Licence, or (at your option) any later version.
10 */
11#include <linux/module.h>
12#include <linux/errno.h>
13#include <linux/sched.h>
14#include <linux/kernel.h>
15#include <linux/mm.h>
16#include <linux/smp.h>
17#include <linux/smp_lock.h>
18#include <linux/stddef.h>
19#include <linux/unistd.h>
20#include <linux/ptrace.h>
21#include <linux/slab.h>
22#include <linux/user.h>
23#include <linux/a.out.h>
24#include <linux/interrupt.h>
25#include <linux/delay.h>
26#include <linux/reboot.h>
27#include <linux/percpu.h>
28#include <linux/err.h>
29#include <linux/fs.h>
30#include <asm/uaccess.h>
31#include <asm/pgtable.h>
32#include <asm/system.h>
33#include <asm/io.h>
34#include <asm/processor.h>
35#include <asm/mmu_context.h>
36#include <asm/fpu.h>
37#include <asm/reset-regs.h>
38#include <asm/gdb-stub.h>
39#include "internal.h"
40
41/*
42 * power management idle function, if any..
43 */
44void (*pm_idle)(void);
45EXPORT_SYMBOL(pm_idle);
46
47/*
48 * return saved PC of a blocked thread.
49 */
50unsigned long thread_saved_pc(struct task_struct *tsk)
51{
52 return ((unsigned long *) tsk->thread.sp)[3];
53}
54
55/*
56 * power off function, if any
57 */
58void (*pm_power_off)(void);
59EXPORT_SYMBOL(pm_power_off);
60
61/*
62 * we use this if we don't have any better idle routine
63 */
64static void default_idle(void)
65{
66 local_irq_disable();
67 if (!need_resched())
68 safe_halt();
69 else
70 local_irq_enable();
71}
72
73/*
74 * the idle thread
75 * - there's no useful work to be done, so just try to conserve power and have
76 * a low exit latency (ie sit in a loop waiting for somebody to say that
77 * they'd like to reschedule)
78 */
79void cpu_idle(void)
80{
81 int cpu = smp_processor_id();
82
83 /* endless idle loop with no priority at all */
84 for (;;) {
85 while (!need_resched()) {
86 void (*idle)(void);
87
88 smp_rmb();
89 idle = pm_idle;
90 if (!idle)
91 idle = default_idle;
92
93 irq_stat[cpu].idle_timestamp = jiffies;
94 idle();
95 }
96
97 preempt_enable_no_resched();
98 schedule();
99 preempt_disable();
100 }
101}
102
103void release_segments(struct mm_struct *mm)
104{
105}
106
107void machine_restart(char *cmd)
108{
109#ifdef CONFIG_GDBSTUB
110 gdbstub_exit(0);
111#endif
112
113#ifdef mn10300_unit_hard_reset
114 mn10300_unit_hard_reset();
115#else
116 mn10300_proc_hard_reset();
117#endif
118}
119
120void machine_halt(void)
121{
122#ifdef CONFIG_GDBSTUB
123 gdbstub_exit(0);
124#endif
125}
126
127void machine_power_off(void)
128{
129#ifdef CONFIG_GDBSTUB
130 gdbstub_exit(0);
131#endif
132}
133
134void show_regs(struct pt_regs *regs)
135{
136}
137
138/*
139 * create a kernel thread
140 */
141int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
142{
143 struct pt_regs regs;
144
145 memset(&regs, 0, sizeof(regs));
146
147 regs.a2 = (unsigned long) fn;
148 regs.d2 = (unsigned long) arg;
149 regs.pc = (unsigned long) kernel_thread_helper;
150 local_save_flags(regs.epsw);
151 regs.epsw |= EPSW_IE | EPSW_IM_7;
152
153 /* Ok, create the new process.. */
154 return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, &regs, 0,
155 NULL, NULL);
156}
157
158/*
159 * free current thread data structures etc..
160 */
161void exit_thread(void)
162{
163 exit_fpu();
164}
165
166void flush_thread(void)
167{
168 flush_fpu();
169}
170
171void release_thread(struct task_struct *dead_task)
172{
173}
174
175/*
176 * we do not have to muck with descriptors here, that is
177 * done in switch_mm() as needed.
178 */
179void copy_segments(struct task_struct *p, struct mm_struct *new_mm)
180{
181}
182
183/*
184 * this gets called before we allocate a new thread and copy the current task
185 * into it so that we can store lazy state into memory
186 */
187void prepare_to_copy(struct task_struct *tsk)
188{
189 unlazy_fpu(tsk);
190}
191
192/*
193 * set up the kernel stack for a new thread and copy arch-specific thread
194 * control information
195 */
196int copy_thread(int nr, unsigned long clone_flags,
197 unsigned long c_usp, unsigned long ustk_size,
198 struct task_struct *p, struct pt_regs *kregs)
199{
200 struct pt_regs *c_uregs, *c_kregs, *uregs;
201 unsigned long c_ksp;
202
203 uregs = current->thread.uregs;
204
205 c_ksp = (unsigned long) task_stack_page(p) + THREAD_SIZE;
206
207 /* allocate the userspace exception frame and set it up */
208 c_ksp -= sizeof(struct pt_regs);
209 c_uregs = (struct pt_regs *) c_ksp;
210
211 p->thread.uregs = c_uregs;
212 *c_uregs = *uregs;
213 c_uregs->sp = c_usp;
214 c_uregs->epsw &= ~EPSW_FE; /* my FPU */
215
216 c_ksp -= 12; /* allocate function call ABI slack */
217
218 /* the new TLS pointer is passed in as arg #5 to sys_clone() */
219 if (clone_flags & CLONE_SETTLS)
220 c_uregs->e2 = __frame->d3;
221
222 /* set up the return kernel frame if called from kernel_thread() */
223 c_kregs = c_uregs;
224 if (kregs != uregs) {
225 c_ksp -= sizeof(struct pt_regs);
226 c_kregs = (struct pt_regs *) c_ksp;
227 *c_kregs = *kregs;
228 c_kregs->sp = c_usp;
229 c_kregs->next = c_uregs;
230#ifdef CONFIG_MN10300_CURRENT_IN_E2
231 c_kregs->e2 = (unsigned long) p; /* current */
232#endif
233
234 c_ksp -= 12; /* allocate function call ABI slack */
235 }
236
237 /* set up things up so the scheduler can start the new task */
238 p->thread.__frame = c_kregs;
239 p->thread.a3 = (unsigned long) c_kregs;
240 p->thread.sp = c_ksp;
241 p->thread.pc = (unsigned long) ret_from_fork;
242 p->thread.wchan = (unsigned long) ret_from_fork;
243 p->thread.usp = c_usp;
244
245 return 0;
246}
247
248/*
249 * clone a process
250 * - tlsptr is retrieved by copy_thread() from __frame->d3
251 */
252asmlinkage long sys_clone(unsigned long clone_flags, unsigned long newsp,
253 int __user *parent_tidptr, int __user *child_tidptr,
254 int __user *tlsptr)
255{
256 return do_fork(clone_flags, newsp ?: __frame->sp, __frame, 0,
257 parent_tidptr, child_tidptr);
258}
259
260asmlinkage long sys_fork(void)
261{
262 return do_fork(SIGCHLD, __frame->sp, __frame, 0, NULL, NULL);
263}
264
265asmlinkage long sys_vfork(void)
266{
267 return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, __frame->sp, __frame,
268 0, NULL, NULL);
269}
270
271asmlinkage long sys_execve(char __user *name,
272 char __user * __user *argv,
273 char __user * __user *envp)
274{
275 char *filename;
276 int error;
277
278 lock_kernel();
279
280 filename = getname(name);
281 error = PTR_ERR(filename);
282 if (!IS_ERR(filename)) {
283 error = do_execve(filename, argv, envp, __frame);
284 if (error == 0)
285 current->ptrace &= ~PT_DTRACE;
286
287 putname(filename);
288 }
289
290 unlock_kernel();
291 return error;
292}
293
294unsigned long get_wchan(struct task_struct *p)
295{
296 return p->thread.wchan;
297}