1e2e1cc1fSVitaly Kuznetsov // SPDX-License-Identifier: GPL-2.0-only
2e2e1cc1fSVitaly Kuznetsov /*
3e2e1cc1fSVitaly Kuznetsov  * Copyright (C) 2021, Red Hat, Inc.
4e2e1cc1fSVitaly Kuznetsov  *
5e2e1cc1fSVitaly Kuznetsov  * Tests for Hyper-V features enablement
6e2e1cc1fSVitaly Kuznetsov  */
7e2e1cc1fSVitaly Kuznetsov #include <asm/kvm_para.h>
8e2e1cc1fSVitaly Kuznetsov #include <linux/kvm_para.h>
9e2e1cc1fSVitaly Kuznetsov #include <stdint.h>
10e2e1cc1fSVitaly Kuznetsov 
11e2e1cc1fSVitaly Kuznetsov #include "test_util.h"
12e2e1cc1fSVitaly Kuznetsov #include "kvm_util.h"
13e2e1cc1fSVitaly Kuznetsov #include "processor.h"
14e2e1cc1fSVitaly Kuznetsov #include "hyperv.h"
15e2e1cc1fSVitaly Kuznetsov 
162f10428aSVitaly Kuznetsov /*
172f10428aSVitaly Kuznetsov  * HYPERV_CPUID_ENLIGHTMENT_INFO.EBX is not a 'feature' CPUID leaf
182f10428aSVitaly Kuznetsov  * but to activate the feature it is sufficient to set it to a non-zero
192f10428aSVitaly Kuznetsov  * value. Use BIT(0) for that.
202f10428aSVitaly Kuznetsov  */
212f10428aSVitaly Kuznetsov #define HV_PV_SPINLOCKS_TEST            \
222f10428aSVitaly Kuznetsov 	KVM_X86_CPU_FEATURE(HYPERV_CPUID_ENLIGHTMENT_INFO, 0, EBX, 0)
232f10428aSVitaly Kuznetsov 
24e2e1cc1fSVitaly Kuznetsov struct msr_data {
25e2e1cc1fSVitaly Kuznetsov 	uint32_t idx;
2667b16f18SVitaly Kuznetsov 	bool fault_expected;
27e2e1cc1fSVitaly Kuznetsov 	bool write;
28e2e1cc1fSVitaly Kuznetsov 	u64 write_val;
29e2e1cc1fSVitaly Kuznetsov };
30e2e1cc1fSVitaly Kuznetsov 
31e2e1cc1fSVitaly Kuznetsov struct hcall_data {
32e2e1cc1fSVitaly Kuznetsov 	uint64_t control;
33e2e1cc1fSVitaly Kuznetsov 	uint64_t expect;
342476b5a1SVitaly Kuznetsov 	bool ud_expected;
35e2e1cc1fSVitaly Kuznetsov };
36e2e1cc1fSVitaly Kuznetsov 
is_write_only_msr(uint32_t msr)3791a0b547SVitaly Kuznetsov static bool is_write_only_msr(uint32_t msr)
3891a0b547SVitaly Kuznetsov {
3991a0b547SVitaly Kuznetsov 	return msr == HV_X64_MSR_EOI;
4091a0b547SVitaly Kuznetsov }
4191a0b547SVitaly Kuznetsov 
guest_msr(struct msr_data * msr)42e2e1cc1fSVitaly Kuznetsov static void guest_msr(struct msr_data *msr)
43e2e1cc1fSVitaly Kuznetsov {
4491a0b547SVitaly Kuznetsov 	uint8_t vector = 0;
4591a0b547SVitaly Kuznetsov 	uint64_t msr_val = 0;
46cc5851c6SSean Christopherson 
479f88d062SSean Christopherson 	GUEST_ASSERT(msr->idx);
48e2e1cc1fSVitaly Kuznetsov 
4991a0b547SVitaly Kuznetsov 	if (msr->write)
50cc5851c6SSean Christopherson 		vector = wrmsr_safe(msr->idx, msr->write_val);
51e2e1cc1fSVitaly Kuznetsov 
5291a0b547SVitaly Kuznetsov 	if (!vector && (!msr->write || !is_write_only_msr(msr->idx)))
5391a0b547SVitaly Kuznetsov 		vector = rdmsr_safe(msr->idx, &msr_val);
5491a0b547SVitaly Kuznetsov 
5567b16f18SVitaly Kuznetsov 	if (msr->fault_expected)
568d1d3ce6SSean Christopherson 		__GUEST_ASSERT(vector == GP_VECTOR,
578d1d3ce6SSean Christopherson 			       "Expected #GP on %sMSR(0x%x), got vector '0x%x'",
588d1d3ce6SSean Christopherson 			       msr->idx, msr->write ? "WR" : "RD", vector);
5967b16f18SVitaly Kuznetsov 	else
608d1d3ce6SSean Christopherson 		__GUEST_ASSERT(!vector,
618d1d3ce6SSean Christopherson 			       "Expected success on %sMSR(0x%x), got vector '0x%x'",
628d1d3ce6SSean Christopherson 			       msr->idx, msr->write ? "WR" : "RD", vector);
6391a0b547SVitaly Kuznetsov 
6491a0b547SVitaly Kuznetsov 	if (vector || is_write_only_msr(msr->idx))
6591a0b547SVitaly Kuznetsov 		goto done;
6691a0b547SVitaly Kuznetsov 
6791a0b547SVitaly Kuznetsov 	if (msr->write)
688d1d3ce6SSean Christopherson 		__GUEST_ASSERT(!vector,
698d1d3ce6SSean Christopherson 			       "WRMSR(0x%x) to '0x%llx', RDMSR read '0x%llx'",
708d1d3ce6SSean Christopherson 			       msr->idx, msr->write_val, msr_val);
71bd827bd7SVitaly Kuznetsov 
72bd827bd7SVitaly Kuznetsov 	/* Invariant TSC bit appears when TSC invariant control MSR is written to */
73bd827bd7SVitaly Kuznetsov 	if (msr->idx == HV_X64_MSR_TSC_INVARIANT_CONTROL) {
74bd827bd7SVitaly Kuznetsov 		if (!this_cpu_has(HV_ACCESS_TSC_INVARIANT))
75bd827bd7SVitaly Kuznetsov 			GUEST_ASSERT(this_cpu_has(X86_FEATURE_INVTSC));
76bd827bd7SVitaly Kuznetsov 		else
77bd827bd7SVitaly Kuznetsov 			GUEST_ASSERT(this_cpu_has(X86_FEATURE_INVTSC) ==
78bd827bd7SVitaly Kuznetsov 				     !!(msr_val & HV_INVARIANT_TSC_EXPOSED));
79bd827bd7SVitaly Kuznetsov 	}
80bd827bd7SVitaly Kuznetsov 
8191a0b547SVitaly Kuznetsov done:
82e2e1cc1fSVitaly Kuznetsov 	GUEST_DONE();
83e2e1cc1fSVitaly Kuznetsov }
84e2e1cc1fSVitaly Kuznetsov 
guest_hcall(vm_vaddr_t pgs_gpa,struct hcall_data * hcall)85e2e1cc1fSVitaly Kuznetsov static void guest_hcall(vm_vaddr_t pgs_gpa, struct hcall_data *hcall)
86e2e1cc1fSVitaly Kuznetsov {
872476b5a1SVitaly Kuznetsov 	u64 res, input, output;
88cc5851c6SSean Christopherson 	uint8_t vector;
89e2e1cc1fSVitaly Kuznetsov 
908d1d3ce6SSean Christopherson 	GUEST_ASSERT_NE(hcall->control, 0);
919f88d062SSean Christopherson 
92c05a0a71SVitaly Kuznetsov 	wrmsr(HV_X64_MSR_GUEST_OS_ID, HYPERV_LINUX_OS_ID);
93e2e1cc1fSVitaly Kuznetsov 	wrmsr(HV_X64_MSR_HYPERCALL, pgs_gpa);
94e2e1cc1fSVitaly Kuznetsov 
952476b5a1SVitaly Kuznetsov 	if (!(hcall->control & HV_HYPERCALL_FAST_BIT)) {
962476b5a1SVitaly Kuznetsov 		input = pgs_gpa;
972476b5a1SVitaly Kuznetsov 		output = pgs_gpa + 4096;
982476b5a1SVitaly Kuznetsov 	} else {
992476b5a1SVitaly Kuznetsov 		input = output = 0;
1002476b5a1SVitaly Kuznetsov 	}
1012476b5a1SVitaly Kuznetsov 
10299848924SVitaly Kuznetsov 	vector = __hyperv_hypercall(hcall->control, input, output, &res);
103bf3f1158SVipin Sharma 	if (hcall->ud_expected) {
1048d1d3ce6SSean Christopherson 		__GUEST_ASSERT(vector == UD_VECTOR,
1058d1d3ce6SSean Christopherson 			       "Expected #UD for control '%u', got vector '0x%x'",
1068d1d3ce6SSean Christopherson 			       hcall->control, vector);
107bf3f1158SVipin Sharma 	} else {
1088d1d3ce6SSean Christopherson 		__GUEST_ASSERT(!vector,
1098d1d3ce6SSean Christopherson 			       "Expected no exception for control '%u', got vector '0x%x'",
1108d1d3ce6SSean Christopherson 			       hcall->control, vector);
1118d1d3ce6SSean Christopherson 		GUEST_ASSERT_EQ(res, hcall->expect);
112bf3f1158SVipin Sharma 	}
1132476b5a1SVitaly Kuznetsov 
114e2e1cc1fSVitaly Kuznetsov 	GUEST_DONE();
115e2e1cc1fSVitaly Kuznetsov }
116e2e1cc1fSVitaly Kuznetsov 
vcpu_reset_hv_cpuid(struct kvm_vcpu * vcpu)1174dcd130cSSean Christopherson static void vcpu_reset_hv_cpuid(struct kvm_vcpu *vcpu)
118e2e1cc1fSVitaly Kuznetsov {
1194dcd130cSSean Christopherson 	/*
1204dcd130cSSean Christopherson 	 * Enable all supported Hyper-V features, then clear the leafs holding
1214dcd130cSSean Christopherson 	 * the features that will be tested one by one.
1224dcd130cSSean Christopherson 	 */
1234dcd130cSSean Christopherson 	vcpu_set_hv_cpuid(vcpu);
1244dcd130cSSean Christopherson 
1254dcd130cSSean Christopherson 	vcpu_clear_cpuid_entry(vcpu, HYPERV_CPUID_FEATURES);
1264dcd130cSSean Christopherson 	vcpu_clear_cpuid_entry(vcpu, HYPERV_CPUID_ENLIGHTMENT_INFO);
1274dcd130cSSean Christopherson 	vcpu_clear_cpuid_entry(vcpu, HYPERV_CPUID_SYNDBG_PLATFORM_CAPABILITIES);
128e2e1cc1fSVitaly Kuznetsov }
129e2e1cc1fSVitaly Kuznetsov 
guest_test_msrs_access(void)1306c118643SVitaly Kuznetsov static void guest_test_msrs_access(void)
131e2e1cc1fSVitaly Kuznetsov {
1324dcd130cSSean Christopherson 	struct kvm_cpuid2 *prev_cpuid = NULL;
133d96b9596SSean Christopherson 	struct kvm_vcpu *vcpu;
1346c118643SVitaly Kuznetsov 	struct kvm_vm *vm;
135e2e1cc1fSVitaly Kuznetsov 	struct ucall uc;
136d96b9596SSean Christopherson 	int stage = 0;
1376c118643SVitaly Kuznetsov 	vm_vaddr_t msr_gva;
1386c118643SVitaly Kuznetsov 	struct msr_data *msr;
139bd827bd7SVitaly Kuznetsov 	bool has_invtsc = kvm_cpu_has(X86_FEATURE_INVTSC);
1406c118643SVitaly Kuznetsov 
1416c118643SVitaly Kuznetsov 	while (true) {
142d96b9596SSean Christopherson 		vm = vm_create_with_one_vcpu(&vcpu, guest_msr);
1436c118643SVitaly Kuznetsov 
1446c118643SVitaly Kuznetsov 		msr_gva = vm_vaddr_alloc_page(vm);
1456c118643SVitaly Kuznetsov 		memset(addr_gva2hva(vm, msr_gva), 0x0, getpagesize());
1466c118643SVitaly Kuznetsov 		msr = addr_gva2hva(vm, msr_gva);
1476c118643SVitaly Kuznetsov 
148768e9a61SSean Christopherson 		vcpu_args_set(vcpu, 1, msr_gva);
149768e9a61SSean Christopherson 		vcpu_enable_cap(vcpu, KVM_CAP_HYPERV_ENFORCE_CPUID, 1);
1506c118643SVitaly Kuznetsov 
1514dcd130cSSean Christopherson 		if (!prev_cpuid) {
1524dcd130cSSean Christopherson 			vcpu_reset_hv_cpuid(vcpu);
1536c118643SVitaly Kuznetsov 
1544dcd130cSSean Christopherson 			prev_cpuid = allocate_kvm_cpuid2(vcpu->cpuid->nent);
1554dcd130cSSean Christopherson 		} else {
1564dcd130cSSean Christopherson 			vcpu_init_cpuid(vcpu, prev_cpuid);
1574dcd130cSSean Christopherson 		}
1584dcd130cSSean Christopherson 
1596c118643SVitaly Kuznetsov 		vm_init_descriptor_tables(vm);
160768e9a61SSean Christopherson 		vcpu_init_descriptor_tables(vcpu);
161e2e1cc1fSVitaly Kuznetsov 
1629f88d062SSean Christopherson 		/* TODO: Make this entire test easier to maintain. */
1639f88d062SSean Christopherson 		if (stage >= 21)
1649f88d062SSean Christopherson 			vcpu_enable_cap(vcpu, KVM_CAP_HYPERV_SYNIC2, 0);
1659f88d062SSean Christopherson 
166e2e1cc1fSVitaly Kuznetsov 		switch (stage) {
167e2e1cc1fSVitaly Kuznetsov 		case 0:
168e2e1cc1fSVitaly Kuznetsov 			/*
169e2e1cc1fSVitaly Kuznetsov 			 * Only available when Hyper-V identification is set
170e2e1cc1fSVitaly Kuznetsov 			 */
171e2e1cc1fSVitaly Kuznetsov 			msr->idx = HV_X64_MSR_GUEST_OS_ID;
17267b16f18SVitaly Kuznetsov 			msr->write = false;
17367b16f18SVitaly Kuznetsov 			msr->fault_expected = true;
174e2e1cc1fSVitaly Kuznetsov 			break;
175e2e1cc1fSVitaly Kuznetsov 		case 1:
176e2e1cc1fSVitaly Kuznetsov 			msr->idx = HV_X64_MSR_HYPERCALL;
17767b16f18SVitaly Kuznetsov 			msr->write = false;
17867b16f18SVitaly Kuznetsov 			msr->fault_expected = true;
179e2e1cc1fSVitaly Kuznetsov 			break;
180e2e1cc1fSVitaly Kuznetsov 		case 2:
1812f10428aSVitaly Kuznetsov 			vcpu_set_cpuid_feature(vcpu, HV_MSR_HYPERCALL_AVAILABLE);
182e2e1cc1fSVitaly Kuznetsov 			/*
183e2e1cc1fSVitaly Kuznetsov 			 * HV_X64_MSR_GUEST_OS_ID has to be written first to make
184e2e1cc1fSVitaly Kuznetsov 			 * HV_X64_MSR_HYPERCALL available.
185e2e1cc1fSVitaly Kuznetsov 			 */
186e2e1cc1fSVitaly Kuznetsov 			msr->idx = HV_X64_MSR_GUEST_OS_ID;
18767b16f18SVitaly Kuznetsov 			msr->write = true;
188c05a0a71SVitaly Kuznetsov 			msr->write_val = HYPERV_LINUX_OS_ID;
18967b16f18SVitaly Kuznetsov 			msr->fault_expected = false;
190e2e1cc1fSVitaly Kuznetsov 			break;
191e2e1cc1fSVitaly Kuznetsov 		case 3:
192e2e1cc1fSVitaly Kuznetsov 			msr->idx = HV_X64_MSR_GUEST_OS_ID;
19367b16f18SVitaly Kuznetsov 			msr->write = false;
19467b16f18SVitaly Kuznetsov 			msr->fault_expected = false;
195e2e1cc1fSVitaly Kuznetsov 			break;
196e2e1cc1fSVitaly Kuznetsov 		case 4:
197e2e1cc1fSVitaly Kuznetsov 			msr->idx = HV_X64_MSR_HYPERCALL;
19867b16f18SVitaly Kuznetsov 			msr->write = false;
19967b16f18SVitaly Kuznetsov 			msr->fault_expected = false;
200e2e1cc1fSVitaly Kuznetsov 			break;
201e2e1cc1fSVitaly Kuznetsov 
202e2e1cc1fSVitaly Kuznetsov 		case 5:
203e2e1cc1fSVitaly Kuznetsov 			msr->idx = HV_X64_MSR_VP_RUNTIME;
20467b16f18SVitaly Kuznetsov 			msr->write = false;
20567b16f18SVitaly Kuznetsov 			msr->fault_expected = true;
206e2e1cc1fSVitaly Kuznetsov 			break;
207e2e1cc1fSVitaly Kuznetsov 		case 6:
2082f10428aSVitaly Kuznetsov 			vcpu_set_cpuid_feature(vcpu, HV_MSR_VP_RUNTIME_AVAILABLE);
2099f88d062SSean Christopherson 			msr->idx = HV_X64_MSR_VP_RUNTIME;
21067b16f18SVitaly Kuznetsov 			msr->write = false;
21167b16f18SVitaly Kuznetsov 			msr->fault_expected = false;
212e2e1cc1fSVitaly Kuznetsov 			break;
213e2e1cc1fSVitaly Kuznetsov 		case 7:
214e2e1cc1fSVitaly Kuznetsov 			/* Read only */
2159f88d062SSean Christopherson 			msr->idx = HV_X64_MSR_VP_RUNTIME;
21667b16f18SVitaly Kuznetsov 			msr->write = true;
217e2e1cc1fSVitaly Kuznetsov 			msr->write_val = 1;
21867b16f18SVitaly Kuznetsov 			msr->fault_expected = true;
219e2e1cc1fSVitaly Kuznetsov 			break;
220e2e1cc1fSVitaly Kuznetsov 
221e2e1cc1fSVitaly Kuznetsov 		case 8:
222e2e1cc1fSVitaly Kuznetsov 			msr->idx = HV_X64_MSR_TIME_REF_COUNT;
22367b16f18SVitaly Kuznetsov 			msr->write = false;
22467b16f18SVitaly Kuznetsov 			msr->fault_expected = true;
225e2e1cc1fSVitaly Kuznetsov 			break;
226e2e1cc1fSVitaly Kuznetsov 		case 9:
2272f10428aSVitaly Kuznetsov 			vcpu_set_cpuid_feature(vcpu, HV_MSR_TIME_REF_COUNT_AVAILABLE);
2289f88d062SSean Christopherson 			msr->idx = HV_X64_MSR_TIME_REF_COUNT;
22967b16f18SVitaly Kuznetsov 			msr->write = false;
23067b16f18SVitaly Kuznetsov 			msr->fault_expected = false;
231e2e1cc1fSVitaly Kuznetsov 			break;
232e2e1cc1fSVitaly Kuznetsov 		case 10:
233e2e1cc1fSVitaly Kuznetsov 			/* Read only */
2349f88d062SSean Christopherson 			msr->idx = HV_X64_MSR_TIME_REF_COUNT;
23567b16f18SVitaly Kuznetsov 			msr->write = true;
236e2e1cc1fSVitaly Kuznetsov 			msr->write_val = 1;
23767b16f18SVitaly Kuznetsov 			msr->fault_expected = true;
238e2e1cc1fSVitaly Kuznetsov 			break;
239e2e1cc1fSVitaly Kuznetsov 
240e2e1cc1fSVitaly Kuznetsov 		case 11:
241e2e1cc1fSVitaly Kuznetsov 			msr->idx = HV_X64_MSR_VP_INDEX;
24267b16f18SVitaly Kuznetsov 			msr->write = false;
24367b16f18SVitaly Kuznetsov 			msr->fault_expected = true;
244e2e1cc1fSVitaly Kuznetsov 			break;
245e2e1cc1fSVitaly Kuznetsov 		case 12:
2462f10428aSVitaly Kuznetsov 			vcpu_set_cpuid_feature(vcpu, HV_MSR_VP_INDEX_AVAILABLE);
2479f88d062SSean Christopherson 			msr->idx = HV_X64_MSR_VP_INDEX;
24867b16f18SVitaly Kuznetsov 			msr->write = false;
24967b16f18SVitaly Kuznetsov 			msr->fault_expected = false;
250e2e1cc1fSVitaly Kuznetsov 			break;
251e2e1cc1fSVitaly Kuznetsov 		case 13:
252e2e1cc1fSVitaly Kuznetsov 			/* Read only */
2539f88d062SSean Christopherson 			msr->idx = HV_X64_MSR_VP_INDEX;
25467b16f18SVitaly Kuznetsov 			msr->write = true;
255e2e1cc1fSVitaly Kuznetsov 			msr->write_val = 1;
25667b16f18SVitaly Kuznetsov 			msr->fault_expected = true;
257e2e1cc1fSVitaly Kuznetsov 			break;
258e2e1cc1fSVitaly Kuznetsov 
259e2e1cc1fSVitaly Kuznetsov 		case 14:
260e2e1cc1fSVitaly Kuznetsov 			msr->idx = HV_X64_MSR_RESET;
26167b16f18SVitaly Kuznetsov 			msr->write = false;
26267b16f18SVitaly Kuznetsov 			msr->fault_expected = true;
263e2e1cc1fSVitaly Kuznetsov 			break;
264e2e1cc1fSVitaly Kuznetsov 		case 15:
2652f10428aSVitaly Kuznetsov 			vcpu_set_cpuid_feature(vcpu, HV_MSR_RESET_AVAILABLE);
2669f88d062SSean Christopherson 			msr->idx = HV_X64_MSR_RESET;
26767b16f18SVitaly Kuznetsov 			msr->write = false;
26867b16f18SVitaly Kuznetsov 			msr->fault_expected = false;
269e2e1cc1fSVitaly Kuznetsov 			break;
270e2e1cc1fSVitaly Kuznetsov 		case 16:
2719f88d062SSean Christopherson 			msr->idx = HV_X64_MSR_RESET;
27267b16f18SVitaly Kuznetsov 			msr->write = true;
27391a0b547SVitaly Kuznetsov 			/*
27491a0b547SVitaly Kuznetsov 			 * TODO: the test only writes '0' to HV_X64_MSR_RESET
27591a0b547SVitaly Kuznetsov 			 * at the moment, writing some other value there will
27691a0b547SVitaly Kuznetsov 			 * trigger real vCPU reset and the code is not prepared
27791a0b547SVitaly Kuznetsov 			 * to handle it yet.
27891a0b547SVitaly Kuznetsov 			 */
279e2e1cc1fSVitaly Kuznetsov 			msr->write_val = 0;
28067b16f18SVitaly Kuznetsov 			msr->fault_expected = false;
281e2e1cc1fSVitaly Kuznetsov 			break;
282e2e1cc1fSVitaly Kuznetsov 
283e2e1cc1fSVitaly Kuznetsov 		case 17:
284e2e1cc1fSVitaly Kuznetsov 			msr->idx = HV_X64_MSR_REFERENCE_TSC;
28567b16f18SVitaly Kuznetsov 			msr->write = false;
28667b16f18SVitaly Kuznetsov 			msr->fault_expected = true;
287e2e1cc1fSVitaly Kuznetsov 			break;
288e2e1cc1fSVitaly Kuznetsov 		case 18:
2892f10428aSVitaly Kuznetsov 			vcpu_set_cpuid_feature(vcpu, HV_MSR_REFERENCE_TSC_AVAILABLE);
2909f88d062SSean Christopherson 			msr->idx = HV_X64_MSR_REFERENCE_TSC;
29167b16f18SVitaly Kuznetsov 			msr->write = false;
29267b16f18SVitaly Kuznetsov 			msr->fault_expected = false;
293e2e1cc1fSVitaly Kuznetsov 			break;
294e2e1cc1fSVitaly Kuznetsov 		case 19:
2959f88d062SSean Christopherson 			msr->idx = HV_X64_MSR_REFERENCE_TSC;
29667b16f18SVitaly Kuznetsov 			msr->write = true;
297e2e1cc1fSVitaly Kuznetsov 			msr->write_val = 0;
29867b16f18SVitaly Kuznetsov 			msr->fault_expected = false;
299e2e1cc1fSVitaly Kuznetsov 			break;
300e2e1cc1fSVitaly Kuznetsov 
301e2e1cc1fSVitaly Kuznetsov 		case 20:
302e2e1cc1fSVitaly Kuznetsov 			msr->idx = HV_X64_MSR_EOM;
30367b16f18SVitaly Kuznetsov 			msr->write = false;
30467b16f18SVitaly Kuznetsov 			msr->fault_expected = true;
305e2e1cc1fSVitaly Kuznetsov 			break;
306e2e1cc1fSVitaly Kuznetsov 		case 21:
307e2e1cc1fSVitaly Kuznetsov 			/*
308e2e1cc1fSVitaly Kuznetsov 			 * Remains unavailable even with KVM_CAP_HYPERV_SYNIC2
309e2e1cc1fSVitaly Kuznetsov 			 * capability enabled and guest visible CPUID bit unset.
310e2e1cc1fSVitaly Kuznetsov 			 */
3119f88d062SSean Christopherson 			msr->idx = HV_X64_MSR_EOM;
31267b16f18SVitaly Kuznetsov 			msr->write = false;
31367b16f18SVitaly Kuznetsov 			msr->fault_expected = true;
314e2e1cc1fSVitaly Kuznetsov 			break;
315e2e1cc1fSVitaly Kuznetsov 		case 22:
3162f10428aSVitaly Kuznetsov 			vcpu_set_cpuid_feature(vcpu, HV_MSR_SYNIC_AVAILABLE);
3179f88d062SSean Christopherson 			msr->idx = HV_X64_MSR_EOM;
31867b16f18SVitaly Kuznetsov 			msr->write = false;
31967b16f18SVitaly Kuznetsov 			msr->fault_expected = false;
320e2e1cc1fSVitaly Kuznetsov 			break;
321e2e1cc1fSVitaly Kuznetsov 		case 23:
3229f88d062SSean Christopherson 			msr->idx = HV_X64_MSR_EOM;
32367b16f18SVitaly Kuznetsov 			msr->write = true;
324e2e1cc1fSVitaly Kuznetsov 			msr->write_val = 0;
32567b16f18SVitaly Kuznetsov 			msr->fault_expected = false;
326e2e1cc1fSVitaly Kuznetsov 			break;
327e2e1cc1fSVitaly Kuznetsov 
328e2e1cc1fSVitaly Kuznetsov 		case 24:
329e2e1cc1fSVitaly Kuznetsov 			msr->idx = HV_X64_MSR_STIMER0_CONFIG;
33067b16f18SVitaly Kuznetsov 			msr->write = false;
33167b16f18SVitaly Kuznetsov 			msr->fault_expected = true;
332e2e1cc1fSVitaly Kuznetsov 			break;
333e2e1cc1fSVitaly Kuznetsov 		case 25:
3342f10428aSVitaly Kuznetsov 			vcpu_set_cpuid_feature(vcpu, HV_MSR_SYNTIMER_AVAILABLE);
3359f88d062SSean Christopherson 			msr->idx = HV_X64_MSR_STIMER0_CONFIG;
33667b16f18SVitaly Kuznetsov 			msr->write = false;
33767b16f18SVitaly Kuznetsov 			msr->fault_expected = false;
338e2e1cc1fSVitaly Kuznetsov 			break;
339e2e1cc1fSVitaly Kuznetsov 		case 26:
3409f88d062SSean Christopherson 			msr->idx = HV_X64_MSR_STIMER0_CONFIG;
34167b16f18SVitaly Kuznetsov 			msr->write = true;
342e2e1cc1fSVitaly Kuznetsov 			msr->write_val = 0;
34367b16f18SVitaly Kuznetsov 			msr->fault_expected = false;
344e2e1cc1fSVitaly Kuznetsov 			break;
345e2e1cc1fSVitaly Kuznetsov 		case 27:
346e2e1cc1fSVitaly Kuznetsov 			/* Direct mode test */
3479f88d062SSean Christopherson 			msr->idx = HV_X64_MSR_STIMER0_CONFIG;
34867b16f18SVitaly Kuznetsov 			msr->write = true;
349e2e1cc1fSVitaly Kuznetsov 			msr->write_val = 1 << 12;
35067b16f18SVitaly Kuznetsov 			msr->fault_expected = true;
351e2e1cc1fSVitaly Kuznetsov 			break;
352e2e1cc1fSVitaly Kuznetsov 		case 28:
3532f10428aSVitaly Kuznetsov 			vcpu_set_cpuid_feature(vcpu, HV_STIMER_DIRECT_MODE_AVAILABLE);
3549f88d062SSean Christopherson 			msr->idx = HV_X64_MSR_STIMER0_CONFIG;
35567b16f18SVitaly Kuznetsov 			msr->write = true;
3569f88d062SSean Christopherson 			msr->write_val = 1 << 12;
35767b16f18SVitaly Kuznetsov 			msr->fault_expected = false;
358e2e1cc1fSVitaly Kuznetsov 			break;
359e2e1cc1fSVitaly Kuznetsov 
360e2e1cc1fSVitaly Kuznetsov 		case 29:
361e2e1cc1fSVitaly Kuznetsov 			msr->idx = HV_X64_MSR_EOI;
36267b16f18SVitaly Kuznetsov 			msr->write = false;
36367b16f18SVitaly Kuznetsov 			msr->fault_expected = true;
364e2e1cc1fSVitaly Kuznetsov 			break;
365e2e1cc1fSVitaly Kuznetsov 		case 30:
3662f10428aSVitaly Kuznetsov 			vcpu_set_cpuid_feature(vcpu, HV_MSR_APIC_ACCESS_AVAILABLE);
3679f88d062SSean Christopherson 			msr->idx = HV_X64_MSR_EOI;
36867b16f18SVitaly Kuznetsov 			msr->write = true;
369e2e1cc1fSVitaly Kuznetsov 			msr->write_val = 1;
37067b16f18SVitaly Kuznetsov 			msr->fault_expected = false;
371e2e1cc1fSVitaly Kuznetsov 			break;
372e2e1cc1fSVitaly Kuznetsov 
373e2e1cc1fSVitaly Kuznetsov 		case 31:
374e2e1cc1fSVitaly Kuznetsov 			msr->idx = HV_X64_MSR_TSC_FREQUENCY;
37567b16f18SVitaly Kuznetsov 			msr->write = false;
37667b16f18SVitaly Kuznetsov 			msr->fault_expected = true;
377e2e1cc1fSVitaly Kuznetsov 			break;
378e2e1cc1fSVitaly Kuznetsov 		case 32:
3792f10428aSVitaly Kuznetsov 			vcpu_set_cpuid_feature(vcpu, HV_ACCESS_FREQUENCY_MSRS);
3809f88d062SSean Christopherson 			msr->idx = HV_X64_MSR_TSC_FREQUENCY;
38167b16f18SVitaly Kuznetsov 			msr->write = false;
38267b16f18SVitaly Kuznetsov 			msr->fault_expected = false;
383e2e1cc1fSVitaly Kuznetsov 			break;
384e2e1cc1fSVitaly Kuznetsov 		case 33:
385e2e1cc1fSVitaly Kuznetsov 			/* Read only */
3869f88d062SSean Christopherson 			msr->idx = HV_X64_MSR_TSC_FREQUENCY;
38767b16f18SVitaly Kuznetsov 			msr->write = true;
388e2e1cc1fSVitaly Kuznetsov 			msr->write_val = 1;
38967b16f18SVitaly Kuznetsov 			msr->fault_expected = true;
390e2e1cc1fSVitaly Kuznetsov 			break;
391e2e1cc1fSVitaly Kuznetsov 
392e2e1cc1fSVitaly Kuznetsov 		case 34:
393e2e1cc1fSVitaly Kuznetsov 			msr->idx = HV_X64_MSR_REENLIGHTENMENT_CONTROL;
39467b16f18SVitaly Kuznetsov 			msr->write = false;
39567b16f18SVitaly Kuznetsov 			msr->fault_expected = true;
396e2e1cc1fSVitaly Kuznetsov 			break;
397e2e1cc1fSVitaly Kuznetsov 		case 35:
3982f10428aSVitaly Kuznetsov 			vcpu_set_cpuid_feature(vcpu, HV_ACCESS_REENLIGHTENMENT);
3999f88d062SSean Christopherson 			msr->idx = HV_X64_MSR_REENLIGHTENMENT_CONTROL;
40067b16f18SVitaly Kuznetsov 			msr->write = false;
40167b16f18SVitaly Kuznetsov 			msr->fault_expected = false;
402e2e1cc1fSVitaly Kuznetsov 			break;
403e2e1cc1fSVitaly Kuznetsov 		case 36:
4049f88d062SSean Christopherson 			msr->idx = HV_X64_MSR_REENLIGHTENMENT_CONTROL;
40567b16f18SVitaly Kuznetsov 			msr->write = true;
406e2e1cc1fSVitaly Kuznetsov 			msr->write_val = 1;
40767b16f18SVitaly Kuznetsov 			msr->fault_expected = false;
408e2e1cc1fSVitaly Kuznetsov 			break;
409e2e1cc1fSVitaly Kuznetsov 		case 37:
410e2e1cc1fSVitaly Kuznetsov 			/* Can only write '0' */
411e2e1cc1fSVitaly Kuznetsov 			msr->idx = HV_X64_MSR_TSC_EMULATION_STATUS;
41267b16f18SVitaly Kuznetsov 			msr->write = true;
413e2e1cc1fSVitaly Kuznetsov 			msr->write_val = 1;
41467b16f18SVitaly Kuznetsov 			msr->fault_expected = true;
415e2e1cc1fSVitaly Kuznetsov 			break;
416e2e1cc1fSVitaly Kuznetsov 
417e2e1cc1fSVitaly Kuznetsov 		case 38:
418e2e1cc1fSVitaly Kuznetsov 			msr->idx = HV_X64_MSR_CRASH_P0;
41967b16f18SVitaly Kuznetsov 			msr->write = false;
42067b16f18SVitaly Kuznetsov 			msr->fault_expected = true;
421e2e1cc1fSVitaly Kuznetsov 			break;
422e2e1cc1fSVitaly Kuznetsov 		case 39:
4232f10428aSVitaly Kuznetsov 			vcpu_set_cpuid_feature(vcpu, HV_FEATURE_GUEST_CRASH_MSR_AVAILABLE);
4249f88d062SSean Christopherson 			msr->idx = HV_X64_MSR_CRASH_P0;
42567b16f18SVitaly Kuznetsov 			msr->write = false;
42667b16f18SVitaly Kuznetsov 			msr->fault_expected = false;
427e2e1cc1fSVitaly Kuznetsov 			break;
428e2e1cc1fSVitaly Kuznetsov 		case 40:
4299f88d062SSean Christopherson 			msr->idx = HV_X64_MSR_CRASH_P0;
43067b16f18SVitaly Kuznetsov 			msr->write = true;
431e2e1cc1fSVitaly Kuznetsov 			msr->write_val = 1;
43267b16f18SVitaly Kuznetsov 			msr->fault_expected = false;
433e2e1cc1fSVitaly Kuznetsov 			break;
434e2e1cc1fSVitaly Kuznetsov 
435e2e1cc1fSVitaly Kuznetsov 		case 41:
436e2e1cc1fSVitaly Kuznetsov 			msr->idx = HV_X64_MSR_SYNDBG_STATUS;
43767b16f18SVitaly Kuznetsov 			msr->write = false;
43867b16f18SVitaly Kuznetsov 			msr->fault_expected = true;
439e2e1cc1fSVitaly Kuznetsov 			break;
440e2e1cc1fSVitaly Kuznetsov 		case 42:
4412f10428aSVitaly Kuznetsov 			vcpu_set_cpuid_feature(vcpu, HV_FEATURE_DEBUG_MSRS_AVAILABLE);
4422f10428aSVitaly Kuznetsov 			vcpu_set_cpuid_feature(vcpu, HV_X64_SYNDBG_CAP_ALLOW_KERNEL_DEBUGGING);
4439f88d062SSean Christopherson 			msr->idx = HV_X64_MSR_SYNDBG_STATUS;
44467b16f18SVitaly Kuznetsov 			msr->write = false;
44567b16f18SVitaly Kuznetsov 			msr->fault_expected = false;
446e2e1cc1fSVitaly Kuznetsov 			break;
447e2e1cc1fSVitaly Kuznetsov 		case 43:
4489f88d062SSean Christopherson 			msr->idx = HV_X64_MSR_SYNDBG_STATUS;
44967b16f18SVitaly Kuznetsov 			msr->write = true;
450e2e1cc1fSVitaly Kuznetsov 			msr->write_val = 0;
45167b16f18SVitaly Kuznetsov 			msr->fault_expected = false;
452e2e1cc1fSVitaly Kuznetsov 			break;
453e2e1cc1fSVitaly Kuznetsov 
454e2e1cc1fSVitaly Kuznetsov 		case 44:
455bd827bd7SVitaly Kuznetsov 			/* MSR is not available when CPUID feature bit is unset */
456bd827bd7SVitaly Kuznetsov 			if (!has_invtsc)
457*267f7b04SVitaly Kuznetsov 				goto next_stage;
458bd827bd7SVitaly Kuznetsov 			msr->idx = HV_X64_MSR_TSC_INVARIANT_CONTROL;
459bd827bd7SVitaly Kuznetsov 			msr->write = false;
460bd827bd7SVitaly Kuznetsov 			msr->fault_expected = true;
461bd827bd7SVitaly Kuznetsov 			break;
462bd827bd7SVitaly Kuznetsov 		case 45:
463bd827bd7SVitaly Kuznetsov 			/* MSR is vailable when CPUID feature bit is set */
464bd827bd7SVitaly Kuznetsov 			if (!has_invtsc)
465*267f7b04SVitaly Kuznetsov 				goto next_stage;
466bd827bd7SVitaly Kuznetsov 			vcpu_set_cpuid_feature(vcpu, HV_ACCESS_TSC_INVARIANT);
467bd827bd7SVitaly Kuznetsov 			msr->idx = HV_X64_MSR_TSC_INVARIANT_CONTROL;
468bd827bd7SVitaly Kuznetsov 			msr->write = false;
469bd827bd7SVitaly Kuznetsov 			msr->fault_expected = false;
470bd827bd7SVitaly Kuznetsov 			break;
471bd827bd7SVitaly Kuznetsov 		case 46:
472bd827bd7SVitaly Kuznetsov 			/* Writing bits other than 0 is forbidden */
473bd827bd7SVitaly Kuznetsov 			if (!has_invtsc)
474*267f7b04SVitaly Kuznetsov 				goto next_stage;
475bd827bd7SVitaly Kuznetsov 			msr->idx = HV_X64_MSR_TSC_INVARIANT_CONTROL;
476bd827bd7SVitaly Kuznetsov 			msr->write = true;
477bd827bd7SVitaly Kuznetsov 			msr->write_val = 0xdeadbeef;
478bd827bd7SVitaly Kuznetsov 			msr->fault_expected = true;
479bd827bd7SVitaly Kuznetsov 			break;
480bd827bd7SVitaly Kuznetsov 		case 47:
481bd827bd7SVitaly Kuznetsov 			/* Setting bit 0 enables the feature */
482bd827bd7SVitaly Kuznetsov 			if (!has_invtsc)
483*267f7b04SVitaly Kuznetsov 				goto next_stage;
484bd827bd7SVitaly Kuznetsov 			msr->idx = HV_X64_MSR_TSC_INVARIANT_CONTROL;
485bd827bd7SVitaly Kuznetsov 			msr->write = true;
486bd827bd7SVitaly Kuznetsov 			msr->write_val = 1;
487bd827bd7SVitaly Kuznetsov 			msr->fault_expected = false;
488bd827bd7SVitaly Kuznetsov 			break;
489bd827bd7SVitaly Kuznetsov 
490bd827bd7SVitaly Kuznetsov 		default:
4919f88d062SSean Christopherson 			kvm_vm_free(vm);
4929f88d062SSean Christopherson 			return;
493e2e1cc1fSVitaly Kuznetsov 		}
494e2e1cc1fSVitaly Kuznetsov 
4954dcd130cSSean Christopherson 		vcpu_set_cpuid(vcpu);
4964dcd130cSSean Christopherson 
4974dcd130cSSean Christopherson 		memcpy(prev_cpuid, vcpu->cpuid, kvm_cpuid2_size(vcpu->cpuid->nent));
498e2e1cc1fSVitaly Kuznetsov 
499e2e1cc1fSVitaly Kuznetsov 		pr_debug("Stage %d: testing msr: 0x%x for %s\n", stage,
500e2e1cc1fSVitaly Kuznetsov 			 msr->idx, msr->write ? "write" : "read");
501e2e1cc1fSVitaly Kuznetsov 
502768e9a61SSean Christopherson 		vcpu_run(vcpu);
503c96f57b0SVipin Sharma 		TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO);
504e2e1cc1fSVitaly Kuznetsov 
505768e9a61SSean Christopherson 		switch (get_ucall(vcpu, &uc)) {
506e2e1cc1fSVitaly Kuznetsov 		case UCALL_ABORT:
5078d1d3ce6SSean Christopherson 			REPORT_GUEST_ASSERT(uc);
508e2e1cc1fSVitaly Kuznetsov 			return;
509e2e1cc1fSVitaly Kuznetsov 		case UCALL_DONE:
5109f88d062SSean Christopherson 			break;
5119f88d062SSean Christopherson 		default:
5129f88d062SSean Christopherson 			TEST_FAIL("Unhandled ucall: %ld", uc.cmd);
513e2e1cc1fSVitaly Kuznetsov 			return;
514e2e1cc1fSVitaly Kuznetsov 		}
515e2e1cc1fSVitaly Kuznetsov 
516*267f7b04SVitaly Kuznetsov next_stage:
517e2e1cc1fSVitaly Kuznetsov 		stage++;
5186c118643SVitaly Kuznetsov 		kvm_vm_free(vm);
519e2e1cc1fSVitaly Kuznetsov 	}
520e2e1cc1fSVitaly Kuznetsov }
521e2e1cc1fSVitaly Kuznetsov 
guest_test_hcalls_access(void)5226c118643SVitaly Kuznetsov static void guest_test_hcalls_access(void)
523e2e1cc1fSVitaly Kuznetsov {
5244dcd130cSSean Christopherson 	struct kvm_cpuid2 *prev_cpuid = NULL;
525d96b9596SSean Christopherson 	struct kvm_vcpu *vcpu;
5266c118643SVitaly Kuznetsov 	struct kvm_vm *vm;
527e2e1cc1fSVitaly Kuznetsov 	struct ucall uc;
528d96b9596SSean Christopherson 	int stage = 0;
5296c118643SVitaly Kuznetsov 	vm_vaddr_t hcall_page, hcall_params;
5306c118643SVitaly Kuznetsov 	struct hcall_data *hcall;
5316c118643SVitaly Kuznetsov 
5326c118643SVitaly Kuznetsov 	while (true) {
533d96b9596SSean Christopherson 		vm = vm_create_with_one_vcpu(&vcpu, guest_hcall);
5346c118643SVitaly Kuznetsov 
5356c118643SVitaly Kuznetsov 		vm_init_descriptor_tables(vm);
536768e9a61SSean Christopherson 		vcpu_init_descriptor_tables(vcpu);
5376c118643SVitaly Kuznetsov 
5386c118643SVitaly Kuznetsov 		/* Hypercall input/output */
5396c118643SVitaly Kuznetsov 		hcall_page = vm_vaddr_alloc_pages(vm, 2);
5406c118643SVitaly Kuznetsov 		memset(addr_gva2hva(vm, hcall_page), 0x0, 2 * getpagesize());
5416c118643SVitaly Kuznetsov 
5426c118643SVitaly Kuznetsov 		hcall_params = vm_vaddr_alloc_page(vm);
5436c118643SVitaly Kuznetsov 		memset(addr_gva2hva(vm, hcall_params), 0x0, getpagesize());
5449f88d062SSean Christopherson 		hcall = addr_gva2hva(vm, hcall_params);
5456c118643SVitaly Kuznetsov 
546768e9a61SSean Christopherson 		vcpu_args_set(vcpu, 2, addr_gva2gpa(vm, hcall_page), hcall_params);
547768e9a61SSean Christopherson 		vcpu_enable_cap(vcpu, KVM_CAP_HYPERV_ENFORCE_CPUID, 1);
5486c118643SVitaly Kuznetsov 
5494dcd130cSSean Christopherson 		if (!prev_cpuid) {
5504dcd130cSSean Christopherson 			vcpu_reset_hv_cpuid(vcpu);
5516c118643SVitaly Kuznetsov 
5524dcd130cSSean Christopherson 			prev_cpuid = allocate_kvm_cpuid2(vcpu->cpuid->nent);
5534dcd130cSSean Christopherson 		} else {
5544dcd130cSSean Christopherson 			vcpu_init_cpuid(vcpu, prev_cpuid);
5554dcd130cSSean Christopherson 		}
5564dcd130cSSean Christopherson 
557e2e1cc1fSVitaly Kuznetsov 		switch (stage) {
558e2e1cc1fSVitaly Kuznetsov 		case 0:
5592f10428aSVitaly Kuznetsov 			vcpu_set_cpuid_feature(vcpu, HV_MSR_HYPERCALL_AVAILABLE);
56031d3b871SVitaly Kuznetsov 			hcall->control = 0xbeef;
561e2e1cc1fSVitaly Kuznetsov 			hcall->expect = HV_STATUS_INVALID_HYPERCALL_CODE;
562e2e1cc1fSVitaly Kuznetsov 			break;
563e2e1cc1fSVitaly Kuznetsov 
564e2e1cc1fSVitaly Kuznetsov 		case 1:
565e2e1cc1fSVitaly Kuznetsov 			hcall->control = HVCALL_POST_MESSAGE;
566e2e1cc1fSVitaly Kuznetsov 			hcall->expect = HV_STATUS_ACCESS_DENIED;
567e2e1cc1fSVitaly Kuznetsov 			break;
568e2e1cc1fSVitaly Kuznetsov 		case 2:
5692f10428aSVitaly Kuznetsov 			vcpu_set_cpuid_feature(vcpu, HV_POST_MESSAGES);
5709f88d062SSean Christopherson 			hcall->control = HVCALL_POST_MESSAGE;
571e2e1cc1fSVitaly Kuznetsov 			hcall->expect = HV_STATUS_INVALID_HYPERCALL_INPUT;
572e2e1cc1fSVitaly Kuznetsov 			break;
573e2e1cc1fSVitaly Kuznetsov 
574e2e1cc1fSVitaly Kuznetsov 		case 3:
575e2e1cc1fSVitaly Kuznetsov 			hcall->control = HVCALL_SIGNAL_EVENT;
576e2e1cc1fSVitaly Kuznetsov 			hcall->expect = HV_STATUS_ACCESS_DENIED;
577e2e1cc1fSVitaly Kuznetsov 			break;
578e2e1cc1fSVitaly Kuznetsov 		case 4:
5792f10428aSVitaly Kuznetsov 			vcpu_set_cpuid_feature(vcpu, HV_SIGNAL_EVENTS);
5809f88d062SSean Christopherson 			hcall->control = HVCALL_SIGNAL_EVENT;
581e2e1cc1fSVitaly Kuznetsov 			hcall->expect = HV_STATUS_INVALID_HYPERCALL_INPUT;
582e2e1cc1fSVitaly Kuznetsov 			break;
583e2e1cc1fSVitaly Kuznetsov 
584e2e1cc1fSVitaly Kuznetsov 		case 5:
585e2e1cc1fSVitaly Kuznetsov 			hcall->control = HVCALL_RESET_DEBUG_SESSION;
586e2e1cc1fSVitaly Kuznetsov 			hcall->expect = HV_STATUS_INVALID_HYPERCALL_CODE;
587e2e1cc1fSVitaly Kuznetsov 			break;
588e2e1cc1fSVitaly Kuznetsov 		case 6:
5892f10428aSVitaly Kuznetsov 			vcpu_set_cpuid_feature(vcpu, HV_X64_SYNDBG_CAP_ALLOW_KERNEL_DEBUGGING);
5909f88d062SSean Christopherson 			hcall->control = HVCALL_RESET_DEBUG_SESSION;
591e2e1cc1fSVitaly Kuznetsov 			hcall->expect = HV_STATUS_ACCESS_DENIED;
592e2e1cc1fSVitaly Kuznetsov 			break;
593e2e1cc1fSVitaly Kuznetsov 		case 7:
5942f10428aSVitaly Kuznetsov 			vcpu_set_cpuid_feature(vcpu, HV_DEBUGGING);
5959f88d062SSean Christopherson 			hcall->control = HVCALL_RESET_DEBUG_SESSION;
596e2e1cc1fSVitaly Kuznetsov 			hcall->expect = HV_STATUS_OPERATION_DENIED;
597e2e1cc1fSVitaly Kuznetsov 			break;
598e2e1cc1fSVitaly Kuznetsov 
599e2e1cc1fSVitaly Kuznetsov 		case 8:
600e2e1cc1fSVitaly Kuznetsov 			hcall->control = HVCALL_FLUSH_VIRTUAL_ADDRESS_SPACE;
601e2e1cc1fSVitaly Kuznetsov 			hcall->expect = HV_STATUS_ACCESS_DENIED;
602e2e1cc1fSVitaly Kuznetsov 			break;
603e2e1cc1fSVitaly Kuznetsov 		case 9:
6042f10428aSVitaly Kuznetsov 			vcpu_set_cpuid_feature(vcpu, HV_X64_REMOTE_TLB_FLUSH_RECOMMENDED);
6059f88d062SSean Christopherson 			hcall->control = HVCALL_FLUSH_VIRTUAL_ADDRESS_SPACE;
606e2e1cc1fSVitaly Kuznetsov 			hcall->expect = HV_STATUS_SUCCESS;
607e2e1cc1fSVitaly Kuznetsov 			break;
608e2e1cc1fSVitaly Kuznetsov 		case 10:
609e2e1cc1fSVitaly Kuznetsov 			hcall->control = HVCALL_FLUSH_VIRTUAL_ADDRESS_SPACE_EX;
610e2e1cc1fSVitaly Kuznetsov 			hcall->expect = HV_STATUS_ACCESS_DENIED;
611e2e1cc1fSVitaly Kuznetsov 			break;
612e2e1cc1fSVitaly Kuznetsov 		case 11:
6132f10428aSVitaly Kuznetsov 			vcpu_set_cpuid_feature(vcpu, HV_X64_EX_PROCESSOR_MASKS_RECOMMENDED);
6149f88d062SSean Christopherson 			hcall->control = HVCALL_FLUSH_VIRTUAL_ADDRESS_SPACE_EX;
615e2e1cc1fSVitaly Kuznetsov 			hcall->expect = HV_STATUS_SUCCESS;
616e2e1cc1fSVitaly Kuznetsov 			break;
617e2e1cc1fSVitaly Kuznetsov 
618e2e1cc1fSVitaly Kuznetsov 		case 12:
619e2e1cc1fSVitaly Kuznetsov 			hcall->control = HVCALL_SEND_IPI;
620e2e1cc1fSVitaly Kuznetsov 			hcall->expect = HV_STATUS_ACCESS_DENIED;
621e2e1cc1fSVitaly Kuznetsov 			break;
622e2e1cc1fSVitaly Kuznetsov 		case 13:
6232f10428aSVitaly Kuznetsov 			vcpu_set_cpuid_feature(vcpu, HV_X64_CLUSTER_IPI_RECOMMENDED);
6249f88d062SSean Christopherson 			hcall->control = HVCALL_SEND_IPI;
625e2e1cc1fSVitaly Kuznetsov 			hcall->expect = HV_STATUS_INVALID_HYPERCALL_INPUT;
626e2e1cc1fSVitaly Kuznetsov 			break;
627e2e1cc1fSVitaly Kuznetsov 		case 14:
628e2e1cc1fSVitaly Kuznetsov 			/* Nothing in 'sparse banks' -> success */
629e2e1cc1fSVitaly Kuznetsov 			hcall->control = HVCALL_SEND_IPI_EX;
630e2e1cc1fSVitaly Kuznetsov 			hcall->expect = HV_STATUS_SUCCESS;
631e2e1cc1fSVitaly Kuznetsov 			break;
632e2e1cc1fSVitaly Kuznetsov 
633e2e1cc1fSVitaly Kuznetsov 		case 15:
634e2e1cc1fSVitaly Kuznetsov 			hcall->control = HVCALL_NOTIFY_LONG_SPIN_WAIT;
635e2e1cc1fSVitaly Kuznetsov 			hcall->expect = HV_STATUS_ACCESS_DENIED;
636e2e1cc1fSVitaly Kuznetsov 			break;
637e2e1cc1fSVitaly Kuznetsov 		case 16:
6382f10428aSVitaly Kuznetsov 			vcpu_set_cpuid_feature(vcpu, HV_PV_SPINLOCKS_TEST);
6399f88d062SSean Christopherson 			hcall->control = HVCALL_NOTIFY_LONG_SPIN_WAIT;
640e2e1cc1fSVitaly Kuznetsov 			hcall->expect = HV_STATUS_SUCCESS;
641e2e1cc1fSVitaly Kuznetsov 			break;
642e2e1cc1fSVitaly Kuznetsov 		case 17:
6432476b5a1SVitaly Kuznetsov 			/* XMM fast hypercall */
6442476b5a1SVitaly Kuznetsov 			hcall->control = HVCALL_FLUSH_VIRTUAL_ADDRESS_SPACE | HV_HYPERCALL_FAST_BIT;
6452476b5a1SVitaly Kuznetsov 			hcall->ud_expected = true;
6462476b5a1SVitaly Kuznetsov 			break;
6472476b5a1SVitaly Kuznetsov 		case 18:
6482f10428aSVitaly Kuznetsov 			vcpu_set_cpuid_feature(vcpu, HV_X64_HYPERCALL_XMM_INPUT_AVAILABLE);
6499f88d062SSean Christopherson 			hcall->control = HVCALL_FLUSH_VIRTUAL_ADDRESS_SPACE | HV_HYPERCALL_FAST_BIT;
6502476b5a1SVitaly Kuznetsov 			hcall->ud_expected = false;
6512476b5a1SVitaly Kuznetsov 			hcall->expect = HV_STATUS_SUCCESS;
6522476b5a1SVitaly Kuznetsov 			break;
6532476b5a1SVitaly Kuznetsov 		case 19:
654c4a46627SVipin Sharma 			hcall->control = HV_EXT_CALL_QUERY_CAPABILITIES;
655c4a46627SVipin Sharma 			hcall->expect = HV_STATUS_ACCESS_DENIED;
656c4a46627SVipin Sharma 			break;
657c4a46627SVipin Sharma 		case 20:
658c4a46627SVipin Sharma 			vcpu_set_cpuid_feature(vcpu, HV_ENABLE_EXTENDED_HYPERCALLS);
659c4a46627SVipin Sharma 			hcall->control = HV_EXT_CALL_QUERY_CAPABILITIES | HV_HYPERCALL_FAST_BIT;
660c4a46627SVipin Sharma 			hcall->expect = HV_STATUS_INVALID_PARAMETER;
661c4a46627SVipin Sharma 			break;
662c4a46627SVipin Sharma 		case 21:
6639f88d062SSean Christopherson 			kvm_vm_free(vm);
6649f88d062SSean Christopherson 			return;
665e2e1cc1fSVitaly Kuznetsov 		}
666e2e1cc1fSVitaly Kuznetsov 
6674dcd130cSSean Christopherson 		vcpu_set_cpuid(vcpu);
6684dcd130cSSean Christopherson 
6694dcd130cSSean Christopherson 		memcpy(prev_cpuid, vcpu->cpuid, kvm_cpuid2_size(vcpu->cpuid->nent));
670e2e1cc1fSVitaly Kuznetsov 
6719f88d062SSean Christopherson 		pr_debug("Stage %d: testing hcall: 0x%lx\n", stage, hcall->control);
672e2e1cc1fSVitaly Kuznetsov 
673768e9a61SSean Christopherson 		vcpu_run(vcpu);
674c96f57b0SVipin Sharma 		TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO);
675e2e1cc1fSVitaly Kuznetsov 
676768e9a61SSean Christopherson 		switch (get_ucall(vcpu, &uc)) {
677e2e1cc1fSVitaly Kuznetsov 		case UCALL_ABORT:
6788d1d3ce6SSean Christopherson 			REPORT_GUEST_ASSERT(uc);
679e2e1cc1fSVitaly Kuznetsov 			return;
680e2e1cc1fSVitaly Kuznetsov 		case UCALL_DONE:
6819f88d062SSean Christopherson 			break;
6829f88d062SSean Christopherson 		default:
6839f88d062SSean Christopherson 			TEST_FAIL("Unhandled ucall: %ld", uc.cmd);
684e2e1cc1fSVitaly Kuznetsov 			return;
685e2e1cc1fSVitaly Kuznetsov 		}
686e2e1cc1fSVitaly Kuznetsov 
687e2e1cc1fSVitaly Kuznetsov 		stage++;
6886c118643SVitaly Kuznetsov 		kvm_vm_free(vm);
689e2e1cc1fSVitaly Kuznetsov 	}
690e2e1cc1fSVitaly Kuznetsov }
691e2e1cc1fSVitaly Kuznetsov 
main(void)692e2e1cc1fSVitaly Kuznetsov int main(void)
693e2e1cc1fSVitaly Kuznetsov {
694e2e1cc1fSVitaly Kuznetsov 	pr_info("Testing access to Hyper-V specific MSRs\n");
6956c118643SVitaly Kuznetsov 	guest_test_msrs_access();
696e2e1cc1fSVitaly Kuznetsov 
697e2e1cc1fSVitaly Kuznetsov 	pr_info("Testing access to Hyper-V hypercalls\n");
6986c118643SVitaly Kuznetsov 	guest_test_hcalls_access();
699e2e1cc1fSVitaly Kuznetsov }
700