 f03c4866d3
			
		
	
	
	f03c4866d3
	
	
	
		
			
			Quite a bit of fallout all over the place, nothing terribly exciting. Signed-off-by: Paul Mundt <lethal@linux-sh.org>
		
			
				
	
	
		
			86 lines
		
	
	
	
		
			1.6 KiB
			
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			86 lines
		
	
	
	
		
			1.6 KiB
			
		
	
	
	
		
			C
		
	
	
	
	
	
| #include <linux/sched.h>
 | |
| #include <linux/slab.h>
 | |
| #include <asm/processor.h>
 | |
| #include <asm/fpu.h>
 | |
| #include <asm/traps.h>
 | |
| 
 | |
| int init_fpu(struct task_struct *tsk)
 | |
| {
 | |
| 	if (tsk_used_math(tsk)) {
 | |
| 		if ((boot_cpu_data.flags & CPU_HAS_FPU) && tsk == current)
 | |
| 			unlazy_fpu(tsk, task_pt_regs(tsk));
 | |
| 		return 0;
 | |
| 	}
 | |
| 
 | |
| 	/*
 | |
| 	 * Memory allocation at the first usage of the FPU and other state.
 | |
| 	 */
 | |
| 	if (!tsk->thread.xstate) {
 | |
| 		tsk->thread.xstate = kmem_cache_alloc(task_xstate_cachep,
 | |
| 						      GFP_KERNEL);
 | |
| 		if (!tsk->thread.xstate)
 | |
| 			return -ENOMEM;
 | |
| 	}
 | |
| 
 | |
| 	if (boot_cpu_data.flags & CPU_HAS_FPU) {
 | |
| 		struct sh_fpu_hard_struct *fp = &tsk->thread.xstate->hardfpu;
 | |
| 		memset(fp, 0, xstate_size);
 | |
| 		fp->fpscr = FPSCR_INIT;
 | |
| 	} else {
 | |
| 		struct sh_fpu_soft_struct *fp = &tsk->thread.xstate->softfpu;
 | |
| 		memset(fp, 0, xstate_size);
 | |
| 		fp->fpscr = FPSCR_INIT;
 | |
| 	}
 | |
| 
 | |
| 	set_stopped_child_used_math(tsk);
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| #ifdef CONFIG_SH_FPU
 | |
| void __fpu_state_restore(void)
 | |
| {
 | |
| 	struct task_struct *tsk = current;
 | |
| 
 | |
| 	restore_fpu(tsk);
 | |
| 
 | |
| 	task_thread_info(tsk)->status |= TS_USEDFPU;
 | |
| 	tsk->fpu_counter++;
 | |
| }
 | |
| 
 | |
| void fpu_state_restore(struct pt_regs *regs)
 | |
| {
 | |
| 	struct task_struct *tsk = current;
 | |
| 
 | |
| 	if (unlikely(!user_mode(regs))) {
 | |
| 		printk(KERN_ERR "BUG: FPU is used in kernel mode.\n");
 | |
| 		BUG();
 | |
| 		return;
 | |
| 	}
 | |
| 
 | |
| 	if (!tsk_used_math(tsk)) {
 | |
| 		local_irq_enable();
 | |
| 		/*
 | |
| 		 * does a slab alloc which can sleep
 | |
| 		 */
 | |
| 		if (init_fpu(tsk)) {
 | |
| 			/*
 | |
| 			 * ran out of memory!
 | |
| 			 */
 | |
| 			do_group_exit(SIGKILL);
 | |
| 			return;
 | |
| 		}
 | |
| 		local_irq_disable();
 | |
| 	}
 | |
| 
 | |
| 	grab_fpu(regs);
 | |
| 
 | |
| 	__fpu_state_restore();
 | |
| }
 | |
| 
 | |
| BUILD_TRAP_HANDLER(fpu_state_restore)
 | |
| {
 | |
| 	TRAP_HANDLER_DECL;
 | |
| 
 | |
| 	fpu_state_restore(regs);
 | |
| }
 | |
| #endif /* CONFIG_SH_FPU */
 |