fpu.S 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. /* SPDX-License-Identifier: GPL-2.0-or-later */
  2. /*
  3. * FPU support code, moved here from head.S so that it can be used
  4. * by chips which use other head-whatever.S files.
  5. *
  6. * Copyright (C) 1995-1996 Gary Thomas ([email protected])
  7. * Copyright (C) 1996 Cort Dougan <[email protected]>
  8. * Copyright (C) 1996 Paul Mackerras.
  9. * Copyright (C) 1997 Dan Malek ([email protected]).
  10. */
  11. #include <asm/reg.h>
  12. #include <asm/page.h>
  13. #include <asm/mmu.h>
  14. #include <asm/cputable.h>
  15. #include <asm/cache.h>
  16. #include <asm/thread_info.h>
  17. #include <asm/ppc_asm.h>
  18. #include <asm/asm-offsets.h>
  19. #include <asm/ptrace.h>
  20. #include <asm/export.h>
  21. #include <asm/asm-compat.h>
  22. #include <asm/feature-fixups.h>
  23. #ifdef CONFIG_VSX
  24. #define __REST_1FPVSR(n,c,base) \
  25. BEGIN_FTR_SECTION \
  26. b 2f; \
  27. END_FTR_SECTION_IFSET(CPU_FTR_VSX); \
  28. REST_FPR(n,base); \
  29. b 3f; \
  30. 2: REST_VSR(n,c,base); \
  31. 3:
  32. #define __REST_32FPVSRS(n,c,base) \
  33. BEGIN_FTR_SECTION \
  34. b 2f; \
  35. END_FTR_SECTION_IFSET(CPU_FTR_VSX); \
  36. REST_32FPRS(n,base); \
  37. b 3f; \
  38. 2: REST_32VSRS(n,c,base); \
  39. 3:
  40. #define __SAVE_32FPVSRS(n,c,base) \
  41. BEGIN_FTR_SECTION \
  42. b 2f; \
  43. END_FTR_SECTION_IFSET(CPU_FTR_VSX); \
  44. SAVE_32FPRS(n,base); \
  45. b 3f; \
  46. 2: SAVE_32VSRS(n,c,base); \
  47. 3:
  48. #else
  49. #define __REST_1FPVSR(n,b,base) REST_FPR(n, base)
  50. #define __REST_32FPVSRS(n,b,base) REST_32FPRS(n, base)
  51. #define __SAVE_32FPVSRS(n,b,base) SAVE_32FPRS(n, base)
  52. #endif
  53. #define REST_1FPVSR(n,c,base) __REST_1FPVSR(n,__REG_##c,__REG_##base)
  54. #define REST_32FPVSRS(n,c,base) __REST_32FPVSRS(n,__REG_##c,__REG_##base)
  55. #define SAVE_32FPVSRS(n,c,base) __SAVE_32FPVSRS(n,__REG_##c,__REG_##base)
  56. /*
  57. * Load state from memory into FP registers including FPSCR.
  58. * Assumes the caller has enabled FP in the MSR.
  59. */
  60. _GLOBAL(load_fp_state)
  61. lfd fr0,FPSTATE_FPSCR(r3)
  62. MTFSF_L(fr0)
  63. REST_32FPVSRS(0, R4, R3)
  64. blr
  65. EXPORT_SYMBOL(load_fp_state)
  66. _ASM_NOKPROBE_SYMBOL(load_fp_state); /* used by restore_math */
  67. /*
  68. * Store FP state into memory, including FPSCR
  69. * Assumes the caller has enabled FP in the MSR.
  70. */
  71. _GLOBAL(store_fp_state)
  72. SAVE_32FPVSRS(0, R4, R3)
  73. mffs fr0
  74. stfd fr0,FPSTATE_FPSCR(r3)
  75. REST_1FPVSR(0, R4, R3)
  76. blr
  77. EXPORT_SYMBOL(store_fp_state)
  78. /*
  79. * This task wants to use the FPU now.
  80. * On UP, disable FP for the task which had the FPU previously,
  81. * and save its floating-point registers in its thread_struct.
  82. * Load up this task's FP registers from its thread_struct,
  83. * enable the FPU for the current task and return to the task.
  84. * Note that on 32-bit this can only use registers that will be
  85. * restored by fast_exception_return, i.e. r3 - r6, r10 and r11.
  86. */
  87. _GLOBAL(load_up_fpu)
  88. mfmsr r5
  89. #ifdef CONFIG_PPC_BOOK3S_64
  90. /* interrupt doesn't set MSR[RI] and HPT can fault on current access */
  91. ori r5,r5,MSR_FP|MSR_RI
  92. #else
  93. ori r5,r5,MSR_FP
  94. #endif
  95. #ifdef CONFIG_VSX
  96. BEGIN_FTR_SECTION
  97. oris r5,r5,MSR_VSX@h
  98. END_FTR_SECTION_IFSET(CPU_FTR_VSX)
  99. #endif
  100. MTMSRD(r5) /* enable use of fpu now */
  101. isync
  102. /* enable use of FP after return */
  103. #ifdef CONFIG_PPC32
  104. addi r5,r2,THREAD
  105. lwz r4,THREAD_FPEXC_MODE(r5)
  106. ori r9,r9,MSR_FP /* enable FP for current */
  107. or r9,r9,r4
  108. #else
  109. ld r4,PACACURRENT(r13)
  110. addi r5,r4,THREAD /* Get THREAD */
  111. lwz r4,THREAD_FPEXC_MODE(r5)
  112. ori r12,r12,MSR_FP
  113. or r12,r12,r4
  114. std r12,_MSR(r1)
  115. #ifdef CONFIG_PPC_BOOK3S_64
  116. li r4,0
  117. stb r4,PACASRR_VALID(r13)
  118. #endif
  119. #endif
  120. li r4,1
  121. stb r4,THREAD_LOAD_FP(r5)
  122. addi r10,r5,THREAD_FPSTATE
  123. lfd fr0,FPSTATE_FPSCR(r10)
  124. MTFSF_L(fr0)
  125. REST_32FPVSRS(0, R4, R10)
  126. /* restore registers and return */
  127. /* we haven't used ctr or xer or lr */
  128. blr
  129. _ASM_NOKPROBE_SYMBOL(load_up_fpu)
  130. /*
  131. * save_fpu(tsk)
  132. * Save the floating-point registers in its thread_struct.
  133. * Enables the FPU for use in the kernel on return.
  134. */
  135. _GLOBAL(save_fpu)
  136. addi r3,r3,THREAD /* want THREAD of task */
  137. PPC_LL r6,THREAD_FPSAVEAREA(r3)
  138. PPC_LL r5,PT_REGS(r3)
  139. PPC_LCMPI 0,r6,0
  140. bne 2f
  141. addi r6,r3,THREAD_FPSTATE
  142. 2: SAVE_32FPVSRS(0, R4, R6)
  143. mffs fr0
  144. stfd fr0,FPSTATE_FPSCR(r6)
  145. REST_1FPVSR(0, R4, R6)
  146. blr