mmio.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (C) 2012 - Virtual Open Systems and Columbia University
  4. * Author: Christoffer Dall <[email protected]>
  5. */
  6. #include <linux/kvm_host.h>
  7. #include <asm/kvm_emulate.h>
  8. #include <trace/events/kvm.h>
  9. #include "trace.h"
  10. void kvm_mmio_write_buf(void *buf, unsigned int len, unsigned long data)
  11. {
  12. void *datap = NULL;
  13. union {
  14. u8 byte;
  15. u16 hword;
  16. u32 word;
  17. u64 dword;
  18. } tmp;
  19. switch (len) {
  20. case 1:
  21. tmp.byte = data;
  22. datap = &tmp.byte;
  23. break;
  24. case 2:
  25. tmp.hword = data;
  26. datap = &tmp.hword;
  27. break;
  28. case 4:
  29. tmp.word = data;
  30. datap = &tmp.word;
  31. break;
  32. case 8:
  33. tmp.dword = data;
  34. datap = &tmp.dword;
  35. break;
  36. }
  37. memcpy(buf, datap, len);
  38. }
  39. unsigned long kvm_mmio_read_buf(const void *buf, unsigned int len)
  40. {
  41. unsigned long data = 0;
  42. union {
  43. u16 hword;
  44. u32 word;
  45. u64 dword;
  46. } tmp;
  47. switch (len) {
  48. case 1:
  49. data = *(u8 *)buf;
  50. break;
  51. case 2:
  52. memcpy(&tmp.hword, buf, len);
  53. data = tmp.hword;
  54. break;
  55. case 4:
  56. memcpy(&tmp.word, buf, len);
  57. data = tmp.word;
  58. break;
  59. case 8:
  60. memcpy(&tmp.dword, buf, len);
  61. data = tmp.dword;
  62. break;
  63. }
  64. return data;
  65. }
  66. /**
  67. * kvm_handle_mmio_return -- Handle MMIO loads after user space emulation
  68. * or in-kernel IO emulation
  69. *
  70. * @vcpu: The VCPU pointer
  71. */
  72. int kvm_handle_mmio_return(struct kvm_vcpu *vcpu)
  73. {
  74. unsigned long data;
  75. unsigned int len;
  76. int mask;
  77. /* Detect an already handled MMIO return */
  78. if (unlikely(!vcpu->mmio_needed))
  79. return 0;
  80. vcpu->mmio_needed = 0;
  81. if (!kvm_vcpu_dabt_iswrite(vcpu)) {
  82. struct kvm_run *run = vcpu->run;
  83. len = kvm_vcpu_dabt_get_as(vcpu);
  84. data = kvm_mmio_read_buf(run->mmio.data, len);
  85. if (kvm_vcpu_dabt_issext(vcpu) &&
  86. len < sizeof(unsigned long)) {
  87. mask = 1U << ((len * 8) - 1);
  88. data = (data ^ mask) - mask;
  89. }
  90. if (!kvm_vcpu_dabt_issf(vcpu))
  91. data = data & 0xffffffff;
  92. trace_kvm_mmio(KVM_TRACE_MMIO_READ, len, run->mmio.phys_addr,
  93. &data);
  94. data = vcpu_data_host_to_guest(vcpu, data, len);
  95. vcpu_set_reg(vcpu, kvm_vcpu_dabt_get_rd(vcpu), data);
  96. }
  97. /*
  98. * The MMIO instruction is emulated and should not be re-executed
  99. * in the guest.
  100. */
  101. kvm_incr_pc(vcpu);
  102. return 0;
  103. }
  104. int io_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa)
  105. {
  106. struct kvm_run *run = vcpu->run;
  107. unsigned long data;
  108. unsigned long rt;
  109. int ret;
  110. bool is_write;
  111. int len;
  112. u8 data_buf[8];
  113. /*
  114. * No valid syndrome? Ask userspace for help if it has
  115. * volunteered to do so, and bail out otherwise.
  116. *
  117. * In the protected VM case, there isn't much userspace can do
  118. * though, so directly deliver an exception to the guest.
  119. */
  120. if (!kvm_vcpu_dabt_isvalid(vcpu)) {
  121. if (is_protected_kvm_enabled() &&
  122. kvm_vm_is_protected(vcpu->kvm)) {
  123. kvm_inject_dabt(vcpu, kvm_vcpu_get_hfar(vcpu));
  124. return 1;
  125. }
  126. if (test_bit(KVM_ARCH_FLAG_RETURN_NISV_IO_ABORT_TO_USER,
  127. &vcpu->kvm->arch.flags)) {
  128. run->exit_reason = KVM_EXIT_ARM_NISV;
  129. run->arm_nisv.esr_iss = kvm_vcpu_dabt_iss_nisv_sanitized(vcpu);
  130. run->arm_nisv.fault_ipa = fault_ipa;
  131. return 0;
  132. }
  133. kvm_pr_unimpl("Data abort outside memslots with no valid syndrome info\n");
  134. return -ENOSYS;
  135. }
  136. /*
  137. * Prepare MMIO operation. First decode the syndrome data we get
  138. * from the CPU. Then try if some in-kernel emulation feels
  139. * responsible, otherwise let user space do its magic.
  140. */
  141. is_write = kvm_vcpu_dabt_iswrite(vcpu);
  142. len = kvm_vcpu_dabt_get_as(vcpu);
  143. rt = kvm_vcpu_dabt_get_rd(vcpu);
  144. if (is_write) {
  145. data = vcpu_data_guest_to_host(vcpu, vcpu_get_reg(vcpu, rt),
  146. len);
  147. trace_kvm_mmio(KVM_TRACE_MMIO_WRITE, len, fault_ipa, &data);
  148. kvm_mmio_write_buf(data_buf, len, data);
  149. ret = kvm_io_bus_write(vcpu, KVM_MMIO_BUS, fault_ipa, len,
  150. data_buf);
  151. } else {
  152. trace_kvm_mmio(KVM_TRACE_MMIO_READ_UNSATISFIED, len,
  153. fault_ipa, NULL);
  154. ret = kvm_io_bus_read(vcpu, KVM_MMIO_BUS, fault_ipa, len,
  155. data_buf);
  156. }
  157. /* Now prepare kvm_run for the potential return to userland. */
  158. run->mmio.is_write = is_write;
  159. run->mmio.phys_addr = fault_ipa;
  160. run->mmio.len = len;
  161. vcpu->mmio_needed = 1;
  162. if (!ret) {
  163. /* We handled the access successfully in the kernel. */
  164. if (!is_write)
  165. memcpy(run->mmio.data, data_buf, len);
  166. vcpu->stat.mmio_exit_kernel++;
  167. kvm_handle_mmio_return(vcpu);
  168. return 1;
  169. }
  170. if (is_write)
  171. memcpy(run->mmio.data, data_buf, len);
  172. vcpu->stat.mmio_exit_user++;
  173. run->exit_reason = KVM_EXIT_MMIO;
  174. return 0;
  175. }