fpu.c 1.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. #include <linux/sched/signal.h>
  2. #include <linux/sched/task.h>
  3. #include <linux/sched/task_stack.h>
  4. #include <linux/slab.h>
  5. #include <asm/processor.h>
  6. #include <asm/fpu.h>
  7. #include <asm/traps.h>
  8. #include <asm/ptrace.h>
  9. int init_fpu(struct task_struct *tsk)
  10. {
  11. if (tsk_used_math(tsk)) {
  12. if ((boot_cpu_data.flags & CPU_HAS_FPU) && tsk == current)
  13. unlazy_fpu(tsk, task_pt_regs(tsk));
  14. return 0;
  15. }
  16. /*
  17. * Memory allocation at the first usage of the FPU and other state.
  18. */
  19. if (!tsk->thread.xstate) {
  20. tsk->thread.xstate = kmem_cache_alloc(task_xstate_cachep,
  21. GFP_KERNEL);
  22. if (!tsk->thread.xstate)
  23. return -ENOMEM;
  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. set_stopped_child_used_math(tsk);
  35. return 0;
  36. }
  37. #ifdef CONFIG_SH_FPU
  38. void __fpu_state_restore(void)
  39. {
  40. struct task_struct *tsk = current;
  41. restore_fpu(tsk);
  42. task_thread_info(tsk)->status |= TS_USEDFPU;
  43. tsk->thread.fpu_counter++;
  44. }
  45. void fpu_state_restore(struct pt_regs *regs)
  46. {
  47. struct task_struct *tsk = current;
  48. if (unlikely(!user_mode(regs))) {
  49. printk(KERN_ERR "BUG: FPU is used in kernel mode.\n");
  50. BUG();
  51. return;
  52. }
  53. if (!tsk_used_math(tsk)) {
  54. local_irq_enable();
  55. /*
  56. * does a slab alloc which can sleep
  57. */
  58. if (init_fpu(tsk)) {
  59. /*
  60. * ran out of memory!
  61. */
  62. do_group_exit(SIGKILL);
  63. return;
  64. }
  65. local_irq_disable();
  66. }
  67. grab_fpu(regs);
  68. __fpu_state_restore();
  69. }
  70. BUILD_TRAP_HANDLER(fpu_state_restore)
  71. {
  72. TRAP_HANDLER_DECL;
  73. fpu_state_restore(regs);
  74. }
  75. #endif /* CONFIG_SH_FPU */