1
2
3
4
5
6
7
8
9
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/stddef.h>
18#include <linux/unistd.h>
19#include <linux/ptrace.h>
20#include <linux/user.h>
21#include <linux/interrupt.h>
22#include <linux/delay.h>
23#include <linux/reboot.h>
24#include <linux/percpu.h>
25#include <linux/err.h>
26#include <linux/fs.h>
27#include <linux/slab.h>
28#include <asm/uaccess.h>
29#include <asm/pgtable.h>
30#include <asm/io.h>
31#include <asm/processor.h>
32#include <asm/mmu_context.h>
33#include <asm/fpu.h>
34#include <asm/reset-regs.h>
35#include <asm/gdb-stub.h>
36#include "internal.h"
37
38
39
40
41void (*pm_idle)(void);
42EXPORT_SYMBOL(pm_idle);
43
44
45
46
47unsigned long thread_saved_pc(struct task_struct *tsk)
48{
49 return ((unsigned long *) tsk->thread.sp)[3];
50}
51
52
53
54
55void (*pm_power_off)(void);
56EXPORT_SYMBOL(pm_power_off);
57
58#if !defined(CONFIG_SMP) || defined(CONFIG_HOTPLUG_CPU)
59
60
61
62static void default_idle(void)
63{
64 local_irq_disable();
65 if (!need_resched())
66 safe_halt();
67 else
68 local_irq_enable();
69}
70
71#else
72
73
74
75
76
77static inline void poll_idle(void)
78{
79 int oldval;
80
81 local_irq_enable();
82
83
84
85
86
87 oldval = test_and_clear_thread_flag(TIF_NEED_RESCHED);
88
89 if (!oldval) {
90 set_thread_flag(TIF_POLLING_NRFLAG);
91 while (!need_resched())
92 cpu_relax();
93 clear_thread_flag(TIF_POLLING_NRFLAG);
94 } else {
95 set_need_resched();
96 }
97}
98#endif
99
100
101
102
103
104
105
106void cpu_idle(void)
107{
108
109 for (;;) {
110 while (!need_resched()) {
111 void (*idle)(void);
112
113 smp_rmb();
114 idle = pm_idle;
115 if (!idle) {
116#if defined(CONFIG_SMP) && !defined(CONFIG_HOTPLUG_CPU)
117 idle = poll_idle;
118#else
119 idle = default_idle;
120#endif
121 }
122 idle();
123 }
124
125 schedule_preempt_disabled();
126 }
127}
128
129void release_segments(struct mm_struct *mm)
130{
131}
132
133void machine_restart(char *cmd)
134{
135#ifdef CONFIG_KERNEL_DEBUGGER
136 gdbstub_exit(0);
137#endif
138
139#ifdef mn10300_unit_hard_reset
140 mn10300_unit_hard_reset();
141#else
142 mn10300_proc_hard_reset();
143#endif
144}
145
146void machine_halt(void)
147{
148#ifdef CONFIG_KERNEL_DEBUGGER
149 gdbstub_exit(0);
150#endif
151}
152
153void machine_power_off(void)
154{
155#ifdef CONFIG_KERNEL_DEBUGGER
156 gdbstub_exit(0);
157#endif
158}
159
160void show_regs(struct pt_regs *regs)
161{
162}
163
164
165
166
167int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
168{
169 struct pt_regs regs;
170
171 memset(®s, 0, sizeof(regs));
172
173 regs.a2 = (unsigned long) fn;
174 regs.d2 = (unsigned long) arg;
175 regs.pc = (unsigned long) kernel_thread_helper;
176 local_save_flags(regs.epsw);
177 regs.epsw |= EPSW_IE | EPSW_IM_7;
178
179
180 return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, ®s, 0,
181 NULL, NULL);
182}
183EXPORT_SYMBOL(kernel_thread);
184
185
186
187
188void exit_thread(void)
189{
190 exit_fpu();
191}
192
193void flush_thread(void)
194{
195 flush_fpu();
196}
197
198void release_thread(struct task_struct *dead_task)
199{
200}
201
202
203
204
205
206void copy_segments(struct task_struct *p, struct mm_struct *new_mm)
207{
208}
209
210
211
212
213
214int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
215{
216 unlazy_fpu(src);
217 *dst = *src;
218 return 0;
219}
220
221
222
223
224
225int copy_thread(unsigned long clone_flags,
226 unsigned long c_usp, unsigned long ustk_size,
227 struct task_struct *p, struct pt_regs *kregs)
228{
229 struct thread_info *ti = task_thread_info(p);
230 struct pt_regs *c_uregs, *c_kregs, *uregs;
231 unsigned long c_ksp;
232
233 uregs = current->thread.uregs;
234
235 c_ksp = (unsigned long) task_stack_page(p) + THREAD_SIZE;
236
237
238 c_ksp -= sizeof(struct pt_regs);
239 c_uregs = (struct pt_regs *) c_ksp;
240
241 p->thread.uregs = c_uregs;
242 *c_uregs = *uregs;
243 c_uregs->sp = c_usp;
244 c_uregs->epsw &= ~EPSW_FE;
245
246 c_ksp -= 12;
247
248
249 if (clone_flags & CLONE_SETTLS)
250 c_uregs->e2 = current_frame()->d3;
251
252
253 c_kregs = c_uregs;
254 if (kregs != uregs) {
255 c_ksp -= sizeof(struct pt_regs);
256 c_kregs = (struct pt_regs *) c_ksp;
257 *c_kregs = *kregs;
258 c_kregs->sp = c_usp;
259 c_kregs->next = c_uregs;
260#ifdef CONFIG_MN10300_CURRENT_IN_E2
261 c_kregs->e2 = (unsigned long) p;
262#endif
263
264 c_ksp -= 12;
265 }
266
267
268 ti->frame = c_kregs;
269 p->thread.a3 = (unsigned long) c_kregs;
270 p->thread.sp = c_ksp;
271 p->thread.pc = (unsigned long) ret_from_fork;
272 p->thread.wchan = (unsigned long) ret_from_fork;
273 p->thread.usp = c_usp;
274
275 return 0;
276}
277
278
279
280
281
282asmlinkage long sys_clone(unsigned long clone_flags, unsigned long newsp,
283 int __user *parent_tidptr, int __user *child_tidptr,
284 int __user *tlsptr)
285{
286 return do_fork(clone_flags, newsp ?: current_frame()->sp,
287 current_frame(), 0, parent_tidptr, child_tidptr);
288}
289
290asmlinkage long sys_fork(void)
291{
292 return do_fork(SIGCHLD, current_frame()->sp,
293 current_frame(), 0, NULL, NULL);
294}
295
296asmlinkage long sys_vfork(void)
297{
298 return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, current_frame()->sp,
299 current_frame(), 0, NULL, NULL);
300}
301
302asmlinkage long sys_execve(const char __user *name,
303 const char __user *const __user *argv,
304 const char __user *const __user *envp)
305{
306 char *filename;
307 int error;
308
309 filename = getname(name);
310 error = PTR_ERR(filename);
311 if (IS_ERR(filename))
312 return error;
313 error = do_execve(filename, argv, envp, current_frame());
314 putname(filename);
315 return error;
316}
317
318unsigned long get_wchan(struct task_struct *p)
319{
320 return p->thread.wchan;
321}
322