diff options
Diffstat (limited to 'arch/xtensa/kernel/process.c')
-rw-r--r-- | arch/xtensa/kernel/process.c | 71 |
1 files changed, 41 insertions, 30 deletions
diff --git a/arch/xtensa/kernel/process.c b/arch/xtensa/kernel/process.c index 3785f3481d71..795bd5ac6f4c 100644 --- a/arch/xtensa/kernel/process.c +++ b/arch/xtensa/kernel/process.c | |||
@@ -161,36 +161,6 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp, | |||
161 | 161 | ||
162 | 162 | ||
163 | /* | 163 | /* |
164 | * Create a kernel thread | ||
165 | */ | ||
166 | |||
167 | int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) | ||
168 | { | ||
169 | long retval; | ||
170 | __asm__ __volatile__ | ||
171 | ("mov a5, %4\n\t" /* preserve fn in a5 */ | ||
172 | "mov a6, %3\n\t" /* preserve and setup arg in a6 */ | ||
173 | "movi a2, %1\n\t" /* load __NR_clone for syscall*/ | ||
174 | "mov a3, sp\n\t" /* sp check and sys_clone */ | ||
175 | "mov a4, %5\n\t" /* load flags for syscall */ | ||
176 | "syscall\n\t" | ||
177 | "beq a3, sp, 1f\n\t" /* branch if parent */ | ||
178 | "callx4 a5\n\t" /* call fn */ | ||
179 | "movi a2, %2\n\t" /* load __NR_exit for syscall */ | ||
180 | "mov a3, a6\n\t" /* load fn return value */ | ||
181 | "syscall\n" | ||
182 | "1:\n\t" | ||
183 | "mov %0, a2\n\t" /* parent returns zero */ | ||
184 | :"=r" (retval) | ||
185 | :"i" (__NR_clone), "i" (__NR_exit), | ||
186 | "r" (arg), "r" (fn), | ||
187 | "r" (flags | CLONE_VM) | ||
188 | : "a2", "a3", "a4", "a5", "a6" ); | ||
189 | return retval; | ||
190 | } | ||
191 | |||
192 | |||
193 | /* | ||
194 | * These bracket the sleeping functions.. | 164 | * These bracket the sleeping functions.. |
195 | */ | 165 | */ |
196 | 166 | ||
@@ -452,3 +422,44 @@ int dump_fpu(struct pt_regs *regs, elf_fpregset_t *r) | |||
452 | { | 422 | { |
453 | return dump_task_fpu(regs, current, r); | 423 | return dump_task_fpu(regs, current, r); |
454 | } | 424 | } |
425 | |||
426 | asmlinkage | ||
427 | long xtensa_clone(unsigned long clone_flags, unsigned long newsp, | ||
428 | void __user *parent_tid, void *child_tls, | ||
429 | void __user *child_tid, long a5, | ||
430 | struct pt_regs *regs) | ||
431 | { | ||
432 | if (!newsp) | ||
433 | newsp = regs->areg[1]; | ||
434 | return do_fork(clone_flags, newsp, regs, 0, parent_tid, child_tid); | ||
435 | } | ||
436 | |||
437 | /* | ||
438 | * * xtensa_execve() executes a new program. | ||
439 | * */ | ||
440 | |||
441 | asmlinkage | ||
442 | long xtensa_execve(char __user *name, char __user * __user *argv, | ||
443 | char __user * __user *envp, | ||
444 | long a3, long a4, long a5, | ||
445 | struct pt_regs *regs) | ||
446 | { | ||
447 | long error; | ||
448 | char * filename; | ||
449 | |||
450 | filename = getname(name); | ||
451 | error = PTR_ERR(filename); | ||
452 | if (IS_ERR(filename)) | ||
453 | goto out; | ||
454 | // FIXME: release coprocessor?? | ||
455 | error = do_execve(filename, argv, envp, regs); | ||
456 | if (error == 0) { | ||
457 | task_lock(current); | ||
458 | current->ptrace &= ~PT_DTRACE; | ||
459 | task_unlock(current); | ||
460 | } | ||
461 | putname(filename); | ||
462 | out: | ||
463 | return error; | ||
464 | } | ||
465 | |||