diff options
Diffstat (limited to 'arch/frv/kernel/process.c')
| -rw-r--r-- | arch/frv/kernel/process.c | 175 |
1 files changed, 43 insertions, 132 deletions
diff --git a/arch/frv/kernel/process.c b/arch/frv/kernel/process.c index 0fff8a61ef2..5d40aeb7712 100644 --- a/arch/frv/kernel/process.c +++ b/arch/frv/kernel/process.c @@ -10,13 +10,12 @@ * 2 of the License, or (at your option) any later version. */ -#include <linux/config.h> +#include <linux/module.h> #include <linux/errno.h> #include <linux/sched.h> #include <linux/kernel.h> #include <linux/mm.h> #include <linux/smp.h> -#include <linux/smp_lock.h> #include <linux/stddef.h> #include <linux/unistd.h> #include <linux/ptrace.h> @@ -25,33 +24,26 @@ #include <linux/elf.h> #include <linux/reboot.h> #include <linux/interrupt.h> +#include <linux/pagemap.h> +#include <linux/rcupdate.h> +#include <asm/asm-offsets.h> #include <asm/uaccess.h> -#include <asm/system.h> #include <asm/setup.h> #include <asm/pgtable.h> +#include <asm/tlb.h> #include <asm/gdb-stub.h> #include <asm/mb-regs.h> #include "local.h" asmlinkage void ret_from_fork(void); +asmlinkage void ret_from_kernel_thread(void); #include <asm/pgalloc.h> -struct task_struct *alloc_task_struct(void) -{ - struct task_struct *p = kmalloc(THREAD_SIZE, GFP_KERNEL); - if (p) - atomic_set((atomic_t *)(p+1), 1); - return p; -} - -void free_task_struct(struct task_struct *p) -{ - if (atomic_dec_and_test((atomic_t *)(p+1))) - kfree(p); -} +void (*pm_power_off)(void); +EXPORT_SYMBOL(pm_power_off); static void core_sleep_idle(void) { @@ -67,31 +59,12 @@ static void core_sleep_idle(void) mb(); } -void (*idle)(void) = core_sleep_idle; - -/* - * The idle thread. There's no useful work to be - * done, so just try to conserve power and have a - * low exit latency (ie sit in a loop waiting for - * somebody to say that they'd like to reschedule) - */ -void cpu_idle(void) +void arch_cpu_idle(void) { - int cpu = smp_processor_id(); - - /* endless idle loop with no priority at all */ - while (1) { - while (!need_resched()) { - irq_stat[cpu].idle_timestamp = jiffies; - - if (!frv_dma_inprogress && idle) - idle(); - } - - preempt_enable_no_resched(); - schedule(); - preempt_disable(); - } + if (!frv_dma_inprogress) + core_sleep_idle(); + else + local_irq_enable(); } void machine_restart(char * __unused) @@ -139,10 +112,7 @@ void machine_power_off(void) void flush_thread(void) { -#if 0 //ndef NO_FPU - unsigned long zero = 0; -#endif - set_fs(USER_DS); + /* nothing */ } inline unsigned long user_stack(const struct pt_regs *regs) @@ -152,87 +122,40 @@ inline unsigned long user_stack(const struct pt_regs *regs) return user_mode(regs) ? regs->sp : 0; } -asmlinkage int sys_fork(void) -{ -#ifndef CONFIG_MMU - /* fork almost works, enough to trick you into looking elsewhere:-( */ - return -EINVAL; -#else - return do_fork(SIGCHLD, user_stack(__frame), __frame, 0, NULL, NULL); -#endif -} - -asmlinkage int sys_vfork(void) -{ - return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, user_stack(__frame), __frame, 0, - NULL, NULL); -} - -/*****************************************************************************/ -/* - * clone a process - * - tlsptr is retrieved by copy_thread() - */ -asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp, - int __user *parent_tidptr, int __user *child_tidptr, - int __user *tlsptr) -{ - if (!newsp) - newsp = user_stack(__frame); - return do_fork(clone_flags, newsp, __frame, 0, parent_tidptr, child_tidptr); -} /* end sys_clone() */ - -/*****************************************************************************/ -/* - * This gets called before we allocate a new thread and copy - * the current task into it. - */ -void prepare_to_copy(struct task_struct *tsk) -{ - //unlazy_fpu(tsk); -} /* end prepare_to_copy() */ - -/*****************************************************************************/ /* * set up the kernel stack and exception frames for a new process */ -int copy_thread(int nr, unsigned long clone_flags, - unsigned long usp, unsigned long topstk, - struct task_struct *p, struct pt_regs *regs) +int copy_thread(unsigned long clone_flags, + unsigned long usp, unsigned long arg, + struct task_struct *p) { - struct pt_regs *childregs0, *childregs, *regs0; + struct pt_regs *childregs; - regs0 = __kernel_frame0_ptr; - childregs0 = (struct pt_regs *) - (task_stack_page(p) + THREAD_SIZE - USER_CONTEXT_SIZE); - childregs = childregs0; + childregs = (struct pt_regs *) + (task_stack_page(p) + THREAD_SIZE - FRV_FRAME0_SIZE); /* set up the userspace frame (the only place that the USP is stored) */ - *childregs0 = *regs0; - - childregs0->gr8 = 0; - childregs0->sp = usp; - childregs0->next_frame = NULL; - - /* set up the return kernel frame if called from kernel_thread() */ - if (regs != regs0) { - childregs--; - *childregs = *regs; - childregs->sp = (unsigned long) childregs0; - childregs->next_frame = childregs0; - childregs->gr15 = (unsigned long) task_thread_info(p); - childregs->gr29 = (unsigned long) p; - } - - p->set_child_tid = p->clear_child_tid = NULL; + *childregs = *current_pt_regs(); p->thread.frame = childregs; p->thread.curr = p; p->thread.sp = (unsigned long) childregs; p->thread.fp = 0; p->thread.lr = 0; - p->thread.pc = (unsigned long) ret_from_fork; - p->thread.frame0 = childregs0; + p->thread.frame0 = childregs; + + if (unlikely(p->flags & PF_KTHREAD)) { + childregs->gr9 = usp; /* function */ + childregs->gr8 = arg; + p->thread.pc = (unsigned long) ret_from_kernel_thread; + save_user_regs(p->thread.user); + return 0; + } + if (usp) + childregs->sp = usp; + childregs->next_frame = NULL; + + p->thread.pc = (unsigned long) ret_from_fork; /* the new TLS pointer is passed in as arg #5 to sys_clone() */ if (clone_flags & CLONE_SETTLS) @@ -243,26 +166,6 @@ int copy_thread(int nr, unsigned long clone_flags, return 0; } /* end copy_thread() */ -/* - * sys_execve() executes a new program. - */ -asmlinkage int sys_execve(char *name, char **argv, char **envp) -{ - int error; - char * filename; - - lock_kernel(); - filename = getname(name); - error = PTR_ERR(filename); - if (IS_ERR(filename)) - goto out; - error = do_execve(filename, argv, envp, __frame); - putname(filename); - out: - unlock_kernel(); - return error; -} - unsigned long get_wchan(struct task_struct *p) { struct pt_regs *regs0; @@ -368,3 +271,11 @@ int elf_check_arch(const struct elf32_hdr *hdr) return 1; } + +int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpregs) +{ + memcpy(fpregs, + ¤t->thread.user->f, + sizeof(current->thread.user->f)); + return 1; +} |
