aboutsummaryrefslogtreecommitdiffstats
path: root/arch/alpha/kernel/process.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/alpha/kernel/process.c')
-rw-r--r--arch/alpha/kernel/process.c79
1 files changed, 20 insertions, 59 deletions
diff --git a/arch/alpha/kernel/process.c b/arch/alpha/kernel/process.c
index 83638aa096d5..4054e0ffe2b2 100644
--- a/arch/alpha/kernel/process.c
+++ b/arch/alpha/kernel/process.c
@@ -263,33 +263,35 @@ alpha_vfork(struct pt_regs *regs)
263 263
264/* 264/*
265 * Copy an alpha thread.. 265 * Copy an alpha thread..
266 *
267 * Note the "stack_offset" stuff: when returning to kernel mode, we need
268 * to have some extra stack-space for the kernel stack that still exists
269 * after the "ret_from_fork". When returning to user mode, we only want
270 * the space needed by the syscall stack frame (ie "struct pt_regs").
271 * Use the passed "regs" pointer to determine how much space we need
272 * for a kernel fork().
273 */ 266 */
274 267
275int 268int
276copy_thread(unsigned long clone_flags, unsigned long usp, 269copy_thread(unsigned long clone_flags, unsigned long usp,
277 unsigned long unused, 270 unsigned long arg,
278 struct task_struct * p, struct pt_regs * regs) 271 struct task_struct * p, struct pt_regs * regs)
279{ 272{
280 extern void ret_from_fork(void); 273 extern void ret_from_fork(void);
274 extern void ret_from_kernel_thread(void);
281 275
282 struct thread_info *childti = task_thread_info(p); 276 struct thread_info *childti = task_thread_info(p);
283 struct pt_regs * childregs; 277 struct pt_regs *childregs = task_pt_regs(p);
284 struct switch_stack * childstack, *stack; 278 struct switch_stack *childstack, *stack;
285 unsigned long stack_offset, settls; 279 unsigned long settls;
286 280
287 stack_offset = PAGE_SIZE - sizeof(struct pt_regs); 281 childstack = ((struct switch_stack *) childregs) - 1;
288 if (!(regs->ps & 8)) 282 if (unlikely(!regs)) {
289 stack_offset = (PAGE_SIZE-1) & (unsigned long) regs; 283 /* kernel thread */
290 childregs = (struct pt_regs *) 284 memset(childstack, 0,
291 (stack_offset + PAGE_SIZE + task_stack_page(p)); 285 sizeof(struct switch_stack) + sizeof(struct pt_regs));
292 286 childstack->r26 = (unsigned long) ret_from_kernel_thread;
287 childstack->r9 = usp; /* function */
288 childstack->r10 = arg;
289 childregs->hae = alpha_mv.hae_cache,
290 childti->pcb.usp = 0;
291 childti->pcb.ksp = (unsigned long) childstack;
292 childti->pcb.flags = 1; /* set FEN, clear everything else */
293 return 0;
294 }
293 *childregs = *regs; 295 *childregs = *regs;
294 settls = regs->r20; 296 settls = regs->r20;
295 childregs->r0 = 0; 297 childregs->r0 = 0;
@@ -297,7 +299,6 @@ copy_thread(unsigned long clone_flags, unsigned long usp,
297 childregs->r20 = 1; /* OSF/1 has some strange fork() semantics. */ 299 childregs->r20 = 1; /* OSF/1 has some strange fork() semantics. */
298 regs->r20 = 0; 300 regs->r20 = 0;
299 stack = ((struct switch_stack *) regs) - 1; 301 stack = ((struct switch_stack *) regs) - 1;
300 childstack = ((struct switch_stack *) childregs) - 1;
301 *childstack = *stack; 302 *childstack = *stack;
302 childstack->r26 = (unsigned long) ret_from_fork; 303 childstack->r26 = (unsigned long) ret_from_fork;
303 childti->pcb.usp = usp; 304 childti->pcb.usp = usp;
@@ -386,27 +387,6 @@ dump_elf_task_fp(elf_fpreg_t *dest, struct task_struct *task)
386EXPORT_SYMBOL(dump_elf_task_fp); 387EXPORT_SYMBOL(dump_elf_task_fp);
387 388
388/* 389/*
389 * sys_execve() executes a new program.
390 */
391asmlinkage int
392do_sys_execve(const char __user *ufilename,
393 const char __user *const __user *argv,
394 const char __user *const __user *envp, struct pt_regs *regs)
395{
396 int error;
397 char *filename;
398
399 filename = getname(ufilename);
400 error = PTR_ERR(filename);
401 if (IS_ERR(filename))
402 goto out;
403 error = do_execve(filename, argv, envp, regs);
404 putname(filename);
405out:
406 return error;
407}
408
409/*
410 * Return saved PC of a blocked thread. This assumes the frame 390 * Return saved PC of a blocked thread. This assumes the frame
411 * pointer is the 6th saved long on the kernel stack and that the 391 * pointer is the 6th saved long on the kernel stack and that the
412 * saved return address is the first long in the frame. This all 392 * saved return address is the first long in the frame. This all
@@ -459,22 +439,3 @@ get_wchan(struct task_struct *p)
459 } 439 }
460 return pc; 440 return pc;
461} 441}
462
463int kernel_execve(const char *path, const char *const argv[], const char *const envp[])
464{
465 /* Avoid the HAE being gratuitously wrong, which would cause us
466 to do the whole turn off interrupts thing and restore it. */
467 struct pt_regs regs = {.hae = alpha_mv.hae_cache};
468 int err = do_execve(path, argv, envp, &regs);
469 if (!err) {
470 struct pt_regs *p = current_pt_regs();
471 /* copy regs to normal position and off to userland we go... */
472 *p = regs;
473 __asm__ __volatile__ (
474 "mov %0, $sp;"
475 "br $31, ret_from_sys_call"
476 : : "r"(p));
477 }
478 return err;
479}
480EXPORT_SYMBOL(kernel_execve);