cpu_helpers.S 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314
  1. /*
  2. * Copyright (c) 2014-2018, ARM Limited and Contributors. All rights reserved.
  3. *
  4. * SPDX-License-Identifier: BSD-3-Clause
  5. */
  6. #include <arch.h>
  7. #include <asm_macros.S>
  8. #include <assert_macros.S>
  9. #include <cpu_data.h>
  10. #include <cpu_macros.S>
  11. #include <debug.h>
  12. #include <errata_report.h>
  13. /* Reset fn is needed in BL at reset vector */
  14. #if defined(IMAGE_BL1) || defined(IMAGE_BL31) || (defined(IMAGE_BL2) && BL2_AT_EL3)
  15. /*
  16. * The reset handler common to all platforms. After a matching
  17. * cpu_ops structure entry is found, the correponding reset_handler
  18. * in the cpu_ops is invoked.
  19. * Clobbers: x0 - x19, x30
  20. */
  21. .globl reset_handler
  22. func reset_handler
  23. mov x19, x30
  24. /* The plat_reset_handler can clobber x0 - x18, x30 */
  25. bl plat_reset_handler
  26. /* Get the matching cpu_ops pointer */
  27. bl get_cpu_ops_ptr
  28. #if ENABLE_ASSERTIONS
  29. cmp x0, #0
  30. ASM_ASSERT(ne)
  31. #endif
  32. /* Get the cpu_ops reset handler */
  33. ldr x2, [x0, #CPU_RESET_FUNC]
  34. mov x30, x19
  35. cbz x2, 1f
  36. /* The cpu_ops reset handler can clobber x0 - x19, x30 */
  37. br x2
  38. 1:
  39. ret
  40. endfunc reset_handler
  41. #endif
  42. #ifdef IMAGE_BL31 /* The power down core and cluster is needed only in BL31 */
  43. /*
  44. * void prepare_cpu_pwr_dwn(unsigned int power_level)
  45. *
  46. * Prepare CPU power down function for all platforms. The function takes
  47. * a domain level to be powered down as its parameter. After the cpu_ops
  48. * pointer is retrieved from cpu_data, the handler for requested power
  49. * level is called.
  50. */
  51. .globl prepare_cpu_pwr_dwn
  52. func prepare_cpu_pwr_dwn
  53. /*
  54. * If the given power level exceeds CPU_MAX_PWR_DWN_OPS, we call the
  55. * power down handler for the last power level
  56. */
  57. mov_imm x2, (CPU_MAX_PWR_DWN_OPS - 1)
  58. cmp x0, x2
  59. csel x2, x2, x0, hi
  60. mrs x1, tpidr_el3
  61. ldr x0, [x1, #CPU_DATA_CPU_OPS_PTR]
  62. #if ENABLE_ASSERTIONS
  63. cmp x0, #0
  64. ASM_ASSERT(ne)
  65. #endif
  66. /* Get the appropriate power down handler */
  67. mov x1, #CPU_PWR_DWN_OPS
  68. add x1, x1, x2, lsl #3
  69. ldr x1, [x0, x1]
  70. br x1
  71. endfunc prepare_cpu_pwr_dwn
  72. /*
  73. * Initializes the cpu_ops_ptr if not already initialized
  74. * in cpu_data. This can be called without a runtime stack, but may
  75. * only be called after the MMU is enabled.
  76. * clobbers: x0 - x6, x10
  77. */
  78. .globl init_cpu_ops
  79. func init_cpu_ops
  80. mrs x6, tpidr_el3
  81. ldr x0, [x6, #CPU_DATA_CPU_OPS_PTR]
  82. cbnz x0, 1f
  83. mov x10, x30
  84. bl get_cpu_ops_ptr
  85. #if ENABLE_ASSERTIONS
  86. cmp x0, #0
  87. ASM_ASSERT(ne)
  88. #endif
  89. str x0, [x6, #CPU_DATA_CPU_OPS_PTR]!
  90. mov x30, x10
  91. 1:
  92. ret
  93. endfunc init_cpu_ops
  94. #endif /* IMAGE_BL31 */
  95. #if defined(IMAGE_BL31) && CRASH_REPORTING
  96. /*
  97. * The cpu specific registers which need to be reported in a crash
  98. * are reported via cpu_ops cpu_reg_dump function. After a matching
  99. * cpu_ops structure entry is found, the correponding cpu_reg_dump
  100. * in the cpu_ops is invoked.
  101. */
  102. .globl do_cpu_reg_dump
  103. func do_cpu_reg_dump
  104. mov x16, x30
  105. /* Get the matching cpu_ops pointer */
  106. bl get_cpu_ops_ptr
  107. cbz x0, 1f
  108. /* Get the cpu_ops cpu_reg_dump */
  109. ldr x2, [x0, #CPU_REG_DUMP]
  110. cbz x2, 1f
  111. blr x2
  112. 1:
  113. mov x30, x16
  114. ret
  115. endfunc do_cpu_reg_dump
  116. #endif
  117. /*
  118. * The below function returns the cpu_ops structure matching the
  119. * midr of the core. It reads the MIDR_EL1 and finds the matching
  120. * entry in cpu_ops entries. Only the implementation and part number
  121. * are used to match the entries.
  122. * Return :
  123. * x0 - The matching cpu_ops pointer on Success
  124. * x0 - 0 on failure.
  125. * Clobbers : x0 - x5
  126. */
  127. .globl get_cpu_ops_ptr
  128. func get_cpu_ops_ptr
  129. /* Get the cpu_ops start and end locations */
  130. adr x4, (__CPU_OPS_START__ + CPU_MIDR)
  131. adr x5, (__CPU_OPS_END__ + CPU_MIDR)
  132. /* Initialize the return parameter */
  133. mov x0, #0
  134. /* Read the MIDR_EL1 */
  135. mrs x2, midr_el1
  136. mov_imm x3, CPU_IMPL_PN_MASK
  137. /* Retain only the implementation and part number using mask */
  138. and w2, w2, w3
  139. 1:
  140. /* Check if we have reached end of list */
  141. cmp x4, x5
  142. b.eq error_exit
  143. /* load the midr from the cpu_ops */
  144. ldr x1, [x4], #CPU_OPS_SIZE
  145. and w1, w1, w3
  146. /* Check if midr matches to midr of this core */
  147. cmp w1, w2
  148. b.ne 1b
  149. /* Subtract the increment and offset to get the cpu-ops pointer */
  150. sub x0, x4, #(CPU_OPS_SIZE + CPU_MIDR)
  151. error_exit:
  152. ret
  153. endfunc get_cpu_ops_ptr
  154. /*
  155. * Extract CPU revision and variant, and combine them into a single numeric for
  156. * easier comparison.
  157. */
  158. .globl cpu_get_rev_var
  159. func cpu_get_rev_var
  160. mrs x1, midr_el1
  161. /*
  162. * Extract the variant[23:20] and revision[3:0] from MIDR, and pack them
  163. * as variant[7:4] and revision[3:0] of x0.
  164. *
  165. * First extract x1[23:16] to x0[7:0] and zero fill the rest. Then
  166. * extract x1[3:0] into x0[3:0] retaining other bits.
  167. */
  168. ubfx x0, x1, #(MIDR_VAR_SHIFT - MIDR_REV_BITS), #(MIDR_REV_BITS + MIDR_VAR_BITS)
  169. bfxil x0, x1, #MIDR_REV_SHIFT, #MIDR_REV_BITS
  170. ret
  171. endfunc cpu_get_rev_var
  172. /*
  173. * Compare the CPU's revision-variant (x0) with a given value (x1), for errata
  174. * application purposes. If the revision-variant is less than or same as a given
  175. * value, indicates that errata applies; otherwise not.
  176. */
  177. .globl cpu_rev_var_ls
  178. func cpu_rev_var_ls
  179. mov x2, #ERRATA_APPLIES
  180. mov x3, #ERRATA_NOT_APPLIES
  181. cmp x0, x1
  182. csel x0, x2, x3, ls
  183. ret
  184. endfunc cpu_rev_var_ls
  185. /*
  186. * Compare the CPU's revision-variant (x0) with a given value (x1), for errata
  187. * application purposes. If the revision-variant is higher than or same as a
  188. * given value, indicates that errata applies; otherwise not.
  189. */
  190. .globl cpu_rev_var_hs
  191. func cpu_rev_var_hs
  192. mov x2, #ERRATA_APPLIES
  193. mov x3, #ERRATA_NOT_APPLIES
  194. cmp x0, x1
  195. csel x0, x2, x3, hs
  196. ret
  197. endfunc cpu_rev_var_hs
  198. #if REPORT_ERRATA
  199. /*
  200. * void print_errata_status(void);
  201. *
  202. * Function to print errata status for CPUs of its class. Must be called only:
  203. *
  204. * - with MMU and data caches are enabled;
  205. * - after cpu_ops have been initialized in per-CPU data.
  206. */
  207. .globl print_errata_status
  208. func print_errata_status
  209. #ifdef IMAGE_BL1
  210. /*
  211. * BL1 doesn't have per-CPU data. So retrieve the CPU operations
  212. * directly.
  213. */
  214. stp xzr, x30, [sp, #-16]!
  215. bl get_cpu_ops_ptr
  216. ldp xzr, x30, [sp], #16
  217. ldr x1, [x0, #CPU_ERRATA_FUNC]
  218. cbnz x1, .Lprint
  219. #else
  220. /*
  221. * Retrieve pointer to cpu_ops from per-CPU data, and further, the
  222. * errata printing function. If it's non-NULL, jump to the function in
  223. * turn.
  224. */
  225. mrs x0, tpidr_el3
  226. ldr x1, [x0, #CPU_DATA_CPU_OPS_PTR]
  227. ldr x0, [x1, #CPU_ERRATA_FUNC]
  228. cbz x0, .Lnoprint
  229. /*
  230. * Printing errata status requires atomically testing the printed flag.
  231. */
  232. stp x19, x30, [sp, #-16]!
  233. mov x19, x0
  234. /*
  235. * Load pointers to errata lock and printed flag. Call
  236. * errata_needs_reporting to check whether this CPU needs to report
  237. * errata status pertaining to its class.
  238. */
  239. ldr x0, [x1, #CPU_ERRATA_LOCK]
  240. ldr x1, [x1, #CPU_ERRATA_PRINTED]
  241. bl errata_needs_reporting
  242. mov x1, x19
  243. ldp x19, x30, [sp], #16
  244. cbnz x0, .Lprint
  245. #endif
  246. .Lnoprint:
  247. ret
  248. .Lprint:
  249. /* Jump to errata reporting function for this CPU */
  250. br x1
  251. endfunc print_errata_status
  252. #endif
  253. /*
  254. * int check_workaround_cve_2017_5715(void);
  255. *
  256. * This function returns:
  257. * - ERRATA_APPLIES when firmware mitigation is required.
  258. * - ERRATA_NOT_APPLIES when firmware mitigation is _not_ required.
  259. * - ERRATA_MISSING when firmware mitigation would be required but
  260. * is not compiled in.
  261. *
  262. * NOTE: Must be called only after cpu_ops have been initialized
  263. * in per-CPU data.
  264. */
  265. .globl check_workaround_cve_2017_5715
  266. func check_workaround_cve_2017_5715
  267. mrs x0, tpidr_el3
  268. #if ENABLE_ASSERTIONS
  269. cmp x0, #0
  270. ASM_ASSERT(ne)
  271. #endif
  272. ldr x0, [x0, #CPU_DATA_CPU_OPS_PTR]
  273. ldr x0, [x0, #CPU_EXTRA1_FUNC]
  274. /*
  275. * If the reserved function pointer is NULL, this CPU
  276. * is unaffected by CVE-2017-5715 so bail out.
  277. */
  278. cmp x0, #0
  279. beq 1f
  280. br x0
  281. 1:
  282. mov x0, #ERRATA_NOT_APPLIES
  283. ret
  284. endfunc check_workaround_cve_2017_5715