vgic-v2-switch.S 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. /*
  2. * Copyright (C) 2012,2013 - 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/linkage.h>
  18. #include <linux/irqchip/arm-gic.h>
  19. #include <asm/assembler.h>
  20. #include <asm/memory.h>
  21. #include <asm/asm-offsets.h>
  22. #include <asm/kvm.h>
  23. #include <asm/kvm_asm.h>
  24. #include <asm/kvm_arm.h>
  25. #include <asm/kvm_mmu.h>
  26. .text
  27. .pushsection .hyp.text, "ax"
  28. /*
  29. * Save the VGIC CPU state into memory
  30. * x0: Register pointing to VCPU struct
  31. * Do not corrupt x1!!!
  32. */
  33. ENTRY(__save_vgic_v2_state)
  34. __save_vgic_v2_state:
  35. /* Get VGIC VCTRL base into x2 */
  36. ldr x2, [x0, #VCPU_KVM]
  37. kern_hyp_va x2
  38. ldr x2, [x2, #KVM_VGIC_VCTRL]
  39. kern_hyp_va x2
  40. cbz x2, 2f // disabled
  41. /* Compute the address of struct vgic_cpu */
  42. add x3, x0, #VCPU_VGIC_CPU
  43. /* Save all interesting registers */
  44. ldr w5, [x2, #GICH_VMCR]
  45. ldr w6, [x2, #GICH_MISR]
  46. ldr w7, [x2, #GICH_EISR0]
  47. ldr w8, [x2, #GICH_EISR1]
  48. ldr w9, [x2, #GICH_ELRSR0]
  49. ldr w10, [x2, #GICH_ELRSR1]
  50. ldr w11, [x2, #GICH_APR]
  51. CPU_BE( rev w5, w5 )
  52. CPU_BE( rev w6, w6 )
  53. CPU_BE( rev w7, w7 )
  54. CPU_BE( rev w8, w8 )
  55. CPU_BE( rev w9, w9 )
  56. CPU_BE( rev w10, w10 )
  57. CPU_BE( rev w11, w11 )
  58. str w5, [x3, #VGIC_V2_CPU_VMCR]
  59. str w6, [x3, #VGIC_V2_CPU_MISR]
  60. CPU_LE( str w7, [x3, #VGIC_V2_CPU_EISR] )
  61. CPU_LE( str w8, [x3, #(VGIC_V2_CPU_EISR + 4)] )
  62. CPU_LE( str w9, [x3, #VGIC_V2_CPU_ELRSR] )
  63. CPU_LE( str w10, [x3, #(VGIC_V2_CPU_ELRSR + 4)] )
  64. CPU_BE( str w7, [x3, #(VGIC_V2_CPU_EISR + 4)] )
  65. CPU_BE( str w8, [x3, #VGIC_V2_CPU_EISR] )
  66. CPU_BE( str w9, [x3, #(VGIC_V2_CPU_ELRSR + 4)] )
  67. CPU_BE( str w10, [x3, #VGIC_V2_CPU_ELRSR] )
  68. str w11, [x3, #VGIC_V2_CPU_APR]
  69. /* Clear GICH_HCR */
  70. str wzr, [x2, #GICH_HCR]
  71. /* Save list registers */
  72. add x2, x2, #GICH_LR0
  73. ldr w4, [x3, #VGIC_CPU_NR_LR]
  74. add x3, x3, #VGIC_V2_CPU_LR
  75. 1: ldr w5, [x2], #4
  76. CPU_BE( rev w5, w5 )
  77. str w5, [x3], #4
  78. sub w4, w4, #1
  79. cbnz w4, 1b
  80. 2:
  81. ret
  82. ENDPROC(__save_vgic_v2_state)
  83. /*
  84. * Restore the VGIC CPU state from memory
  85. * x0: Register pointing to VCPU struct
  86. */
  87. ENTRY(__restore_vgic_v2_state)
  88. __restore_vgic_v2_state:
  89. /* Get VGIC VCTRL base into x2 */
  90. ldr x2, [x0, #VCPU_KVM]
  91. kern_hyp_va x2
  92. ldr x2, [x2, #KVM_VGIC_VCTRL]
  93. kern_hyp_va x2
  94. cbz x2, 2f // disabled
  95. /* Compute the address of struct vgic_cpu */
  96. add x3, x0, #VCPU_VGIC_CPU
  97. /* We only restore a minimal set of registers */
  98. ldr w4, [x3, #VGIC_V2_CPU_HCR]
  99. ldr w5, [x3, #VGIC_V2_CPU_VMCR]
  100. ldr w6, [x3, #VGIC_V2_CPU_APR]
  101. CPU_BE( rev w4, w4 )
  102. CPU_BE( rev w5, w5 )
  103. CPU_BE( rev w6, w6 )
  104. str w4, [x2, #GICH_HCR]
  105. str w5, [x2, #GICH_VMCR]
  106. str w6, [x2, #GICH_APR]
  107. /* Restore list registers */
  108. add x2, x2, #GICH_LR0
  109. ldr w4, [x3, #VGIC_CPU_NR_LR]
  110. add x3, x3, #VGIC_V2_CPU_LR
  111. 1: ldr w5, [x3], #4
  112. CPU_BE( rev w5, w5 )
  113. str w5, [x2], #4
  114. sub w4, w4, #1
  115. cbnz w4, 1b
  116. 2:
  117. ret
  118. ENDPROC(__restore_vgic_v2_state)
  119. .popsection