init.S 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  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/assembler.h>
  20. #include <asm/unified.h>
  21. #include <asm/asm-offsets.h>
  22. #include <asm/kvm_asm.h>
  23. #include <asm/kvm_arm.h>
  24. #include <asm/kvm_mmu.h>
  25. #include <asm/virt.h>
  26. /********************************************************************
  27. * Hypervisor initialization
  28. * - should be called with:
  29. * r0 = top of Hyp stack (kernel VA)
  30. * r1 = pointer to hyp vectors
  31. * r2,r3 = Hypervisor pgd pointer
  32. *
  33. * The init scenario is:
  34. * - We jump in HYP with 3 parameters: runtime HYP pgd, runtime stack,
  35. * runtime vectors
  36. * - Invalidate TLBs
  37. * - Set stack and vectors
  38. * - Setup the page tables
  39. * - Enable the MMU
  40. * - Profit! (or eret, if you only care about the code).
  41. *
  42. * Another possibility is to get a HYP stub hypercall.
  43. * We discriminate between the two by checking if r0 contains a value
  44. * that is less than HVC_STUB_HCALL_NR.
  45. */
  46. .text
  47. .pushsection .hyp.idmap.text,"ax"
  48. .align 5
  49. __kvm_hyp_init:
  50. .globl __kvm_hyp_init
  51. @ Hyp-mode exception vector
  52. W(b) .
  53. W(b) .
  54. W(b) .
  55. W(b) .
  56. W(b) .
  57. W(b) __do_hyp_init
  58. W(b) .
  59. W(b) .
  60. __do_hyp_init:
  61. @ Check for a stub hypercall
  62. cmp r0, #HVC_STUB_HCALL_NR
  63. blo __kvm_handle_stub_hvc
  64. @ Set stack pointer
  65. mov sp, r0
  66. @ Set HVBAR to point to the HYP vectors
  67. mcr p15, 4, r1, c12, c0, 0 @ HVBAR
  68. @ Set the HTTBR to point to the hypervisor PGD pointer passed
  69. mcrr p15, 4, rr_lo_hi(r2, r3), c2
  70. @ Set the HTCR and VTCR to the same shareability and cacheability
  71. @ settings as the non-secure TTBCR and with T0SZ == 0.
  72. mrc p15, 4, r0, c2, c0, 2 @ HTCR
  73. ldr r2, =HTCR_MASK
  74. bic r0, r0, r2
  75. mrc p15, 0, r1, c2, c0, 2 @ TTBCR
  76. and r1, r1, #(HTCR_MASK & ~TTBCR_T0SZ)
  77. orr r0, r0, r1
  78. mcr p15, 4, r0, c2, c0, 2 @ HTCR
  79. @ Use the same memory attributes for hyp. accesses as the kernel
  80. @ (copy MAIRx ro HMAIRx).
  81. mrc p15, 0, r0, c10, c2, 0
  82. mcr p15, 4, r0, c10, c2, 0
  83. mrc p15, 0, r0, c10, c2, 1
  84. mcr p15, 4, r0, c10, c2, 1
  85. @ Invalidate the stale TLBs from Bootloader
  86. mcr p15, 4, r0, c8, c7, 0 @ TLBIALLH
  87. dsb ish
  88. @ Set the HSCTLR to:
  89. @ - ARM/THUMB exceptions: Kernel config (Thumb-2 kernel)
  90. @ - Endianness: Kernel config
  91. @ - Fast Interrupt Features: Kernel config
  92. @ - Write permission implies XN: disabled
  93. @ - Instruction cache: enabled
  94. @ - Data/Unified cache: enabled
  95. @ - Memory alignment checks: enabled
  96. @ - MMU: enabled (this code must be run from an identity mapping)
  97. mrc p15, 4, r0, c1, c0, 0 @ HSCR
  98. ldr r2, =HSCTLR_MASK
  99. bic r0, r0, r2
  100. mrc p15, 0, r1, c1, c0, 0 @ SCTLR
  101. ldr r2, =(HSCTLR_EE | HSCTLR_FI | HSCTLR_I | HSCTLR_C)
  102. and r1, r1, r2
  103. ARM( ldr r2, =(HSCTLR_M | HSCTLR_A) )
  104. THUMB( ldr r2, =(HSCTLR_M | HSCTLR_A | HSCTLR_TE) )
  105. orr r1, r1, r2
  106. orr r0, r0, r1
  107. mcr p15, 4, r0, c1, c0, 0 @ HSCR
  108. isb
  109. eret
  110. ENTRY(__kvm_handle_stub_hvc)
  111. cmp r0, #HVC_SOFT_RESTART
  112. bne 1f
  113. /* The target is expected in r1 */
  114. msr ELR_hyp, r1
  115. mrs r0, cpsr
  116. bic r0, r0, #MODE_MASK
  117. orr r0, r0, #HYP_MODE
  118. THUMB( orr r0, r0, #PSR_T_BIT )
  119. msr spsr_cxsf, r0
  120. b reset
  121. 1: cmp r0, #HVC_RESET_VECTORS
  122. bne 1f
  123. reset:
  124. /* We're now in idmap, disable MMU */
  125. mrc p15, 4, r1, c1, c0, 0 @ HSCTLR
  126. ldr r0, =(HSCTLR_M | HSCTLR_A | HSCTLR_C | HSCTLR_I)
  127. bic r1, r1, r0
  128. mcr p15, 4, r1, c1, c0, 0 @ HSCTLR
  129. /*
  130. * Install stub vectors, using ardb's VA->PA trick.
  131. */
  132. 0: adr r0, 0b @ PA(0)
  133. movw r1, #:lower16:__hyp_stub_vectors - 0b @ VA(stub) - VA(0)
  134. movt r1, #:upper16:__hyp_stub_vectors - 0b
  135. add r1, r1, r0 @ PA(stub)
  136. mcr p15, 4, r1, c12, c0, 0 @ HVBAR
  137. b exit
  138. 1: ldr r0, =HVC_STUB_ERR
  139. eret
  140. exit:
  141. mov r0, #0
  142. eret
  143. ENDPROC(__kvm_handle_stub_hvc)
  144. .ltorg
  145. .globl __kvm_hyp_init_end
  146. __kvm_hyp_init_end:
  147. .popsection