aboutsummaryrefslogtreecommitdiff
path: root/arch/blackfin/kernel/process.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/blackfin/kernel/process.c')
-rw-r--r--arch/blackfin/kernel/process.c137
1 files changed, 26 insertions, 111 deletions
diff --git a/arch/blackfin/kernel/process.c b/arch/blackfin/kernel/process.c
index bb1cc721fcf..4aa5545c4fd 100644
--- a/arch/blackfin/kernel/process.c
+++ b/arch/blackfin/kernel/process.c
@@ -39,12 +39,6 @@ int nr_l1stack_tasks;
void *l1_stack_base;
unsigned long l1_stack_len;
-/*
- * Powermanagement idle function, if any..
- */
-void (*pm_idle)(void) = NULL;
-EXPORT_SYMBOL(pm_idle);
-
void (*pm_power_off)(void) = NULL;
EXPORT_SYMBOL(pm_power_off);
@@ -52,15 +46,14 @@ EXPORT_SYMBOL(pm_power_off);
* The idle loop on BFIN
*/
#ifdef CONFIG_IDLE_L1
-static void default_idle(void)__attribute__((l1_text));
-void cpu_idle(void)__attribute__((l1_text));
+void arch_cpu_idle(void)__attribute__((l1_text));
#endif
/*
* This is our default idle handler. We need to disable
* interrupts here to ensure we don't miss a wakeup call.
*/
-static void default_idle(void)
+void arch_cpu_idle(void)
{
#ifdef CONFIG_IPIPE
ipipe_suspend_domain();
@@ -72,68 +65,12 @@ static void default_idle(void)
hard_local_irq_enable();
}
-/*
- * The idle thread. We try to conserve power, while trying to keep
- * overall latency low. The architecture specific idle is passed
- * a value to indicate the level of "idleness" of the system.
- */
-void cpu_idle(void)
-{
- /* endless idle loop with no priority at all */
- while (1) {
- void (*idle)(void) = pm_idle;
-
#ifdef CONFIG_HOTPLUG_CPU
- if (cpu_is_offline(smp_processor_id()))
- cpu_die();
-#endif
- if (!idle)
- idle = default_idle;
- tick_nohz_idle_enter();
- rcu_idle_enter();
- while (!need_resched())
- idle();
- rcu_idle_exit();
- tick_nohz_idle_exit();
- preempt_enable_no_resched();
- schedule();
- preempt_disable();
- }
-}
-
-/*
- * 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)
+void arch_cpu_idle_dead(void)
{
- 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);
+ cpu_die();
}
-EXPORT_SYMBOL(kernel_thread);
+#endif
/*
* Do necessary setup to start up a newly executed thread.
@@ -161,70 +98,48 @@ void flush_thread(void)
{
}
-asmlinkage int bfin_vfork(struct pt_regs *regs)
+asmlinkage int bfin_clone(unsigned long clone_flags, unsigned long newsp)
{
- return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, rdusp(), regs, 0, NULL,
- NULL);
-}
-
-asmlinkage int bfin_clone(struct pt_regs *regs)
-{
- unsigned long clone_flags;
- unsigned long newsp;
-
#ifdef __ARCH_SYNC_CORE_DCACHE
if (current->nr_cpus_allowed == num_possible_cpus())
set_cpus_allowed_ptr(current, cpumask_of(smp_processor_id()));
#endif
-
- /* syscall2 puts clone_flags in r0 and usp in r1 */
- clone_flags = regs->r0;
- newsp = regs->r1;
- if (!newsp)
- newsp = rdusp();
- else
+ if (newsp)
newsp -= 12;
- return do_fork(clone_flags, newsp, regs, 0, NULL, NULL);
+ return do_fork(clone_flags, newsp, 0, NULL, NULL);
}
int
copy_thread(unsigned long clone_flags,
unsigned long usp, unsigned long topstk,
- struct task_struct *p, struct pt_regs *regs)
+ struct task_struct *p)
{
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(p->flags & PF_KTHREAD)) {
+ 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 = *current_pt_regs();
+ childregs->r0 = 0;
+ p->thread.usp = usp ? : rdusp();
+ 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;
}
-/*
- * sys_execve() executes a new program.
- */
-asmlinkage int sys_execve(const char __user *name,
- const char __user *const __user *argv,
- const char __user *const __user *envp)
-{
- int error;
- struct filename *filename;
- struct pt_regs *regs = (struct pt_regs *)((&name) + 6);
-
- filename = getname(name);
- error = PTR_ERR(filename);
- if (IS_ERR(filename))
- return error;
- error = do_execve(filename->name, argv, envp, regs);
- putname(filename);
- return error;
-}
-
unsigned long get_wchan(struct task_struct *p)
{
unsigned long fp, pc;