hyp-entry.S 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. /*
  2. * Copyright (C) 2012 - Virtual Open Systems and Columbia University
  3. * Author: Christoffer Dall <c.dall@virtualopensystems.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, write to the Free Software
  16. * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  17. */
  18. #include <linux/linkage.h>
  19. #include <asm/kvm_arm.h>
  20. #include <asm/kvm_asm.h>
  21. .arch_extension virt
  22. .text
  23. .pushsection .hyp.text, "ax"
  24. .macro load_vcpu reg
  25. mrc p15, 4, \reg, c13, c0, 2 @ HTPIDR
  26. .endm
  27. /********************************************************************
  28. * Hypervisor exception vector and handlers
  29. *
  30. *
  31. * The KVM/ARM Hypervisor ABI is defined as follows:
  32. *
  33. * Entry to Hyp mode from the host kernel will happen _only_ when an HVC
  34. * instruction is issued since all traps are disabled when running the host
  35. * kernel as per the Hyp-mode initialization at boot time.
  36. *
  37. * HVC instructions cause a trap to the vector page + offset 0x14 (see hyp_hvc
  38. * below) when the HVC instruction is called from SVC mode (i.e. a guest or the
  39. * host kernel) and they cause a trap to the vector page + offset 0x8 when HVC
  40. * instructions are called from within Hyp-mode.
  41. *
  42. * Hyp-ABI: Calling HYP-mode functions from host (in SVC mode):
  43. * Switching to Hyp mode is done through a simple HVC #0 instruction. The
  44. * exception vector code will check that the HVC comes from VMID==0.
  45. * - r0 contains a pointer to a HYP function
  46. * - r1, r2, and r3 contain arguments to the above function.
  47. * - The HYP function will be called with its arguments in r0, r1 and r2.
  48. * On HYP function return, we return directly to SVC.
  49. *
  50. * Note that the above is used to execute code in Hyp-mode from a host-kernel
  51. * point of view, and is a different concept from performing a world-switch and
  52. * executing guest code SVC mode (with a VMID != 0).
  53. */
  54. .align 5
  55. __kvm_hyp_vector:
  56. .global __kvm_hyp_vector
  57. @ Hyp-mode exception vector
  58. W(b) hyp_reset
  59. W(b) hyp_undef
  60. W(b) hyp_svc
  61. W(b) hyp_pabt
  62. W(b) hyp_dabt
  63. W(b) hyp_hvc
  64. W(b) hyp_irq
  65. W(b) hyp_fiq
  66. .macro invalid_vector label, cause
  67. .align
  68. \label: mov r0, #\cause
  69. b __hyp_panic
  70. .endm
  71. invalid_vector hyp_reset ARM_EXCEPTION_RESET
  72. invalid_vector hyp_undef ARM_EXCEPTION_UNDEFINED
  73. invalid_vector hyp_svc ARM_EXCEPTION_SOFTWARE
  74. invalid_vector hyp_pabt ARM_EXCEPTION_PREF_ABORT
  75. invalid_vector hyp_fiq ARM_EXCEPTION_FIQ
  76. ENTRY(__hyp_do_panic)
  77. mrs lr, cpsr
  78. bic lr, lr, #MODE_MASK
  79. orr lr, lr, #SVC_MODE
  80. THUMB( orr lr, lr, #PSR_T_BIT )
  81. msr spsr_cxsf, lr
  82. ldr lr, =panic
  83. msr ELR_hyp, lr
  84. ldr lr, =kvm_call_hyp
  85. clrex
  86. eret
  87. ENDPROC(__hyp_do_panic)
  88. hyp_hvc:
  89. /*
  90. * Getting here is either because of a trap from a guest,
  91. * or from executing HVC from the host kernel, which means
  92. * "do something in Hyp mode".
  93. */
  94. push {r0, r1, r2}
  95. @ Check syndrome register
  96. mrc p15, 4, r1, c5, c2, 0 @ HSR
  97. lsr r0, r1, #HSR_EC_SHIFT
  98. cmp r0, #HSR_EC_HVC
  99. bne guest_trap @ Not HVC instr.
  100. /*
  101. * Let's check if the HVC came from VMID 0 and allow simple
  102. * switch to Hyp mode
  103. */
  104. mrrc p15, 6, r0, r2, c2
  105. lsr r2, r2, #16
  106. and r2, r2, #0xff
  107. cmp r2, #0
  108. bne guest_trap @ Guest called HVC
  109. /*
  110. * Getting here means host called HVC, we shift parameters and branch
  111. * to Hyp function.
  112. */
  113. pop {r0, r1, r2}
  114. /* Check for __hyp_get_vectors */
  115. cmp r0, #-1
  116. mrceq p15, 4, r0, c12, c0, 0 @ get HVBAR
  117. beq 1f
  118. push {lr}
  119. mov lr, r0
  120. mov r0, r1
  121. mov r1, r2
  122. mov r2, r3
  123. THUMB( orr lr, #1)
  124. blx lr @ Call the HYP function
  125. pop {lr}
  126. 1: eret
  127. guest_trap:
  128. load_vcpu r0 @ Load VCPU pointer to r0
  129. #ifdef CONFIG_VFPv3
  130. @ Check for a VFP access
  131. lsr r1, r1, #HSR_EC_SHIFT
  132. cmp r1, #HSR_EC_CP_0_13
  133. beq __vfp_guest_restore
  134. #endif
  135. mov r1, #ARM_EXCEPTION_HVC
  136. b __guest_exit
  137. hyp_irq:
  138. push {r0, r1, r2}
  139. mov r1, #ARM_EXCEPTION_IRQ
  140. load_vcpu r0 @ Load VCPU pointer to r0
  141. b __guest_exit
  142. hyp_dabt:
  143. push {r0, r1}
  144. mrs r0, ELR_hyp
  145. ldr r1, =abort_guest_exit_start
  146. THUMB( add r1, r1, #1)
  147. cmp r0, r1
  148. ldrne r1, =abort_guest_exit_end
  149. THUMB( addne r1, r1, #1)
  150. cmpne r0, r1
  151. pop {r0, r1}
  152. bne __hyp_panic
  153. orr r0, r0, #(1 << ARM_EXIT_WITH_ABORT_BIT)
  154. eret
  155. .ltorg
  156. .popsection