Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

KVM: selftests: Test access to XMM fast hypercalls

Check that #UD is raised if bit 16 is clear in
HYPERV_CPUID_FEATURES.EDX and an 'XMM fast' hypercall is issued.

Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com>
Reviewed-by: Siddharth Chandrasekaran <sidcha@amazon.de>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20210730122625.112848-5-vkuznets@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>

authored by

Vitaly Kuznetsov and committed by
Paolo Bonzini
2476b5a1 4e62aa96

+42 -4
+4 -1
tools/testing/selftests/kvm/include/x86_64/hyperv.h
··· 117 117 #define HV_X64_GUEST_DEBUGGING_AVAILABLE BIT(1) 118 118 #define HV_X64_PERF_MONITOR_AVAILABLE BIT(2) 119 119 #define HV_X64_CPU_DYNAMIC_PARTITIONING_AVAILABLE BIT(3) 120 - #define HV_X64_HYPERCALL_PARAMS_XMM_AVAILABLE BIT(4) 120 + #define HV_X64_HYPERCALL_XMM_INPUT_AVAILABLE BIT(4) 121 121 #define HV_X64_GUEST_IDLE_STATE_AVAILABLE BIT(5) 122 122 #define HV_FEATURE_FREQUENCY_MSRS_AVAILABLE BIT(8) 123 123 #define HV_FEATURE_GUEST_CRASH_MSR_AVAILABLE BIT(10) ··· 181 181 #define HV_STATUS_INVALID_PORT_ID 17 182 182 #define HV_STATUS_INVALID_CONNECTION_ID 18 183 183 #define HV_STATUS_INSUFFICIENT_BUFFERS 19 184 + 185 + /* hypercall options */ 186 + #define HV_HYPERCALL_FAST_BIT BIT(16) 184 187 185 188 #endif /* !SELFTEST_KVM_HYPERV_H */
+38 -3
tools/testing/selftests/kvm/x86_64/hyperv_features.c
··· 47 47 } 48 48 49 49 static int nr_gp; 50 + static int nr_ud; 50 51 51 52 static inline u64 hypercall(u64 control, vm_vaddr_t input_address, 52 53 vm_vaddr_t output_address) ··· 81 80 regs->rip = (uint64_t)&wrmsr_end; 82 81 } 83 82 83 + static void guest_ud_handler(struct ex_regs *regs) 84 + { 85 + nr_ud++; 86 + regs->rip += 3; 87 + } 88 + 84 89 struct msr_data { 85 90 uint32_t idx; 86 91 bool available; ··· 97 90 struct hcall_data { 98 91 uint64_t control; 99 92 uint64_t expect; 93 + bool ud_expected; 100 94 }; 101 95 102 96 static void guest_msr(struct msr_data *msr) ··· 125 117 static void guest_hcall(vm_vaddr_t pgs_gpa, struct hcall_data *hcall) 126 118 { 127 119 int i = 0; 120 + u64 res, input, output; 128 121 129 122 wrmsr(HV_X64_MSR_GUEST_OS_ID, LINUX_OS_ID); 130 123 wrmsr(HV_X64_MSR_HYPERCALL, pgs_gpa); 131 124 132 125 while (hcall->control) { 133 - GUEST_ASSERT(hypercall(hcall->control, pgs_gpa, 134 - pgs_gpa + 4096) == hcall->expect); 126 + nr_ud = 0; 127 + if (!(hcall->control & HV_HYPERCALL_FAST_BIT)) { 128 + input = pgs_gpa; 129 + output = pgs_gpa + 4096; 130 + } else { 131 + input = output = 0; 132 + } 133 + 134 + res = hypercall(hcall->control, input, output); 135 + if (hcall->ud_expected) 136 + GUEST_ASSERT(nr_ud == 1); 137 + else 138 + GUEST_ASSERT(res == hcall->expect); 139 + 135 140 GUEST_SYNC(i++); 136 141 } 137 142 ··· 573 552 recomm.ebx = 0xfff; 574 553 hcall->expect = HV_STATUS_SUCCESS; 575 554 break; 576 - 577 555 case 17: 556 + /* XMM fast hypercall */ 557 + hcall->control = HVCALL_FLUSH_VIRTUAL_ADDRESS_SPACE | HV_HYPERCALL_FAST_BIT; 558 + hcall->ud_expected = true; 559 + break; 560 + case 18: 561 + feat.edx |= HV_X64_HYPERCALL_XMM_INPUT_AVAILABLE; 562 + hcall->ud_expected = false; 563 + hcall->expect = HV_STATUS_SUCCESS; 564 + break; 565 + 566 + case 19: 578 567 /* END */ 579 568 hcall->control = 0; 580 569 break; ··· 655 624 656 625 /* Test hypercalls */ 657 626 vm = vm_create_default(VCPU_ID, 0, guest_hcall); 627 + 628 + vm_init_descriptor_tables(vm); 629 + vcpu_init_descriptor_tables(vm, VCPU_ID); 630 + vm_install_exception_handler(vm, UD_VECTOR, guest_ud_handler); 658 631 659 632 /* Hypercall input/output */ 660 633 hcall_page = vm_vaddr_alloc_pages(vm, 2);