From e3b4abcb9607063735ea134eca6fad62f8147f20 Mon Sep 17 00:00:00 2001 From: Kanoj Sarcar Date: Thu, 11 May 2000 20:59:13 +0000 Subject: SMP FPU management: similar to what sparc does, no lazy fpu context switching in SMP mode, use PF_USEDFPU to determine whether a program used the fpu in the last time quantum and so needs the fpu context to be saved during context switch. --- arch/mips64/kernel/process.c | 11 ++++++----- arch/mips64/kernel/ptrace.c | 11 +++++++++-- arch/mips64/kernel/signal.c | 9 +++++---- arch/mips64/kernel/signal32.c | 10 ++++++---- arch/mips64/kernel/traps.c | 10 ++++++++++ 5 files changed, 36 insertions(+), 15 deletions(-) (limited to 'arch/mips64') diff --git a/arch/mips64/kernel/process.c b/arch/mips64/kernel/process.c index d6d8b7435..22ce0ed6d 100644 --- a/arch/mips64/kernel/process.c +++ b/arch/mips64/kernel/process.c @@ -7,6 +7,7 @@ * Copyright (C) 1994 - 1999 by Ralf Baechle and others. * Copyright (C) 1999 Silicon Graphics, Inc. */ +#include #include #include #include @@ -52,20 +53,20 @@ asmlinkage void ret_from_fork(void); void exit_thread(void) { /* Forget lazy fpu state */ - if (last_task_used_math == current) { + if (IS_FPU_OWNER()) { set_cp0_status(ST0_CU1, ST0_CU1); __asm__ __volatile__("cfc1\t$0,$31"); - last_task_used_math = NULL; + CLEAR_FPU_OWNER(); } } void flush_thread(void) { /* Forget lazy fpu state */ - if (last_task_used_math == current) { + if (IS_FPU_OWNER()) { set_cp0_status(ST0_CU1, ST0_CU1); __asm__ __volatile__("cfc1\t$0,$31"); - last_task_used_math = NULL; + CLEAR_FPU_OWNER(); } } @@ -77,7 +78,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp, childksp = (unsigned long)p + KERNEL_STACK_SIZE - 32; - if (last_task_used_math == current) { + if (IS_FPU_OWNER()) { save_fp(p); } /* set up new TSS. */ diff --git a/arch/mips64/kernel/ptrace.c b/arch/mips64/kernel/ptrace.c index 0301a66a3..b79a61f0e 100644 --- a/arch/mips64/kernel/ptrace.c +++ b/arch/mips64/kernel/ptrace.c @@ -13,6 +13,7 @@ * At this time Linux/MIPS64 only supports syscall tracing, even for 32-bit * binaries. */ +#include #include #include #include @@ -36,7 +37,6 @@ asmlinkage int sys32_ptrace(int request, int pid, int addr, int data) struct task_struct *child; unsigned long flags; int ret; - extern void save_fp(void*); lock_kernel(); #if 0 @@ -132,12 +132,14 @@ asmlinkage int sys32_ptrace(int request, int pid, int addr, int data) break; case FPR_BASE ... FPR_BASE + 31: if (child->used_math) { +#ifndef CONFIG_SMP if (last_task_used_math == child) { set_cp0_status(ST0_CU1, ST0_CU1); save_fp(child); set_cp0_status(ST0_CU1, 0); last_task_used_math = NULL; } +#endif tmp = child->thread.fpu.hard.fp_regs[addr - 32]; } else { tmp = -EIO; @@ -199,6 +201,7 @@ asmlinkage int sys32_ptrace(int request, int pid, int addr, int data) case FPR_BASE ... FPR_BASE + 31: { unsigned long *fregs; if (child->used_math) { +#ifndef CONFIG_SMP if (last_task_used_math == child) { set_cp0_status(ST0_CU1, ST0_CU1); save_fp(child); @@ -206,6 +209,7 @@ asmlinkage int sys32_ptrace(int request, int pid, int addr, int data) last_task_used_math = NULL; regs->cp0_status &= ~ST0_CU1; } +#endif } else { /* FP not yet used */ memset(&child->thread.fpu.hard, ~0, @@ -293,7 +297,6 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) struct task_struct *child; unsigned long flags; int ret; - extern void save_fp(void*); lock_kernel(); #if 0 @@ -389,12 +392,14 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) break; case FPR_BASE ... FPR_BASE + 31: if (child->used_math) { +#ifndef CONFIG_SMP if (last_task_used_math == child) { set_cp0_status(ST0_CU1, ST0_CU1); save_fp(child); set_cp0_status(ST0_CU1, 0); last_task_used_math = NULL; } +#endif tmp = child->thread.fpu.hard.fp_regs[addr - 32]; } else { tmp = -EIO; @@ -456,6 +461,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) case FPR_BASE ... FPR_BASE + 31: { unsigned long *fregs; if (child->used_math) { +#ifndef CONFIG_SMP if (last_task_used_math == child) { set_cp0_status(ST0_CU1, ST0_CU1); save_fp(child); @@ -463,6 +469,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) last_task_used_math = NULL; regs->cp0_status &= ~ST0_CU1; } +#endif } else { /* FP not yet used */ memset(&child->thread.fpu.hard, ~0, diff --git a/arch/mips64/kernel/signal.c b/arch/mips64/kernel/signal.c index 40a727831..7f644a437 100644 --- a/arch/mips64/kernel/signal.c +++ b/arch/mips64/kernel/signal.c @@ -26,6 +26,7 @@ #include #include #include +#include #define DEBUG_SIG 0 @@ -209,8 +210,8 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext *sc) err |= __get_user(owned_fp, &sc->sc_ownedfp); if (owned_fp) { - if (current == last_task_used_math) { - last_task_used_math = 0; + if (IS_FPU_OWNER()) { + CLEAR_FPU_OWNER(); regs->cp0_status &= ~ST0_CU1; } current->used_math = 1; @@ -338,9 +339,9 @@ setup_sigcontext(struct pt_regs *regs, struct sigcontext *sc) err |= __put_user(regs->cp0_badvaddr, &sc->sc_badvaddr); if (current->used_math) { /* fp is active. */ - if (current == last_task_used_math) { + if (IS_FPU_OWNER()) { lazy_fpu_switch(current, 0); - last_task_used_math = NULL; + CLEAR_FPU_OWNER(); regs->cp0_status &= ~ST0_CU1; } err |= __put_user(1, &sc->sc_ownedfp); diff --git a/arch/mips64/kernel/signal32.c b/arch/mips64/kernel/signal32.c index 4addc707c..e33a69d5e 100644 --- a/arch/mips64/kernel/signal32.c +++ b/arch/mips64/kernel/signal32.c @@ -8,6 +8,7 @@ * Copyright (C) 1994 - 1999 Ralf Baechle * Copyright (C) 1999 Silicon Graphics, Inc. */ +#include #include #include #include @@ -25,6 +26,7 @@ #include #include #include +#include #define DEBUG_SIG 0 @@ -239,8 +241,8 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext *sc) err |= __get_user(owned_fp, &sc->sc_ownedfp); if (owned_fp) { - if (current == last_task_used_math) { - last_task_used_math = 0; + if (IS_FPU_OWNER()) { + CLEAR_FPU_OWNER(); regs->cp0_status &= ~ST0_CU1; } current->used_math = 1; @@ -373,9 +375,9 @@ setup_sigcontext(struct pt_regs *regs, struct sigcontext *sc) err |= __put_user(regs->cp0_badvaddr, &sc->sc_badvaddr); if (current->used_math) { /* fp is active. */ - if (current == last_task_used_math) { + if (IS_FPU_OWNER()) { lazy_fpu_switch(current, 0); - last_task_used_math = NULL; + CLEAR_FPU_OWNER(); regs->cp0_status &= ~ST0_CU1; } err |= __put_user(1, &sc->sc_ownedfp); diff --git a/arch/mips64/kernel/traps.c b/arch/mips64/kernel/traps.c index 9f97fb0d8..fa58017cf 100644 --- a/arch/mips64/kernel/traps.c +++ b/arch/mips64/kernel/traps.c @@ -346,6 +346,7 @@ void do_cpu(struct pt_regs *regs) goto bad_cid; regs->cp0_status |= ST0_CU1; +#ifndef CONFIG_SMP if (last_task_used_math == current) return; @@ -357,6 +358,15 @@ void do_cpu(struct pt_regs *regs) current->used_math = 1; } last_task_used_math = current; +#else + if (current->used_math) { + lazy_fpu_switch(0, current); + } else { + init_fpu(); + current->used_math = 1; + } + current->flags |= PF_USEDFPU; +#endif return; bad_cid: -- cgit v1.2.3