switch_to.h 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. /* SPDX-License-Identifier: GPL-2.0-only */
  2. /*
  3. * Copyright (C) 2012 Regents of the University of California
  4. */
  5. #ifndef _ASM_RISCV_SWITCH_TO_H
  6. #define _ASM_RISCV_SWITCH_TO_H
  7. #include <linux/sched/task_stack.h>
  8. #include <asm/processor.h>
  9. #include <asm/ptrace.h>
  10. #include <asm/csr.h>
  11. #ifdef CONFIG_FPU
  12. extern void __fstate_save(struct task_struct *save_to);
  13. extern void __fstate_restore(struct task_struct *restore_from);
  14. static inline void __fstate_clean(struct pt_regs *regs)
  15. {
  16. regs->status = (regs->status & ~SR_FS) | SR_FS_CLEAN;
  17. }
  18. static inline void fstate_off(struct task_struct *task,
  19. struct pt_regs *regs)
  20. {
  21. regs->status = (regs->status & ~SR_FS) | SR_FS_OFF;
  22. }
  23. static inline void fstate_save(struct task_struct *task,
  24. struct pt_regs *regs)
  25. {
  26. if ((regs->status & SR_FS) == SR_FS_DIRTY) {
  27. __fstate_save(task);
  28. __fstate_clean(regs);
  29. }
  30. }
  31. static inline void fstate_restore(struct task_struct *task,
  32. struct pt_regs *regs)
  33. {
  34. if ((regs->status & SR_FS) != SR_FS_OFF) {
  35. __fstate_restore(task);
  36. __fstate_clean(regs);
  37. }
  38. }
  39. static inline void __switch_to_aux(struct task_struct *prev,
  40. struct task_struct *next)
  41. {
  42. struct pt_regs *regs;
  43. regs = task_pt_regs(prev);
  44. if (unlikely(regs->status & SR_SD))
  45. fstate_save(prev, regs);
  46. fstate_restore(next, task_pt_regs(next));
  47. }
  48. extern bool has_fpu;
  49. #else
  50. #define has_fpu false
  51. #define fstate_save(task, regs) do { } while (0)
  52. #define fstate_restore(task, regs) do { } while (0)
  53. #define __switch_to_aux(__prev, __next) do { } while (0)
  54. #endif
  55. #ifdef CONFIG_VECTOR
  56. extern void __vstate_save(struct task_struct *save_to);
  57. extern void __vstate_restore(struct task_struct *restore_from);
  58. static inline void __vstate_clean(struct pt_regs *regs)
  59. {
  60. regs->status |= (regs->status & ~(SR_VS)) | SR_VS_CLEAN;
  61. }
  62. static inline void vstate_save(struct task_struct *task,
  63. struct pt_regs *regs)
  64. {
  65. if ((regs->status & SR_VS) == SR_VS_DIRTY) {
  66. __vstate_save(task);
  67. __vstate_clean(regs);
  68. }
  69. }
  70. static inline void vstate_restore(struct task_struct *task,
  71. struct pt_regs *regs)
  72. {
  73. if ((regs->status & SR_VS) != SR_VS_OFF) {
  74. __vstate_restore(task);
  75. __vstate_clean(regs);
  76. }
  77. }
  78. static inline void __switch_to_vector(struct task_struct *prev,
  79. struct task_struct *next)
  80. {
  81. struct pt_regs *regs;
  82. regs = task_pt_regs(prev);
  83. if (unlikely(regs->status & SR_SD))
  84. vstate_save(prev, regs);
  85. vstate_restore(next, task_pt_regs(next));
  86. }
  87. extern bool has_vector;
  88. #else
  89. #define has_vector false
  90. #define vstate_save(task, regs) do { } while (0)
  91. #define vstate_restore(task, regs) do { } while (0)
  92. #define __switch_to_vector(__prev, __next) do { } while (0)
  93. #endif
  94. extern struct task_struct *__switch_to(struct task_struct *,
  95. struct task_struct *);
  96. #define switch_to(prev, next, last) \
  97. do { \
  98. struct task_struct *__prev = (prev); \
  99. struct task_struct *__next = (next); \
  100. if (has_fpu) \
  101. __switch_to_aux(__prev, __next); \
  102. if (has_vector) \
  103. __switch_to_vector(__prev, __next); \
  104. ((last) = __switch_to(__prev, __next)); \
  105. } while (0)
  106. #endif /* _ASM_RISCV_SWITCH_TO_H */