Merge tag 'trace-printf-v6.13' of git://git.kernel.org/pub/scm/linux/kernel/git/trace...
[drm/drm-misc.git] / tools / testing / selftests / kvm / x86_64 / xcr0_cpuid_test.c
blobc8a5c5e516619de79c7f0435e84bb9b9a78cb2f1
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * XCR0 cpuid test
5 * Copyright (C) 2022, Google LLC.
6 */
7 #include <fcntl.h>
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <sys/ioctl.h>
13 #include "test_util.h"
15 #include "kvm_util.h"
16 #include "processor.h"
19 * Assert that architectural dependency rules are satisfied, e.g. that AVX is
20 * supported if and only if SSE is supported.
22 #define ASSERT_XFEATURE_DEPENDENCIES(supported_xcr0, xfeatures, dependencies) \
23 do { \
24 uint64_t __supported = (supported_xcr0) & ((xfeatures) | (dependencies)); \
26 __GUEST_ASSERT((__supported & (xfeatures)) != (xfeatures) || \
27 __supported == ((xfeatures) | (dependencies)), \
28 "supported = 0x%lx, xfeatures = 0x%llx, dependencies = 0x%llx", \
29 __supported, (xfeatures), (dependencies)); \
30 } while (0)
33 * Assert that KVM reports a sane, usable as-is XCR0. Architecturally, a CPU
34 * isn't strictly required to _support_ all XFeatures related to a feature, but
35 * at the same time XSETBV will #GP if bundled XFeatures aren't enabled and
36 * disabled coherently. E.g. a CPU can technically enumerate supported for
37 * XTILE_CFG but not XTILE_DATA, but attempting to enable XTILE_CFG without
38 * XTILE_DATA will #GP.
40 #define ASSERT_ALL_OR_NONE_XFEATURE(supported_xcr0, xfeatures) \
41 do { \
42 uint64_t __supported = (supported_xcr0) & (xfeatures); \
44 __GUEST_ASSERT(!__supported || __supported == (xfeatures), \
45 "supported = 0x%lx, xfeatures = 0x%llx", \
46 __supported, (xfeatures)); \
47 } while (0)
49 static void guest_code(void)
51 uint64_t initial_xcr0;
52 uint64_t supported_xcr0;
53 int i, vector;
55 set_cr4(get_cr4() | X86_CR4_OSXSAVE);
57 initial_xcr0 = xgetbv(0);
58 supported_xcr0 = this_cpu_supported_xcr0();
60 GUEST_ASSERT(initial_xcr0 == supported_xcr0);
62 /* Check AVX */
63 ASSERT_XFEATURE_DEPENDENCIES(supported_xcr0,
64 XFEATURE_MASK_YMM,
65 XFEATURE_MASK_SSE);
67 /* Check MPX */
68 ASSERT_ALL_OR_NONE_XFEATURE(supported_xcr0,
69 XFEATURE_MASK_BNDREGS | XFEATURE_MASK_BNDCSR);
71 /* Check AVX-512 */
72 ASSERT_XFEATURE_DEPENDENCIES(supported_xcr0,
73 XFEATURE_MASK_AVX512,
74 XFEATURE_MASK_SSE | XFEATURE_MASK_YMM);
75 ASSERT_ALL_OR_NONE_XFEATURE(supported_xcr0,
76 XFEATURE_MASK_AVX512);
78 /* Check AMX */
79 ASSERT_ALL_OR_NONE_XFEATURE(supported_xcr0,
80 XFEATURE_MASK_XTILE);
82 vector = xsetbv_safe(0, XFEATURE_MASK_FP);
83 __GUEST_ASSERT(!vector,
84 "Expected success on XSETBV(FP), got vector '0x%x'",
85 vector);
87 vector = xsetbv_safe(0, supported_xcr0);
88 __GUEST_ASSERT(!vector,
89 "Expected success on XSETBV(0x%lx), got vector '0x%x'",
90 supported_xcr0, vector);
92 for (i = 0; i < 64; i++) {
93 if (supported_xcr0 & BIT_ULL(i))
94 continue;
96 vector = xsetbv_safe(0, supported_xcr0 | BIT_ULL(i));
97 __GUEST_ASSERT(vector == GP_VECTOR,
98 "Expected #GP on XSETBV(0x%llx), supported XCR0 = %lx, got vector '0x%x'",
99 BIT_ULL(i), supported_xcr0, vector);
102 GUEST_DONE();
105 int main(int argc, char *argv[])
107 struct kvm_vcpu *vcpu;
108 struct kvm_run *run;
109 struct kvm_vm *vm;
110 struct ucall uc;
112 TEST_REQUIRE(kvm_cpu_has(X86_FEATURE_XSAVE));
114 vm = vm_create_with_one_vcpu(&vcpu, guest_code);
115 run = vcpu->run;
117 while (1) {
118 vcpu_run(vcpu);
120 TEST_ASSERT(run->exit_reason == KVM_EXIT_IO,
121 "Unexpected exit reason: %u (%s),",
122 run->exit_reason,
123 exit_reason_str(run->exit_reason));
125 switch (get_ucall(vcpu, &uc)) {
126 case UCALL_ABORT:
127 REPORT_GUEST_ASSERT(uc);
128 break;
129 case UCALL_DONE:
130 goto done;
131 default:
132 TEST_FAIL("Unknown ucall %lu", uc.cmd);
136 done:
137 kvm_vm_free(vm);
138 return 0;