diff options
Diffstat (limited to 'arch/xtensa/kernel/process.c')
-rw-r--r-- | arch/xtensa/kernel/process.c | 108 |
1 files changed, 44 insertions, 64 deletions
diff --git a/arch/xtensa/kernel/process.c b/arch/xtensa/kernel/process.c index a7c4178c2a8c..795bd5ac6f4c 100644 --- a/arch/xtensa/kernel/process.c +++ b/arch/xtensa/kernel/process.c | |||
@@ -1,4 +1,3 @@ | |||
1 | // TODO verify coprocessor handling | ||
2 | /* | 1 | /* |
3 | * arch/xtensa/kernel/process.c | 2 | * arch/xtensa/kernel/process.c |
4 | * | 3 | * |
@@ -43,7 +42,7 @@ | |||
43 | #include <asm/irq.h> | 42 | #include <asm/irq.h> |
44 | #include <asm/atomic.h> | 43 | #include <asm/atomic.h> |
45 | #include <asm/asm-offsets.h> | 44 | #include <asm/asm-offsets.h> |
46 | #include <asm/coprocessor.h> | 45 | #include <asm/regs.h> |
47 | 46 | ||
48 | extern void ret_from_fork(void); | 47 | extern void ret_from_fork(void); |
49 | 48 | ||
@@ -67,25 +66,6 @@ void (*pm_power_off)(void) = NULL; | |||
67 | EXPORT_SYMBOL(pm_power_off); | 66 | EXPORT_SYMBOL(pm_power_off); |
68 | 67 | ||
69 | 68 | ||
70 | #if XCHAL_CP_NUM > 0 | ||
71 | |||
72 | /* | ||
73 | * Coprocessor ownership. | ||
74 | */ | ||
75 | |||
76 | coprocessor_info_t coprocessor_info[] = { | ||
77 | { 0, XTENSA_CPE_CP0_OFFSET }, | ||
78 | { 0, XTENSA_CPE_CP1_OFFSET }, | ||
79 | { 0, XTENSA_CPE_CP2_OFFSET }, | ||
80 | { 0, XTENSA_CPE_CP3_OFFSET }, | ||
81 | { 0, XTENSA_CPE_CP4_OFFSET }, | ||
82 | { 0, XTENSA_CPE_CP5_OFFSET }, | ||
83 | { 0, XTENSA_CPE_CP6_OFFSET }, | ||
84 | { 0, XTENSA_CPE_CP7_OFFSET }, | ||
85 | }; | ||
86 | |||
87 | #endif | ||
88 | |||
89 | /* | 69 | /* |
90 | * Powermanagement idle function, if any is provided by the platform. | 70 | * Powermanagement idle function, if any is provided by the platform. |
91 | */ | 71 | */ |
@@ -110,12 +90,10 @@ void cpu_idle(void) | |||
110 | 90 | ||
111 | void exit_thread(void) | 91 | void exit_thread(void) |
112 | { | 92 | { |
113 | release_coprocessors(current); /* Empty macro if no CPs are defined */ | ||
114 | } | 93 | } |
115 | 94 | ||
116 | void flush_thread(void) | 95 | void flush_thread(void) |
117 | { | 96 | { |
118 | release_coprocessors(current); /* Empty macro if no CPs are defined */ | ||
119 | } | 97 | } |
120 | 98 | ||
121 | /* | 99 | /* |
@@ -183,36 +161,6 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp, | |||
183 | 161 | ||
184 | 162 | ||
185 | /* | 163 | /* |
186 | * Create a kernel thread | ||
187 | */ | ||
188 | |||
189 | int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) | ||
190 | { | ||
191 | long retval; | ||
192 | __asm__ __volatile__ | ||
193 | ("mov a5, %4\n\t" /* preserve fn in a5 */ | ||
194 | "mov a6, %3\n\t" /* preserve and setup arg in a6 */ | ||
195 | "movi a2, %1\n\t" /* load __NR_clone for syscall*/ | ||
196 | "mov a3, sp\n\t" /* sp check and sys_clone */ | ||
197 | "mov a4, %5\n\t" /* load flags for syscall */ | ||
198 | "syscall\n\t" | ||
199 | "beq a3, sp, 1f\n\t" /* branch if parent */ | ||
200 | "callx4 a5\n\t" /* call fn */ | ||
201 | "movi a2, %2\n\t" /* load __NR_exit for syscall */ | ||
202 | "mov a3, a6\n\t" /* load fn return value */ | ||
203 | "syscall\n" | ||
204 | "1:\n\t" | ||
205 | "mov %0, a2\n\t" /* parent returns zero */ | ||
206 | :"=r" (retval) | ||
207 | :"i" (__NR_clone), "i" (__NR_exit), | ||
208 | "r" (arg), "r" (fn), | ||
209 | "r" (flags | CLONE_VM) | ||
210 | : "a2", "a3", "a4", "a5", "a6" ); | ||
211 | return retval; | ||
212 | } | ||
213 | |||
214 | |||
215 | /* | ||
216 | * These bracket the sleeping functions.. | 164 | * These bracket the sleeping functions.. |
217 | */ | 165 | */ |
218 | 166 | ||
@@ -275,7 +223,7 @@ void do_copy_regs (xtensa_gregset_t *elfregs, struct pt_regs *regs, | |||
275 | */ | 223 | */ |
276 | 224 | ||
277 | elfregs->pc = regs->pc; | 225 | elfregs->pc = regs->pc; |
278 | elfregs->ps = (regs->ps & ~XCHAL_PS_EXCM_MASK); | 226 | elfregs->ps = (regs->ps & ~(1 << PS_EXCM_BIT)); |
279 | elfregs->exccause = regs->exccause; | 227 | elfregs->exccause = regs->exccause; |
280 | elfregs->excvaddr = regs->excvaddr; | 228 | elfregs->excvaddr = regs->excvaddr; |
281 | elfregs->windowbase = regs->windowbase; | 229 | elfregs->windowbase = regs->windowbase; |
@@ -325,7 +273,7 @@ void do_restore_regs (xtensa_gregset_t *elfregs, struct pt_regs *regs, | |||
325 | */ | 273 | */ |
326 | 274 | ||
327 | regs->pc = elfregs->pc; | 275 | regs->pc = elfregs->pc; |
328 | regs->ps = (elfregs->ps | XCHAL_PS_EXCM_MASK); | 276 | regs->ps = (elfregs->ps | (1 << PS_EXCM_BIT)); |
329 | regs->exccause = elfregs->exccause; | 277 | regs->exccause = elfregs->exccause; |
330 | regs->excvaddr = elfregs->excvaddr; | 278 | regs->excvaddr = elfregs->excvaddr; |
331 | regs->windowbase = elfregs->windowbase; | 279 | regs->windowbase = elfregs->windowbase; |
@@ -459,16 +407,7 @@ int do_restore_fpregs (elf_fpregset_t *fpregs, struct pt_regs *regs, | |||
459 | int | 407 | int |
460 | dump_task_fpu(struct pt_regs *regs, struct task_struct *task, elf_fpregset_t *r) | 408 | dump_task_fpu(struct pt_regs *regs, struct task_struct *task, elf_fpregset_t *r) |
461 | { | 409 | { |
462 | /* see asm/coprocessor.h for this magic number 16 */ | ||
463 | #if XTENSA_CP_EXTRA_SIZE > 16 | ||
464 | do_save_fpregs (r, regs, task); | ||
465 | |||
466 | /* For now, bit 16 means some extra state may be present: */ | ||
467 | // FIXME!! need to track to return more accurate mask | ||
468 | return 0x10000 | XCHAL_CP_MASK; | ||
469 | #else | ||
470 | return 0; /* no coprocessors active on this processor */ | 410 | return 0; /* no coprocessors active on this processor */ |
471 | #endif | ||
472 | } | 411 | } |
473 | 412 | ||
474 | /* | 413 | /* |
@@ -483,3 +422,44 @@ int dump_fpu(struct pt_regs *regs, elf_fpregset_t *r) | |||
483 | { | 422 | { |
484 | return dump_task_fpu(regs, current, r); | 423 | return dump_task_fpu(regs, current, r); |
485 | } | 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 | |||