fpu.c 1.6 KB

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