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. @ - MMU: enabled (this code must be run from an identity mapping)
  96. mrc p15, 4, r0, c1, c0, 0 @ HSCR
  97. ldr r2, =HSCTLR_MASK
  98. bic r0, r0, r2
  99. mrc p15, 0, r1, c1, c0, 0 @ SCTLR
  100. ldr r2, =(HSCTLR_EE | HSCTLR_FI | HSCTLR_I | HSCTLR_C)
  101. and r1, r1, r2
  102. ARM( ldr r2, =(HSCTLR_M) )
  103. THUMB( ldr r2, =(HSCTLR_M | HSCTLR_TE) )
  104. orr r1, r1, r2
  105. orr r0, r0, r1
  106. mcr p15, 4, r0, c1, c0, 0 @ HSCR
  107. isb
  108. eret
  109. ENTRY(__kvm_handle_stub_hvc)
  110. cmp r0, #HVC_SOFT_RESTART
  111. bne 1f
  112. /* The target is expected in r1 */
  113. msr ELR_hyp, r1
  114. mrs r0, cpsr
  115. bic r0, r0, #MODE_MASK
  116. orr r0, r0, #HYP_MODE
  117. THUMB( orr r0, r0, #PSR_T_BIT )
  118. msr spsr_cxsf, r0
  119. b reset
  120. 1: cmp r0, #HVC_RESET_VECTORS
  121. bne 1f
  122. reset:
  123. /* We're now in idmap, disable MMU */
  124. mrc p15, 4, r1, c1, c0, 0 @ HSCTLR
  125. ldr r0, =(HSCTLR_M | HSCTLR_A | HSCTLR_C | HSCTLR_I)
  126. bic r1, r1, r0
  127. mcr p15, 4, r1, c1, c0, 0 @ HSCTLR
  128. /*
  129. * Install stub vectors, using ardb's VA->PA trick.
  130. */
  131. 0: adr r0, 0b @ PA(0)
  132. movw r1, #:lower16:__hyp_stub_vectors - 0b @ VA(stub) - VA(0)
  133. movt r1, #:upper16:__hyp_stub_vectors - 0b
  134. add r1, r1, r0 @ PA(stub)
  135. mcr p15, 4, r1, c12, c0, 0 @ HVBAR
  136. b exit
  137. 1: ldr r0, =HVC_STUB_ERR
  138. eret
  139. exit:
  140. mov r0, #0
  141. eret
  142. ENDPROC(__kvm_handle_stub_hvc)
  143. .ltorg
  144. .globl __kvm_hyp_init_end
  145. __kvm_hyp_init_end:
  146. .popsection