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