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/stddef.h>
47#include <linux/unistd.h>
48#include <linux/kallsyms.h>
49#include <linux/uaccess.h>
50
51#include <asm/io.h>
52#include <asm/asm-offsets.h>
53#include <asm/pdc.h>
54#include <asm/pdc_chassis.h>
55#include <asm/pgalloc.h>
56#include <asm/unwind.h>
57#include <asm/sections.h>
58
59
60
61
62
63
64
65void cpu_idle(void)
66{
67 set_thread_flag(TIF_POLLING_NRFLAG);
68
69
70 while (1) {
71 while (!need_resched())
72 barrier();
73 preempt_enable_no_resched();
74 schedule();
75 preempt_disable();
76 check_pgt_cache();
77 }
78}
79
80
81#define COMMAND_GLOBAL F_EXTEND(0xfffe0030)
82#define CMD_RESET 5
83
84
85
86
87
88
89
90
91
92
93
94
95
96void machine_restart(char *cmd)
97{
98#ifdef FASTBOOT_SELFTEST_SUPPORT
99
100
101
102
103
104
105
106
107
108
109
110 if (ftc_bitmap) {
111 pdc_do_firm_test_reset(ftc_bitmap);
112 }
113#endif
114
115 pdc_chassis_send_status(PDC_CHASSIS_DIRECT_SHUTDOWN);
116
117
118 pdc_do_reset();
119
120
121 gsc_writel(CMD_RESET, COMMAND_GLOBAL);
122
123
124 while (1) ;
125
126}
127
128void machine_halt(void)
129{
130
131
132
133
134}
135
136void (*chassis_power_off)(void);
137
138
139
140
141
142void machine_power_off(void)
143{
144
145 if (chassis_power_off)
146 chassis_power_off();
147
148
149
150
151 pdc_soft_power_button(0);
152
153 pdc_chassis_send_status(PDC_CHASSIS_DIRECT_SHUTDOWN);
154
155
156
157
158 printk(KERN_EMERG "System shut down completed.\n"
159 "Please power this system off now.");
160}
161
162void (*pm_power_off)(void) = machine_power_off;
163EXPORT_SYMBOL(pm_power_off);
164
165
166
167
168
169extern pid_t __kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);
170pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
171{
172
173
174
175
176
177
178 return __kernel_thread(fn, arg, flags);
179}
180EXPORT_SYMBOL(kernel_thread);
181
182
183
184
185void exit_thread(void)
186{
187}
188
189void flush_thread(void)
190{
191
192
193
194 set_fs(USER_DS);
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, (char __user * __user *) regs->gr[25],
351 (char __user * __user *) regs->gr[24], regs);
352 putname(filename);
353out:
354
355 return error;
356}
357
358extern int __execve(const char *filename, char *const argv[],
359 char *const envp[], struct task_struct *task);
360int kernel_execve(const char *filename, char *const argv[], char *const envp[])
361{
362 return __execve(filename, argv, envp, current);
363}
364
365unsigned long
366get_wchan(struct task_struct *p)
367{
368 struct unwind_frame_info info;
369 unsigned long ip;
370 int count = 0;
371
372 if (!p || p == current || p->state == TASK_RUNNING)
373 return 0;
374
375
376
377
378
379 unwind_frame_init_from_blocked_task(&info, p);
380 do {
381 if (unwind_once(&info) < 0)
382 return 0;
383 ip = info.ip;
384 if (!in_sched_functions(ip))
385 return ip;
386 } while (count++ < 16);
387 return 0;
388}
389
390#ifdef CONFIG_64BIT
391void *dereference_function_descriptor(void *ptr)
392{
393 Elf64_Fdesc *desc = ptr;
394 void *p;
395
396 if (!probe_kernel_address(&desc->addr, p))
397 ptr = p;
398 return ptr;
399}
400#endif
401