1 // SPDX-License-Identifier: GPL-2.0
5 * Copyright (C) 2022, Google LLC.
12 #include <sys/ioctl.h>
14 #include "test_util.h"
17 #include "processor.h"
20 * Assert that architectural dependency rules are satisfied, e.g. that AVX is
21 * supported if and only if SSE is supported.
23 #define ASSERT_XFEATURE_DEPENDENCIES(supported_xcr0, xfeatures, dependencies) \
25 uint64_t __supported = (supported_xcr0) & ((xfeatures) | (dependencies)); \
27 GUEST_ASSERT_3((__supported & (xfeatures)) != (xfeatures) || \
28 __supported == ((xfeatures) | (dependencies)), \
29 __supported, (xfeatures), (dependencies)); \
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) \
42 uint64_t __supported = (supported_xcr0) & (xfeatures); \
44 GUEST_ASSERT_2(!__supported || __supported == (xfeatures), \
45 __supported, (xfeatures)); \
48 static void guest_code(void)
51 uint64_t supported_xcr0;
54 set_cr4(get_cr4() | X86_CR4_OSXSAVE);
56 xcr0_reset = xgetbv(0);
57 supported_xcr0 = this_cpu_supported_xcr0();
59 GUEST_ASSERT(xcr0_reset == XFEATURE_MASK_FP);
62 ASSERT_XFEATURE_DEPENDENCIES(supported_xcr0,
67 ASSERT_ALL_OR_NONE_XFEATURE(supported_xcr0,
68 XFEATURE_MASK_BNDREGS | XFEATURE_MASK_BNDCSR);
71 ASSERT_XFEATURE_DEPENDENCIES(supported_xcr0,
73 XFEATURE_MASK_SSE | XFEATURE_MASK_YMM);
74 ASSERT_ALL_OR_NONE_XFEATURE(supported_xcr0,
75 XFEATURE_MASK_AVX512);
78 ASSERT_ALL_OR_NONE_XFEATURE(supported_xcr0,
81 vector = xsetbv_safe(0, supported_xcr0);
82 GUEST_ASSERT_2(!vector, supported_xcr0, vector);
84 for (i = 0; i < 64; i++) {
85 if (supported_xcr0 & BIT_ULL(i))
88 vector = xsetbv_safe(0, supported_xcr0 | BIT_ULL(i));
89 GUEST_ASSERT_3(vector == GP_VECTOR, supported_xcr0, vector, BIT_ULL(i));
95 int main(int argc, char *argv[])
97 struct kvm_vcpu *vcpu;
102 TEST_REQUIRE(kvm_cpu_has(X86_FEATURE_XSAVE));
104 vm = vm_create_with_one_vcpu(&vcpu, guest_code);
107 vm_init_descriptor_tables(vm);
108 vcpu_init_descriptor_tables(vcpu);
113 TEST_ASSERT(run->exit_reason == KVM_EXIT_IO,
114 "Unexpected exit reason: %u (%s),\n",
116 exit_reason_str(run->exit_reason));
118 switch (get_ucall(vcpu, &uc)) {
120 REPORT_GUEST_ASSERT_3(uc, "0x%lx 0x%lx 0x%lx");
125 TEST_FAIL("Unknown ucall %lu", uc.cmd);