hyperv_evmcs.c 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright (C) 2018, Red Hat, Inc.
  4. *
  5. * Tests for Enlightened VMCS, including nested guest state.
  6. */
  7. #include <fcntl.h>
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include <string.h>
  11. #include <sys/ioctl.h>
  12. #include <linux/bitmap.h>
  13. #include "test_util.h"
  14. #include "kvm_util.h"
  15. #include "hyperv.h"
  16. #include "vmx.h"
  17. static int ud_count;
  18. static void guest_ud_handler(struct ex_regs *regs)
  19. {
  20. ud_count++;
  21. regs->rip += 3; /* VMLAUNCH */
  22. }
  23. static void guest_nmi_handler(struct ex_regs *regs)
  24. {
  25. }
  26. static inline void rdmsr_from_l2(uint32_t msr)
  27. {
  28. /* Currently, L1 doesn't preserve GPRs during vmexits. */
  29. __asm__ __volatile__ ("rdmsr" : : "c"(msr) :
  30. "rax", "rbx", "rdx", "rsi", "rdi", "r8", "r9",
  31. "r10", "r11", "r12", "r13", "r14", "r15");
  32. }
  33. /* Exit to L1 from L2 with RDMSR instruction */
  34. void l2_guest_code(void)
  35. {
  36. u64 unused;
  37. GUEST_SYNC(7);
  38. GUEST_SYNC(8);
  39. /* Forced exit to L1 upon restore */
  40. GUEST_SYNC(9);
  41. vmcall();
  42. /* MSR-Bitmap tests */
  43. rdmsr_from_l2(MSR_FS_BASE); /* intercepted */
  44. rdmsr_from_l2(MSR_FS_BASE); /* intercepted */
  45. rdmsr_from_l2(MSR_GS_BASE); /* not intercepted */
  46. vmcall();
  47. rdmsr_from_l2(MSR_GS_BASE); /* intercepted */
  48. /* L2 TLB flush tests */
  49. hyperv_hypercall(HVCALL_FLUSH_VIRTUAL_ADDRESS_SPACE | HV_HYPERCALL_FAST_BIT, 0x0,
  50. HV_FLUSH_ALL_VIRTUAL_ADDRESS_SPACES | HV_FLUSH_ALL_PROCESSORS);
  51. rdmsr_from_l2(MSR_FS_BASE);
  52. /*
  53. * Note: hypercall status (RAX) is not preserved correctly by L1 after
  54. * synthetic vmexit, use unchecked version.
  55. */
  56. __hyperv_hypercall(HVCALL_FLUSH_VIRTUAL_ADDRESS_SPACE | HV_HYPERCALL_FAST_BIT, 0x0,
  57. HV_FLUSH_ALL_VIRTUAL_ADDRESS_SPACES | HV_FLUSH_ALL_PROCESSORS,
  58. &unused);
  59. /* Done, exit to L1 and never come back. */
  60. vmcall();
  61. }
  62. void guest_code(struct vmx_pages *vmx_pages, struct hyperv_test_pages *hv_pages,
  63. vm_vaddr_t hv_hcall_page_gpa)
  64. {
  65. #define L2_GUEST_STACK_SIZE 64
  66. unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE];
  67. wrmsr(HV_X64_MSR_GUEST_OS_ID, HYPERV_LINUX_OS_ID);
  68. wrmsr(HV_X64_MSR_HYPERCALL, hv_hcall_page_gpa);
  69. x2apic_enable();
  70. GUEST_SYNC(1);
  71. GUEST_SYNC(2);
  72. enable_vp_assist(hv_pages->vp_assist_gpa, hv_pages->vp_assist);
  73. evmcs_enable();
  74. GUEST_ASSERT(prepare_for_vmx_operation(vmx_pages));
  75. GUEST_SYNC(3);
  76. GUEST_ASSERT(load_evmcs(hv_pages));
  77. GUEST_ASSERT(vmptrstz() == hv_pages->enlightened_vmcs_gpa);
  78. GUEST_SYNC(4);
  79. GUEST_ASSERT(vmptrstz() == hv_pages->enlightened_vmcs_gpa);
  80. prepare_vmcs(vmx_pages, l2_guest_code,
  81. &l2_guest_stack[L2_GUEST_STACK_SIZE]);
  82. GUEST_SYNC(5);
  83. GUEST_ASSERT(vmptrstz() == hv_pages->enlightened_vmcs_gpa);
  84. current_evmcs->revision_id = -1u;
  85. GUEST_ASSERT(vmlaunch());
  86. current_evmcs->revision_id = EVMCS_VERSION;
  87. GUEST_SYNC(6);
  88. vmwrite(PIN_BASED_VM_EXEC_CONTROL, vmreadz(PIN_BASED_VM_EXEC_CONTROL) |
  89. PIN_BASED_NMI_EXITING);
  90. /* L2 TLB flush setup */
  91. current_evmcs->partition_assist_page = hv_pages->partition_assist_gpa;
  92. current_evmcs->hv_enlightenments_control.nested_flush_hypercall = 1;
  93. current_evmcs->hv_vm_id = 1;
  94. current_evmcs->hv_vp_id = 1;
  95. current_vp_assist->nested_control.features.directhypercall = 1;
  96. *(u32 *)(hv_pages->partition_assist) = 0;
  97. GUEST_ASSERT(!vmlaunch());
  98. GUEST_ASSERT_EQ(vmreadz(VM_EXIT_REASON), EXIT_REASON_EXCEPTION_NMI);
  99. GUEST_ASSERT_EQ((vmreadz(VM_EXIT_INTR_INFO) & 0xff), NMI_VECTOR);
  100. GUEST_ASSERT(vmptrstz() == hv_pages->enlightened_vmcs_gpa);
  101. /*
  102. * NMI forces L2->L1 exit, resuming L2 and hope that EVMCS is
  103. * up-to-date (RIP points where it should and not at the beginning
  104. * of l2_guest_code(). GUEST_SYNC(9) checkes that.
  105. */
  106. GUEST_ASSERT(!vmresume());
  107. GUEST_SYNC(10);
  108. GUEST_ASSERT(vmreadz(VM_EXIT_REASON) == EXIT_REASON_VMCALL);
  109. current_evmcs->guest_rip += 3; /* vmcall */
  110. /* Intercept RDMSR 0xc0000100 */
  111. vmwrite(CPU_BASED_VM_EXEC_CONTROL, vmreadz(CPU_BASED_VM_EXEC_CONTROL) |
  112. CPU_BASED_USE_MSR_BITMAPS);
  113. __set_bit(MSR_FS_BASE & 0x1fff, vmx_pages->msr + 0x400);
  114. GUEST_ASSERT(!vmresume());
  115. GUEST_ASSERT(vmreadz(VM_EXIT_REASON) == EXIT_REASON_MSR_READ);
  116. current_evmcs->guest_rip += 2; /* rdmsr */
  117. /* Enable enlightened MSR bitmap */
  118. current_evmcs->hv_enlightenments_control.msr_bitmap = 1;
  119. GUEST_ASSERT(!vmresume());
  120. GUEST_ASSERT(vmreadz(VM_EXIT_REASON) == EXIT_REASON_MSR_READ);
  121. current_evmcs->guest_rip += 2; /* rdmsr */
  122. /* Intercept RDMSR 0xc0000101 without telling KVM about it */
  123. __set_bit(MSR_GS_BASE & 0x1fff, vmx_pages->msr + 0x400);
  124. /* Make sure HV_VMX_ENLIGHTENED_CLEAN_FIELD_MSR_BITMAP is set */
  125. current_evmcs->hv_clean_fields |= HV_VMX_ENLIGHTENED_CLEAN_FIELD_MSR_BITMAP;
  126. GUEST_ASSERT(!vmresume());
  127. /* Make sure we don't see EXIT_REASON_MSR_READ here so eMSR bitmap works */
  128. GUEST_ASSERT(vmreadz(VM_EXIT_REASON) == EXIT_REASON_VMCALL);
  129. current_evmcs->guest_rip += 3; /* vmcall */
  130. /* Now tell KVM we've changed MSR-Bitmap */
  131. current_evmcs->hv_clean_fields &= ~HV_VMX_ENLIGHTENED_CLEAN_FIELD_MSR_BITMAP;
  132. GUEST_ASSERT(!vmresume());
  133. GUEST_ASSERT(vmreadz(VM_EXIT_REASON) == EXIT_REASON_MSR_READ);
  134. current_evmcs->guest_rip += 2; /* rdmsr */
  135. /*
  136. * L2 TLB flush test. First VMCALL should be handled directly by L0,
  137. * no VMCALL exit expected.
  138. */
  139. GUEST_ASSERT(!vmresume());
  140. GUEST_ASSERT(vmreadz(VM_EXIT_REASON) == EXIT_REASON_MSR_READ);
  141. current_evmcs->guest_rip += 2; /* rdmsr */
  142. /* Enable synthetic vmexit */
  143. *(u32 *)(hv_pages->partition_assist) = 1;
  144. GUEST_ASSERT(!vmresume());
  145. GUEST_ASSERT(vmreadz(VM_EXIT_REASON) == HV_VMX_SYNTHETIC_EXIT_REASON_TRAP_AFTER_FLUSH);
  146. GUEST_ASSERT(!vmresume());
  147. GUEST_ASSERT(vmreadz(VM_EXIT_REASON) == EXIT_REASON_VMCALL);
  148. GUEST_SYNC(11);
  149. /* Try enlightened vmptrld with an incorrect GPA */
  150. evmcs_vmptrld(0xdeadbeef, hv_pages->enlightened_vmcs);
  151. GUEST_ASSERT(vmlaunch());
  152. GUEST_ASSERT(ud_count == 1);
  153. GUEST_DONE();
  154. }
  155. void inject_nmi(struct kvm_vcpu *vcpu)
  156. {
  157. struct kvm_vcpu_events events;
  158. vcpu_events_get(vcpu, &events);
  159. events.nmi.pending = 1;
  160. events.flags |= KVM_VCPUEVENT_VALID_NMI_PENDING;
  161. vcpu_events_set(vcpu, &events);
  162. }
  163. static struct kvm_vcpu *save_restore_vm(struct kvm_vm *vm,
  164. struct kvm_vcpu *vcpu)
  165. {
  166. struct kvm_regs regs1, regs2;
  167. struct kvm_x86_state *state;
  168. state = vcpu_save_state(vcpu);
  169. memset(&regs1, 0, sizeof(regs1));
  170. vcpu_regs_get(vcpu, &regs1);
  171. kvm_vm_release(vm);
  172. /* Restore state in a new VM. */
  173. vcpu = vm_recreate_with_one_vcpu(vm);
  174. vcpu_set_hv_cpuid(vcpu);
  175. vcpu_enable_evmcs(vcpu);
  176. vcpu_load_state(vcpu, state);
  177. kvm_x86_state_cleanup(state);
  178. memset(&regs2, 0, sizeof(regs2));
  179. vcpu_regs_get(vcpu, &regs2);
  180. TEST_ASSERT(!memcmp(&regs1, &regs2, sizeof(regs2)),
  181. "Unexpected register values after vcpu_load_state; rdi: %lx rsi: %lx",
  182. (ulong) regs2.rdi, (ulong) regs2.rsi);
  183. return vcpu;
  184. }
  185. int main(int argc, char *argv[])
  186. {
  187. vm_vaddr_t vmx_pages_gva = 0, hv_pages_gva = 0;
  188. vm_vaddr_t hcall_page;
  189. struct kvm_vcpu *vcpu;
  190. struct kvm_vm *vm;
  191. struct ucall uc;
  192. int stage;
  193. TEST_REQUIRE(kvm_cpu_has(X86_FEATURE_VMX));
  194. TEST_REQUIRE(kvm_has_cap(KVM_CAP_NESTED_STATE));
  195. TEST_REQUIRE(kvm_has_cap(KVM_CAP_HYPERV_ENLIGHTENED_VMCS));
  196. TEST_REQUIRE(kvm_hv_cpu_has(HV_X64_NESTED_DIRECT_FLUSH));
  197. vm = vm_create_with_one_vcpu(&vcpu, guest_code);
  198. hcall_page = vm_vaddr_alloc_pages(vm, 1);
  199. memset(addr_gva2hva(vm, hcall_page), 0x0, getpagesize());
  200. vcpu_set_hv_cpuid(vcpu);
  201. vcpu_enable_evmcs(vcpu);
  202. vcpu_alloc_vmx(vm, &vmx_pages_gva);
  203. vcpu_alloc_hyperv_test_pages(vm, &hv_pages_gva);
  204. vcpu_args_set(vcpu, 3, vmx_pages_gva, hv_pages_gva, addr_gva2gpa(vm, hcall_page));
  205. vcpu_set_msr(vcpu, HV_X64_MSR_VP_INDEX, vcpu->id);
  206. vm_install_exception_handler(vm, UD_VECTOR, guest_ud_handler);
  207. vm_install_exception_handler(vm, NMI_VECTOR, guest_nmi_handler);
  208. pr_info("Running L1 which uses EVMCS to run L2\n");
  209. for (stage = 1;; stage++) {
  210. vcpu_run(vcpu);
  211. TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO);
  212. switch (get_ucall(vcpu, &uc)) {
  213. case UCALL_ABORT:
  214. REPORT_GUEST_ASSERT(uc);
  215. /* NOT REACHED */
  216. case UCALL_SYNC:
  217. break;
  218. case UCALL_DONE:
  219. goto done;
  220. default:
  221. TEST_FAIL("Unknown ucall %lu", uc.cmd);
  222. }
  223. /* UCALL_SYNC is handled here. */
  224. TEST_ASSERT(!strcmp((const char *)uc.args[0], "hello") &&
  225. uc.args[1] == stage, "Stage %d: Unexpected register values vmexit, got %lx",
  226. stage, (ulong)uc.args[1]);
  227. vcpu = save_restore_vm(vm, vcpu);
  228. /* Force immediate L2->L1 exit before resuming */
  229. if (stage == 8) {
  230. pr_info("Injecting NMI into L1 before L2 had a chance to run after restore\n");
  231. inject_nmi(vcpu);
  232. }
  233. /*
  234. * Do KVM_GET_NESTED_STATE/KVM_SET_NESTED_STATE for a freshly
  235. * restored VM (before the first KVM_RUN) to check that
  236. * KVM_STATE_NESTED_EVMCS is not lost.
  237. */
  238. if (stage == 9) {
  239. pr_info("Trying extra KVM_GET_NESTED_STATE/KVM_SET_NESTED_STATE cycle\n");
  240. vcpu = save_restore_vm(vm, vcpu);
  241. }
  242. }
  243. done:
  244. kvm_vm_free(vm);
  245. }