Index: arch/mips/kernel/ptrace.c =================================================================== RCS file: /cvsroot/hhl-2.4.2/linux/arch/mips/kernel/ptrace.c,v retrieving revision 1.3 diff -u -r1.3 ptrace.c --- arch/mips/kernel/ptrace.c 2001/06/15 00:58:41 1.3 +++ arch/mips/kernel/ptrace.c 2001/06/16 19:06:59 @@ -149,8 +149,19 @@ save_fp(child); disable_cp1(); last_task_used_math = NULL; + regs->cp0_status &= ~ST0_CU1; } - tmp = (unsigned long) fregs[(addr - 32)]; + /* The odd registers are actually the high order bits of the values + stored in the even registers - unless we're using r2k_switch.S. */ +#if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_R3912) + if (mips_cpu_options & MIPS_CPU_FPU) + tmp = *(unsigned long *)(fregs + addr); + else +#endif + if (addr & 1) + tmp = (unsigned long) (fregs[((addr & ~1) - 32)] >> 32); + else + tmp = (unsigned long) (fregs[(addr - 32)] & 0xffffffff); } else { tmp = -1; /* FP not yet used */ } @@ -238,8 +249,21 @@ memset(&child->thread.fpu.hard, ~0, sizeof(child->thread.fpu.hard)); child->thread.fpu.hard.control = 0; + } + /* The odd registers are actually the high order bits of the values + stored in the even registers - unless we're using r2k_switch.S. */ +#if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_R3912) + if (mips_cpu_options & MIPS_CPU_FPU) + *(unsigned long *)(fregs + addr) = data; + else +#endif + if (addr & 1) { + fregs[(addr & ~1) - FPR_BASE] &= 0xffffffff; + fregs[(addr & ~1) - FPR_BASE] |= ((unsigned long long) data) << 32; + } else { + fregs[addr - FPR_BASE] &= ~0xffffffffLL; + fregs[addr - FPR_BASE] |= data; } - fregs[addr - FPR_BASE] = data; break; } case PC: Index: arch/mips/kernel/signal.c =================================================================== RCS file: /cvsroot/hhl-2.4.2/linux/arch/mips/kernel/signal.c,v retrieving revision 1.2 diff -u -r1.2 signal.c --- arch/mips/kernel/signal.c 2001/05/30 00:08:10 1.2 +++ arch/mips/kernel/signal.c 2001/06/16 19:06:59 @@ -220,8 +220,10 @@ err |= __get_user(owned_fp, &sc->sc_ownedfp); if (owned_fp) { + if (last_task_used_math && (last_task_used_math != current)) + last_task_used_math->thread.cp0_status &= ~ST0_CU1; err |= restore_fp_context(sc); last_task_used_math = current; } return err; @@ -353,12 +355,11 @@ owned_fp = (current == last_task_used_math); err |= __put_user(owned_fp, &sc->sc_ownedfp); - if (current->used_math) { /* fp is active. */ + if (owned_fp) { /* fp is active. */ set_cp0_status(ST0_CU1); err |= save_fp_context(sc); last_task_used_math = NULL; regs->cp0_status &= ~ST0_CU1; - current->used_math = 0; } return err; Index: include/asm-mips/processor.h =================================================================== RCS file: /cvsroot/hhl-2.4.2/linux/include/asm-mips/processor.h,v retrieving revision 1.1.1.2 diff -u -r1.1.1.2 processor.h --- include/asm-mips/processor.h 2001/03/27 22:01:19 1.1.1.2 +++ include/asm-mips/processor.h 2001/06/16 19:07:05 @@ -235,8 +235,8 @@ * Do necessary setup to start up a newly executed thread. */ #define start_thread(regs, new_pc, new_sp) do { \ - /* New thread looses kernel privileges. */ \ - regs->cp0_status = (regs->cp0_status & ~(ST0_CU0|ST0_KSU)) | KU_USER;\ + /* New thread loses kernel and FPU privileges. */ \ + regs->cp0_status = (regs->cp0_status & ~(ST0_CU0|ST0_KSU|ST0_CU1)) | KU_USER;\ regs->cp0_epc = new_pc; \ regs->regs[29] = new_sp; \ current->thread.current_ds = USER_DS; \