1 #include <linux/sched.h> 2 #include <asm/processor.h> 3 #include <asm/fpu.h> 4 5 int init_fpu(struct task_struct *tsk) 6 { 7 if (tsk_used_math(tsk)) { 8 if ((boot_cpu_data.flags & CPU_HAS_FPU) && tsk == current) 9 unlazy_fpu(tsk, task_pt_regs(tsk)); 10 return 0; 11 } 12 13 /* 14 * Memory allocation at the first usage of the FPU and other state. 15 */ 16 if (!tsk->thread.xstate) { 17 tsk->thread.xstate = kmem_cache_alloc(task_xstate_cachep, 18 GFP_KERNEL); 19 if (!tsk->thread.xstate) 20 return -ENOMEM; 21 } 22 23 if (boot_cpu_data.flags & CPU_HAS_FPU) { 24 struct sh_fpu_hard_struct *fp = &tsk->thread.xstate->hardfpu; 25 memset(fp, 0, xstate_size); 26 fp->fpscr = FPSCR_INIT; 27 } else { 28 struct sh_fpu_soft_struct *fp = &tsk->thread.xstate->softfpu; 29 memset(fp, 0, xstate_size); 30 fp->fpscr = FPSCR_INIT; 31 } 32 33 set_stopped_child_used_math(tsk); 34 return 0; 35 } 36 37 #ifdef CONFIG_SH_FPU 38 void __fpu_state_restore(void) 39 { 40 struct task_struct *tsk = current; 41 42 restore_fpu(tsk); 43 44 task_thread_info(tsk)->status |= TS_USEDFPU; 45 tsk->fpu_counter++; 46 } 47 48 void fpu_state_restore(struct pt_regs *regs) 49 { 50 struct task_struct *tsk = current; 51 52 if (unlikely(!user_mode(regs))) { 53 printk(KERN_ERR "BUG: FPU is used in kernel mode.\n"); 54 BUG(); 55 return; 56 } 57 58 if (!tsk_used_math(tsk)) { 59 /* 60 * does a slab alloc which can sleep 61 */ 62 if (init_fpu(tsk)) { 63 /* 64 * ran out of memory! 65 */ 66 do_group_exit(SIGKILL); 67 return; 68 } 69 } 70 71 grab_fpu(regs); 72 73 __fpu_state_restore(); 74 } 75 76 BUILD_TRAP_HANDLER(fpu_state_restore) 77 { 78 TRAP_HANDLER_DECL; 79 80 fpu_state_restore(regs); 81 } 82 #endif /* CONFIG_SH_FPU */ 83