diff options
Diffstat (limited to 'arch/blackfin/kernel/process.c')
| -rw-r--r-- | arch/blackfin/kernel/process.c | 148 |
1 files changed, 33 insertions, 115 deletions
diff --git a/arch/blackfin/kernel/process.c b/arch/blackfin/kernel/process.c index cd0c090ebc5..4aa5545c4fd 100644 --- a/arch/blackfin/kernel/process.c +++ b/arch/blackfin/kernel/process.c @@ -7,7 +7,6 @@ */ #include <linux/module.h> -#include <linux/smp_lock.h> #include <linux/unistd.h> #include <linux/user.h> #include <linux/uaccess.h> @@ -20,6 +19,7 @@ #include <asm/blackfin.h> #include <asm/fixed_code.h> #include <asm/mem_map.h> +#include <asm/irq.h> asmlinkage void ret_from_fork(void); @@ -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,66 +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_stop_sched_tick(1); - while (!need_resched()) - idle(); - tick_nohz_restart_sched_tick(); - 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(®s, 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, ®s, 0, NULL, - NULL); + cpu_die(); } -EXPORT_SYMBOL(kernel_thread); +#endif /* * Do necessary setup to start up a newly executed thread. @@ -141,7 +80,6 @@ EXPORT_SYMBOL(kernel_thread); */ void start_thread(struct pt_regs *regs, unsigned long new_ip, unsigned long new_sp) { - set_fs(USER_DS); regs->pc = new_ip; if (current->mm) regs->p5 = current->mm->start_data; @@ -160,72 +98,48 @@ void flush_thread(void) { } -asmlinkage int bfin_vfork(struct pt_regs *regs) -{ - return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, rdusp(), regs, 0, NULL, - NULL); -} - -asmlinkage int bfin_clone(struct pt_regs *regs) +asmlinkage int bfin_clone(unsigned long clone_flags, unsigned long newsp) { - unsigned long clone_flags; - unsigned long newsp; - #ifdef __ARCH_SYNC_CORE_DCACHE - if (current->rt.nr_cpus_allowed == num_possible_cpus()) { - current->cpus_allowed = cpumask_of_cpu(smp_processor_id()); - current->rt.nr_cpus_allowed = 1; - } + 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; - char *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, argv, envp, regs); - putname(filename); - return error; -} - unsigned long get_wchan(struct task_struct *p) { unsigned long fp, pc; @@ -332,12 +246,16 @@ int in_mem_const(unsigned long addr, unsigned long size, { return in_mem_const_off(addr, size, 0, const_addr, const_size); } +#ifdef CONFIG_BF60x +#define ASYNC_ENABLED(bnum, bctlnum) 1 +#else #define ASYNC_ENABLED(bnum, bctlnum) \ ({ \ (bfin_read_EBIU_AMGCTL() & 0xe) < ((bnum + 1) << 1) ? 0 : \ bfin_read_EBIU_AMBCTL##bctlnum() & B##bnum##RDYEN ? 0 : \ 1; \ }) +#endif /* * We can't read EBIU banks that aren't enabled or we end up hanging * on the access to the async space. Make sure we validate accesses |
