Commit bb459c65 authored by Andrea Arcangeli's avatar Andrea Arcangeli Committed by Linus Torvalds

[PATCH] make used_math SMP-safe

Convert the unsafe signed (16bit) used_math to a safe and optimal
PF_USED_MATH

I might have broken arm, see the very first change in the patch to
asm-offsets.c, rest looks ok at first glance.

If you want used_math to return 0 or 1 (instead of 0 or PF_USED_MATH), just
s/!!// in the below patch and place !!  in sched.h::*used_math()
accordingly after applying the patch, it should work just fine.  Using !!
only when necessary as the below is optimal.

From: Yoichi Yuasa <yuasa@hh.iij4u.or.jp>

This patch had fixed restore_sigcontext/restore_sigcontext32 about MIPS.
Signed-off-by: default avatarYoichi Yuasa <yuasa@hh.iij4u.or.jp>
Signed-off-by: default avatarAndrea Arcangeli <andrea@suse.de>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 6e486e8b
...@@ -42,7 +42,6 @@ ...@@ -42,7 +42,6 @@
int main(void) int main(void)
{ {
DEFINE(TSK_USED_MATH, offsetof(struct task_struct, used_math));
DEFINE(TSK_ACTIVE_MM, offsetof(struct task_struct, active_mm)); DEFINE(TSK_ACTIVE_MM, offsetof(struct task_struct, active_mm));
BLANK(); BLANK();
DEFINE(VMA_VM_MM, offsetof(struct vm_area_struct, vm_mm)); DEFINE(VMA_VM_MM, offsetof(struct vm_area_struct, vm_mm));
......
...@@ -271,7 +271,7 @@ void flush_thread(void) ...@@ -271,7 +271,7 @@ void flush_thread(void)
memset(&tsk->thread.debug, 0, sizeof(struct debug_info)); memset(&tsk->thread.debug, 0, sizeof(struct debug_info));
memset(&thread->fpstate, 0, sizeof(union fp_state)); memset(&thread->fpstate, 0, sizeof(union fp_state));
current->used_math = 0; clear_used_math();
} }
void release_thread(struct task_struct *dead_task) void release_thread(struct task_struct *dead_task)
...@@ -305,7 +305,7 @@ copy_thread(int nr, unsigned long clone_flags, unsigned long stack_start, ...@@ -305,7 +305,7 @@ copy_thread(int nr, unsigned long clone_flags, unsigned long stack_start,
int dump_fpu (struct pt_regs *regs, struct user_fp *fp) int dump_fpu (struct pt_regs *regs, struct user_fp *fp)
{ {
struct thread_info *thread = current_thread_info(); struct thread_info *thread = current_thread_info();
int used_math = current->used_math; int used_math = !!used_math();
if (used_math) if (used_math)
memcpy(fp, &thread->fpstate.soft, sizeof (*fp)); memcpy(fp, &thread->fpstate.soft, sizeof (*fp));
......
...@@ -540,7 +540,7 @@ static int ptrace_getfpregs(struct task_struct *tsk, void *ufp) ...@@ -540,7 +540,7 @@ static int ptrace_getfpregs(struct task_struct *tsk, void *ufp)
*/ */
static int ptrace_setfpregs(struct task_struct *tsk, void *ufp) static int ptrace_setfpregs(struct task_struct *tsk, void *ufp)
{ {
tsk->used_math = 1; set_stopped_child_used_math(tsk);
return copy_from_user(&tsk->thread_info->fpstate, ufp, return copy_from_user(&tsk->thread_info->fpstate, ufp,
sizeof(struct user_fp)) ? -EFAULT : 0; sizeof(struct user_fp)) ? -EFAULT : 0;
} }
......
...@@ -629,6 +629,6 @@ void __init cpu_init (void) ...@@ -629,6 +629,6 @@ void __init cpu_init (void)
* Force FPU initialization: * Force FPU initialization:
*/ */
current_thread_info()->status = 0; current_thread_info()->status = 0;
current->used_math = 0; clear_used_math();
mxcsr_feature_mask_init(); mxcsr_feature_mask_init();
} }
...@@ -60,7 +60,8 @@ void init_fpu(struct task_struct *tsk) ...@@ -60,7 +60,8 @@ void init_fpu(struct task_struct *tsk)
tsk->thread.i387.fsave.twd = 0xffffffffu; tsk->thread.i387.fsave.twd = 0xffffffffu;
tsk->thread.i387.fsave.fos = 0xffff0000u; tsk->thread.i387.fsave.fos = 0xffff0000u;
} }
tsk->used_math = 1; /* only the device not available exception or ptrace can call init_fpu */
set_stopped_child_used_math(tsk);
} }
/* /*
...@@ -331,13 +332,13 @@ static int save_i387_fxsave( struct _fpstate __user *buf ) ...@@ -331,13 +332,13 @@ static int save_i387_fxsave( struct _fpstate __user *buf )
int save_i387( struct _fpstate __user *buf ) int save_i387( struct _fpstate __user *buf )
{ {
if ( !current->used_math ) if ( !used_math() )
return 0; return 0;
/* This will cause a "finit" to be triggered by the next /* This will cause a "finit" to be triggered by the next
* attempted FPU operation by the 'current' process. * attempted FPU operation by the 'current' process.
*/ */
current->used_math = 0; clear_used_math();
if ( HAVE_HWFP ) { if ( HAVE_HWFP ) {
if ( cpu_has_fxsr ) { if ( cpu_has_fxsr ) {
...@@ -383,7 +384,7 @@ int restore_i387( struct _fpstate __user *buf ) ...@@ -383,7 +384,7 @@ int restore_i387( struct _fpstate __user *buf )
} else { } else {
err = restore_i387_soft( &current->thread.i387.soft, buf ); err = restore_i387_soft( &current->thread.i387.soft, buf );
} }
current->used_math = 1; set_used_math();
return err; return err;
} }
...@@ -507,7 +508,7 @@ int dump_fpu( struct pt_regs *regs, struct user_i387_struct *fpu ) ...@@ -507,7 +508,7 @@ int dump_fpu( struct pt_regs *regs, struct user_i387_struct *fpu )
int fpvalid; int fpvalid;
struct task_struct *tsk = current; struct task_struct *tsk = current;
fpvalid = tsk->used_math; fpvalid = !!used_math();
if ( fpvalid ) { if ( fpvalid ) {
unlazy_fpu( tsk ); unlazy_fpu( tsk );
if ( cpu_has_fxsr ) { if ( cpu_has_fxsr ) {
...@@ -522,7 +523,7 @@ int dump_fpu( struct pt_regs *regs, struct user_i387_struct *fpu ) ...@@ -522,7 +523,7 @@ int dump_fpu( struct pt_regs *regs, struct user_i387_struct *fpu )
int dump_task_fpu(struct task_struct *tsk, struct user_i387_struct *fpu) int dump_task_fpu(struct task_struct *tsk, struct user_i387_struct *fpu)
{ {
int fpvalid = tsk->used_math; int fpvalid = !!tsk_used_math(tsk);
if (fpvalid) { if (fpvalid) {
if (tsk == current) if (tsk == current)
...@@ -537,7 +538,7 @@ int dump_task_fpu(struct task_struct *tsk, struct user_i387_struct *fpu) ...@@ -537,7 +538,7 @@ int dump_task_fpu(struct task_struct *tsk, struct user_i387_struct *fpu)
int dump_task_extended_fpu(struct task_struct *tsk, struct user_fxsr_struct *fpu) int dump_task_extended_fpu(struct task_struct *tsk, struct user_fxsr_struct *fpu)
{ {
int fpvalid = tsk->used_math && cpu_has_fxsr; int fpvalid = tsk_used_math(tsk) && cpu_has_fxsr;
if (fpvalid) { if (fpvalid) {
if (tsk == current) if (tsk == current)
......
...@@ -351,7 +351,7 @@ void flush_thread(void) ...@@ -351,7 +351,7 @@ void flush_thread(void)
* Forget coprocessor state.. * Forget coprocessor state..
*/ */
clear_fpu(tsk); clear_fpu(tsk);
tsk->used_math = 0; clear_used_math();
} }
void release_thread(struct task_struct *dead_task) void release_thread(struct task_struct *dead_task)
......
...@@ -592,7 +592,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) ...@@ -592,7 +592,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
break; break;
} }
ret = 0; ret = 0;
if (!child->used_math) if (!tsk_used_math(child))
init_fpu(child); init_fpu(child);
get_fpregs((struct user_i387_struct __user *)data, child); get_fpregs((struct user_i387_struct __user *)data, child);
break; break;
...@@ -604,7 +604,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) ...@@ -604,7 +604,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
ret = -EIO; ret = -EIO;
break; break;
} }
child->used_math = 1; set_stopped_child_used_math(child);
set_fpregs(child, (struct user_i387_struct __user *)data); set_fpregs(child, (struct user_i387_struct __user *)data);
ret = 0; ret = 0;
break; break;
...@@ -616,7 +616,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) ...@@ -616,7 +616,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
ret = -EIO; ret = -EIO;
break; break;
} }
if (!child->used_math) if (!tsk_used_math(child))
init_fpu(child); init_fpu(child);
ret = get_fpxregs((struct user_fxsr_struct __user *)data, child); ret = get_fpxregs((struct user_fxsr_struct __user *)data, child);
break; break;
...@@ -628,7 +628,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) ...@@ -628,7 +628,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
ret = -EIO; ret = -EIO;
break; break;
} }
child->used_math = 1; set_stopped_child_used_math(child);
ret = set_fpxregs(child, (struct user_fxsr_struct __user *)data); ret = set_fpxregs(child, (struct user_fxsr_struct __user *)data);
break; break;
} }
......
...@@ -192,9 +192,9 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, int *peax ...@@ -192,9 +192,9 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, int *peax
err |= restore_i387(buf); err |= restore_i387(buf);
} else { } else {
struct task_struct *me = current; struct task_struct *me = current;
if (me->used_math) { if (used_math()) {
clear_fpu(me); clear_fpu(me);
me->used_math = 0; clear_used_math();
} }
} }
} }
......
...@@ -911,7 +911,7 @@ asmlinkage void math_state_restore(struct pt_regs regs) ...@@ -911,7 +911,7 @@ asmlinkage void math_state_restore(struct pt_regs regs)
struct task_struct *tsk = thread->task; struct task_struct *tsk = thread->task;
clts(); /* Allow maths ops (or we recurse) */ clts(); /* Allow maths ops (or we recurse) */
if (!tsk->used_math) if (!tsk_used_math(tsk))
init_fpu(tsk); init_fpu(tsk);
restore_fpu(tsk); restore_fpu(tsk);
thread->status |= TS_USEDFPU; /* So we fnsave on switch_to() */ thread->status |= TS_USEDFPU; /* So we fnsave on switch_to() */
......
...@@ -155,10 +155,10 @@ asmlinkage void math_emulate(long arg) ...@@ -155,10 +155,10 @@ asmlinkage void math_emulate(long arg)
RE_ENTRANT_CHECK_ON; RE_ENTRANT_CHECK_ON;
#endif /* RE_ENTRANT_CHECKING */ #endif /* RE_ENTRANT_CHECKING */
if (!current->used_math) if (!used_math())
{ {
finit(); finit();
current->used_math = 1; set_used_math();
} }
SETUP_DATA_AREA(arg); SETUP_DATA_AREA(arg);
......
...@@ -106,7 +106,7 @@ elf_core_copy_task_fpregs(struct task_struct *tsk, struct pt_regs *regs, elf_fpr ...@@ -106,7 +106,7 @@ elf_core_copy_task_fpregs(struct task_struct *tsk, struct pt_regs *regs, elf_fpr
struct ia32_user_i387_struct *fpstate = (void*)fpu; struct ia32_user_i387_struct *fpstate = (void*)fpu;
mm_segment_t old_fs; mm_segment_t old_fs;
if (!tsk->used_math) if (!tsk_used_math(tsk))
return 0; return 0;
old_fs = get_fs(); old_fs = get_fs();
...@@ -124,7 +124,7 @@ elf_core_copy_task_xfpregs(struct task_struct *tsk, elf_fpxregset_t *xfpu) ...@@ -124,7 +124,7 @@ elf_core_copy_task_xfpregs(struct task_struct *tsk, elf_fpxregset_t *xfpu)
struct ia32_user_fxsr_struct *fpxstate = (void*) xfpu; struct ia32_user_fxsr_struct *fpxstate = (void*) xfpu;
mm_segment_t old_fs; mm_segment_t old_fs;
if (!tsk->used_math) if (!tsk_used_math(tsk))
return 0; return 0;
old_fs = get_fs(); old_fs = get_fs();
......
...@@ -130,7 +130,7 @@ static int ptrace_read_user(struct task_struct *tsk, unsigned long off, ...@@ -130,7 +130,7 @@ static int ptrace_read_user(struct task_struct *tsk, unsigned long off,
#ifndef NO_FPU #ifndef NO_FPU
else if (off >= (long)(&dummy->fpu >> 2) && else if (off >= (long)(&dummy->fpu >> 2) &&
off < (long)(&dummy->u_fpvalid >> 2)) { off < (long)(&dummy->u_fpvalid >> 2)) {
if (!tsk->used_math) { if (!tsk_used_math(tsk)) {
if (off == (long)(&dummy->fpu.fpscr >> 2)) if (off == (long)(&dummy->fpu.fpscr >> 2))
tmp = FPSCR_INIT; tmp = FPSCR_INIT;
else else
...@@ -139,7 +139,7 @@ static int ptrace_read_user(struct task_struct *tsk, unsigned long off, ...@@ -139,7 +139,7 @@ static int ptrace_read_user(struct task_struct *tsk, unsigned long off,
tmp = ((long *)(&tsk->thread.fpu >> 2)) tmp = ((long *)(&tsk->thread.fpu >> 2))
[off - (long)&dummy->fpu]; [off - (long)&dummy->fpu];
} else if (off == (long)(&dummy->u_fpvalid >> 2)) } else if (off == (long)(&dummy->u_fpvalid >> 2))
tmp = tsk->used_math; tmp = !!tsk_used_math(tsk);
#endif /* not NO_FPU */ #endif /* not NO_FPU */
else else
tmp = 0; tmp = 0;
...@@ -187,12 +187,12 @@ static int ptrace_write_user(struct task_struct *tsk, unsigned long off, ...@@ -187,12 +187,12 @@ static int ptrace_write_user(struct task_struct *tsk, unsigned long off,
#ifndef NO_FPU #ifndef NO_FPU
else if (off >= (long)(&dummy->fpu >> 2) && else if (off >= (long)(&dummy->fpu >> 2) &&
off < (long)(&dummy->u_fpvalid >> 2)) { off < (long)(&dummy->u_fpvalid >> 2)) {
tsk->used_math = 1; set_stopped_child_used_math(tsk);
((long *)&tsk->thread.fpu) ((long *)&tsk->thread.fpu)
[off - (long)&dummy->fpu] = data; [off - (long)&dummy->fpu] = data;
ret = 0; ret = 0;
} else if (off == (long)(&dummy->u_fpvalid >> 2)) { } else if (off == (long)(&dummy->u_fpvalid >> 2)) {
tsk->used_math = data ? 1 : 0; conditional_stopped_child_used_math(data, tsk);
ret = 0; ret = 0;
} }
#endif /* not NO_FPU */ #endif /* not NO_FPU */
......
...@@ -391,7 +391,7 @@ void __init cpu_init (void) ...@@ -391,7 +391,7 @@ void __init cpu_init (void)
/* Force FPU initialization */ /* Force FPU initialization */
current_thread_info()->status = 0; current_thread_info()->status = 0;
current->used_math = 0; clear_used_math();
#ifdef CONFIG_MMU #ifdef CONFIG_MMU
/* Set up MMU */ /* Set up MMU */
......
...@@ -99,7 +99,7 @@ static void setup_irix_frame(struct k_sigaction *ka, struct pt_regs *regs, ...@@ -99,7 +99,7 @@ static void setup_irix_frame(struct k_sigaction *ka, struct pt_regs *regs,
__put_user((u64) regs->hi, &ctx->hi); __put_user((u64) regs->hi, &ctx->hi);
__put_user((u64) regs->lo, &ctx->lo); __put_user((u64) regs->lo, &ctx->lo);
__put_user((u64) regs->cp0_epc, &ctx->pc); __put_user((u64) regs->cp0_epc, &ctx->pc);
__put_user(current->used_math, &ctx->usedfp); __put_user(!!used_math(), &ctx->usedfp);
__put_user((u64) regs->cp0_cause, &ctx->cp0_cause); __put_user((u64) regs->cp0_cause, &ctx->cp0_cause);
__put_user((u64) regs->cp0_badvaddr, &ctx->cp0_badvaddr); __put_user((u64) regs->cp0_badvaddr, &ctx->cp0_badvaddr);
...@@ -725,7 +725,7 @@ asmlinkage int irix_getcontext(struct pt_regs *regs) ...@@ -725,7 +725,7 @@ asmlinkage int irix_getcontext(struct pt_regs *regs)
__put_user(regs->cp0_epc, &ctx->regs[35]); __put_user(regs->cp0_epc, &ctx->regs[35]);
flags = 0x0f; flags = 0x0f;
if(!current->used_math) { if(!used_math()) {
flags &= ~(0x08); flags &= ~(0x08);
} else { } else {
/* XXX wheee... */ /* XXX wheee... */
......
...@@ -76,7 +76,7 @@ void start_thread(struct pt_regs * regs, unsigned long pc, unsigned long sp) ...@@ -76,7 +76,7 @@ void start_thread(struct pt_regs * regs, unsigned long pc, unsigned long sp)
#endif #endif
status |= KU_USER; status |= KU_USER;
regs->cp0_status = status; regs->cp0_status = status;
current->used_math = 0; clear_used_math();
lose_fpu(); lose_fpu();
regs->cp0_epc = pc; regs->cp0_epc = pc;
regs->regs[29] = sp; regs->regs[29] = sp;
......
...@@ -119,7 +119,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) ...@@ -119,7 +119,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
tmp = regs->regs[addr]; tmp = regs->regs[addr];
break; break;
case FPR_BASE ... FPR_BASE + 31: case FPR_BASE ... FPR_BASE + 31:
if (child->used_math) { if (tsk_used_math(child)) {
fpureg_t *fregs = get_fpu_regs(child); fpureg_t *fregs = get_fpu_regs(child);
#ifdef CONFIG_MIPS32 #ifdef CONFIG_MIPS32
...@@ -205,7 +205,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) ...@@ -205,7 +205,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
case FPR_BASE ... FPR_BASE + 31: { case FPR_BASE ... FPR_BASE + 31: {
fpureg_t *fregs = get_fpu_regs(child); fpureg_t *fregs = get_fpu_regs(child);
if (!child->used_math) { if (!tsk_used_math(child)) {
/* FP not yet used */ /* FP not yet used */
memset(&child->thread.fpu.hard, ~0, memset(&child->thread.fpu.hard, ~0,
sizeof(child->thread.fpu.hard)); sizeof(child->thread.fpu.hard));
......
...@@ -112,7 +112,7 @@ asmlinkage int sys32_ptrace(int request, int pid, int addr, int data) ...@@ -112,7 +112,7 @@ asmlinkage int sys32_ptrace(int request, int pid, int addr, int data)
tmp = regs->regs[addr]; tmp = regs->regs[addr];
break; break;
case FPR_BASE ... FPR_BASE + 31: case FPR_BASE ... FPR_BASE + 31:
if (child->used_math) { if (tsk_used_math(child)) {
fpureg_t *fregs = get_fpu_regs(child); fpureg_t *fregs = get_fpu_regs(child);
/* /*
...@@ -193,7 +193,7 @@ asmlinkage int sys32_ptrace(int request, int pid, int addr, int data) ...@@ -193,7 +193,7 @@ asmlinkage int sys32_ptrace(int request, int pid, int addr, int data)
case FPR_BASE ... FPR_BASE + 31: { case FPR_BASE ... FPR_BASE + 31: {
fpureg_t *fregs = get_fpu_regs(child); fpureg_t *fregs = get_fpu_regs(child);
if (!child->used_math) { if (!tsk_used_math(child)) {
/* FP not yet used */ /* FP not yet used */
memset(&child->thread.fpu.hard, ~0, memset(&child->thread.fpu.hard, ~0,
sizeof(child->thread.fpu.hard)); sizeof(child->thread.fpu.hard));
......
...@@ -154,6 +154,7 @@ asmlinkage int sys_sigaltstack(nabi_no_regargs struct pt_regs regs) ...@@ -154,6 +154,7 @@ asmlinkage int sys_sigaltstack(nabi_no_regargs struct pt_regs regs)
asmlinkage int restore_sigcontext(struct pt_regs *regs, struct sigcontext *sc) asmlinkage int restore_sigcontext(struct pt_regs *regs, struct sigcontext *sc)
{ {
int err = 0; int err = 0;
unsigned int used_math;
/* Always make any pending restarted system calls return -EINTR */ /* Always make any pending restarted system calls return -EINTR */
current_thread_info()->restart_block.fn = do_no_restart_syscall; current_thread_info()->restart_block.fn = do_no_restart_syscall;
...@@ -178,11 +179,12 @@ asmlinkage int restore_sigcontext(struct pt_regs *regs, struct sigcontext *sc) ...@@ -178,11 +179,12 @@ asmlinkage int restore_sigcontext(struct pt_regs *regs, struct sigcontext *sc)
restore_gp_reg(31); restore_gp_reg(31);
#undef restore_gp_reg #undef restore_gp_reg
err |= __get_user(current->used_math, &sc->sc_used_math); err |= __get_user(used_math, &sc->sc_used_math);
conditional_used_math(used_math);
preempt_disable(); preempt_disable();
if (current->used_math) { if (used_math()) {
/* restore fpu context if we have used it before */ /* restore fpu context if we have used it before */
own_fpu(); own_fpu();
err |= restore_fp_context(sc); err |= restore_fp_context(sc);
...@@ -323,9 +325,9 @@ inline int setup_sigcontext(struct pt_regs *regs, struct sigcontext *sc) ...@@ -323,9 +325,9 @@ inline int setup_sigcontext(struct pt_regs *regs, struct sigcontext *sc)
err |= __put_user(regs->cp0_cause, &sc->sc_cause); err |= __put_user(regs->cp0_cause, &sc->sc_cause);
err |= __put_user(regs->cp0_badvaddr, &sc->sc_badvaddr); err |= __put_user(regs->cp0_badvaddr, &sc->sc_badvaddr);
err |= __put_user(current->used_math, &sc->sc_used_math); err |= __put_user(!!used_math(), &sc->sc_used_math);
if (!current->used_math) if (!used_math())
goto out; goto out;
/* /*
......
...@@ -337,6 +337,7 @@ static asmlinkage int restore_sigcontext32(struct pt_regs *regs, ...@@ -337,6 +337,7 @@ static asmlinkage int restore_sigcontext32(struct pt_regs *regs,
struct sigcontext32 *sc) struct sigcontext32 *sc)
{ {
int err = 0; int err = 0;
__u32 used_math;
/* Always make any pending restarted system calls return -EINTR */ /* Always make any pending restarted system calls return -EINTR */
current_thread_info()->restart_block.fn = do_no_restart_syscall; current_thread_info()->restart_block.fn = do_no_restart_syscall;
...@@ -361,11 +362,12 @@ static asmlinkage int restore_sigcontext32(struct pt_regs *regs, ...@@ -361,11 +362,12 @@ static asmlinkage int restore_sigcontext32(struct pt_regs *regs,
restore_gp_reg(31); restore_gp_reg(31);
#undef restore_gp_reg #undef restore_gp_reg
err |= __get_user(current->used_math, &sc->sc_used_math); err |= __get_user(used_math, &sc->sc_used_math);
conditional_used_math(used_math);
preempt_disable(); preempt_disable();
if (current->used_math) { if (used_math()) {
/* restore fpu context if we have used it before */ /* restore fpu context if we have used it before */
own_fpu(); own_fpu();
err |= restore_fp_context32(sc); err |= restore_fp_context32(sc);
...@@ -552,9 +554,9 @@ static inline int setup_sigcontext32(struct pt_regs *regs, ...@@ -552,9 +554,9 @@ static inline int setup_sigcontext32(struct pt_regs *regs,
err |= __put_user(regs->cp0_cause, &sc->sc_cause); err |= __put_user(regs->cp0_cause, &sc->sc_cause);
err |= __put_user(regs->cp0_badvaddr, &sc->sc_badvaddr); err |= __put_user(regs->cp0_badvaddr, &sc->sc_badvaddr);
err |= __put_user(current->used_math, &sc->sc_used_math); err |= __put_user(!!used_math(), &sc->sc_used_math);
if (!current->used_math) if (!used_math())
goto out; goto out;
/* /*
......
...@@ -655,11 +655,11 @@ asmlinkage void do_cpu(struct pt_regs *regs) ...@@ -655,11 +655,11 @@ asmlinkage void do_cpu(struct pt_regs *regs)
preempt_disable(); preempt_disable();
own_fpu(); own_fpu();
if (current->used_math) { /* Using the FPU again. */ if (used_math()) { /* Using the FPU again. */
restore_fp(current); restore_fp(current);
} else { /* First time FPU user. */ } else { /* First time FPU user. */
init_fpu(); init_fpu();
current->used_math = 1; set_used_math();
} }
if (!cpu_has_fpu) { if (!cpu_has_fpu) {
......
...@@ -215,8 +215,7 @@ void exit_thread(void) ...@@ -215,8 +215,7 @@ void exit_thread(void)
void flush_thread(void) void flush_thread(void)
{ {
clear_used_math();
current->used_math = 0;
clear_tsk_thread_flag(current, TIF_USEDFPU); clear_tsk_thread_flag(current, TIF_USEDFPU);
} }
......
...@@ -96,7 +96,7 @@ void __devinit cpu_init (void) ...@@ -96,7 +96,7 @@ void __devinit cpu_init (void)
* Force FPU initialization: * Force FPU initialization:
*/ */
clear_thread_flag(TIF_USEDFPU); clear_thread_flag(TIF_USEDFPU);
current->used_math = 0; clear_used_math();
atomic_inc(&init_mm.mm_count); atomic_inc(&init_mm.mm_count);
current->active_mm = &init_mm; current->active_mm = &init_mm;
......
...@@ -194,7 +194,7 @@ asmlinkage void __init sh_cpu_init(void) ...@@ -194,7 +194,7 @@ asmlinkage void __init sh_cpu_init(void)
/* FPU initialization */ /* FPU initialization */
if ((cpu_data->flags & CPU_HAS_FPU)) { if ((cpu_data->flags & CPU_HAS_FPU)) {
clear_thread_flag(TIF_USEDFPU); clear_thread_flag(TIF_USEDFPU);
current->used_math = 0; clear_used_math();
} }
#ifdef CONFIG_SH_DSP #ifdef CONFIG_SH_DSP
......
...@@ -323,13 +323,13 @@ do_fpu_state_restore(unsigned long r4, unsigned long r5, unsigned long r6, ...@@ -323,13 +323,13 @@ do_fpu_state_restore(unsigned long r4, unsigned long r5, unsigned long r6,
return; return;
} }
if (tsk->used_math) { if (used_math()) {
/* Using the FPU again. */ /* Using the FPU again. */
restore_fpu(tsk); restore_fpu(tsk);
} else { } else {
/* First time FPU user. */ /* First time FPU user. */
fpu_init(); fpu_init();
tsk->used_math = 1; set_used_math();
} }
set_tsk_thread_flag(tsk, TIF_USEDFPU); set_tsk_thread_flag(tsk, TIF_USEDFPU);
} }
...@@ -208,7 +208,7 @@ void flush_thread(void) ...@@ -208,7 +208,7 @@ void flush_thread(void)
/* Forget lazy FPU state */ /* Forget lazy FPU state */
clear_fpu(tsk, regs); clear_fpu(tsk, regs);
tsk->used_math = 0; clear_used_math();
#endif #endif
} }
...@@ -225,7 +225,7 @@ int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu) ...@@ -225,7 +225,7 @@ int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu)
#if defined(CONFIG_SH_FPU) #if defined(CONFIG_SH_FPU)
struct task_struct *tsk = current; struct task_struct *tsk = current;
fpvalid = tsk->used_math; fpvalid = !!tsk_used_math(tsk);
if (fpvalid) { if (fpvalid) {
unlazy_fpu(tsk, regs); unlazy_fpu(tsk, regs);
memcpy(fpu, &tsk->thread.fpu.hard, sizeof(*fpu)); memcpy(fpu, &tsk->thread.fpu.hard, sizeof(*fpu));
...@@ -260,7 +260,7 @@ dump_task_fpu (struct task_struct *tsk, elf_fpregset_t *fpu) ...@@ -260,7 +260,7 @@ dump_task_fpu (struct task_struct *tsk, elf_fpregset_t *fpu)
int fpvalid = 0; int fpvalid = 0;
#if defined(CONFIG_SH_FPU) #if defined(CONFIG_SH_FPU)
fpvalid = tsk->used_math; fpvalid = !!tsk_used_math(tsk);
if (fpvalid) { if (fpvalid) {
struct pt_regs *regs = (struct pt_regs *) struct pt_regs *regs = (struct pt_regs *)
((unsigned long)tsk->thread_info ((unsigned long)tsk->thread_info
...@@ -286,7 +286,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp, ...@@ -286,7 +286,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
unlazy_fpu(tsk, regs); unlazy_fpu(tsk, regs);
p->thread.fpu = tsk->thread.fpu; p->thread.fpu = tsk->thread.fpu;
p->used_math = tsk->used_math; copy_to_stopped_child_used_math(p);
#endif #endif
childregs = ((struct pt_regs *) childregs = ((struct pt_regs *)
......
...@@ -150,7 +150,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) ...@@ -150,7 +150,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
tmp = get_stack_long(child, addr); tmp = get_stack_long(child, addr);
else if (addr >= (long) &dummy->fpu && else if (addr >= (long) &dummy->fpu &&
addr < (long) &dummy->u_fpvalid) { addr < (long) &dummy->u_fpvalid) {
if (!child->used_math) { if (!tsk_used_math(child)) {
if (addr == (long)&dummy->fpu.fpscr) if (addr == (long)&dummy->fpu.fpscr)
tmp = FPSCR_INIT; tmp = FPSCR_INIT;
else else
...@@ -159,7 +159,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) ...@@ -159,7 +159,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
tmp = ((long *)&child->thread.fpu) tmp = ((long *)&child->thread.fpu)
[(addr - (long)&dummy->fpu) >> 2]; [(addr - (long)&dummy->fpu) >> 2];
} else if (addr == (long) &dummy->u_fpvalid) } else if (addr == (long) &dummy->u_fpvalid)
tmp = child->used_math; tmp = !!tsk_used_math(child);
else else
tmp = 0; tmp = 0;
ret = put_user(tmp, (unsigned long *)data); ret = put_user(tmp, (unsigned long *)data);
...@@ -185,12 +185,12 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) ...@@ -185,12 +185,12 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
ret = put_stack_long(child, addr, data); ret = put_stack_long(child, addr, data);
else if (addr >= (long) &dummy->fpu && else if (addr >= (long) &dummy->fpu &&
addr < (long) &dummy->u_fpvalid) { addr < (long) &dummy->u_fpvalid) {
child->used_math = 1; set_stopped_child_used_math(child);
((long *)&child->thread.fpu) ((long *)&child->thread.fpu)
[(addr - (long)&dummy->fpu) >> 2] = data; [(addr - (long)&dummy->fpu) >> 2] = data;
ret = 0; ret = 0;
} else if (addr == (long) &dummy->u_fpvalid) { } else if (addr == (long) &dummy->u_fpvalid) {
child->used_math = data?1:0; conditional_stopped_child_used_math(data, child);
ret = 0; ret = 0;
} }
break; break;
......
...@@ -162,7 +162,7 @@ static inline int restore_sigcontext_fpu(struct sigcontext __user *sc) ...@@ -162,7 +162,7 @@ static inline int restore_sigcontext_fpu(struct sigcontext __user *sc)
if (!(cpu_data->flags & CPU_HAS_FPU)) if (!(cpu_data->flags & CPU_HAS_FPU))
return 0; return 0;
tsk->used_math = 1; set_used_math();
return __copy_from_user(&tsk->thread.fpu.hard, &sc->sc_fpregs[0], return __copy_from_user(&tsk->thread.fpu.hard, &sc->sc_fpregs[0],
sizeof(long)*(16*2+2)); sizeof(long)*(16*2+2));
} }
...@@ -175,7 +175,7 @@ static inline int save_sigcontext_fpu(struct sigcontext __user *sc, ...@@ -175,7 +175,7 @@ static inline int save_sigcontext_fpu(struct sigcontext __user *sc,
if (!(cpu_data->flags & CPU_HAS_FPU)) if (!(cpu_data->flags & CPU_HAS_FPU))
return 0; return 0;
if (!tsk->used_math) { if (!used_math()) {
__put_user(0, &sc->sc_ownedfp); __put_user(0, &sc->sc_ownedfp);
return 0; return 0;
} }
...@@ -185,7 +185,7 @@ static inline int save_sigcontext_fpu(struct sigcontext __user *sc, ...@@ -185,7 +185,7 @@ static inline int save_sigcontext_fpu(struct sigcontext __user *sc,
/* This will cause a "finit" to be triggered by the next /* This will cause a "finit" to be triggered by the next
attempted FPU operation by the 'current' process. attempted FPU operation by the 'current' process.
*/ */
tsk->used_math = 0; clear_used_math();
unlazy_fpu(tsk, regs); unlazy_fpu(tsk, regs);
return __copy_to_user(&sc->sc_fpregs[0], &tsk->thread.fpu.hard, return __copy_to_user(&sc->sc_fpregs[0], &tsk->thread.fpu.hard,
...@@ -219,7 +219,7 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, int *r0_p ...@@ -219,7 +219,7 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, int *r0_p
regs->sr |= SR_FD; /* Release FPU */ regs->sr |= SR_FD; /* Release FPU */
clear_fpu(tsk, regs); clear_fpu(tsk, regs);
tsk->used_math = 0; clear_used_math();
__get_user (owned_fp, &sc->sc_ownedfp); __get_user (owned_fp, &sc->sc_ownedfp);
if (owned_fp) if (owned_fp)
err |= restore_sigcontext_fpu(sc); err |= restore_sigcontext_fpu(sc);
......
...@@ -158,12 +158,12 @@ do_fpu_state_restore(unsigned long ex, struct pt_regs *regs) ...@@ -158,12 +158,12 @@ do_fpu_state_restore(unsigned long ex, struct pt_regs *regs)
fpsave(&last_task_used_math->thread.fpu.hard); fpsave(&last_task_used_math->thread.fpu.hard);
} }
last_task_used_math = current; last_task_used_math = current;
if (current->used_math) { if (used_math()) {
fpload(&current->thread.fpu.hard); fpload(&current->thread.fpu.hard);
} else { } else {
/* First time FPU user. */ /* First time FPU user. */
fpload(&init_fpuregs.hard); fpload(&init_fpuregs.hard);
current->used_math = 1; set_used_math();
} }
release_fpu(); release_fpu();
} }
......
...@@ -688,7 +688,7 @@ void flush_thread(void) ...@@ -688,7 +688,7 @@ void flush_thread(void)
last_task_used_math = NULL; last_task_used_math = NULL;
} }
/* Force FPU state to be reinitialised after exec */ /* Force FPU state to be reinitialised after exec */
current->used_math = 0; clear_used_math();
#endif #endif
/* if we are a kernel thread, about to change to user thread, /* if we are a kernel thread, about to change to user thread,
...@@ -713,7 +713,7 @@ int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu) ...@@ -713,7 +713,7 @@ int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu)
int fpvalid; int fpvalid;
struct task_struct *tsk = current; struct task_struct *tsk = current;
fpvalid = tsk->used_math; fpvalid = !!tsk_used_math(tsk);
if (fpvalid) { if (fpvalid) {
if (current == last_task_used_math) { if (current == last_task_used_math) {
grab_fpu(); grab_fpu();
......
...@@ -63,7 +63,7 @@ get_fpu_long(struct task_struct *task, unsigned long addr) ...@@ -63,7 +63,7 @@ get_fpu_long(struct task_struct *task, unsigned long addr)
struct pt_regs *regs; struct pt_regs *regs;
regs = (struct pt_regs*)((unsigned char *)task + THREAD_SIZE) - 1; regs = (struct pt_regs*)((unsigned char *)task + THREAD_SIZE) - 1;
if (!task->used_math) { if (!tsk_used_math(task)) {
if (addr == offsetof(struct user_fpu_struct, fpscr)) { if (addr == offsetof(struct user_fpu_struct, fpscr)) {
tmp = FPSCR_INIT; tmp = FPSCR_INIT;
} else { } else {
...@@ -105,9 +105,9 @@ put_fpu_long(struct task_struct *task, unsigned long addr, unsigned long data) ...@@ -105,9 +105,9 @@ put_fpu_long(struct task_struct *task, unsigned long addr, unsigned long data)
regs = (struct pt_regs*)((unsigned char *)task + THREAD_SIZE) - 1; regs = (struct pt_regs*)((unsigned char *)task + THREAD_SIZE) - 1;
if (!task->used_math) { if (!tsk_used_math(task)) {
fpinit(&task->thread.fpu.hard); fpinit(&task->thread.fpu.hard);
task->used_math = 1; set_stopped_child_used_math(task);
} else if (last_task_used_math == task) { } else if (last_task_used_math == task) {
grab_fpu(); grab_fpu();
fpsave(&task->thread.fpu.hard); fpsave(&task->thread.fpu.hard);
...@@ -187,7 +187,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) ...@@ -187,7 +187,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
(addr < offsetof(struct user, u_fpvalid))) { (addr < offsetof(struct user, u_fpvalid))) {
tmp = get_fpu_long(child, addr - offsetof(struct user, fpu)); tmp = get_fpu_long(child, addr - offsetof(struct user, fpu));
} else if (addr == offsetof(struct user, u_fpvalid)) { } else if (addr == offsetof(struct user, u_fpvalid)) {
tmp = child->used_math; tmp = !!tsk_used_math(child);
} else { } else {
break; break;
} }
......
...@@ -186,7 +186,7 @@ restore_sigcontext_fpu(struct pt_regs *regs, struct sigcontext __user *sc) ...@@ -186,7 +186,7 @@ restore_sigcontext_fpu(struct pt_regs *regs, struct sigcontext __user *sc)
int fpvalid; int fpvalid;
err |= __get_user (fpvalid, &sc->sc_fpvalid); err |= __get_user (fpvalid, &sc->sc_fpvalid);
current->used_math = fpvalid; conditional_used_math(fpvalid);
if (! fpvalid) if (! fpvalid)
return err; return err;
...@@ -207,7 +207,7 @@ setup_sigcontext_fpu(struct pt_regs *regs, struct sigcontext __user *sc) ...@@ -207,7 +207,7 @@ setup_sigcontext_fpu(struct pt_regs *regs, struct sigcontext __user *sc)
int err = 0; int err = 0;
int fpvalid; int fpvalid;
fpvalid = current->used_math; fpvalid = !!used_math();
err |= __put_user(fpvalid, &sc->sc_fpvalid); err |= __put_user(fpvalid, &sc->sc_fpvalid);
if (! fpvalid) if (! fpvalid)
return err; return err;
...@@ -222,7 +222,7 @@ setup_sigcontext_fpu(struct pt_regs *regs, struct sigcontext __user *sc) ...@@ -222,7 +222,7 @@ setup_sigcontext_fpu(struct pt_regs *regs, struct sigcontext __user *sc)
err |= __copy_to_user(&sc->sc_fpregs[0], &current->thread.fpu.hard, err |= __copy_to_user(&sc->sc_fpregs[0], &current->thread.fpu.hard,
(sizeof(long long) * 32) + (sizeof(int) * 1)); (sizeof(long long) * 32) + (sizeof(int) * 1));
current->used_math = 0; clear_used_math();
return err; return err;
} }
......
...@@ -599,7 +599,7 @@ void dump_thread(struct pt_regs * regs, struct user * dump) ...@@ -599,7 +599,7 @@ void dump_thread(struct pt_regs * regs, struct user * dump)
*/ */
int dump_fpu (struct pt_regs * regs, elf_fpregset_t * fpregs) int dump_fpu (struct pt_regs * regs, elf_fpregset_t * fpregs)
{ {
if (current->used_math == 0) { if (used_math()) {
memset(fpregs, 0, sizeof(*fpregs)); memset(fpregs, 0, sizeof(*fpregs));
fpregs->pr_q_entrysize = 8; fpregs->pr_q_entrysize = 8;
return 1; return 1;
......
...@@ -202,7 +202,7 @@ restore_fpu_state(struct pt_regs *regs, __siginfo_fpu_t __user *fpu) ...@@ -202,7 +202,7 @@ restore_fpu_state(struct pt_regs *regs, __siginfo_fpu_t __user *fpu)
regs->psr &= ~PSR_EF; regs->psr &= ~PSR_EF;
} }
#endif #endif
current->used_math = 1; set_used_math();
clear_tsk_thread_flag(current, TIF_USEDFPU); clear_tsk_thread_flag(current, TIF_USEDFPU);
if (verify_area(VERIFY_READ, fpu, sizeof(*fpu))) if (verify_area(VERIFY_READ, fpu, sizeof(*fpu)))
...@@ -584,7 +584,7 @@ save_fpu_state(struct pt_regs *regs, __siginfo_fpu_t __user *fpu) ...@@ -584,7 +584,7 @@ save_fpu_state(struct pt_regs *regs, __siginfo_fpu_t __user *fpu)
&current->thread.fpqueue[0], &current->thread.fpqueue[0],
((sizeof(unsigned long) + ((sizeof(unsigned long) +
(sizeof(unsigned long *)))*16)); (sizeof(unsigned long *)))*16));
current->used_math = 0; clear_used_math();
return err; return err;
} }
...@@ -599,7 +599,7 @@ new_setup_frame(struct k_sigaction *ka, struct pt_regs *regs, ...@@ -599,7 +599,7 @@ new_setup_frame(struct k_sigaction *ka, struct pt_regs *regs,
synchronize_user_stack(); synchronize_user_stack();
sigframe_size = NF_ALIGNEDSZ; sigframe_size = NF_ALIGNEDSZ;
if (!current->used_math) if (!used_math())
sigframe_size -= sizeof(__siginfo_fpu_t); sigframe_size -= sizeof(__siginfo_fpu_t);
sf = (struct new_signal_frame __user *) sf = (struct new_signal_frame __user *)
...@@ -616,7 +616,7 @@ new_setup_frame(struct k_sigaction *ka, struct pt_regs *regs, ...@@ -616,7 +616,7 @@ new_setup_frame(struct k_sigaction *ka, struct pt_regs *regs,
err |= __put_user(0, &sf->extra_size); err |= __put_user(0, &sf->extra_size);
if (current->used_math) { if (used_math()) {
err |= save_fpu_state(regs, &sf->fpu_state); err |= save_fpu_state(regs, &sf->fpu_state);
err |= __put_user(&sf->fpu_state, &sf->fpu_save); err |= __put_user(&sf->fpu_state, &sf->fpu_save);
} else { } else {
...@@ -677,7 +677,7 @@ new_setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs, ...@@ -677,7 +677,7 @@ new_setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs,
synchronize_user_stack(); synchronize_user_stack();
sigframe_size = RT_ALIGNEDSZ; sigframe_size = RT_ALIGNEDSZ;
if (!current->used_math) if (!used_math())
sigframe_size -= sizeof(__siginfo_fpu_t); sigframe_size -= sizeof(__siginfo_fpu_t);
sf = (struct rt_signal_frame __user *) sf = (struct rt_signal_frame __user *)
get_sigframe(&ka->sa, regs, sigframe_size); get_sigframe(&ka->sa, regs, sigframe_size);
...@@ -690,7 +690,7 @@ new_setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs, ...@@ -690,7 +690,7 @@ new_setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs,
err |= __put_user(regs->npc, &sf->regs.npc); err |= __put_user(regs->npc, &sf->regs.npc);
err |= __put_user(regs->y, &sf->regs.y); err |= __put_user(regs->y, &sf->regs.y);
psr = regs->psr; psr = regs->psr;
if (current->used_math) if (used_math())
psr |= PSR_EF; psr |= PSR_EF;
err |= __put_user(psr, &sf->regs.psr); err |= __put_user(psr, &sf->regs.psr);
err |= __copy_to_user(&sf->regs.u_regs, regs->u_regs, sizeof(regs->u_regs)); err |= __copy_to_user(&sf->regs.u_regs, regs->u_regs, sizeof(regs->u_regs));
......
...@@ -246,17 +246,17 @@ void do_fpd_trap(struct pt_regs *regs, unsigned long pc, unsigned long npc, ...@@ -246,17 +246,17 @@ void do_fpd_trap(struct pt_regs *regs, unsigned long pc, unsigned long npc,
&fptask->thread.fpqueue[0], &fptask->thread.fpqdepth); &fptask->thread.fpqueue[0], &fptask->thread.fpqdepth);
} }
last_task_used_math = current; last_task_used_math = current;
if(current->used_math) { if(used_math()) {
fpload(&current->thread.float_regs[0], &current->thread.fsr); fpload(&current->thread.float_regs[0], &current->thread.fsr);
} else { } else {
/* Set initial sane state. */ /* Set initial sane state. */
fpload(&init_fregs[0], &init_fsr); fpload(&init_fregs[0], &init_fsr);
current->used_math = 1; set_used_math();
} }
#else #else
if(!current->used_math) { if(!used_math()) {
fpload(&init_fregs[0], &init_fsr); fpload(&init_fregs[0], &init_fsr);
current->used_math = 1; set_used_math();
} else { } else {
fpload(&current->thread.float_regs[0], &current->thread.fsr); fpload(&current->thread.float_regs[0], &current->thread.fsr);
} }
......
...@@ -157,7 +157,7 @@ int restore_i387_ia32(struct task_struct *tsk, struct _fpstate_ia32 __user *buf, ...@@ -157,7 +157,7 @@ int restore_i387_ia32(struct task_struct *tsk, struct _fpstate_ia32 __user *buf,
sizeof(struct i387_fxsave_struct))) sizeof(struct i387_fxsave_struct)))
return -1; return -1;
tsk->thread.i387.fxsave.mxcsr &= mxcsr_feature_mask; tsk->thread.i387.fxsave.mxcsr &= mxcsr_feature_mask;
tsk->used_math = 1; set_stopped_child_used_math(tsk);
} }
return convert_fxsr_from_user(&tsk->thread.i387.fxsave, buf); return convert_fxsr_from_user(&tsk->thread.i387.fxsave, buf);
} }
......
...@@ -214,7 +214,7 @@ elf_core_copy_task_fpregs(struct task_struct *tsk, struct pt_regs *regs, elf_fpr ...@@ -214,7 +214,7 @@ elf_core_copy_task_fpregs(struct task_struct *tsk, struct pt_regs *regs, elf_fpr
struct _fpstate_ia32 *fpstate = (void*)fpu; struct _fpstate_ia32 *fpstate = (void*)fpu;
mm_segment_t oldfs = get_fs(); mm_segment_t oldfs = get_fs();
if (!tsk->used_math) if (!tsk_used_math(tsk))
return 0; return 0;
if (!regs) if (!regs)
regs = (struct pt_regs *)tsk->thread.rsp0; regs = (struct pt_regs *)tsk->thread.rsp0;
...@@ -235,7 +235,7 @@ static inline int ...@@ -235,7 +235,7 @@ static inline int
elf_core_copy_task_xfpregs(struct task_struct *t, elf_fpxregset_t *xfpu) elf_core_copy_task_xfpregs(struct task_struct *t, elf_fpxregset_t *xfpu)
{ {
struct pt_regs *regs = ((struct pt_regs *)(t->thread.rsp0))-1; struct pt_regs *regs = ((struct pt_regs *)(t->thread.rsp0))-1;
if (!t->used_math) if (!tsk_used_math(t))
return 0; return 0;
if (t == current) if (t == current)
unlazy_fpu(t); unlazy_fpu(t);
......
...@@ -263,9 +263,9 @@ ia32_restore_sigcontext(struct pt_regs *regs, struct sigcontext_ia32 __user *sc, ...@@ -263,9 +263,9 @@ ia32_restore_sigcontext(struct pt_regs *regs, struct sigcontext_ia32 __user *sc,
err |= restore_i387_ia32(current, buf, 0); err |= restore_i387_ia32(current, buf, 0);
} else { } else {
struct task_struct *me = current; struct task_struct *me = current;
if (me->used_math) { if (used_math()) {
clear_fpu(me); clear_fpu(me);
me->used_math = 0; clear_used_math();
} }
} }
} }
...@@ -389,7 +389,7 @@ ia32_setup_sigcontext(struct sigcontext_ia32 __user *sc, struct _fpstate_ia32 __ ...@@ -389,7 +389,7 @@ ia32_setup_sigcontext(struct sigcontext_ia32 __user *sc, struct _fpstate_ia32 __
if (tmp < 0) if (tmp < 0)
err = -EFAULT; err = -EFAULT;
else { else {
current->used_math = 0; clear_used_math();
stts(); stts();
err |= __put_user((u32)(u64)(tmp ? fpstate : NULL), &sc->fpstate); err |= __put_user((u32)(u64)(tmp ? fpstate : NULL), &sc->fpstate);
} }
......
...@@ -358,7 +358,7 @@ asmlinkage long sys32_ptrace(long request, u32 pid, u32 addr, u32 data) ...@@ -358,7 +358,7 @@ asmlinkage long sys32_ptrace(long request, u32 pid, u32 addr, u32 data)
break; break;
/* no checking to be bug-to-bug compatible with i386 */ /* no checking to be bug-to-bug compatible with i386 */
__copy_from_user(&child->thread.i387.fxsave, u, sizeof(*u)); __copy_from_user(&child->thread.i387.fxsave, u, sizeof(*u));
child->used_math = 1; set_stopped_child_used_math(child);
child->thread.i387.fxsave.mxcsr &= mxcsr_feature_mask; child->thread.i387.fxsave.mxcsr &= mxcsr_feature_mask;
ret = 0; ret = 0;
break; break;
......
...@@ -57,12 +57,12 @@ void __init fpu_init(void) ...@@ -57,12 +57,12 @@ void __init fpu_init(void)
mxcsr_feature_mask_init(); mxcsr_feature_mask_init();
/* clean state in init */ /* clean state in init */
current_thread_info()->status = 0; current_thread_info()->status = 0;
current->used_math = 0; clear_used_math();
} }
void init_fpu(struct task_struct *child) void init_fpu(struct task_struct *child)
{ {
if (child->used_math) { if (tsk_used_math(child)) {
if (child == current) if (child == current)
unlazy_fpu(child); unlazy_fpu(child);
return; return;
...@@ -70,7 +70,8 @@ void init_fpu(struct task_struct *child) ...@@ -70,7 +70,8 @@ void init_fpu(struct task_struct *child)
memset(&child->thread.i387.fxsave, 0, sizeof(struct i387_fxsave_struct)); memset(&child->thread.i387.fxsave, 0, sizeof(struct i387_fxsave_struct));
child->thread.i387.fxsave.cwd = 0x37f; child->thread.i387.fxsave.cwd = 0x37f;
child->thread.i387.fxsave.mxcsr = 0x1f80; child->thread.i387.fxsave.mxcsr = 0x1f80;
child->used_math = 1; /* only the device not available exception or ptrace can call init_fpu */
set_stopped_child_used_math(child);
} }
/* /*
...@@ -91,9 +92,9 @@ int save_i387(struct _fpstate __user *buf) ...@@ -91,9 +92,9 @@ int save_i387(struct _fpstate __user *buf)
if ((unsigned long)buf % 16) if ((unsigned long)buf % 16)
printk("save_i387: bad fpstate %p\n",buf); printk("save_i387: bad fpstate %p\n",buf);
if (!tsk->used_math) if (!used_math())
return 0; return 0;
tsk->used_math = 0; /* trigger finit */ clear_used_math(); /* trigger finit */
if (tsk->thread_info->status & TS_USEDFPU) { if (tsk->thread_info->status & TS_USEDFPU) {
err = save_i387_checking((struct i387_fxsave_struct __user *)buf); err = save_i387_checking((struct i387_fxsave_struct __user *)buf);
if (err) return err; if (err) return err;
...@@ -133,7 +134,7 @@ int dump_fpu( struct pt_regs *regs, struct user_i387_struct *fpu ) ...@@ -133,7 +134,7 @@ int dump_fpu( struct pt_regs *regs, struct user_i387_struct *fpu )
{ {
struct task_struct *tsk = current; struct task_struct *tsk = current;
if (!tsk->used_math) if (!used_math())
return 0; return 0;
unlazy_fpu(tsk); unlazy_fpu(tsk);
...@@ -143,7 +144,7 @@ int dump_fpu( struct pt_regs *regs, struct user_i387_struct *fpu ) ...@@ -143,7 +144,7 @@ int dump_fpu( struct pt_regs *regs, struct user_i387_struct *fpu )
int dump_task_fpu(struct task_struct *tsk, struct user_i387_struct *fpu) int dump_task_fpu(struct task_struct *tsk, struct user_i387_struct *fpu)
{ {
int fpvalid = tsk->used_math; int fpvalid = !!tsk_used_math(tsk);
if (fpvalid) { if (fpvalid) {
if (tsk == current) if (tsk == current)
......
...@@ -314,7 +314,7 @@ void flush_thread(void) ...@@ -314,7 +314,7 @@ void flush_thread(void)
* Forget coprocessor state.. * Forget coprocessor state..
*/ */
clear_fpu(tsk); clear_fpu(tsk);
tsk->used_math = 0; clear_used_math();
} }
void release_thread(struct task_struct *dead_task) void release_thread(struct task_struct *dead_task)
......
...@@ -480,7 +480,7 @@ asmlinkage long sys_ptrace(long request, long pid, unsigned long addr, long data ...@@ -480,7 +480,7 @@ asmlinkage long sys_ptrace(long request, long pid, unsigned long addr, long data
ret = -EIO; ret = -EIO;
break; break;
} }
child->used_math = 1; set_stopped_child_used_math(child);
ret = set_fpregs(child, (struct user_i387_struct __user *)data); ret = set_fpregs(child, (struct user_i387_struct __user *)data);
break; break;
} }
......
...@@ -126,9 +126,9 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, unsigned ...@@ -126,9 +126,9 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, unsigned
err |= restore_i387(buf); err |= restore_i387(buf);
} else { } else {
struct task_struct *me = current; struct task_struct *me = current;
if (me->used_math) { if (used_math()) {
clear_fpu(me); clear_fpu(me);
me->used_math = 0; clear_used_math();
} }
} }
} }
...@@ -251,7 +251,7 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -251,7 +251,7 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
int err = 0; int err = 0;
struct task_struct *me = current; struct task_struct *me = current;
if (me->used_math) { if (used_math()) {
fp = get_stack(ka, regs, sizeof(struct _fpstate)); fp = get_stack(ka, regs, sizeof(struct _fpstate));
frame = (void __user *)round_down((unsigned long)fp - sizeof(struct rt_sigframe), 16) - 8; frame = (void __user *)round_down((unsigned long)fp - sizeof(struct rt_sigframe), 16) - 8;
......
...@@ -892,7 +892,7 @@ asmlinkage void math_state_restore(void) ...@@ -892,7 +892,7 @@ asmlinkage void math_state_restore(void)
struct task_struct *me = current; struct task_struct *me = current;
clts(); /* Allow maths ops (or we recurse) */ clts(); /* Allow maths ops (or we recurse) */
if (!me->used_math) if (!used_math())
init_fpu(me); init_fpu(me);
restore_fpu_checking(&me->thread.i387.fxsave); restore_fpu_checking(&me->thread.i387.fxsave);
me->thread_info->status |= TS_USEDFPU; me->thread_info->status |= TS_USEDFPU;
......
...@@ -7,7 +7,6 @@ ...@@ -7,7 +7,6 @@
* *
*/ */
#define TSK_USED_MATH 788 /* offsetof(struct task_struct, used_math) */
#define TSK_ACTIVE_MM 96 /* offsetof(struct task_struct, active_mm) */ #define TSK_ACTIVE_MM 96 /* offsetof(struct task_struct, active_mm) */
#define VMA_VM_MM 0 /* offsetof(struct vm_area_struct, vm_mm) */ #define VMA_VM_MM 0 /* offsetof(struct vm_area_struct, vm_mm) */
......
...@@ -25,16 +25,6 @@ extern void mxcsr_feature_mask_init(void); ...@@ -25,16 +25,6 @@ extern void mxcsr_feature_mask_init(void);
extern void init_fpu(struct task_struct *child); extern void init_fpu(struct task_struct *child);
extern int save_i387(struct _fpstate __user *buf); extern int save_i387(struct _fpstate __user *buf);
static inline int need_signal_i387(struct task_struct *me)
{
if (!me->used_math)
return 0;
me->used_math = 0;
if (me->thread_info->status & TS_USEDFPU)
return 0;
return 1;
}
/* /*
* FPU lazy state save handling... * FPU lazy state save handling...
*/ */
......
...@@ -614,19 +614,7 @@ struct task_struct { ...@@ -614,19 +614,7 @@ struct task_struct {
struct key *process_keyring; /* keyring private to this process (CLONE_THREAD) */ struct key *process_keyring; /* keyring private to this process (CLONE_THREAD) */
struct key *thread_keyring; /* keyring private to this thread */ struct key *thread_keyring; /* keyring private to this thread */
#endif #endif
/* int oomkilladj; /* OOM kill score adjustment (bit shift). */
* Must be changed atomically so it shouldn't be
* be a shareable bitflag.
*/
unsigned char used_math;
/*
* OOM kill score adjustment (bit shift).
* Cannot live together with used_math since
* used_math and oomkilladj can be changed at the
* same time, so they would race if they're in the
* same atomic block.
*/
short oomkilladj;
char comm[TASK_COMM_LEN]; char comm[TASK_COMM_LEN];
/* file system info */ /* file system info */
int link_count, total_link_count; int link_count, total_link_count;
...@@ -695,7 +683,7 @@ struct task_struct { ...@@ -695,7 +683,7 @@ struct task_struct {
#endif #endif
#ifdef CONFIG_NUMA #ifdef CONFIG_NUMA
struct mempolicy *mempolicy; struct mempolicy *mempolicy;
short il_next; /* could be shared with used_math */ short il_next;
#endif #endif
}; };
...@@ -737,7 +725,7 @@ do { if (atomic_dec_and_test(&(tsk)->usage)) __put_task_struct(tsk); } while(0) ...@@ -737,7 +725,7 @@ do { if (atomic_dec_and_test(&(tsk)->usage)) __put_task_struct(tsk); } while(0)
#define PF_SIGNALED 0x00000400 /* killed by a signal */ #define PF_SIGNALED 0x00000400 /* killed by a signal */
#define PF_MEMALLOC 0x00000800 /* Allocating memory */ #define PF_MEMALLOC 0x00000800 /* Allocating memory */
#define PF_FLUSHER 0x00001000 /* responsible for disk writeback */ #define PF_FLUSHER 0x00001000 /* responsible for disk writeback */
#define PF_USED_MATH 0x00002000 /* if unset the fpu must be initialized before use */
#define PF_FREEZE 0x00004000 /* this task is being frozen for suspend now */ #define PF_FREEZE 0x00004000 /* this task is being frozen for suspend now */
#define PF_NOFREEZE 0x00008000 /* this thread should not be frozen */ #define PF_NOFREEZE 0x00008000 /* this thread should not be frozen */
#define PF_FROZEN 0x00010000 /* frozen for system suspend */ #define PF_FROZEN 0x00010000 /* frozen for system suspend */
...@@ -748,6 +736,31 @@ do { if (atomic_dec_and_test(&(tsk)->usage)) __put_task_struct(tsk); } while(0) ...@@ -748,6 +736,31 @@ do { if (atomic_dec_and_test(&(tsk)->usage)) __put_task_struct(tsk); } while(0)
#define PF_SYNCWRITE 0x00200000 /* I am doing a sync write */ #define PF_SYNCWRITE 0x00200000 /* I am doing a sync write */
#define PF_BORROWED_MM 0x00400000 /* I am a kthread doing use_mm */ #define PF_BORROWED_MM 0x00400000 /* I am a kthread doing use_mm */
/*
* Only the _current_ task can read/write to tsk->flags, but other
* tasks can access tsk->flags in readonly mode for example
* with tsk_used_math (like during threaded core dumping).
* There is however an exception to this rule during ptrace
* or during fork: the ptracer task is allowed to write to the
* child->flags of its traced child (same goes for fork, the parent
* can write to the child->flags), because we're guaranteed the
* child is not running and in turn not changing child->flags
* at the same time the parent does it.
*/
#define clear_stopped_child_used_math(child) do { (child)->flags &= ~PF_USED_MATH; } while (0)
#define set_stopped_child_used_math(child) do { (child)->flags |= PF_USED_MATH; } while (0)
#define clear_used_math() clear_stopped_child_used_math(current)
#define set_used_math() set_stopped_child_used_math(current)
#define conditional_stopped_child_used_math(condition, child) \
do { (child)->flags &= ~PF_USED_MATH, (child)->flags |= (condition) ? PF_USED_MATH : 0; } while (0)
#define conditional_used_math(condition) \
conditional_stopped_child_used_math(condition, current)
#define copy_to_stopped_child_used_math(child) \
do { (child)->flags &= ~PF_USED_MATH, (child)->flags |= current->flags & PF_USED_MATH; } while (0)
/* NOTE: this will return 0 or PF_USED_MATH, it will never return 1 */
#define tsk_used_math(p) ((p)->flags & PF_USED_MATH)
#define used_math() tsk_used_math(current)
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
extern int set_cpus_allowed(task_t *p, cpumask_t new_mask); extern int set_cpus_allowed(task_t *p, cpumask_t new_mask);
#else #else
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment