• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/linux/linux-2.6.36/arch/sh/kernel/cpu/
1#include <linux/sched.h>
2#include <linux/slab.h>
3#include <asm/processor.h>
4#include <asm/fpu.h>
5
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
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
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
79BUILD_TRAP_HANDLER(fpu_state_restore)
80{
81	TRAP_HANDLER_DECL;
82
83	fpu_state_restore(regs);
84}
85#endif /* CONFIG_SH_FPU */
86