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