X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=arch%2Fsparc%2Fkernel%2Fprocess.c;h=4dd490e7c7baf13fc47127c7a04748e059d71f8f;hb=refs%2Fheads%2Fvserver;hp=277883d6cbcf07815f3c9cd02ff548b41961ab3d;hpb=9213980e6a70d8473e0ffd4b39ab5b6caaba9ff5;p=linux-2.6.git diff --git a/arch/sparc/kernel/process.c b/arch/sparc/kernel/process.c index 277883d6c..4dd490e7c 100644 --- a/arch/sparc/kernel/process.c +++ b/arch/sparc/kernel/process.c @@ -22,7 +22,6 @@ #include #include #include -#include #include #include #include @@ -45,7 +44,7 @@ /* * Power management idle function - * Set in pm platform drivers + * Set in pm platform drivers (apc.c and pmc.c) */ void (*pm_idle)(void); @@ -54,7 +53,8 @@ void (*pm_idle)(void); * This is done via auxio, but could be used as a fallback * handler when auxio is not present-- unused for now... */ -void (*pm_power_off)(void); +void (*pm_power_off)(void) = machine_power_off; +EXPORT_SYMBOL(pm_power_off); /* * sysctl - toggle power-off restriction for serial console @@ -67,13 +67,6 @@ extern void fpsave(unsigned long *, unsigned long *, void *, unsigned long *); struct task_struct *last_task_used_math = NULL; struct thread_info *current_set[NR_CPUS]; -/* - * default_idle is new in 2.5. XXX Review, currently stolen from sparc64. - */ -void default_idle(void) -{ -} - #ifndef CONFIG_SMP #define SUN4C_FAULT_HIGH 100 @@ -81,13 +74,8 @@ void default_idle(void) /* * the idle loop on a Sparc... ;) */ -int cpu_idle(void) +void cpu_idle(void) { - int ret = -EPERM; - - if (current->pid != 0) - goto out; - /* endless idle loop with no priority at all */ for (;;) { if (ARCH_SUN4C_SUN4) { @@ -97,12 +85,11 @@ int cpu_idle(void) static unsigned long fps; unsigned long now; unsigned long faults; - unsigned long flags; extern unsigned long sun4c_kernel_faults; extern void sun4c_grow_kernel_ring(void); - local_irq_save(flags); + local_irq_disable(); now = jiffies; count -= (now - last_jiffies); last_jiffies = now; @@ -118,33 +105,37 @@ int cpu_idle(void) sun4c_grow_kernel_ring(); } } - local_irq_restore(flags); + local_irq_enable(); } - while((!need_resched()) && pm_idle) { - (*pm_idle)(); /* XXX Huh? On sparc?! */ + if (pm_idle) { + while (!need_resched()) + (*pm_idle)(); + } else { + while (!need_resched()) + cpu_relax(); } - + preempt_enable_no_resched(); schedule(); + preempt_disable(); check_pgt_cache(); } - ret = 0; -out: - return ret; } #else /* This is being executed in task 0 'user space'. */ -int cpu_idle(void) +void cpu_idle(void) { + set_thread_flag(TIF_POLLING_NRFLAG); /* endless idle loop with no priority at all */ while(1) { - if(need_resched()) { - schedule(); - check_pgt_cache(); - } - barrier(); /* or else gcc optimizes... */ + while (!need_resched()) + cpu_relax(); + preempt_enable_no_resched(); + schedule(); + preempt_disable(); + check_pgt_cache(); } } @@ -166,8 +157,6 @@ void machine_halt(void) panic("Halt failed!"); } -EXPORT_SYMBOL(machine_halt); - void machine_restart(char * cmd) { char *p; @@ -188,8 +177,6 @@ void machine_restart(char * cmd) panic("Reboot failed!"); } -EXPORT_SYMBOL(machine_restart); - void machine_power_off(void) { #ifdef CONFIG_SUN_AUXIO @@ -199,9 +186,7 @@ void machine_power_off(void) machine_halt(); } -EXPORT_SYMBOL(machine_power_off); - -static spinlock_t sparc_backtrace_lock = SPIN_LOCK_UNLOCKED; +static DEFINE_SPINLOCK(sparc_backtrace_lock); void __show_backtrace(unsigned long fp) { @@ -317,7 +302,7 @@ void show_stack(struct task_struct *tsk, unsigned long *_ksp) int count = 0; if (tsk != NULL) - task_base = (unsigned long) tsk->thread_info; + task_base = (unsigned long) task_stack_page(tsk); else task_base = (unsigned long) current_thread_info(); @@ -336,12 +321,23 @@ void show_stack(struct task_struct *tsk, unsigned long *_ksp) printk("\n"); } +void dump_stack(void) +{ + unsigned long *ksp; + + __asm__ __volatile__("mov %%fp, %0" + : "=r" (ksp)); + show_stack(current, ksp); +} + +EXPORT_SYMBOL(dump_stack); + /* * Note: sparc64 has a pretty intricated thread_saved_pc, check it out. */ unsigned long thread_saved_pc(struct task_struct *tsk) { - return tsk->thread_info->kpc; + return task_thread_info(tsk)->kpc; } /* @@ -396,7 +392,7 @@ void flush_thread(void) /* We must fixup kregs as well. */ /* XXX This was not fixed for ti for a while, worked. Unused? */ current->thread.kregs = (struct pt_regs *) - ((char *)current->thread_info + (THREAD_SIZE - TRACEREG_SZ)); + (task_stack_page(current) + (THREAD_SIZE - TRACEREG_SZ)); } } @@ -435,8 +431,6 @@ asmlinkage int sparc_do_fork(unsigned long clone_flags, { unsigned long parent_tid_ptr, child_tid_ptr; - clone_flags &= ~CLONE_IDLETASK; - parent_tid_ptr = regs->u_regs[UREG_I2]; child_tid_ptr = regs->u_regs[UREG_I4]; @@ -465,7 +459,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long sp, unsigned long unused, struct task_struct *p, struct pt_regs *regs) { - struct thread_info *ti = p->thread_info; + struct thread_info *ti = task_thread_info(p); struct pt_regs *childregs; char *new_stack; @@ -482,15 +476,13 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long sp, #endif } - p->set_child_tid = p->clear_child_tid = NULL; - /* * p->thread_info new_stack childregs * ! ! ! {if(PSR_PS) } * V V (stk.fr.) V (pt_regs) { (stk.fr.) } * +----- - - - - - ------+===========+============={+==========}+ */ - new_stack = (char*)ti + THREAD_SIZE; + new_stack = task_stack_page(p) + THREAD_SIZE; if (regs->psr & PSR_PS) new_stack -= STACKFRAME_SZ; new_stack -= STACKFRAME_SZ + TRACEREG_SZ; @@ -556,6 +548,11 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long sp, } } +#ifdef CONFIG_SMP + /* FPU must be disabled on SMP. */ + childregs->psr &= ~PSR_EF; +#endif + /* Set the return value for the child. */ childregs->u_regs[UREG_I0] = current->pid; childregs->u_regs[UREG_I1] = 1; @@ -606,7 +603,7 @@ void dump_thread(struct pt_regs * regs, struct user * dump) */ int dump_fpu (struct pt_regs * regs, elf_fpregset_t * fpregs) { - if (current->used_math == 0) { + if (used_math()) { memset(fpregs, 0, sizeof(*fpregs)); fpregs->pr_q_entrysize = 8; return 1; @@ -628,7 +625,7 @@ int dump_fpu (struct pt_regs * regs, elf_fpregset_t * fpregs) ¤t->thread.fpqueue[0], ¤t->thread.fpqdepth); if (regs != NULL) { regs->psr &= ~(PSR_EF); - last_task_used_math = 0; + last_task_used_math = NULL; } } #endif @@ -672,8 +669,11 @@ asmlinkage int sparc_execve(struct pt_regs *regs) (char __user * __user *)regs->u_regs[base + UREG_I2], regs); putname(filename); - if (error == 0) + if (error == 0) { + task_lock(current); current->ptrace &= ~PT_DTRACE; + task_unlock(current); + } out: return error; } @@ -706,7 +706,8 @@ pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) /* Notreached by child. */ "1: mov %%o0, %0\n\t" : "=r" (retval) : - "i" (__NR_clone), "r" (flags | CLONE_VM | CLONE_UNTRACED), + "i" (__NR_clone), "r" (flags | + CLONE_VM | CLONE_UNTRACED | CLONE_KTHREAD), "i" (__NR_exit), "r" (fn), "r" (arg) : "g1", "g2", "g3", "o0", "o1", "memory", "cc"); return retval; @@ -724,7 +725,7 @@ unsigned long get_wchan(struct task_struct *task) task->state == TASK_RUNNING) goto out; - fp = task->thread_info->ksp + bias; + fp = task_thread_info(task)->ksp + bias; do { /* Bogus frame pointer? */ if (fp < (task_base + sizeof(struct thread_info)) ||