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