1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (C) 2019, Google LLC.
4  *
5  * Tests for the IA32_XSS MSR.
6  */
7 
8 #define _GNU_SOURCE /* for program_invocation_short_name */
9 #include <sys/ioctl.h>
10 
11 #include "test_util.h"
12 #include "kvm_util.h"
13 #include "vmx.h"
14 
15 #define VCPU_ID	      1
16 #define MSR_BITS      64
17 
18 #define X86_FEATURE_XSAVES	(1<<3)
19 
20 bool is_supported_msr(u32 msr_index)
21 {
22 	struct kvm_msr_list *list;
23 	bool found = false;
24 	int i;
25 
26 	list = kvm_get_msr_index_list();
27 	for (i = 0; i < list->nmsrs; ++i) {
28 		if (list->indices[i] == msr_index) {
29 			found = true;
30 			break;
31 		}
32 	}
33 
34 	free(list);
35 	return found;
36 }
37 
38 int main(int argc, char *argv[])
39 {
40 	struct kvm_cpuid_entry2 *entry;
41 	bool xss_supported = false;
42 	struct kvm_vm *vm;
43 	uint64_t xss_val;
44 	int i, r;
45 
46 	/* Create VM */
47 	vm = vm_create_default(VCPU_ID, 0, 0);
48 
49 	if (kvm_get_cpuid_max_basic() >= 0xd) {
50 		entry = kvm_get_supported_cpuid_index(0xd, 1);
51 		xss_supported = entry && !!(entry->eax & X86_FEATURE_XSAVES);
52 	}
53 	if (!xss_supported) {
54 		print_skip("IA32_XSS is not supported by the vCPU");
55 		exit(KSFT_SKIP);
56 	}
57 
58 	xss_val = vcpu_get_msr(vm, VCPU_ID, MSR_IA32_XSS);
59 	TEST_ASSERT(xss_val == 0,
60 		    "MSR_IA32_XSS should be initialized to zero\n");
61 
62 	vcpu_set_msr(vm, VCPU_ID, MSR_IA32_XSS, xss_val);
63 	/*
64 	 * At present, KVM only supports a guest IA32_XSS value of 0. Verify
65 	 * that trying to set the guest IA32_XSS to an unsupported value fails.
66 	 * Also, in the future when a non-zero value succeeds check that
67 	 * IA32_XSS is in the KVM_GET_MSR_INDEX_LIST.
68 	 */
69 	for (i = 0; i < MSR_BITS; ++i) {
70 		r = _vcpu_set_msr(vm, VCPU_ID, MSR_IA32_XSS, 1ull << i);
71 		TEST_ASSERT(r == 0 || is_supported_msr(MSR_IA32_XSS),
72 			    "IA32_XSS was able to be set, but was not found in KVM_GET_MSR_INDEX_LIST.\n");
73 	}
74 
75 	kvm_vm_free(vm);
76 }
77