hyp-entry.S 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337
  1. /*
  2. * Copyright (C) 2015-2018 - ARM Ltd
  3. * Author: Marc Zyngier <marc.zyngier@arm.com>
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License version 2 as
  7. * published by the Free Software Foundation.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  16. */
  17. #include <linux/arm-smccc.h>
  18. #include <linux/linkage.h>
  19. #include <asm/alternative.h>
  20. #include <asm/assembler.h>
  21. #include <asm/cpufeature.h>
  22. #include <asm/kvm_arm.h>
  23. #include <asm/kvm_asm.h>
  24. #include <asm/kvm_mmu.h>
  25. #include <asm/mmu.h>
  26. .macro save_caller_saved_regs_vect
  27. /* x0 and x1 were saved in the vector entry */
  28. stp x2, x3, [sp, #-16]!
  29. stp x4, x5, [sp, #-16]!
  30. stp x6, x7, [sp, #-16]!
  31. stp x8, x9, [sp, #-16]!
  32. stp x10, x11, [sp, #-16]!
  33. stp x12, x13, [sp, #-16]!
  34. stp x14, x15, [sp, #-16]!
  35. stp x16, x17, [sp, #-16]!
  36. .endm
  37. .macro restore_caller_saved_regs_vect
  38. ldp x16, x17, [sp], #16
  39. ldp x14, x15, [sp], #16
  40. ldp x12, x13, [sp], #16
  41. ldp x10, x11, [sp], #16
  42. ldp x8, x9, [sp], #16
  43. ldp x6, x7, [sp], #16
  44. ldp x4, x5, [sp], #16
  45. ldp x2, x3, [sp], #16
  46. ldp x0, x1, [sp], #16
  47. .endm
  48. .text
  49. .pushsection .hyp.text, "ax"
  50. .macro do_el2_call
  51. /*
  52. * Shuffle the parameters before calling the function
  53. * pointed to in x0. Assumes parameters in x[1,2,3].
  54. */
  55. str lr, [sp, #-16]!
  56. mov lr, x0
  57. mov x0, x1
  58. mov x1, x2
  59. mov x2, x3
  60. blr lr
  61. ldr lr, [sp], #16
  62. .endm
  63. ENTRY(__vhe_hyp_call)
  64. do_el2_call
  65. /*
  66. * We used to rely on having an exception return to get
  67. * an implicit isb. In the E2H case, we don't have it anymore.
  68. * rather than changing all the leaf functions, just do it here
  69. * before returning to the rest of the kernel.
  70. */
  71. isb
  72. ret
  73. ENDPROC(__vhe_hyp_call)
  74. el1_sync: // Guest trapped into EL2
  75. mrs x0, esr_el2
  76. lsr x0, x0, #ESR_ELx_EC_SHIFT
  77. cmp x0, #ESR_ELx_EC_HVC64
  78. ccmp x0, #ESR_ELx_EC_HVC32, #4, ne
  79. b.ne el1_trap
  80. mrs x1, vttbr_el2 // If vttbr is valid, the guest
  81. cbnz x1, el1_hvc_guest // called HVC
  82. /* Here, we're pretty sure the host called HVC. */
  83. ldp x0, x1, [sp], #16
  84. /* Check for a stub HVC call */
  85. cmp x0, #HVC_STUB_HCALL_NR
  86. b.hs 1f
  87. /*
  88. * Compute the idmap address of __kvm_handle_stub_hvc and
  89. * jump there. Since we use kimage_voffset, do not use the
  90. * HYP VA for __kvm_handle_stub_hvc, but the kernel VA instead
  91. * (by loading it from the constant pool).
  92. *
  93. * Preserve x0-x4, which may contain stub parameters.
  94. */
  95. ldr x5, =__kvm_handle_stub_hvc
  96. ldr_l x6, kimage_voffset
  97. /* x5 = __pa(x5) */
  98. sub x5, x5, x6
  99. br x5
  100. 1:
  101. /*
  102. * Perform the EL2 call
  103. */
  104. kern_hyp_va x0
  105. do_el2_call
  106. eret
  107. el1_hvc_guest:
  108. /*
  109. * Fastest possible path for ARM_SMCCC_ARCH_WORKAROUND_1.
  110. * The workaround has already been applied on the host,
  111. * so let's quickly get back to the guest. We don't bother
  112. * restoring x1, as it can be clobbered anyway.
  113. */
  114. ldr x1, [sp] // Guest's x0
  115. eor w1, w1, #ARM_SMCCC_ARCH_WORKAROUND_1
  116. cbz w1, wa_epilogue
  117. /* ARM_SMCCC_ARCH_WORKAROUND_2 handling */
  118. eor w1, w1, #(ARM_SMCCC_ARCH_WORKAROUND_1 ^ \
  119. ARM_SMCCC_ARCH_WORKAROUND_2)
  120. cbnz w1, el1_trap
  121. #ifdef CONFIG_ARM64_SSBD
  122. alternative_cb arm64_enable_wa2_handling
  123. b wa2_end
  124. alternative_cb_end
  125. get_vcpu_ptr x2, x0
  126. ldr x0, [x2, #VCPU_WORKAROUND_FLAGS]
  127. // Sanitize the argument and update the guest flags
  128. ldr x1, [sp, #8] // Guest's x1
  129. clz w1, w1 // Murphy's device:
  130. lsr w1, w1, #5 // w1 = !!w1 without using
  131. eor w1, w1, #1 // the flags...
  132. bfi x0, x1, #VCPU_WORKAROUND_2_FLAG_SHIFT, #1
  133. str x0, [x2, #VCPU_WORKAROUND_FLAGS]
  134. /* Check that we actually need to perform the call */
  135. hyp_ldr_this_cpu x0, arm64_ssbd_callback_required, x2
  136. cbz x0, wa2_end
  137. mov w0, #ARM_SMCCC_ARCH_WORKAROUND_2
  138. smc #0
  139. /* Don't leak data from the SMC call */
  140. mov x3, xzr
  141. wa2_end:
  142. mov x2, xzr
  143. mov x1, xzr
  144. #endif
  145. wa_epilogue:
  146. mov x0, xzr
  147. add sp, sp, #16
  148. eret
  149. el1_trap:
  150. get_vcpu_ptr x1, x0
  151. mov x0, #ARM_EXCEPTION_TRAP
  152. b __guest_exit
  153. el1_irq:
  154. get_vcpu_ptr x1, x0
  155. mov x0, #ARM_EXCEPTION_IRQ
  156. b __guest_exit
  157. el1_error:
  158. get_vcpu_ptr x1, x0
  159. mov x0, #ARM_EXCEPTION_EL1_SERROR
  160. b __guest_exit
  161. el2_sync:
  162. save_caller_saved_regs_vect
  163. stp x29, x30, [sp, #-16]!
  164. bl kvm_unexpected_el2_exception
  165. ldp x29, x30, [sp], #16
  166. restore_caller_saved_regs_vect
  167. eret
  168. el2_error:
  169. save_caller_saved_regs_vect
  170. stp x29, x30, [sp, #-16]!
  171. bl kvm_unexpected_el2_exception
  172. ldp x29, x30, [sp], #16
  173. restore_caller_saved_regs_vect
  174. eret
  175. ENTRY(__hyp_do_panic)
  176. mov lr, #(PSR_F_BIT | PSR_I_BIT | PSR_A_BIT | PSR_D_BIT |\
  177. PSR_MODE_EL1h)
  178. msr spsr_el2, lr
  179. ldr lr, =panic
  180. msr elr_el2, lr
  181. eret
  182. ENDPROC(__hyp_do_panic)
  183. ENTRY(__hyp_panic)
  184. get_host_ctxt x0, x1
  185. b hyp_panic
  186. ENDPROC(__hyp_panic)
  187. .macro invalid_vector label, target = __hyp_panic
  188. .align 2
  189. \label:
  190. b \target
  191. ENDPROC(\label)
  192. .endm
  193. /* None of these should ever happen */
  194. invalid_vector el2t_sync_invalid
  195. invalid_vector el2t_irq_invalid
  196. invalid_vector el2t_fiq_invalid
  197. invalid_vector el2t_error_invalid
  198. invalid_vector el2h_irq_invalid
  199. invalid_vector el2h_fiq_invalid
  200. invalid_vector el1_fiq_invalid
  201. .ltorg
  202. .align 11
  203. .macro valid_vect target
  204. .align 7
  205. stp x0, x1, [sp, #-16]!
  206. b \target
  207. .endm
  208. .macro invalid_vect target
  209. .align 7
  210. b \target
  211. ldp x0, x1, [sp], #16
  212. b \target
  213. .endm
  214. ENTRY(__kvm_hyp_vector)
  215. invalid_vect el2t_sync_invalid // Synchronous EL2t
  216. invalid_vect el2t_irq_invalid // IRQ EL2t
  217. invalid_vect el2t_fiq_invalid // FIQ EL2t
  218. invalid_vect el2t_error_invalid // Error EL2t
  219. valid_vect el2_sync // Synchronous EL2h
  220. invalid_vect el2h_irq_invalid // IRQ EL2h
  221. invalid_vect el2h_fiq_invalid // FIQ EL2h
  222. valid_vect el2_error // Error EL2h
  223. valid_vect el1_sync // Synchronous 64-bit EL1
  224. valid_vect el1_irq // IRQ 64-bit EL1
  225. invalid_vect el1_fiq_invalid // FIQ 64-bit EL1
  226. valid_vect el1_error // Error 64-bit EL1
  227. valid_vect el1_sync // Synchronous 32-bit EL1
  228. valid_vect el1_irq // IRQ 32-bit EL1
  229. invalid_vect el1_fiq_invalid // FIQ 32-bit EL1
  230. valid_vect el1_error // Error 32-bit EL1
  231. ENDPROC(__kvm_hyp_vector)
  232. #ifdef CONFIG_KVM_INDIRECT_VECTORS
  233. .macro hyp_ventry
  234. .align 7
  235. 1: .rept 27
  236. nop
  237. .endr
  238. /*
  239. * The default sequence is to directly branch to the KVM vectors,
  240. * using the computed offset. This applies for VHE as well as
  241. * !ARM64_HARDEN_EL2_VECTORS.
  242. *
  243. * For ARM64_HARDEN_EL2_VECTORS configurations, this gets replaced
  244. * with:
  245. *
  246. * stp x0, x1, [sp, #-16]!
  247. * movz x0, #(addr & 0xffff)
  248. * movk x0, #((addr >> 16) & 0xffff), lsl #16
  249. * movk x0, #((addr >> 32) & 0xffff), lsl #32
  250. * br x0
  251. *
  252. * Where addr = kern_hyp_va(__kvm_hyp_vector) + vector-offset + 4.
  253. * See kvm_patch_vector_branch for details.
  254. */
  255. alternative_cb kvm_patch_vector_branch
  256. b __kvm_hyp_vector + (1b - 0b)
  257. nop
  258. nop
  259. nop
  260. nop
  261. alternative_cb_end
  262. .endm
  263. .macro generate_vectors
  264. 0:
  265. .rept 16
  266. hyp_ventry
  267. .endr
  268. .org 0b + SZ_2K // Safety measure
  269. .endm
  270. .align 11
  271. ENTRY(__bp_harden_hyp_vecs_start)
  272. .rept BP_HARDEN_EL2_SLOTS
  273. generate_vectors
  274. .endr
  275. ENTRY(__bp_harden_hyp_vecs_end)
  276. .popsection
  277. ENTRY(__smccc_workaround_1_smc_start)
  278. sub sp, sp, #(8 * 4)
  279. stp x2, x3, [sp, #(8 * 0)]
  280. stp x0, x1, [sp, #(8 * 2)]
  281. mov w0, #ARM_SMCCC_ARCH_WORKAROUND_1
  282. smc #0
  283. ldp x2, x3, [sp, #(8 * 0)]
  284. ldp x0, x1, [sp, #(8 * 2)]
  285. add sp, sp, #(8 * 4)
  286. ENTRY(__smccc_workaround_1_smc_end)
  287. #endif