* [PATCH] Cleanup FPU ownership management
@ 2007-03-09 16:23 Atsushi Nemoto
2007-03-10 12:37 ` Ralf Baechle
0 siblings, 1 reply; 2+ messages in thread
From: Atsushi Nemoto @ 2007-03-09 16:23 UTC (permalink / raw)
To: linux-mips; +Cc: ralf
Currently preempt_disable/preempt_enable are scattered in FPU
ownership management code. This patch makes own_fpu() and lost_fpu()
can save/restore FPU context in itself and make these functions (and
init_fpu() too) preempt-proof. This makes the FPU management codes
much readable. Also this patch introduce raw_cpu_has_fpu macro which
is to be used if the caller did not need atomic context.
Signed-off-by: Atsushi Nemoto <anemo@mba.ocn.ne.jp>
---
This is an update of:
http://www.linux-mips.org/archives/linux-mips/2006-11/msg00130.html
This patch depends on:
> Subject: [PATCH] do_fpe() cleanup
> Message-Id: <20070310.010745.07456268.anemo@mba.ocn.ne.jp>
> Subject: [PATCH] rewrite restore_fp_context/save_fp_context
> Message-Id: <20070310.011845.85420915.anemo@mba.ocn.ne.jp>
arch/mips/kernel/signal.c | 12 ++----------
arch/mips/kernel/signal32.c | 12 ++----------
arch/mips/kernel/traps.c | 30 ++++++------------------------
include/asm-mips/cpu-features.h | 3 +++
include/asm-mips/cpu-info.h | 1 +
include/asm-mips/fpu.h | 25 ++++++++++++++++++++-----
6 files changed, 34 insertions(+), 49 deletions(-)
diff --git a/arch/mips/kernel/signal.c b/arch/mips/kernel/signal.c
index d2e6c50..ce00a50 100644
--- a/arch/mips/kernel/signal.c
+++ b/arch/mips/kernel/signal.c
@@ -143,13 +143,7 @@ int setup_sigcontext(struct pt_regs *reg
* Save FPU state to signal context. Signal handler
* will "inherit" current FPU state.
*/
- preempt_disable();
- if (is_fpu_owner()) {
- /* save current context to task_struct */
- save_fp(current);
- lose_fpu();
- }
- preempt_enable();
+ lose_fpu(1);
err |= save_fp_context(sc);
}
return err;
@@ -220,9 +214,7 @@ int restore_sigcontext(struct pt_regs *r
conditional_used_math(used_math);
/* signal handler may have used FPU. Give it up. */
- preempt_disable();
- lose_fpu();
- preempt_enable();
+ lose_fpu(0);
if (used_math()) {
/* restore fpu context if we have used it before */
diff --git a/arch/mips/kernel/signal32.c b/arch/mips/kernel/signal32.c
index f966fc4..3557f17 100644
--- a/arch/mips/kernel/signal32.c
+++ b/arch/mips/kernel/signal32.c
@@ -231,13 +231,7 @@ static int setup_sigcontext32(struct pt_
* Save FPU state to signal context. Signal handler
* will "inherit" current FPU state.
*/
- preempt_disable();
- if (is_fpu_owner()) {
- /* save current context to task_struct */
- save_fp(current);
- lose_fpu();
- }
- preempt_enable();
+ lose_fpu(1);
err |= save_fp_context32(sc);
}
return err;
@@ -286,9 +280,7 @@ static int restore_sigcontext32(struct p
conditional_used_math(used_math);
/* signal handler may have used FPU. Give it up. */
- preempt_disable();
- lose_fpu();
- preempt_enable();
+ lose_fpu(0);
if (used_math()) {
/* restore fpu context if we have used it before */
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index 0873834..441b9a9 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -620,15 +620,8 @@ asmlinkage void do_fpe(struct pt_regs *r
* register operands before invoking the emulator, which seems
* a bit extreme for what should be an infrequent event.
*/
- preempt_disable();
-
- /* We might have lost fpu before disabling preempt... */
- if (is_fpu_owner())
- save_fp(current);
/* Ensure 'resume' not overwrite saved fp context again. */
- lose_fpu();
-
- preempt_enable();
+ lose_fpu(1);
/* Run the emulator */
sig = fpu_emulator_cop1Handler (regs, ¤t->thread.fpu, 1);
@@ -639,13 +632,8 @@ asmlinkage void do_fpe(struct pt_regs *r
*/
current->thread.fpu.fcr31 &= ~FPU_CSR_ALL_X;
- preempt_disable();
-
- own_fpu(); /* Using the FPU again. */
/* Restore the hardware register state */
- restore_fp(current);
-
- preempt_enable();
+ own_fpu(); /* Using the FPU again. */
/* If something went wrong, signal */
if (sig)
@@ -785,21 +773,15 @@ asmlinkage void do_cpu(struct pt_regs *r
break;
case 1:
- preempt_disable();
-
- own_fpu();
- if (used_math()) { /* Using the FPU again. */
- restore_fp(current);
- } else { /* First time FPU user. */
+ if (used_math()) /* Using the FPU again. */
+ own_fpu();
+ else { /* First time FPU user. */
init_fpu();
set_used_math();
}
- if (cpu_has_fpu) {
- preempt_enable();
- } else {
+ if (!raw_cpu_has_fpu) {
int sig;
- preempt_enable();
sig = fpu_emulator_cop1Handler(regs,
¤t->thread.fpu, 0);
if (sig)
diff --git a/include/asm-mips/cpu-features.h b/include/asm-mips/cpu-features.h
index eadca26..5e4bed1 100644
--- a/include/asm-mips/cpu-features.h
+++ b/include/asm-mips/cpu-features.h
@@ -40,6 +40,9 @@
#endif
#ifndef cpu_has_fpu
#define cpu_has_fpu (current_cpu_data.options & MIPS_CPU_FPU)
+#define raw_cpu_has_fpu (raw_current_cpu_data.options & MIPS_CPU_FPU)
+#else
+#define raw_cpu_has_fpu cpu_has_fpu
#endif
#ifndef cpu_has_32fpr
#define cpu_has_32fpr (cpu_data[0].options & MIPS_CPU_32FPR)
diff --git a/include/asm-mips/cpu-info.h b/include/asm-mips/cpu-info.h
index 610d0cd..22fe845 100644
--- a/include/asm-mips/cpu-info.h
+++ b/include/asm-mips/cpu-info.h
@@ -87,6 +87,7 @@ struct cpuinfo_mips {
extern struct cpuinfo_mips cpu_data[];
#define current_cpu_data cpu_data[smp_processor_id()]
+#define raw_current_cpu_data cpu_data[raw_smp_processor_id()]
extern void cpu_probe(void);
extern void cpu_report(void);
diff --git a/include/asm-mips/fpu.h b/include/asm-mips/fpu.h
index 979839c..538dabc 100644
--- a/include/asm-mips/fpu.h
+++ b/include/asm-mips/fpu.h
@@ -84,31 +84,46 @@ static inline int is_fpu_owner(void)
return cpu_has_fpu && __is_fpu_owner();
}
+static inline void __own_fpu(void)
+{
+ __enable_fpu();
+ KSTK_STATUS(current) |= ST0_CU1;
+ set_thread_flag(TIF_USEDFPU);
+}
+
static inline void own_fpu(void)
{
+ preempt_disable();
if (cpu_has_fpu) {
- __enable_fpu();
- KSTK_STATUS(current) |= ST0_CU1;
- set_thread_flag(TIF_USEDFPU);
+ __own_fpu();
+ _restore_fp(current);
}
+ preempt_enable();
}
-static inline void lose_fpu(void)
+static inline void lose_fpu(int save)
{
- if (cpu_has_fpu) {
+ preempt_disable();
+ if (cpu_has_fpu && __is_fpu_owner()) {
+ if (save)
+ _save_fp(current);
KSTK_STATUS(current) &= ~ST0_CU1;
clear_thread_flag(TIF_USEDFPU);
__disable_fpu();
}
+ preempt_enable();
}
static inline void init_fpu(void)
{
+ preempt_disable();
if (cpu_has_fpu) {
+ __own_fpu();
_init_fpu();
} else {
fpu_emulator_init_fpu();
}
+ preempt_enable();
}
static inline void save_fp(struct task_struct *tsk)
^ permalink raw reply related [flat|nested] 2+ messages in thread
* Re: [PATCH] Cleanup FPU ownership management
2007-03-09 16:23 [PATCH] Cleanup FPU ownership management Atsushi Nemoto
@ 2007-03-10 12:37 ` Ralf Baechle
0 siblings, 0 replies; 2+ messages in thread
From: Ralf Baechle @ 2007-03-10 12:37 UTC (permalink / raw)
To: Atsushi Nemoto; +Cc: linux-mips
On Sat, Mar 10, 2007 at 01:23:19AM +0900, Atsushi Nemoto wrote:
> Currently preempt_disable/preempt_enable are scattered in FPU
> ownership management code. This patch makes own_fpu() and lost_fpu()
> can save/restore FPU context in itself and make these functions (and
> init_fpu() too) preempt-proof. This makes the FPU management codes
> much readable. Also this patch introduce raw_cpu_has_fpu macro which
> is to be used if the caller did not need atomic context.
And this one dropped also.
Ralf
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2007-03-10 12:39 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-03-09 16:23 [PATCH] Cleanup FPU ownership management Atsushi Nemoto
2007-03-10 12:37 ` Ralf Baechle
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox