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