X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=arch%2Fsparc%2Fkernel%2Fprocess.c;h=143fe2f3c1c453ace3b46b41552957ffb9aa03af;hb=6a77f38946aaee1cd85eeec6cf4229b204c15071;hp=13b3ac47b3c0c1a19041cb075d379b08cd4335cb;hpb=5273a3df6485dc2ad6aa7ddd441b9a21970f003b;p=linux-2.6.git diff --git a/arch/sparc/kernel/process.c b/arch/sparc/kernel/process.c index 13b3ac47b..143fe2f3c 100644 --- a/arch/sparc/kernel/process.c +++ b/arch/sparc/kernel/process.c @@ -45,7 +45,7 @@ /* * Power management idle function - * Set in pm platform drivers + * Set in pm platform drivers (apc.c and pmc.c) */ void (*pm_idle)(void); @@ -81,10 +81,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; @@ -122,21 +120,20 @@ int cpu_idle(void) } while((!need_resched()) && pm_idle) { - (*pm_idle)(); /* XXX Huh? On sparc?! */ + (*pm_idle)(); } schedule(); check_pgt_cache(); } - ret = 0; out: - return ret; + return; } #else /* This is being executed in task 0 'user space'. */ -int cpu_idle(void) +void cpu_idle(void) { /* endless idle loop with no priority at all */ while(1) { @@ -201,7 +198,7 @@ void machine_power_off(void) 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) { @@ -400,23 +397,30 @@ void flush_thread(void) } } -static __inline__ struct sparc_stackf * -clone_stackframe(struct sparc_stackf *dst, struct sparc_stackf *src) +static __inline__ struct sparc_stackf __user * +clone_stackframe(struct sparc_stackf __user *dst, + struct sparc_stackf __user *src) { - unsigned long size; - struct sparc_stackf *sp; + unsigned long size, fp; + struct sparc_stackf *tmp; + struct sparc_stackf __user *sp; - size = ((unsigned long)src->fp) - ((unsigned long)src); - sp = (struct sparc_stackf *)(((unsigned long)dst) - size); + if (get_user(tmp, &src->fp)) + return NULL; + + fp = (unsigned long) tmp; + size = (fp - ((unsigned long) src)); + fp = (unsigned long) dst; + sp = (struct sparc_stackf __user *)(fp - size); /* do_fork() grabs the parent semaphore, we must release it * temporarily so we can build the child clone stack frame * without deadlocking. */ - if (copy_to_user(sp, src, size)) - sp = (struct sparc_stackf *) 0; - else if (put_user(dst, &sp->fp)) - sp = (struct sparc_stackf *) 0; + if (__copy_user(sp, src, size)) + sp = NULL; + else if (put_user(fp, &sp->fp)) + sp = NULL; return sp; } @@ -428,15 +432,13 @@ 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]; return do_fork(clone_flags, stack_start, regs, stack_size, - (int *) parent_tid_ptr, - (int *) child_tid_ptr); + (int __user *) parent_tid_ptr, + (int __user *) child_tid_ptr); } /* Copy a Sparc thread. The fork() return value conventions @@ -475,8 +477,6 @@ 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) } @@ -519,15 +519,17 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long sp, p->thread.current_ds = USER_DS; if (sp != regs->u_regs[UREG_FP]) { - struct sparc_stackf *childstack; - struct sparc_stackf *parentstack; + struct sparc_stackf __user *childstack; + struct sparc_stackf __user *parentstack; /* * This is a clone() call with supplied user stack. * Set some valid stack frames to give to the child. */ - childstack = (struct sparc_stackf *) (sp & ~0x7UL); - parentstack = (struct sparc_stackf *) regs->u_regs[UREG_FP]; + childstack = (struct sparc_stackf __user *) + (sp & ~0x7UL); + parentstack = (struct sparc_stackf __user *) + regs->u_regs[UREG_FP]; #if 0 printk("clone: parent stack:\n"); @@ -547,6 +549,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; @@ -597,7 +604,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; @@ -619,7 +626,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 @@ -654,15 +661,20 @@ asmlinkage int sparc_execve(struct pt_regs *regs) if(regs->u_regs[UREG_G1] == 0) base = 1; - filename = getname((char *)regs->u_regs[base + UREG_I0]); + filename = getname((char __user *)regs->u_regs[base + UREG_I0]); error = PTR_ERR(filename); if(IS_ERR(filename)) goto out; - error = do_execve(filename, (char **) regs->u_regs[base + UREG_I1], - (char **) regs->u_regs[base + UREG_I2], regs); + error = do_execve(filename, + (char __user * __user *)regs->u_regs[base + UREG_I1], + (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; } @@ -679,25 +691,25 @@ pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) { long retval; - __asm__ __volatile("mov %4, %%g2\n\t" /* Set aside fn ptr... */ - "mov %5, %%g3\n\t" /* and arg. */ - "mov %1, %%g1\n\t" - "mov %2, %%o0\n\t" /* Clone flags. */ - "mov 0, %%o1\n\t" /* usp arg == 0 */ - "t 0x10\n\t" /* Linux/Sparc clone(). */ - "cmp %%o1, 0\n\t" - "be 1f\n\t" /* The parent, just return. */ - " nop\n\t" /* Delay slot. */ - "jmpl %%g2, %%o7\n\t" /* Call the function. */ - " mov %%g3, %%o0\n\t" /* Get back the arg in delay. */ - "mov %3, %%g1\n\t" - "t 0x10\n\t" /* Linux/Sparc exit(). */ - /* Notreached by child. */ - "1: mov %%o0, %0\n\t" : - "=r" (retval) : - "i" (__NR_clone), "r" (flags | CLONE_VM | CLONE_UNTRACED), - "i" (__NR_exit), "r" (fn), "r" (arg) : - "g1", "g2", "g3", "o0", "o1", "memory", "cc"); + __asm__ __volatile__("mov %4, %%g2\n\t" /* Set aside fn ptr... */ + "mov %5, %%g3\n\t" /* and arg. */ + "mov %1, %%g1\n\t" + "mov %2, %%o0\n\t" /* Clone flags. */ + "mov 0, %%o1\n\t" /* usp arg == 0 */ + "t 0x10\n\t" /* Linux/Sparc clone(). */ + "cmp %%o1, 0\n\t" + "be 1f\n\t" /* The parent, just return. */ + " nop\n\t" /* Delay slot. */ + "jmpl %%g2, %%o7\n\t" /* Call the function. */ + " mov %%g3, %%o0\n\t" /* Get back the arg in delay. */ + "mov %3, %%g1\n\t" + "t 0x10\n\t" /* Linux/Sparc exit(). */ + /* Notreached by child. */ + "1: mov %%o0, %0\n\t" : + "=r" (retval) : + "i" (__NR_clone), "r" (flags | CLONE_VM | CLONE_UNTRACED), + "i" (__NR_exit), "r" (fn), "r" (arg) : + "g1", "g2", "g3", "o0", "o1", "memory", "cc"); return retval; } @@ -721,8 +733,7 @@ unsigned long get_wchan(struct task_struct *task) break; rw = (struct reg_window *) fp; pc = rw->ins[7]; - if (pc < ((unsigned long) scheduling_functions_start_here) || - pc >= ((unsigned long) scheduling_functions_end_here)) { + if (!in_sched_functions(pc)) { ret = pc; goto out; }