summaryrefslogtreecommitdiffstats
path: root/arch/blackfin/kernel
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2012-10-13 03:22:53 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2012-10-14 23:06:52 -0400
commitee1e17c69eb3c843d283eb3fbed1616ed9a122eb (patch)
tree18c4beae1331663fadec51f914f2ef50ed1be7fb /arch/blackfin/kernel
parentddffeb8c4d0331609ef2581d84de4d763607bd37 (diff)
downloadlinux-ee1e17c69eb3c843d283eb3fbed1616ed9a122eb.tar.bz2
blackfin: convert kernel_thread() and kernel_execve() to generic ones
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'arch/blackfin/kernel')
-rw-r--r--arch/blackfin/kernel/entry.S22
-rw-r--r--arch/blackfin/kernel/process.c55
2 files changed, 25 insertions, 52 deletions
diff --git a/arch/blackfin/kernel/entry.S b/arch/blackfin/kernel/entry.S
index f33792cc1a0d..78f4f637e155 100644
--- a/arch/blackfin/kernel/entry.S
+++ b/arch/blackfin/kernel/entry.S
@@ -46,22 +46,16 @@ ENTRY(_ret_from_fork)
SP += -12;
pseudo_long_call _schedule_tail, p5;
SP += 12;
- r0 = [sp + PT_IPEND];
- cc = bittst(r0,1);
- if cc jump .Lin_kernel;
+ p1 = [sp++];
+ r0 = [sp++];
+ cc = p1 == 0;
+ if cc jump .Lfork;
+ sp += -12;
+ call (p1);
+ sp += 12;
+.Lfork:
RESTORE_CONTEXT
rti;
-.Lin_kernel:
- bitclr(r0,1);
- [sp + PT_IPEND] = r0;
- /* do a 'fake' RTI by jumping to [RETI]
- * to avoid clearing supervisor mode in child
- */
- r0 = [sp + PT_PC];
- [sp + PT_P0] = r0;
-
- RESTORE_ALL_SYS
- jump (p0);
ENDPROC(_ret_from_fork)
ENTRY(_sys_vfork)
diff --git a/arch/blackfin/kernel/process.c b/arch/blackfin/kernel/process.c
index bb1cc721fcf7..9945b94c63d4 100644
--- a/arch/blackfin/kernel/process.c
+++ b/arch/blackfin/kernel/process.c
@@ -102,40 +102,6 @@ void cpu_idle(void)
}
/*
- * This gets run with P1 containing the
- * function to call, and R1 containing
- * the "args". Note P0 is clobbered on the way here.
- */
-void kernel_thread_helper(void);
-__asm__(".section .text\n"
- ".align 4\n"
- "_kernel_thread_helper:\n\t"
- "\tsp += -12;\n\t"
- "\tr0 = r1;\n\t" "\tcall (p1);\n\t" "\tcall _do_exit;\n" ".previous");
-
-/*
- * Create a kernel thread.
- */
-pid_t kernel_thread(int (*fn) (void *), void *arg, unsigned long flags)
-{
- struct pt_regs regs;
-
- memset(&regs, 0, sizeof(regs));
-
- regs.r1 = (unsigned long)arg;
- regs.p1 = (unsigned long)fn;
- regs.pc = (unsigned long)kernel_thread_helper;
- regs.orig_p0 = -1;
- /* Set bit 2 to tell ret_from_fork we should be returning to kernel
- mode. */
- regs.ipend = 0x8002;
- __asm__ __volatile__("%0 = syscfg;":"=da"(regs.syscfg):);
- return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, &regs, 0, NULL,
- NULL);
-}
-EXPORT_SYMBOL(kernel_thread);
-
-/*
* Do necessary setup to start up a newly executed thread.
*
* pass the data segment into user programs if it exists,
@@ -193,13 +159,26 @@ copy_thread(unsigned long clone_flags,
struct task_struct *p, struct pt_regs *regs)
{
struct pt_regs *childregs;
+ unsigned long *v;
childregs = (struct pt_regs *) (task_stack_page(p) + THREAD_SIZE) - 1;
- *childregs = *regs;
- childregs->r0 = 0;
+ v = ((unsigned long *)childregs) - 2;
+ if (unlikely(!regs)) {
+ memset(childregs, 0, sizeof(struct pt_regs));
+ v[0] = usp;
+ v[1] = topstk;
+ childregs->orig_p0 = -1;
+ childregs->ipend = 0x8000;
+ __asm__ __volatile__("%0 = syscfg;":"=da"(childregs->syscfg):);
+ p->thread.usp = 0;
+ } else {
+ *childregs = *regs;
+ childregs->r0 = 0;
+ p->thread.usp = usp;
+ v[0] = v[1] = 0;
+ }
- p->thread.usp = usp;
- p->thread.ksp = (unsigned long)childregs;
+ p->thread.ksp = (unsigned long)v;
p->thread.pc = (unsigned long)ret_from_fork;
return 0;