diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1998-05-07 02:55:41 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 1998-05-07 02:55:41 +0000 |
commit | dcec8a13bf565e47942a1751a9cec21bec5648fe (patch) | |
tree | 548b69625b18cc2e88c3e68d0923be546c9ebb03 /arch/ppc/kernel/process.c | |
parent | 2e0f55e79c49509b7ff70ff1a10e1e9e90a3dfd4 (diff) |
o Merge with Linux 2.1.99.
o Fix ancient bug in the ELF loader making ldd crash.
o Fix ancient bug in the keyboard code for SGI, SNI and Jazz.
Diffstat (limited to 'arch/ppc/kernel/process.c')
-rw-r--r-- | arch/ppc/kernel/process.c | 110 |
1 files changed, 64 insertions, 46 deletions
diff --git a/arch/ppc/kernel/process.c b/arch/ppc/kernel/process.c index 7ffaf58c0..1c993bdc1 100644 --- a/arch/ppc/kernel/process.c +++ b/arch/ppc/kernel/process.c @@ -1,4 +1,3 @@ - /* * linux/arch/ppc/kernel/process.c * @@ -77,8 +76,13 @@ struct task_struct *current_set[NR_CPUS] = {&init_task, }; int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpregs) { +#ifdef __SMP__ + if ( regs->msr & MSR_FP ) + smp_giveup_fpu(current); +#else if (last_task_used_math == current) giveup_fpu(); +#endif memcpy(fpregs, ¤t->tss.fpr[0], sizeof(*fpregs)); return 1; } @@ -98,7 +102,7 @@ int check_stack(struct task_struct *tsk) printk("tss.magic bad: %08x\n", tsk->tss.magic); } #endif - + if ( !tsk ) printk("check_stack(): tsk bad tsk %p\n",tsk); @@ -157,17 +161,21 @@ switch_to(struct task_struct *prev, struct task_struct *new) #endif #ifdef SHOW_TASK_SWITCHES - printk("%s/%d -> %s/%d cpu %d\n", + printk("%s/%d -> %s/%d NIP %08lx cpu %d sfr %d lock %x\n", prev->comm,prev->pid, - new->comm,new->pid,new->processor); + new->comm,new->pid,new->tss.regs->nip,new->processor, + new->tss.smp_fork_ret,scheduler_lock.lock); #endif #ifdef __SMP__ - /* bad news if last_task_used_math changes processors right now -- Cort */ - if ( (last_task_used_math == new) && - (new->processor != new->last_processor) ) - panic("last_task_used_math switched processors"); + /* avoid complexity of lazy save/restore of fpu + * by just saving it every time we switch out -- Cort + */ + if ( prev->tss.regs->msr & MSR_FP ) + smp_giveup_fpu(prev); + /* be noisy about processor changes for debugging -- Cort */ - if ( new->last_processor != new->processor ) + if ( (new->last_processor != NO_PROC_ID) && + (new->last_processor != new->processor) ) printk("switch_to(): changing cpu's %d -> %d %s/%d\n", new->last_processor,new->processor, new->comm,new->pid); @@ -181,11 +189,6 @@ switch_to(struct task_struct *prev, struct task_struct *new) _enable_interrupts(s); } -asmlinkage int sys_debug(long a, long b, long c, long d, long e, long f,struct pt_regs *regs) -{ - return 0; -} - void show_regs(struct pt_regs * regs) { int i; @@ -257,12 +260,11 @@ copy_thread(int nr, unsigned long clone_flags, unsigned long usp, ((unsigned long)p + sizeof(union task_union) - STACK_FRAME_OVERHEAD)) - 2; *childregs = *regs; - if ((childregs->msr & MSR_PR) == 0) childregs->gpr[2] = (unsigned long) p; /* `current' in new task */ childregs->gpr[3] = 0; /* Result from fork() */ p->tss.ksp = (unsigned long) childregs - STACK_FRAME_OVERHEAD; - p->tss.regs = childregs; + p->tss.regs = childregs; if (usp >= (unsigned long) regs) { /* Stack is in kernel space - must adjust */ childregs->gpr[1] = (unsigned long)(childregs + 1); @@ -271,18 +273,28 @@ copy_thread(int nr, unsigned long clone_flags, unsigned long usp, childregs->gpr[1] = usp; } p->tss.last_syscall = -1; - + /* * copy fpu info - assume lazy fpu switch now always * -- Cort */ +#ifdef __SMP__ + if ( regs->msr & MSR_FP ) + smp_giveup_fpu(current); +#else if ( last_task_used_math == current ) giveup_fpu(); +#endif memcpy(&p->tss.fpr, ¤t->tss.fpr, sizeof(p->tss.fpr)); p->tss.fpscr = current->tss.fpscr; childregs->msr &= ~MSR_FP; +#ifdef __SMP__ + if ( (p->pid != 0) || !(clone_flags & CLONE_PID) ) + p->tss.smp_fork_ret = 1; + p->last_processor = NO_PROC_ID; +#endif /* __SMP__ */ return 0; } @@ -337,20 +349,48 @@ void start_thread(struct pt_regs *regs, unsigned long nip, unsigned long sp) shove_aux_table(sp); } +asmlinkage int sys_clone(int p1, int p2, int p3, int p4, int p5, int p6, + struct pt_regs *regs) +{ + unsigned long clone_flags = p1; + int res; + lock_kernel(); + res = do_fork(clone_flags, regs->gpr[1], regs); + /* + * only parent returns here, child returns to either + * syscall_ret_1() or kernel_thread() + * -- Cort + */ +#ifdef __SMP__ + /* When we clone the idle task we keep the same pid but + * the return value of 0 for both causes problems. + * -- Cort + */ + if ((current->pid == 0) && (current == &init_task)) + res = 1; +#endif /* __SMP__ */ + unlock_kernel(); + return res; +} asmlinkage int sys_fork(int p1, int p2, int p3, int p4, int p5, int p6, struct pt_regs *regs) { - int ret; + int res; lock_kernel(); - ret = do_fork(SIGCHLD, regs->gpr[1], regs); -#if 0/*def __SMP__*/ - if ( ret ) /* drop scheduler lock in child */ - scheduler_lock.lock = 0L; -#endif /* __SMP__ */ + res = do_fork(SIGCHLD, regs->gpr[1], regs); + /* only parent returns here */ +#ifdef __SMP__ + /* When we clone the idle task we keep the same pid but + * the return value of 0 for both causes problems. + * -- Cort + */ + if ((current->pid == 0) && (current == &init_task)) + res = 1; +#endif /* __SMP__ */ unlock_kernel(); - return ret; + return res; } asmlinkage int sys_execve(unsigned long a0, unsigned long a1, unsigned long a2, @@ -374,28 +414,6 @@ out: return error; } -asmlinkage int sys_clone(int p1, int p2, int p3, int p4, int p5, int p6, - struct pt_regs *regs) -{ - unsigned long clone_flags = p1; - int res; - - lock_kernel(); - res = do_fork(clone_flags, regs->gpr[1], regs); -#ifdef __SMP__ - /* When we clone the idle task we keep the same pid but - * the return value of 0 for both causes problems. - * -- Cort - */ - if ((current->pid == 0) && (current == &init_task)) - res = 1; - if ( 0 /*res*/ ) /* drop scheduler lock in child */ - scheduler_lock.lock = 0L; -#endif /* __SMP__ */ - unlock_kernel(); - return res; -} - void print_backtrace(unsigned long *sp) { |