File Index
Files and directories
Sign in
FILE

hyperv_features.c

File preview with syntax highlighting.

linux-6.19.14/tools/testing/selftests/kvm/x86/hyperv_features.c C
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*
  3 * Copyright (C) 2021, Red Hat, Inc.
  4 *
  5 * Tests for Hyper-V features enablement
  6 */
  7#include <asm/kvm_para.h>
  8#include <linux/kvm_para.h>
  9#include <stdint.h>
 10
 11#include "test_util.h"
 12#include "kvm_util.h"
 13#include "processor.h"
 14#include "hyperv.h"
 15
 16/*
 17 * HYPERV_CPUID_ENLIGHTMENT_INFO.EBX is not a 'feature' CPUID leaf
 18 * but to activate the feature it is sufficient to set it to a non-zero
 19 * value. Use BIT(0) for that.
 20 */
 21#define HV_PV_SPINLOCKS_TEST            \
 22	KVM_X86_CPU_FEATURE(HYPERV_CPUID_ENLIGHTMENT_INFO, 0, EBX, 0)
 23
 24struct msr_data {
 25	uint32_t idx;
 26	bool fault_expected;
 27	bool write;
 28	u64 write_val;
 29};
 30
 31struct hcall_data {
 32	uint64_t control;
 33	uint64_t expect;
 34	bool ud_expected;
 35};
 36
 37static bool is_write_only_msr(uint32_t msr)
 38{
 39	return msr == HV_X64_MSR_EOI;
 40}
 41
 42static void guest_msr(struct msr_data *msr)
 43{
 44	uint8_t vector = 0;
 45	uint64_t msr_val = 0;
 46
 47	GUEST_ASSERT(msr->idx);
 48
 49	if (msr->write)
 50		vector = wrmsr_safe(msr->idx, msr->write_val);
 51
 52	if (!vector && (!msr->write || !is_write_only_msr(msr->idx)))
 53		vector = rdmsr_safe(msr->idx, &msr_val);
 54
 55	if (msr->fault_expected)
 56		__GUEST_ASSERT(vector == GP_VECTOR,
 57			       "Expected #GP on %sMSR(0x%x), got %s",
 58			       msr->write ? "WR" : "RD", msr->idx, ex_str(vector));
 59	else
 60		__GUEST_ASSERT(!vector,
 61			       "Expected success on %sMSR(0x%x), got %s",
 62			       msr->write ? "WR" : "RD", msr->idx, ex_str(vector));
 63
 64	if (vector || is_write_only_msr(msr->idx))
 65		goto done;
 66
 67	if (msr->write)
 68		__GUEST_ASSERT(!vector,
 69			       "WRMSR(0x%x) to '0x%lx', RDMSR read '0x%lx'",
 70			       msr->idx, msr->write_val, msr_val);
 71
 72	/* Invariant TSC bit appears when TSC invariant control MSR is written to */
 73	if (msr->idx == HV_X64_MSR_TSC_INVARIANT_CONTROL) {
 74		if (!this_cpu_has(HV_ACCESS_TSC_INVARIANT))
 75			GUEST_ASSERT(this_cpu_has(X86_FEATURE_INVTSC));
 76		else
 77			GUEST_ASSERT(this_cpu_has(X86_FEATURE_INVTSC) ==
 78				     !!(msr_val & HV_INVARIANT_TSC_EXPOSED));
 79	}
 80
 81done:
 82	GUEST_DONE();
 83}
 84
 85static void guest_hcall(vm_vaddr_t pgs_gpa, struct hcall_data *hcall)
 86{
 87	u64 res, input, output;
 88	uint8_t vector;
 89
 90	GUEST_ASSERT_NE(hcall->control, 0);
 91
 92	wrmsr(HV_X64_MSR_GUEST_OS_ID, HYPERV_LINUX_OS_ID);
 93	wrmsr(HV_X64_MSR_HYPERCALL, pgs_gpa);
 94
 95	if (!(hcall->control & HV_HYPERCALL_FAST_BIT)) {
 96		input = pgs_gpa;
 97		output = pgs_gpa + PAGE_SIZE;
 98	} else {
 99		input = output = 0;
100	}
101
102	vector = __hyperv_hypercall(hcall->control, input, output, &res);
103	if (hcall->ud_expected) {
104		__GUEST_ASSERT(vector == UD_VECTOR,
105			       "Expected #UD for control '%lu', got %s",
106			       hcall->control, ex_str(vector));
107	} else {
108		__GUEST_ASSERT(!vector,
109			       "Expected no exception for control '%lu', got %s",
110			       hcall->control, ex_str(vector));
111		GUEST_ASSERT_EQ(res, hcall->expect);
112	}
113
114	GUEST_DONE();
115}
116
117static void vcpu_reset_hv_cpuid(struct kvm_vcpu *vcpu)
118{
119	/*
120	 * Enable all supported Hyper-V features, then clear the leafs holding
121	 * the features that will be tested one by one.
122	 */
123	vcpu_set_hv_cpuid(vcpu);
124
125	vcpu_clear_cpuid_entry(vcpu, HYPERV_CPUID_FEATURES);
126	vcpu_clear_cpuid_entry(vcpu, HYPERV_CPUID_ENLIGHTMENT_INFO);
127	vcpu_clear_cpuid_entry(vcpu, HYPERV_CPUID_SYNDBG_PLATFORM_CAPABILITIES);
128}
129
130static void guest_test_msrs_access(void)
131{
132	struct kvm_cpuid2 *prev_cpuid = NULL;
133	struct kvm_vcpu *vcpu;
134	struct kvm_vm *vm;
135	struct ucall uc;
136	int stage = 0;
137	vm_vaddr_t msr_gva;
138	struct msr_data *msr;
139	bool has_invtsc = kvm_cpu_has(X86_FEATURE_INVTSC);
140
141	while (true) {
142		vm = vm_create_with_one_vcpu(&vcpu, guest_msr);
143
144		msr_gva = vm_vaddr_alloc_page(vm);
145		memset(addr_gva2hva(vm, msr_gva), 0x0, getpagesize());
146		msr = addr_gva2hva(vm, msr_gva);
147
148		vcpu_args_set(vcpu, 1, msr_gva);
149		vcpu_enable_cap(vcpu, KVM_CAP_HYPERV_ENFORCE_CPUID, 1);
150
151		if (!prev_cpuid) {
152			vcpu_reset_hv_cpuid(vcpu);
153
154			prev_cpuid = allocate_kvm_cpuid2(vcpu->cpuid->nent);
155		} else {
156			vcpu_init_cpuid(vcpu, prev_cpuid);
157		}
158
159		/* TODO: Make this entire test easier to maintain. */
160		if (stage >= 21)
161			vcpu_enable_cap(vcpu, KVM_CAP_HYPERV_SYNIC2, 0);
162
163		switch (stage) {
164		case 0:
165			/*
166			 * Only available when Hyper-V identification is set
167			 */
168			msr->idx = HV_X64_MSR_GUEST_OS_ID;
169			msr->write = false;
170			msr->fault_expected = true;
171			break;
172		case 1:
173			msr->idx = HV_X64_MSR_HYPERCALL;
174			msr->write = false;
175			msr->fault_expected = true;
176			break;
177		case 2:
178			vcpu_set_cpuid_feature(vcpu, HV_MSR_HYPERCALL_AVAILABLE);
179			/*
180			 * HV_X64_MSR_GUEST_OS_ID has to be written first to make
181			 * HV_X64_MSR_HYPERCALL available.
182			 */
183			msr->idx = HV_X64_MSR_GUEST_OS_ID;
184			msr->write = true;
185			msr->write_val = HYPERV_LINUX_OS_ID;
186			msr->fault_expected = false;
187			break;
188		case 3:
189			msr->idx = HV_X64_MSR_GUEST_OS_ID;
190			msr->write = false;
191			msr->fault_expected = false;
192			break;
193		case 4:
194			msr->idx = HV_X64_MSR_HYPERCALL;
195			msr->write = false;
196			msr->fault_expected = false;
197			break;
198
199		case 5:
200			msr->idx = HV_X64_MSR_VP_RUNTIME;
201			msr->write = false;
202			msr->fault_expected = true;
203			break;
204		case 6:
205			vcpu_set_cpuid_feature(vcpu, HV_MSR_VP_RUNTIME_AVAILABLE);
206			msr->idx = HV_X64_MSR_VP_RUNTIME;
207			msr->write = false;
208			msr->fault_expected = false;
209			break;
210		case 7:
211			/* Read only */
212			msr->idx = HV_X64_MSR_VP_RUNTIME;
213			msr->write = true;
214			msr->write_val = 1;
215			msr->fault_expected = true;
216			break;
217
218		case 8:
219			msr->idx = HV_X64_MSR_TIME_REF_COUNT;
220			msr->write = false;
221			msr->fault_expected = true;
222			break;
223		case 9:
224			vcpu_set_cpuid_feature(vcpu, HV_MSR_TIME_REF_COUNT_AVAILABLE);
225			msr->idx = HV_X64_MSR_TIME_REF_COUNT;
226			msr->write = false;
227			msr->fault_expected = false;
228			break;
229		case 10:
230			/* Read only */
231			msr->idx = HV_X64_MSR_TIME_REF_COUNT;
232			msr->write = true;
233			msr->write_val = 1;
234			msr->fault_expected = true;
235			break;
236
237		case 11:
238			msr->idx = HV_X64_MSR_VP_INDEX;
239			msr->write = false;
240			msr->fault_expected = true;
241			break;
242		case 12:
243			vcpu_set_cpuid_feature(vcpu, HV_MSR_VP_INDEX_AVAILABLE);
244			msr->idx = HV_X64_MSR_VP_INDEX;
245			msr->write = false;
246			msr->fault_expected = false;
247			break;
248		case 13:
249			/* Read only */
250			msr->idx = HV_X64_MSR_VP_INDEX;
251			msr->write = true;
252			msr->write_val = 1;
253			msr->fault_expected = true;
254			break;
255
256		case 14:
257			msr->idx = HV_X64_MSR_RESET;
258			msr->write = false;
259			msr->fault_expected = true;
260			break;
261		case 15:
262			vcpu_set_cpuid_feature(vcpu, HV_MSR_RESET_AVAILABLE);
263			msr->idx = HV_X64_MSR_RESET;
264			msr->write = false;
265			msr->fault_expected = false;
266			break;
267		case 16:
268			msr->idx = HV_X64_MSR_RESET;
269			msr->write = true;
270			/*
271			 * TODO: the test only writes '0' to HV_X64_MSR_RESET
272			 * at the moment, writing some other value there will
273			 * trigger real vCPU reset and the code is not prepared
274			 * to handle it yet.
275			 */
276			msr->write_val = 0;
277			msr->fault_expected = false;
278			break;
279
280		case 17:
281			msr->idx = HV_X64_MSR_REFERENCE_TSC;
282			msr->write = false;
283			msr->fault_expected = true;
284			break;
285		case 18:
286			vcpu_set_cpuid_feature(vcpu, HV_MSR_REFERENCE_TSC_AVAILABLE);
287			msr->idx = HV_X64_MSR_REFERENCE_TSC;
288			msr->write = false;
289			msr->fault_expected = false;
290			break;
291		case 19:
292			msr->idx = HV_X64_MSR_REFERENCE_TSC;
293			msr->write = true;
294			msr->write_val = 0;
295			msr->fault_expected = false;
296			break;
297
298		case 20:
299			msr->idx = HV_X64_MSR_EOM;
300			msr->write = false;
301			msr->fault_expected = true;
302			break;
303		case 21:
304			/*
305			 * Remains unavailable even with KVM_CAP_HYPERV_SYNIC2
306			 * capability enabled and guest visible CPUID bit unset.
307			 */
308			msr->idx = HV_X64_MSR_EOM;
309			msr->write = false;
310			msr->fault_expected = true;
311			break;
312		case 22:
313			vcpu_set_cpuid_feature(vcpu, HV_MSR_SYNIC_AVAILABLE);
314			msr->idx = HV_X64_MSR_EOM;
315			msr->write = false;
316			msr->fault_expected = false;
317			break;
318		case 23:
319			msr->idx = HV_X64_MSR_EOM;
320			msr->write = true;
321			msr->write_val = 0;
322			msr->fault_expected = false;
323			break;
324
325		case 24:
326			msr->idx = HV_X64_MSR_STIMER0_CONFIG;
327			msr->write = false;
328			msr->fault_expected = true;
329			break;
330		case 25:
331			vcpu_set_cpuid_feature(vcpu, HV_MSR_SYNTIMER_AVAILABLE);
332			msr->idx = HV_X64_MSR_STIMER0_CONFIG;
333			msr->write = false;
334			msr->fault_expected = false;
335			break;
336		case 26:
337			msr->idx = HV_X64_MSR_STIMER0_CONFIG;
338			msr->write = true;
339			msr->write_val = 0;
340			msr->fault_expected = false;
341			break;
342		case 27:
343			/* Direct mode test */
344			msr->idx = HV_X64_MSR_STIMER0_CONFIG;
345			msr->write = true;
346			msr->write_val = 1 << 12;
347			msr->fault_expected = true;
348			break;
349		case 28:
350			vcpu_set_cpuid_feature(vcpu, HV_STIMER_DIRECT_MODE_AVAILABLE);
351			msr->idx = HV_X64_MSR_STIMER0_CONFIG;
352			msr->write = true;
353			msr->write_val = 1 << 12;
354			msr->fault_expected = false;
355			break;
356
357		case 29:
358			msr->idx = HV_X64_MSR_EOI;
359			msr->write = false;
360			msr->fault_expected = true;
361			break;
362		case 30:
363			vcpu_set_cpuid_feature(vcpu, HV_MSR_APIC_ACCESS_AVAILABLE);
364			msr->idx = HV_X64_MSR_EOI;
365			msr->write = true;
366			msr->write_val = 1;
367			msr->fault_expected = false;
368			break;
369
370		case 31:
371			msr->idx = HV_X64_MSR_TSC_FREQUENCY;
372			msr->write = false;
373			msr->fault_expected = true;
374			break;
375		case 32:
376			vcpu_set_cpuid_feature(vcpu, HV_ACCESS_FREQUENCY_MSRS);
377			msr->idx = HV_X64_MSR_TSC_FREQUENCY;
378			msr->write = false;
379			msr->fault_expected = false;
380			break;
381		case 33:
382			/* Read only */
383			msr->idx = HV_X64_MSR_TSC_FREQUENCY;
384			msr->write = true;
385			msr->write_val = 1;
386			msr->fault_expected = true;
387			break;
388
389		case 34:
390			msr->idx = HV_X64_MSR_REENLIGHTENMENT_CONTROL;
391			msr->write = false;
392			msr->fault_expected = true;
393			break;
394		case 35:
395			vcpu_set_cpuid_feature(vcpu, HV_ACCESS_REENLIGHTENMENT);
396			msr->idx = HV_X64_MSR_REENLIGHTENMENT_CONTROL;
397			msr->write = false;
398			msr->fault_expected = false;
399			break;
400		case 36:
401			msr->idx = HV_X64_MSR_REENLIGHTENMENT_CONTROL;
402			msr->write = true;
403			msr->write_val = 1;
404			msr->fault_expected = false;
405			break;
406		case 37:
407			/* Can only write '0' */
408			msr->idx = HV_X64_MSR_TSC_EMULATION_STATUS;
409			msr->write = true;
410			msr->write_val = 1;
411			msr->fault_expected = true;
412			break;
413
414		case 38:
415			msr->idx = HV_X64_MSR_CRASH_P0;
416			msr->write = false;
417			msr->fault_expected = true;
418			break;
419		case 39:
420			vcpu_set_cpuid_feature(vcpu, HV_FEATURE_GUEST_CRASH_MSR_AVAILABLE);
421			msr->idx = HV_X64_MSR_CRASH_P0;
422			msr->write = false;
423			msr->fault_expected = false;
424			break;
425		case 40:
426			msr->idx = HV_X64_MSR_CRASH_P0;
427			msr->write = true;
428			msr->write_val = 1;
429			msr->fault_expected = false;
430			break;
431
432		case 41:
433			msr->idx = HV_X64_MSR_SYNDBG_STATUS;
434			msr->write = false;
435			msr->fault_expected = true;
436			break;
437		case 42:
438			vcpu_set_cpuid_feature(vcpu, HV_FEATURE_DEBUG_MSRS_AVAILABLE);
439			vcpu_set_cpuid_feature(vcpu, HV_X64_SYNDBG_CAP_ALLOW_KERNEL_DEBUGGING);
440			msr->idx = HV_X64_MSR_SYNDBG_STATUS;
441			msr->write = false;
442			msr->fault_expected = false;
443			break;
444		case 43:
445			msr->idx = HV_X64_MSR_SYNDBG_STATUS;
446			msr->write = true;
447			msr->write_val = 0;
448			msr->fault_expected = false;
449			break;
450
451		case 44:
452			/* MSR is not available when CPUID feature bit is unset */
453			if (!has_invtsc)
454				goto next_stage;
455			msr->idx = HV_X64_MSR_TSC_INVARIANT_CONTROL;
456			msr->write = false;
457			msr->fault_expected = true;
458			break;
459		case 45:
460			/* MSR is vailable when CPUID feature bit is set */
461			if (!has_invtsc)
462				goto next_stage;
463			vcpu_set_cpuid_feature(vcpu, HV_ACCESS_TSC_INVARIANT);
464			msr->idx = HV_X64_MSR_TSC_INVARIANT_CONTROL;
465			msr->write = false;
466			msr->fault_expected = false;
467			break;
468		case 46:
469			/* Writing bits other than 0 is forbidden */
470			if (!has_invtsc)
471				goto next_stage;
472			msr->idx = HV_X64_MSR_TSC_INVARIANT_CONTROL;
473			msr->write = true;
474			msr->write_val = 0xdeadbeef;
475			msr->fault_expected = true;
476			break;
477		case 47:
478			/* Setting bit 0 enables the feature */
479			if (!has_invtsc)
480				goto next_stage;
481			msr->idx = HV_X64_MSR_TSC_INVARIANT_CONTROL;
482			msr->write = true;
483			msr->write_val = 1;
484			msr->fault_expected = false;
485			break;
486
487		default:
488			kvm_vm_free(vm);
489			return;
490		}
491
492		vcpu_set_cpuid(vcpu);
493
494		memcpy(prev_cpuid, vcpu->cpuid, kvm_cpuid2_size(vcpu->cpuid->nent));
495
496		pr_debug("Stage %d: testing msr: 0x%x for %s\n", stage,
497			 msr->idx, msr->write ? "write" : "read");
498
499		vcpu_run(vcpu);
500		TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO);
501
502		switch (get_ucall(vcpu, &uc)) {
503		case UCALL_ABORT:
504			REPORT_GUEST_ASSERT(uc);
505			return;
506		case UCALL_DONE:
507			break;
508		default:
509			TEST_FAIL("Unhandled ucall: %ld", uc.cmd);
510			return;
511		}
512
513next_stage:
514		stage++;
515		kvm_vm_free(vm);
516	}
517}
518
519static void guest_test_hcalls_access(void)
520{
521	struct kvm_cpuid2 *prev_cpuid = NULL;
522	struct kvm_vcpu *vcpu;
523	struct kvm_vm *vm;
524	struct ucall uc;
525	int stage = 0;
526	vm_vaddr_t hcall_page, hcall_params;
527	struct hcall_data *hcall;
528
529	while (true) {
530		vm = vm_create_with_one_vcpu(&vcpu, guest_hcall);
531
532		/* Hypercall input/output */
533		hcall_page = vm_vaddr_alloc_pages(vm, 2);
534		memset(addr_gva2hva(vm, hcall_page), 0x0, 2 * getpagesize());
535
536		hcall_params = vm_vaddr_alloc_page(vm);
537		memset(addr_gva2hva(vm, hcall_params), 0x0, getpagesize());
538		hcall = addr_gva2hva(vm, hcall_params);
539
540		vcpu_args_set(vcpu, 2, addr_gva2gpa(vm, hcall_page), hcall_params);
541		vcpu_enable_cap(vcpu, KVM_CAP_HYPERV_ENFORCE_CPUID, 1);
542
543		if (!prev_cpuid) {
544			vcpu_reset_hv_cpuid(vcpu);
545
546			prev_cpuid = allocate_kvm_cpuid2(vcpu->cpuid->nent);
547		} else {
548			vcpu_init_cpuid(vcpu, prev_cpuid);
549		}
550
551		switch (stage) {
552		case 0:
553			vcpu_set_cpuid_feature(vcpu, HV_MSR_HYPERCALL_AVAILABLE);
554			hcall->control = 0xbeef;
555			hcall->expect = HV_STATUS_INVALID_HYPERCALL_CODE;
556			break;
557
558		case 1:
559			hcall->control = HVCALL_POST_MESSAGE;
560			hcall->expect = HV_STATUS_ACCESS_DENIED;
561			break;
562		case 2:
563			vcpu_set_cpuid_feature(vcpu, HV_POST_MESSAGES);
564			hcall->control = HVCALL_POST_MESSAGE;
565			hcall->expect = HV_STATUS_INVALID_HYPERCALL_INPUT;
566			break;
567
568		case 3:
569			hcall->control = HVCALL_SIGNAL_EVENT;
570			hcall->expect = HV_STATUS_ACCESS_DENIED;
571			break;
572		case 4:
573			vcpu_set_cpuid_feature(vcpu, HV_SIGNAL_EVENTS);
574			hcall->control = HVCALL_SIGNAL_EVENT;
575			hcall->expect = HV_STATUS_INVALID_HYPERCALL_INPUT;
576			break;
577
578		case 5:
579			hcall->control = HVCALL_RESET_DEBUG_SESSION;
580			hcall->expect = HV_STATUS_INVALID_HYPERCALL_CODE;
581			break;
582		case 6:
583			vcpu_set_cpuid_feature(vcpu, HV_X64_SYNDBG_CAP_ALLOW_KERNEL_DEBUGGING);
584			hcall->control = HVCALL_RESET_DEBUG_SESSION;
585			hcall->expect = HV_STATUS_ACCESS_DENIED;
586			break;
587		case 7:
588			vcpu_set_cpuid_feature(vcpu, HV_DEBUGGING);
589			hcall->control = HVCALL_RESET_DEBUG_SESSION;
590			hcall->expect = HV_STATUS_OPERATION_DENIED;
591			break;
592
593		case 8:
594			hcall->control = HVCALL_FLUSH_VIRTUAL_ADDRESS_SPACE;
595			hcall->expect = HV_STATUS_ACCESS_DENIED;
596			break;
597		case 9:
598			vcpu_set_cpuid_feature(vcpu, HV_X64_REMOTE_TLB_FLUSH_RECOMMENDED);
599			hcall->control = HVCALL_FLUSH_VIRTUAL_ADDRESS_SPACE;
600			hcall->expect = HV_STATUS_SUCCESS;
601			break;
602		case 10:
603			hcall->control = HVCALL_FLUSH_VIRTUAL_ADDRESS_SPACE_EX;
604			hcall->expect = HV_STATUS_ACCESS_DENIED;
605			break;
606		case 11:
607			vcpu_set_cpuid_feature(vcpu, HV_X64_EX_PROCESSOR_MASKS_RECOMMENDED);
608			hcall->control = HVCALL_FLUSH_VIRTUAL_ADDRESS_SPACE_EX;
609			hcall->expect = HV_STATUS_SUCCESS;
610			break;
611
612		case 12:
613			hcall->control = HVCALL_SEND_IPI;
614			hcall->expect = HV_STATUS_ACCESS_DENIED;
615			break;
616		case 13:
617			vcpu_set_cpuid_feature(vcpu, HV_X64_CLUSTER_IPI_RECOMMENDED);
618			hcall->control = HVCALL_SEND_IPI;
619			hcall->expect = HV_STATUS_INVALID_HYPERCALL_INPUT;
620			break;
621		case 14:
622			/* Nothing in 'sparse banks' -> success */
623			hcall->control = HVCALL_SEND_IPI_EX;
624			hcall->expect = HV_STATUS_SUCCESS;
625			break;
626
627		case 15:
628			hcall->control = HVCALL_NOTIFY_LONG_SPIN_WAIT;
629			hcall->expect = HV_STATUS_ACCESS_DENIED;
630			break;
631		case 16:
632			vcpu_set_cpuid_feature(vcpu, HV_PV_SPINLOCKS_TEST);
633			hcall->control = HVCALL_NOTIFY_LONG_SPIN_WAIT;
634			hcall->expect = HV_STATUS_SUCCESS;
635			break;
636		case 17:
637			/* XMM fast hypercall */
638			hcall->control = HVCALL_FLUSH_VIRTUAL_ADDRESS_SPACE | HV_HYPERCALL_FAST_BIT;
639			hcall->ud_expected = true;
640			break;
641		case 18:
642			vcpu_set_cpuid_feature(vcpu, HV_X64_HYPERCALL_XMM_INPUT_AVAILABLE);
643			hcall->control = HVCALL_FLUSH_VIRTUAL_ADDRESS_SPACE | HV_HYPERCALL_FAST_BIT;
644			hcall->ud_expected = false;
645			hcall->expect = HV_STATUS_SUCCESS;
646			break;
647		case 19:
648			hcall->control = HV_EXT_CALL_QUERY_CAPABILITIES;
649			hcall->expect = HV_STATUS_ACCESS_DENIED;
650			break;
651		case 20:
652			vcpu_set_cpuid_feature(vcpu, HV_ENABLE_EXTENDED_HYPERCALLS);
653			hcall->control = HV_EXT_CALL_QUERY_CAPABILITIES | HV_HYPERCALL_FAST_BIT;
654			hcall->expect = HV_STATUS_INVALID_PARAMETER;
655			break;
656		case 21:
657			kvm_vm_free(vm);
658			return;
659		}
660
661		vcpu_set_cpuid(vcpu);
662
663		memcpy(prev_cpuid, vcpu->cpuid, kvm_cpuid2_size(vcpu->cpuid->nent));
664
665		pr_debug("Stage %d: testing hcall: 0x%lx\n", stage, hcall->control);
666
667		vcpu_run(vcpu);
668		TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO);
669
670		switch (get_ucall(vcpu, &uc)) {
671		case UCALL_ABORT:
672			REPORT_GUEST_ASSERT(uc);
673			return;
674		case UCALL_DONE:
675			break;
676		default:
677			TEST_FAIL("Unhandled ucall: %ld", uc.cmd);
678			return;
679		}
680
681		stage++;
682		kvm_vm_free(vm);
683	}
684}
685
686int main(void)
687{
688	TEST_REQUIRE(kvm_has_cap(KVM_CAP_HYPERV_ENFORCE_CPUID));
689
690	pr_info("Testing access to Hyper-V specific MSRs\n");
691	guest_test_msrs_access();
692
693	pr_info("Testing access to Hyper-V hypercalls\n");
694	guest_test_hcalls_access();
695}
~/ Read-only file preview.