aboutsummaryrefslogtreecommitdiffstats
path: root/arch/xtensa/kernel/process.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/xtensa/kernel/process.c')
-rw-r--r--arch/xtensa/kernel/process.c108
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
48extern void ret_from_fork(void); 47extern void ret_from_fork(void);
49 48
@@ -67,25 +66,6 @@ void (*pm_power_off)(void) = NULL;
67EXPORT_SYMBOL(pm_power_off); 66EXPORT_SYMBOL(pm_power_off);
68 67
69 68
70#if XCHAL_CP_NUM > 0
71
72/*
73 * Coprocessor ownership.
74 */
75
76coprocessor_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
111void exit_thread(void) 91void exit_thread(void)
112{ 92{
113 release_coprocessors(current); /* Empty macro if no CPs are defined */
114} 93}
115 94
116void flush_thread(void) 95void 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
189int 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,
459int 407int
460dump_task_fpu(struct pt_regs *regs, struct task_struct *task, elf_fpregset_t *r) 408dump_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
426asmlinkage
427long 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
441asmlinkage
442long 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);
462out:
463 return error;
464}
465