1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35#include <stdarg.h>
36
37#include <linux/elf.h>
38#include <linux/errno.h>
39#include <linux/kernel.h>
40#include <linux/mm.h>
41#include <linux/fs.h>
42#include <linux/module.h>
43#include <linux/personality.h>
44#include <linux/ptrace.h>
45#include <linux/sched.h>
46#include <linux/slab.h>
47#include <linux/stddef.h>
48#include <linux/unistd.h>
49#include <linux/kallsyms.h>
50#include <linux/uaccess.h>
51
52#include <asm/io.h>
53#include <asm/asm-offsets.h>
54#include <asm/pdc.h>
55#include <asm/pdc_chassis.h>
56#include <asm/pgalloc.h>
57#include <asm/unwind.h>
58#include <asm/sections.h>
59
60
61
62
63
64
65
66void cpu_idle(void)
67{
68 set_thread_flag(TIF_POLLING_NRFLAG);
69
70
71 while (1) {
72 while (!need_resched())
73 barrier();
74 preempt_enable_no_resched();
75 schedule();
76 preempt_disable();
77 check_pgt_cache();
78 }
79}
80
81
82#define COMMAND_GLOBAL F_EXTEND(0xfffe0030)
83#define CMD_RESET 5
84
85
86
87
88
89
90
91
92
93
94
95
96
97void machine_restart(char *cmd)
98{
99#ifdef FASTBOOT_SELFTEST_SUPPORT
100
101
102
103
104
105
106
107
108
109
110
111 if (ftc_bitmap) {
112 pdc_do_firm_test_reset(ftc_bitmap);
113 }
114#endif
115
116 pdc_chassis_send_status(PDC_CHASSIS_DIRECT_SHUTDOWN);
117
118
119 pdc_do_reset();
120
121
122 gsc_writel(CMD_RESET, COMMAND_GLOBAL);
123
124
125 while (1) ;
126
127}
128
129void machine_halt(void)
130{
131
132
133
134
135}
136
137void (*chassis_power_off)(void);
138
139
140
141
142
143void machine_power_off(void)
144{
145
146 if (chassis_power_off)
147 chassis_power_off();
148
149
150
151
152 pdc_soft_power_button(0);
153
154 pdc_chassis_send_status(PDC_CHASSIS_DIRECT_SHUTDOWN);
155
156
157
158
159 printk(KERN_EMERG "System shut down completed.\n"
160 "Please power this system off now.");
161}
162
163void (*pm_power_off)(void) = machine_power_off;
164EXPORT_SYMBOL(pm_power_off);
165
166
167
168
169
170extern pid_t __kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);
171pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
172{
173
174
175
176
177
178
179 return __kernel_thread(fn, arg, flags);
180}
181EXPORT_SYMBOL(kernel_thread);
182
183
184
185
186void exit_thread(void)
187{
188}
189
190void flush_thread(void)
191{
192
193
194
195}
196
197void release_thread(struct task_struct *dead_task)
198{
199}
200
201
202
203
204
205int dump_fpu (struct pt_regs * regs, elf_fpregset_t *r)
206{
207 if (regs == NULL)
208 return 0;
209
210 memcpy(r, regs->fr, sizeof *r);
211 return 1;
212}
213
214int dump_task_fpu (struct task_struct *tsk, elf_fpregset_t *r)
215{
216 memcpy(r, tsk->thread.regs.fr, sizeof(*r));
217 return 1;
218}
219
220
221
222int
223sys_clone(unsigned long clone_flags, unsigned long usp,
224 struct pt_regs *regs)
225{
226
227
228
229
230
231
232
233
234
235 int __user *parent_tidptr = (int __user *)regs->gr[24];
236 int __user *child_tidptr = (int __user *)regs->gr[22];
237
238
239
240
241 usp = ALIGN(usp, 4);
242
243
244 if (usp == 0)
245 usp = regs->gr[30];
246
247 return do_fork(clone_flags, usp, regs, 0, parent_tidptr, child_tidptr);
248}
249
250int
251sys_vfork(struct pt_regs *regs)
252{
253 return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->gr[30], regs, 0, NULL, NULL);
254}
255
256int
257copy_thread(unsigned long clone_flags, unsigned long usp,
258 unsigned long unused,
259 struct task_struct * p, struct pt_regs * pregs)
260{
261 struct pt_regs * cregs = &(p->thread.regs);
262 void *stack = task_stack_page(p);
263
264
265
266
267 extern void * const ret_from_kernel_thread;
268 extern void * const child_return;
269#ifdef CONFIG_HPUX
270 extern void * const hpux_child_return;
271#endif
272
273 *cregs = *pregs;
274
275
276
277
278 cregs->gr[28] = 0;
279
280
281
282
283
284
285
286
287 if (usp == 1) {
288
289 cregs->ksp = (unsigned long)stack + THREAD_SZ_ALGN;
290
291
292
293 cregs->kpc = (unsigned long) &ret_from_kernel_thread;
294
295
296
297
298#ifdef CONFIG_64BIT
299 cregs->gr[27] = pregs->gr[27];
300#endif
301 cregs->gr[26] = pregs->gr[26];
302 cregs->gr[25] = pregs->gr[25];
303 } else {
304
305
306
307
308
309
310
311 cregs->ksp = (unsigned long)stack
312 + (pregs->gr[21] & (THREAD_SIZE - 1));
313 cregs->gr[30] = usp;
314 if (p->personality == PER_HPUX) {
315#ifdef CONFIG_HPUX
316 cregs->kpc = (unsigned long) &hpux_child_return;
317#else
318 BUG();
319#endif
320 } else {
321 cregs->kpc = (unsigned long) &child_return;
322 }
323
324 if (clone_flags & CLONE_SETTLS)
325 cregs->cr27 = pregs->gr[23];
326
327 }
328
329 return 0;
330}
331
332unsigned long thread_saved_pc(struct task_struct *t)
333{
334 return t->thread.regs.kpc;
335}
336
337
338
339
340
341asmlinkage int sys_execve(struct pt_regs *regs)
342{
343 int error;
344 char *filename;
345
346 filename = getname((const char __user *) regs->gr[26]);
347 error = PTR_ERR(filename);
348 if (IS_ERR(filename))
349 goto out;
350 error = do_execve(filename,
351 (const char __user *const __user *) regs->gr[25],
352 (const char __user *const __user *) regs->gr[24],
353 regs);
354 putname(filename);
355out:
356
357 return error;
358}
359
360extern int __execve(const char *filename,
361 const char *const argv[],
362 const char *const envp[], struct task_struct *task);
363int kernel_execve(const char *filename,
364 const char *const argv[],
365 const char *const envp[])
366{
367 return __execve(filename, argv, envp, current);
368}
369
370unsigned long
371get_wchan(struct task_struct *p)
372{
373 struct unwind_frame_info info;
374 unsigned long ip;
375 int count = 0;
376
377 if (!p || p == current || p->state == TASK_RUNNING)
378 return 0;
379
380
381
382
383
384 unwind_frame_init_from_blocked_task(&info, p);
385 do {
386 if (unwind_once(&info) < 0)
387 return 0;
388 ip = info.ip;
389 if (!in_sched_functions(ip))
390 return ip;
391 } while (count++ < 16);
392 return 0;
393}
394
395#ifdef CONFIG_64BIT
396void *dereference_function_descriptor(void *ptr)
397{
398 Elf64_Fdesc *desc = ptr;
399 void *p;
400
401 if (!probe_kernel_address(&desc->addr, p))
402 ptr = p;
403 return ptr;
404}
405#endif
406