aboutsummaryrefslogtreecommitdiffstats
path: root/arch/parisc/kernel/process.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/parisc/kernel/process.c')
-rw-r--r--arch/parisc/kernel/process.c96
1 files changed, 15 insertions, 81 deletions
diff --git a/arch/parisc/kernel/process.c b/arch/parisc/kernel/process.c
index cbc37216bf90..38db36f64307 100644
--- a/arch/parisc/kernel/process.c
+++ b/arch/parisc/kernel/process.c
@@ -52,6 +52,7 @@
52 52
53#include <asm/io.h> 53#include <asm/io.h>
54#include <asm/asm-offsets.h> 54#include <asm/asm-offsets.h>
55#include <asm/assembly.h>
55#include <asm/pdc.h> 56#include <asm/pdc.h>
56#include <asm/pdc_chassis.h> 57#include <asm/pdc_chassis.h>
57#include <asm/pgalloc.h> 58#include <asm/pgalloc.h>
@@ -165,23 +166,6 @@ void (*pm_power_off)(void) = machine_power_off;
165EXPORT_SYMBOL(pm_power_off); 166EXPORT_SYMBOL(pm_power_off);
166 167
167/* 168/*
168 * Create a kernel thread
169 */
170
171extern pid_t __kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);
172pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
173{
174
175 /*
176 * FIXME: Once we are sure we don't need any debug here,
177 * kernel_thread can become a #define.
178 */
179
180 return __kernel_thread(fn, arg, flags);
181}
182EXPORT_SYMBOL(kernel_thread);
183
184/*
185 * Free current thread data structures etc.. 169 * Free current thread data structures etc..
186 */ 170 */
187void exit_thread(void) 171void exit_thread(void)
@@ -256,8 +240,8 @@ sys_vfork(struct pt_regs *regs)
256 240
257int 241int
258copy_thread(unsigned long clone_flags, unsigned long usp, 242copy_thread(unsigned long clone_flags, unsigned long usp,
259 unsigned long unused, /* in ia64 this is "user_stack_size" */ 243 unsigned long arg,
260 struct task_struct * p, struct pt_regs * pregs) 244 struct task_struct *p, struct pt_regs *pregs)
261{ 245{
262 struct pt_regs * cregs = &(p->thread.regs); 246 struct pt_regs * cregs = &(p->thread.regs);
263 void *stack = task_stack_page(p); 247 void *stack = task_stack_page(p);
@@ -270,48 +254,32 @@ copy_thread(unsigned long clone_flags, unsigned long usp,
270#ifdef CONFIG_HPUX 254#ifdef CONFIG_HPUX
271 extern void * const hpux_child_return; 255 extern void * const hpux_child_return;
272#endif 256#endif
257 if (unlikely(p->flags & PF_KTHREAD)) {
258 memset(cregs, 0, sizeof(struct pt_regs));
259 if (!usp) /* idle thread */
260 return 0;
273 261
274 *cregs = *pregs;
275
276 /* Set the return value for the child. Note that this is not
277 actually restored by the syscall exit path, but we put it
278 here for consistency in case of signals. */
279 cregs->gr[28] = 0; /* child */
280
281 /*
282 * We need to differentiate between a user fork and a
283 * kernel fork. We can't use user_mode, because the
284 * the syscall path doesn't save iaoq. Right now
285 * We rely on the fact that kernel_thread passes
286 * in zero for usp.
287 */
288 if (usp == 1) {
289 /* kernel thread */ 262 /* kernel thread */
290 cregs->ksp = (unsigned long)stack + THREAD_SZ_ALGN;
291 /* Must exit via ret_from_kernel_thread in order 263 /* Must exit via ret_from_kernel_thread in order
292 * to call schedule_tail() 264 * to call schedule_tail()
293 */ 265 */
266 cregs->ksp = (unsigned long)stack + THREAD_SZ_ALGN + FRAME_SIZE;
294 cregs->kpc = (unsigned long) &ret_from_kernel_thread; 267 cregs->kpc = (unsigned long) &ret_from_kernel_thread;
295 /* 268 /*
296 * Copy function and argument to be called from 269 * Copy function and argument to be called from
297 * ret_from_kernel_thread. 270 * ret_from_kernel_thread.
298 */ 271 */
299#ifdef CONFIG_64BIT 272#ifdef CONFIG_64BIT
300 cregs->gr[27] = pregs->gr[27]; 273 cregs->gr[27] = ((unsigned long *)usp)[3];
274 cregs->gr[26] = ((unsigned long *)usp)[2];
275#else
276 cregs->gr[26] = usp;
301#endif 277#endif
302 cregs->gr[26] = pregs->gr[26]; 278 cregs->gr[25] = arg;
303 cregs->gr[25] = pregs->gr[25];
304 } else { 279 } else {
305 /* user thread */ 280 /* user thread */
306 /*
307 * Note that the fork wrappers are responsible
308 * for setting gr[21].
309 */
310
311 /* Use same stack depth as parent */
312 cregs->ksp = (unsigned long)stack
313 + (pregs->gr[21] & (THREAD_SIZE - 1));
314 cregs->gr[30] = usp; 281 cregs->gr[30] = usp;
282 cregs->ksp = (unsigned long)stack + THREAD_SZ_ALGN + FRAME_SIZE;
315 if (personality(p->personality) == PER_HPUX) { 283 if (personality(p->personality) == PER_HPUX) {
316#ifdef CONFIG_HPUX 284#ifdef CONFIG_HPUX
317 cregs->kpc = (unsigned long) &hpux_child_return; 285 cregs->kpc = (unsigned long) &hpux_child_return;
@@ -323,8 +291,7 @@ copy_thread(unsigned long clone_flags, unsigned long usp,
323 } 291 }
324 /* Setup thread TLS area from the 4th parameter in clone */ 292 /* Setup thread TLS area from the 4th parameter in clone */
325 if (clone_flags & CLONE_SETTLS) 293 if (clone_flags & CLONE_SETTLS)
326 cregs->cr27 = pregs->gr[23]; 294 cregs->cr27 = pregs->gr[23];
327
328 } 295 }
329 296
330 return 0; 297 return 0;
@@ -335,39 +302,6 @@ unsigned long thread_saved_pc(struct task_struct *t)
335 return t->thread.regs.kpc; 302 return t->thread.regs.kpc;
336} 303}
337 304
338/*
339 * sys_execve() executes a new program.
340 */
341
342asmlinkage int sys_execve(struct pt_regs *regs)
343{
344 int error;
345 struct filename *filename;
346
347 filename = getname((const char __user *) regs->gr[26]);
348 error = PTR_ERR(filename);
349 if (IS_ERR(filename))
350 goto out;
351 error = do_execve(filename->name,
352 (const char __user *const __user *) regs->gr[25],
353 (const char __user *const __user *) regs->gr[24],
354 regs);
355 putname(filename);
356out:
357
358 return error;
359}
360
361extern int __execve(const char *filename,
362 const char *const argv[],
363 const char *const envp[], struct task_struct *task);
364int kernel_execve(const char *filename,
365 const char *const argv[],
366 const char *const envp[])
367{
368 return __execve(filename, argv, envp, current);
369}
370
371unsigned long 305unsigned long
372get_wchan(struct task_struct *p) 306get_wchan(struct task_struct *p)
373{ 307{