inject_fault.c 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. /*
  2. * Fault injection for both 32 and 64bit guests.
  3. *
  4. * Copyright (C) 2012,2013 - ARM Ltd
  5. * Author: Marc Zyngier <marc.zyngier@arm.com>
  6. *
  7. * Based on arch/arm/kvm/emulate.c
  8. * Copyright (C) 2012 - Virtual Open Systems and Columbia University
  9. * Author: Christoffer Dall <c.dall@virtualopensystems.com>
  10. *
  11. * This program is free software: you can redistribute it and/or modify
  12. * it under the terms of the GNU General Public License version 2 as
  13. * published by the Free Software Foundation.
  14. *
  15. * This program is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. * GNU General Public License for more details.
  19. *
  20. * You should have received a copy of the GNU General Public License
  21. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  22. */
  23. #include <linux/kvm_host.h>
  24. #include <asm/kvm_emulate.h>
  25. #include <asm/esr.h>
  26. #define PSTATE_FAULT_BITS_64 (PSR_MODE_EL1h | PSR_A_BIT | PSR_F_BIT | \
  27. PSR_I_BIT | PSR_D_BIT)
  28. #define CURRENT_EL_SP_EL0_VECTOR 0x0
  29. #define CURRENT_EL_SP_ELx_VECTOR 0x200
  30. #define LOWER_EL_AArch64_VECTOR 0x400
  31. #define LOWER_EL_AArch32_VECTOR 0x600
  32. enum exception_type {
  33. except_type_sync = 0,
  34. except_type_irq = 0x80,
  35. except_type_fiq = 0x100,
  36. except_type_serror = 0x180,
  37. };
  38. static u64 get_except_vector(struct kvm_vcpu *vcpu, enum exception_type type)
  39. {
  40. u64 exc_offset;
  41. switch (*vcpu_cpsr(vcpu) & (PSR_MODE_MASK | PSR_MODE32_BIT)) {
  42. case PSR_MODE_EL1t:
  43. exc_offset = CURRENT_EL_SP_EL0_VECTOR;
  44. break;
  45. case PSR_MODE_EL1h:
  46. exc_offset = CURRENT_EL_SP_ELx_VECTOR;
  47. break;
  48. case PSR_MODE_EL0t:
  49. exc_offset = LOWER_EL_AArch64_VECTOR;
  50. break;
  51. default:
  52. exc_offset = LOWER_EL_AArch32_VECTOR;
  53. }
  54. return vcpu_read_sys_reg(vcpu, VBAR_EL1) + exc_offset + type;
  55. }
  56. static void inject_abt64(struct kvm_vcpu *vcpu, bool is_iabt, unsigned long addr)
  57. {
  58. unsigned long cpsr = *vcpu_cpsr(vcpu);
  59. bool is_aarch32 = vcpu_mode_is_32bit(vcpu);
  60. u32 esr = 0;
  61. vcpu_write_elr_el1(vcpu, *vcpu_pc(vcpu));
  62. *vcpu_pc(vcpu) = get_except_vector(vcpu, except_type_sync);
  63. *vcpu_cpsr(vcpu) = PSTATE_FAULT_BITS_64;
  64. vcpu_write_spsr(vcpu, cpsr);
  65. vcpu_write_sys_reg(vcpu, addr, FAR_EL1);
  66. /*
  67. * Build an {i,d}abort, depending on the level and the
  68. * instruction set. Report an external synchronous abort.
  69. */
  70. if (kvm_vcpu_trap_il_is32bit(vcpu))
  71. esr |= ESR_ELx_IL;
  72. /*
  73. * Here, the guest runs in AArch64 mode when in EL1. If we get
  74. * an AArch32 fault, it means we managed to trap an EL0 fault.
  75. */
  76. if (is_aarch32 || (cpsr & PSR_MODE_MASK) == PSR_MODE_EL0t)
  77. esr |= (ESR_ELx_EC_IABT_LOW << ESR_ELx_EC_SHIFT);
  78. else
  79. esr |= (ESR_ELx_EC_IABT_CUR << ESR_ELx_EC_SHIFT);
  80. if (!is_iabt)
  81. esr |= ESR_ELx_EC_DABT_LOW << ESR_ELx_EC_SHIFT;
  82. vcpu_write_sys_reg(vcpu, esr | ESR_ELx_FSC_EXTABT, ESR_EL1);
  83. }
  84. static void inject_undef64(struct kvm_vcpu *vcpu)
  85. {
  86. unsigned long cpsr = *vcpu_cpsr(vcpu);
  87. u32 esr = (ESR_ELx_EC_UNKNOWN << ESR_ELx_EC_SHIFT);
  88. vcpu_write_elr_el1(vcpu, *vcpu_pc(vcpu));
  89. *vcpu_pc(vcpu) = get_except_vector(vcpu, except_type_sync);
  90. *vcpu_cpsr(vcpu) = PSTATE_FAULT_BITS_64;
  91. vcpu_write_spsr(vcpu, cpsr);
  92. /*
  93. * Build an unknown exception, depending on the instruction
  94. * set.
  95. */
  96. if (kvm_vcpu_trap_il_is32bit(vcpu))
  97. esr |= ESR_ELx_IL;
  98. vcpu_write_sys_reg(vcpu, esr, ESR_EL1);
  99. }
  100. /**
  101. * kvm_inject_dabt - inject a data abort into the guest
  102. * @vcpu: The VCPU to receive the undefined exception
  103. * @addr: The address to report in the DFAR
  104. *
  105. * It is assumed that this code is called from the VCPU thread and that the
  106. * VCPU therefore is not currently executing guest code.
  107. */
  108. void kvm_inject_dabt(struct kvm_vcpu *vcpu, unsigned long addr)
  109. {
  110. if (vcpu_el1_is_32bit(vcpu))
  111. kvm_inject_dabt32(vcpu, addr);
  112. else
  113. inject_abt64(vcpu, false, addr);
  114. }
  115. /**
  116. * kvm_inject_pabt - inject a prefetch abort into the guest
  117. * @vcpu: The VCPU to receive the undefined exception
  118. * @addr: The address to report in the DFAR
  119. *
  120. * It is assumed that this code is called from the VCPU thread and that the
  121. * VCPU therefore is not currently executing guest code.
  122. */
  123. void kvm_inject_pabt(struct kvm_vcpu *vcpu, unsigned long addr)
  124. {
  125. if (vcpu_el1_is_32bit(vcpu))
  126. kvm_inject_pabt32(vcpu, addr);
  127. else
  128. inject_abt64(vcpu, true, addr);
  129. }
  130. /**
  131. * kvm_inject_undefined - inject an undefined instruction into the guest
  132. *
  133. * It is assumed that this code is called from the VCPU thread and that the
  134. * VCPU therefore is not currently executing guest code.
  135. */
  136. void kvm_inject_undefined(struct kvm_vcpu *vcpu)
  137. {
  138. if (vcpu_el1_is_32bit(vcpu))
  139. kvm_inject_undef32(vcpu);
  140. else
  141. inject_undef64(vcpu);
  142. }
  143. void kvm_set_sei_esr(struct kvm_vcpu *vcpu, u64 esr)
  144. {
  145. vcpu_set_vsesr(vcpu, esr & ESR_ELx_ISS_MASK);
  146. *vcpu_hcr(vcpu) |= HCR_VSE;
  147. }
  148. /**
  149. * kvm_inject_vabt - inject an async abort / SError into the guest
  150. * @vcpu: The VCPU to receive the exception
  151. *
  152. * It is assumed that this code is called from the VCPU thread and that the
  153. * VCPU therefore is not currently executing guest code.
  154. *
  155. * Systems with the RAS Extensions specify an imp-def ESR (ISV/IDS = 1) with
  156. * the remaining ISS all-zeros so that this error is not interpreted as an
  157. * uncategorized RAS error. Without the RAS Extensions we can't specify an ESR
  158. * value, so the CPU generates an imp-def value.
  159. */
  160. void kvm_inject_vabt(struct kvm_vcpu *vcpu)
  161. {
  162. kvm_set_sei_esr(vcpu, ESR_ELx_ISV);
  163. }