Make sure cpu_has_fpu is used only in atomic context
Subsystems (2)
A message that is not in the archive (sent off-list or not yet received): [email protected]
A message that is not in the archive (sent off-list or not yet received): [email protected]
A message that is not in the archive (sent off-list or not yet received): [email protected]
PATCH 1/1 Make sure cpu_has_fpu is used only in atomic context
Make sure cpu_has_fpu (which uses smp_processor_id()) is used only in atomic context.
Signed-off-by Atsushi Nemoto <[email protected]>
arch/mips/kernel/proc.c | 2 +- arch/mips/kernel/process.c | 2 +- arch/mips/kernel/ptrace.c | 18 ++++++++++-------- arch/mips/kernel/ptrace32.c | 3 ++- arch/mips/kernel/traps.c | 16 +++++++++------- arch/mips/math-emu/cp1emu.c | 7 +++---- include/asm-mips/fpu.h | 6 ++++-- 7 files changed, 30 insertions(+), 24 deletions(-)
arch/mips/kernel/proc.c +1 -1
@@ -107,7 +107,7 @@ #endifseq_printf (m,"processor\t\t: %ld\n" , n);sprintf (fmt,"cpu model\t\t: %%s V%%d.%%d%s\n" , - cpu_has_fpu ?" FPU V%d.%d" :"" ); + cpu_data[n].options &MIPS_CPU_FPU ?" FPU V%d.%d" :"" ); seq_printf(m, fmt, cpu_name[cpu_data[n].cputype <= CPU_LAST ? cpu_data[n].cputype : CPU_UNKNOWN], (version >> 4) & 0x0f, version & 0x0f,
arch/mips/kernel/process.c +1 -1
@@ -115,7 +115,7 @@ #endif status |=KU_USER ; regs->cp0_status = status;clear_used_math (); -lose_fpu (); +clear_fpu_owner ();if (cpu_has_dsp)__init_dsp (); regs->cp0_epc = pc;
arch/mips/kernel/ptrace.c +10 -8
@@ -106,6 +106,7 @@ int ptrace_setregs (struct task_struct *int ptrace_getfpregs (struct task_struct *child,__u32 __user *data) {int i; +unsigned int tmp;if (!access_ok (VERIFY_WRITE , data,33 *8 ))return -EIO ;
@@ -121,10 +122,10 @@ int ptrace_getfpregs (struct task_struct__put_user (child->thread.fpu.fcr31, data +64 ); +preempt_disable ();if (cpu_has_fpu) { -unsigned int flags, tmp; +unsigned int flags; -preempt_disable ();if (cpu_has_mipsmt) {unsigned int vpflags =dvpe (); flags =read_c0_status ();
@@ -138,11 +139,11 @@ int ptrace_getfpregs (struct task_struct __asm__ __volatile__("cfc1\t%0,$0" :"=r" (tmp));write_c0_status (flags); } -preempt_enable (); -__put_user (tmp, data +65 ); }else { -__put_user ((__u32 )0 , data +65 ); + tmp =0 ; } +preempt_enable (); +__put_user (tmp, data +65 );return 0 ; }
@@ -245,16 +246,17 @@ #ifdef CONFIG_MIPS_MT_SMTCunsigned int mtflags;#endif /* CONFIG_MIPS_MT_SMTC */ -if (!cpu_has_fpu) +preempt_disable (); +if (!cpu_has_fpu) { +preempt_enable ();break ; + }#ifdef CONFIG_MIPS_MT_SMTC /* Read-modify-write of Status must be atomic */ local_irq_save (irqflags); mtflags =dmt ();#endif /* CONFIG_MIPS_MT_SMTC */ - -preempt_disable ();if (cpu_has_mipsmt) {unsigned int vpflags =dvpe (); flags =read_c0_status ();
arch/mips/kernel/ptrace32.c +2 -1
@@ -175,7 +175,9 @@ #ifdef CONFIG_MIPS_MT_SMTCunsigned int mtflags;#endif /* CONFIG_MIPS_MT_SMTC */ +preempt_disable ();if (!cpu_has_fpu) { +preempt_enable (); tmp =0 ;break ; }
@@ -186,7 +188,6 @@ #ifdef CONFIG_MIPS_MT_SMTC mtflags =dmt ();#endif /* CONFIG_MIPS_MT_SMTC */ -preempt_disable ();if (cpu_has_mipsmt) {unsigned int vpflags =dvpe (); flags =read_c0_status ();
arch/mips/kernel/traps.c +9 -7
@@ -66,7 +66,7 @@ extern asmlinkage void handle_mcheck(voi extern asmlinkage void handle_reserved(void);extern int fpu_emulator_cop1Handler (struct pt_regs *xcp, -struct mips_fpu_struct *ctx); +struct mips_fpu_struct *ctx,int has_fpu);void (*board_be_init)(void );int (*board_be_handler)(struct pt_regs *regs,int is_fixup);
@@ -641,7 +641,7 @@ #endifpreempt_enable ();/* Run the emulator */ - sig =fpu_emulator_cop1Handler (regs, ¤t->thread.fpu); + sig =fpu_emulator_cop1Handler (regs, ¤t->thread.fpu,1 );preempt_disable ();
@@ -791,11 +791,13 @@ asmlinkage void do_cpu(struct pt_regs *rset_used_math (); } -preempt_enable (); - -if (!cpu_has_fpu) { -int sig =fpu_emulator_cop1Handler (regs, - ¤t->thread.fpu); +if (cpu_has_fpu) { +preempt_enable (); + }else { +int sig; +preempt_enable (); + sig =fpu_emulator_cop1Handler (regs, + ¤t->thread.fpu,0 );if (sig)force_sig (sig, current);#ifdef CONFIG_MIPS_MT_FPAFF
arch/mips/math-emu/cp1emu.c +3 -4
@@ -38,8 +38,6 @@ #include <linux/sched.h>#include <asm/inst.h> #include <asm/bootinfo.h> -#include <asm/cpu.h> -#include <asm/cpu-features.h> #include <asm/processor.h> #include <asm/ptrace.h> #include <asm/signal.h>
@@ -1233,7 +1231,8 @@ #endifreturn 0 ; } -int fpu_emulator_cop1Handler (struct pt_regs *xcp,struct mips_fpu_struct *ctx) +int fpu_emulator_cop1Handler (struct pt_regs *xcp,struct mips_fpu_struct *ctx, +int has_fpu) {unsigned long oldepc, prevepc;mips_instruction insn;
@@ -1263,7 +1262,7 @@ int fpu_emulator_cop1Handler(struct pt_r ieee754_csr.rm = mips_rm[ieee754_csr.rm]; } -if (cpu_has_fpu) +if (has_fpu)break ;if (sig)break ;
include/asm-mips/fpu.h +4 -2
@@ -134,9 +134,11 @@ static inline void restore_fp(struct tasstatic inline fpureg_t *get_fpu_regs (struct task_struct *tsk) { -if (cpu_has_fpu) { -if ((tsk == current) &&__is_fpu_owner ()) +if (tsk == current) { +preempt_disable (); +if (is_fpu_owner ())_save_fp (current); +preempt_enable (); }return tsk->thread.fpu.fpr;
Quoted 2 lines · Atsushi Nemoto
Make sure
cpu_has_fpu(which usessmp_processor_id()) is used only in atomic context.
It's awfully ugly to have an increasing number of preemption kludgery around but it's not so trivial to avoid unfortunately ...
Ralf