vfp_switch.S 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. /*
  2. * Linux 2.6.32 and later Kernel module for VMware MVP Hypervisor Support
  3. *
  4. * Copyright (C) 2010-2013 VMware, Inc. All rights reserved.
  5. *
  6. * This program is free software; you can redistribute it and/or modify it
  7. * under the terms of the GNU General Public License version 2 as published by
  8. * the Free Software Foundation.
  9. *
  10. * This program is distributed in the hope that it will be useful, but WITHOUT
  11. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  12. * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  13. * more details.
  14. *
  15. * You should have received a copy of the GNU General Public License along with
  16. * this program; see the file COPYING. If not, write to the Free Software
  17. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  18. */
  19. #line 5
  20. #include "arm_defs.h"
  21. #include "platdefx.h"
  22. #include "arm_as_macros.h"
  23. /**
  24. * @file
  25. *
  26. * @brief Save and Load VFP entire VFP state.
  27. */
  28. .text
  29. /**
  30. * @brief Save VFP context
  31. * @param R0 = save area pointer:
  32. * .long fpexc,fpscr,fpinst,fpinst2,cpacr,fpexc'
  33. * .double d0..d15
  34. * .double d16..d31
  35. * Note: VFP is left in an enable state regardless of initial state.
  36. */
  37. .align 4
  38. .global SaveVFP
  39. SaveVFP:
  40. /*
  41. * Save registers. GCC does not expect us to preserve R0..R3,R12,LR.
  42. */
  43. stmdb sp!, {r4-r6}
  44. /*
  45. * Save Coproc Access Control register.
  46. */
  47. mrc_p15 COPROC_ACCESS_CONTROL, r5
  48. /*
  49. * If CP10/11 are disabled, enable them so we can save VFP state.
  50. * The host (or guest) may have left data in the data registers that
  51. * must be preserved.
  52. */
  53. orr r2, r5, #CPACR_CP10_CP11_PRIV_ONLY
  54. mcr_p15 COPROC_ACCESS_CONTROL, r2
  55. isb
  56. /*
  57. * Follow procedure on AppxB-22 ARM DDI0406B to save FPINST[2].
  58. * Also enable VFP access with FPEXC_EN.
  59. */
  60. fmrx r1, fpexc @ get existing FPEXC system register
  61. orr r6, r1, #ARM_VFP_SYSTEM_REG_FPEXC_EX|ARM_VFP_SYSTEM_REG_FPEXC_FP2V|ARM_VFP_SYSTEM_REG_FPEXC_EN
  62. #if !defined(MVP_HOST_CODE_forceon)
  63. fmxr fpexc, r6 @ set FPEXC.EX, .FP2V and .EN
  64. fmrx r6, fpexc @ read them back
  65. tst r6, #ARM_VFP_SYSTEM_REG_FPEXC_EX @ see if either one is valid
  66. beq 1000f @ neither, skip it all
  67. fmrx r3, FPINST @ FPINST is valid, save it
  68. tst r6, #ARM_VFP_SYSTEM_REG_FPEXC_FP2V @ see if FPINST2 is valid
  69. beq 1000f
  70. fmrx r4, FPINST2 @ FPINST2 is valid, save it
  71. 1000:
  72. #else
  73. mov r6, r1
  74. #endif
  75. fmrx r2, FPSCR @ always save FPSCR system register
  76. /*
  77. * At this point:
  78. * R1 = original FPEXC
  79. * R2 = FPSCR
  80. * R3 = FPINST
  81. * R4 = FPINST2
  82. * R5 = original CPACR
  83. * R6 = FPEXC readback with FPEXC.EX, .FP2V and .EN set
  84. * telling us whether FPINST/2 are valid
  85. */
  86. stmia r0!, {r1-r6}
  87. /*
  88. * Save floating point data registers.
  89. */
  90. vstmia r0!, {d0-d15} @ Save d0 thru d15
  91. /**
  92. * @todo We should probably just read MVFR0 once at boot/initialization
  93. * time and store it in some variable, to save having to do what might
  94. * be expensive coprocessor accesses.
  95. */
  96. fmrx r1, MVFR0 @ Read Media and VFP Feature Register 0
  97. and r1, r1, #ARM_VFP_SYSTEM_REG_MVFR0_A_SIMD_MASK @ A_SIMD field
  98. cmp r1, #2 @ 32 x 64bit registers?
  99. bne 2000f
  100. vstmia r0!, {d16-d31}
  101. 2000:
  102. /*
  103. * Restore scratch registers and return.
  104. */
  105. ldmia sp!, {r4-r6}
  106. mov pc, lr
  107. /**
  108. * @brief Load VFP context
  109. * @param R0 = load area pointer:
  110. * .long fpexc,fpscr,fpinst,fpinst2,cpacr,fpexc'
  111. * .double d0..d15
  112. * .double d16..d31
  113. * @note VFP is assumed to be in an enabled state on entry.
  114. */
  115. .align 4
  116. .global LoadVFP
  117. LoadVFP:
  118. /*
  119. * Save registers. GCC does not expect us to preserve R0..R3,R12,LR.
  120. */
  121. stmdb sp!, {r4-r6}
  122. /*
  123. * Get status register contents:
  124. * R1 = original FPEXC
  125. * R2 = FPSCR
  126. * R3 = FPINST
  127. * R4 = FPINST2
  128. * R5 = original CPACR
  129. * R6 = FPEXC readback with FPEXC.EX, .FP2V and .EN set
  130. * telling us whether FPINST/2 are valid
  131. */
  132. ldmia r0!, {r1-r6}
  133. /*
  134. * Restore some initial FP status registers.
  135. */
  136. fmxr fpexc, r6 @ with FPEXC.EX, .FP2V and .EN set
  137. fmxr FPSCR, r2 @ always load FPSCR system register
  138. /*
  139. * Follow procedure on AppxB-22 ARM DDI0406B to load FPINST[2].
  140. */
  141. #if !defined(MVP_HOST_CODE_forceon)
  142. fmrx r6, fpexc @ initial call might have different bits
  143. @ ... because FPEXC.EX, .FP2V and .EN
  144. @ are forced set by init code in
  145. @ mvpd.c SetupMonitor()
  146. tst r6, #ARM_VFP_SYSTEM_REG_FPEXC_EX @ see if either one is valid
  147. beq 1000f @ neither, skip it all
  148. fmxr FPINST, r3 @ FPINST is valid, save it
  149. tst r6, #ARM_VFP_SYSTEM_REG_FPEXC_FP2V @ see if FPINST2 is valid
  150. beq 1000f
  151. fmxr FPINST2, r4 @ FPINST2 is valid, save it
  152. 1000:
  153. #endif
  154. /*
  155. * Load floating point data registers.
  156. */
  157. vldmia r0!, {d0-d15}
  158. /**
  159. * @todo We should probably just read MVFR0 once at boot/initialization
  160. * time and store it in some variable, to save having to do what might
  161. * be expensive coprocessor accesses.
  162. */
  163. fmrx r3, MVFR0 @ Read Media and VFP Feature Register 0
  164. and r3, r3, #ARM_VFP_SYSTEM_REG_MVFR0_A_SIMD_MASK @ A_SIMD field
  165. cmp r3, #2 @ 32 x 64bit registers?
  166. bne 2000f
  167. vldmia r0!, {d16-d31}
  168. 2000:
  169. /*
  170. * Now that VFP registers are all loaded, we put the restored values
  171. * back in the registers, possibly disabling the VFP.
  172. */
  173. fmxr fpexc, r1 @ with original FPEXC.EX, FPEXC.FP2V
  174. @ and FPEXC.EN values
  175. /*
  176. * Load Coproc Access Control CP10/CP11 enable bits, possibly disabling
  177. * VFP access.
  178. */
  179. mrc_p15 COPROC_ACCESS_CONTROL, r0
  180. bic r0, r0, #CPACR_CP10_CP11_MASK
  181. and r5, r5, #CPACR_CP10_CP11_MASK
  182. orr r0, r0, r5
  183. mcr_p15 COPROC_ACCESS_CONTROL, r0
  184. isb
  185. /*
  186. * Restore scratch registers and return.
  187. */
  188. ldmia sp!, {r4-r6}
  189. mov pc, lr