Skip to content

Commit 44bc611

Browse files
committed
Merge tag 'kvm-selftests-6.2-2' of https://github.com/kvm-x86/linux into HEAD
KVM selftests fixes for 6.2 - Fix an inverted check in the access tracking perf test, and restore support for asserting that there aren't too many idle pages when running on bare metal. - Fix an ordering issue in the AMX test introduced by recent conversions to use kvm_cpu_has(), and harden the code to guard against similar bugs in the future. Anything that tiggers caching of KVM's supported CPUID, kvm_cpu_has() in this case, effectively hides opt-in XSAVE features if the caching occurs before the test opts in via prctl(). - Fix build errors that occur in certain setups (unsure exactly what is unique about the problematic setup) due to glibc overriding static_assert() to a variant that requires a custom message.
2 parents 10c5e80 + 0c32652 commit 44bc611

File tree

5 files changed

+91
-63
lines changed

5 files changed

+91
-63
lines changed

tools/testing/selftests/kvm/access_tracking_perf_test.c

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
#include "test_util.h"
4747
#include "memstress.h"
4848
#include "guest_modes.h"
49+
#include "processor.h"
4950

5051
/* Global variable used to synchronize all of the vCPU threads. */
5152
static int iteration;
@@ -180,16 +181,21 @@ static void mark_vcpu_memory_idle(struct kvm_vm *vm,
180181
* access tracking but low enough as to not make the test too brittle
181182
* over time and across architectures.
182183
*
183-
* Note that when run in nested virtualization, this check will trigger
184-
* much more frequently because TLB size is unlimited and since no flush
185-
* happens, much more pages are cached there and guest won't see the
186-
* "idle" bit cleared.
184+
* When running the guest as a nested VM, "warn" instead of asserting
185+
* as the TLB size is effectively unlimited and the KVM doesn't
186+
* explicitly flush the TLB when aging SPTEs. As a result, more pages
187+
* are cached and the guest won't see the "idle" bit cleared.
187188
*/
188-
if (still_idle < pages / 10)
189-
printf("WARNING: vCPU%d: Too many pages still idle (%" PRIu64
190-
"out of %" PRIu64 "), this will affect performance results"
191-
".\n",
189+
if (still_idle >= pages / 10) {
190+
#ifdef __x86_64__
191+
TEST_ASSERT(this_cpu_has(X86_FEATURE_HYPERVISOR),
192+
"vCPU%d: Too many pages still idle (%lu out of %lu)",
193+
vcpu_idx, still_idle, pages);
194+
#endif
195+
printf("WARNING: vCPU%d: Too many pages still idle (%lu out of %lu), "
196+
"this will affect performance results.\n",
192197
vcpu_idx, still_idle, pages);
198+
}
193199

194200
close(page_idle_fd);
195201
close(pagemap_fd);

tools/testing/selftests/kvm/include/kvm_util_base.h

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,18 @@
2222

2323
#include "sparsebit.h"
2424

25+
/*
26+
* Provide a version of static_assert() that is guaranteed to have an optional
27+
* message param. If _ISOC11_SOURCE is defined, glibc (/usr/include/assert.h)
28+
* #undefs and #defines static_assert() as a direct alias to _Static_assert(),
29+
* i.e. effectively makes the message mandatory. Many KVM selftests #define
30+
* _GNU_SOURCE for various reasons, and _GNU_SOURCE implies _ISOC11_SOURCE. As
31+
* a result, static_assert() behavior is non-deterministic and may or may not
32+
* require a message depending on #include order.
33+
*/
34+
#define __kvm_static_assert(expr, msg, ...) _Static_assert(expr, msg)
35+
#define kvm_static_assert(expr, ...) __kvm_static_assert(expr, ##__VA_ARGS__, #expr)
36+
2537
#define KVM_DEV_PATH "/dev/kvm"
2638
#define KVM_MAX_VCPUS 512
2739

@@ -196,7 +208,7 @@ static inline bool kvm_has_cap(long cap)
196208

197209
#define kvm_do_ioctl(fd, cmd, arg) \
198210
({ \
199-
static_assert(!_IOC_SIZE(cmd) || sizeof(*arg) == _IOC_SIZE(cmd), ""); \
211+
kvm_static_assert(!_IOC_SIZE(cmd) || sizeof(*arg) == _IOC_SIZE(cmd)); \
200212
ioctl(fd, cmd, arg); \
201213
})
202214

tools/testing/selftests/kvm/include/x86_64/processor.h

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -72,11 +72,11 @@ struct kvm_x86_cpu_feature {
7272
.bit = __bit, \
7373
}; \
7474
\
75-
static_assert((fn & 0xc0000000) == 0 || \
76-
(fn & 0xc0000000) == 0x40000000 || \
77-
(fn & 0xc0000000) == 0x80000000 || \
78-
(fn & 0xc0000000) == 0xc0000000); \
79-
static_assert(idx < BIT(sizeof(feature.index) * BITS_PER_BYTE)); \
75+
kvm_static_assert((fn & 0xc0000000) == 0 || \
76+
(fn & 0xc0000000) == 0x40000000 || \
77+
(fn & 0xc0000000) == 0x80000000 || \
78+
(fn & 0xc0000000) == 0xc0000000); \
79+
kvm_static_assert(idx < BIT(sizeof(feature.index) * BITS_PER_BYTE)); \
8080
feature; \
8181
})
8282

@@ -94,6 +94,7 @@ struct kvm_x86_cpu_feature {
9494
#define X86_FEATURE_XSAVE KVM_X86_CPU_FEATURE(0x1, 0, ECX, 26)
9595
#define X86_FEATURE_OSXSAVE KVM_X86_CPU_FEATURE(0x1, 0, ECX, 27)
9696
#define X86_FEATURE_RDRAND KVM_X86_CPU_FEATURE(0x1, 0, ECX, 30)
97+
#define X86_FEATURE_HYPERVISOR KVM_X86_CPU_FEATURE(0x1, 0, ECX, 31)
9798
#define X86_FEATURE_PAE KVM_X86_CPU_FEATURE(0x1, 0, EDX, 6)
9899
#define X86_FEATURE_MCE KVM_X86_CPU_FEATURE(0x1, 0, EDX, 7)
99100
#define X86_FEATURE_APIC KVM_X86_CPU_FEATURE(0x1, 0, EDX, 9)
@@ -190,12 +191,12 @@ struct kvm_x86_cpu_property {
190191
.hi_bit = high_bit, \
191192
}; \
192193
\
193-
static_assert(low_bit < high_bit); \
194-
static_assert((fn & 0xc0000000) == 0 || \
195-
(fn & 0xc0000000) == 0x40000000 || \
196-
(fn & 0xc0000000) == 0x80000000 || \
197-
(fn & 0xc0000000) == 0xc0000000); \
198-
static_assert(idx < BIT(sizeof(property.index) * BITS_PER_BYTE)); \
194+
kvm_static_assert(low_bit < high_bit); \
195+
kvm_static_assert((fn & 0xc0000000) == 0 || \
196+
(fn & 0xc0000000) == 0x40000000 || \
197+
(fn & 0xc0000000) == 0x80000000 || \
198+
(fn & 0xc0000000) == 0xc0000000); \
199+
kvm_static_assert(idx < BIT(sizeof(property.index) * BITS_PER_BYTE)); \
199200
property; \
200201
})
201202

tools/testing/selftests/kvm/lib/x86_64/processor.c

Lines changed: 44 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -552,40 +552,6 @@ static void vcpu_setup(struct kvm_vm *vm, struct kvm_vcpu *vcpu)
552552
vcpu_sregs_set(vcpu, &sregs);
553553
}
554554

555-
void __vm_xsave_require_permission(int bit, const char *name)
556-
{
557-
int kvm_fd;
558-
u64 bitmask;
559-
long rc;
560-
struct kvm_device_attr attr = {
561-
.group = 0,
562-
.attr = KVM_X86_XCOMP_GUEST_SUPP,
563-
.addr = (unsigned long) &bitmask
564-
};
565-
566-
TEST_REQUIRE(kvm_cpu_has(X86_FEATURE_XFD));
567-
568-
kvm_fd = open_kvm_dev_path_or_exit();
569-
rc = __kvm_ioctl(kvm_fd, KVM_GET_DEVICE_ATTR, &attr);
570-
close(kvm_fd);
571-
572-
if (rc == -1 && (errno == ENXIO || errno == EINVAL))
573-
__TEST_REQUIRE(0, "KVM_X86_XCOMP_GUEST_SUPP not supported");
574-
575-
TEST_ASSERT(rc == 0, "KVM_GET_DEVICE_ATTR(0, KVM_X86_XCOMP_GUEST_SUPP) error: %ld", rc);
576-
577-
__TEST_REQUIRE(bitmask & (1ULL << bit),
578-
"Required XSAVE feature '%s' not supported", name);
579-
580-
TEST_REQUIRE(!syscall(SYS_arch_prctl, ARCH_REQ_XCOMP_GUEST_PERM, bit));
581-
582-
rc = syscall(SYS_arch_prctl, ARCH_GET_XCOMP_GUEST_PERM, &bitmask);
583-
TEST_ASSERT(rc == 0, "prctl(ARCH_GET_XCOMP_GUEST_PERM) error: %ld", rc);
584-
TEST_ASSERT(bitmask & (1ULL << bit),
585-
"prctl(ARCH_REQ_XCOMP_GUEST_PERM) failure bitmask=0x%lx",
586-
bitmask);
587-
}
588-
589555
void kvm_arch_vm_post_create(struct kvm_vm *vm)
590556
{
591557
vm_create_irqchip(vm);
@@ -635,21 +601,24 @@ void vcpu_arch_free(struct kvm_vcpu *vcpu)
635601
free(vcpu->cpuid);
636602
}
637603

604+
/* Do not use kvm_supported_cpuid directly except for validity checks. */
605+
static void *kvm_supported_cpuid;
606+
638607
const struct kvm_cpuid2 *kvm_get_supported_cpuid(void)
639608
{
640-
static struct kvm_cpuid2 *cpuid;
641609
int kvm_fd;
642610

643-
if (cpuid)
644-
return cpuid;
611+
if (kvm_supported_cpuid)
612+
return kvm_supported_cpuid;
645613

646-
cpuid = allocate_kvm_cpuid2(MAX_NR_CPUID_ENTRIES);
614+
kvm_supported_cpuid = allocate_kvm_cpuid2(MAX_NR_CPUID_ENTRIES);
647615
kvm_fd = open_kvm_dev_path_or_exit();
648616

649-
kvm_ioctl(kvm_fd, KVM_GET_SUPPORTED_CPUID, cpuid);
617+
kvm_ioctl(kvm_fd, KVM_GET_SUPPORTED_CPUID,
618+
(struct kvm_cpuid2 *)kvm_supported_cpuid);
650619

651620
close(kvm_fd);
652-
return cpuid;
621+
return kvm_supported_cpuid;
653622
}
654623

655624
static uint32_t __kvm_cpu_has(const struct kvm_cpuid2 *cpuid,
@@ -707,6 +676,41 @@ uint64_t kvm_get_feature_msr(uint64_t msr_index)
707676
return buffer.entry.data;
708677
}
709678

679+
void __vm_xsave_require_permission(int bit, const char *name)
680+
{
681+
int kvm_fd;
682+
u64 bitmask;
683+
long rc;
684+
struct kvm_device_attr attr = {
685+
.group = 0,
686+
.attr = KVM_X86_XCOMP_GUEST_SUPP,
687+
.addr = (unsigned long) &bitmask
688+
};
689+
690+
TEST_ASSERT(!kvm_supported_cpuid,
691+
"kvm_get_supported_cpuid() cannot be used before ARCH_REQ_XCOMP_GUEST_PERM");
692+
693+
kvm_fd = open_kvm_dev_path_or_exit();
694+
rc = __kvm_ioctl(kvm_fd, KVM_GET_DEVICE_ATTR, &attr);
695+
close(kvm_fd);
696+
697+
if (rc == -1 && (errno == ENXIO || errno == EINVAL))
698+
__TEST_REQUIRE(0, "KVM_X86_XCOMP_GUEST_SUPP not supported");
699+
700+
TEST_ASSERT(rc == 0, "KVM_GET_DEVICE_ATTR(0, KVM_X86_XCOMP_GUEST_SUPP) error: %ld", rc);
701+
702+
__TEST_REQUIRE(bitmask & (1ULL << bit),
703+
"Required XSAVE feature '%s' not supported", name);
704+
705+
TEST_REQUIRE(!syscall(SYS_arch_prctl, ARCH_REQ_XCOMP_GUEST_PERM, bit));
706+
707+
rc = syscall(SYS_arch_prctl, ARCH_GET_XCOMP_GUEST_PERM, &bitmask);
708+
TEST_ASSERT(rc == 0, "prctl(ARCH_GET_XCOMP_GUEST_PERM) error: %ld", rc);
709+
TEST_ASSERT(bitmask & (1ULL << bit),
710+
"prctl(ARCH_REQ_XCOMP_GUEST_PERM) failure bitmask=0x%lx",
711+
bitmask);
712+
}
713+
710714
void vcpu_init_cpuid(struct kvm_vcpu *vcpu, const struct kvm_cpuid2 *cpuid)
711715
{
712716
TEST_ASSERT(cpuid != vcpu->cpuid, "@cpuid can't be the vCPU's CPUID");

tools/testing/selftests/kvm/x86_64/amx_test.c

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -249,16 +249,21 @@ int main(int argc, char *argv[])
249249
u32 amx_offset;
250250
int stage, ret;
251251

252+
/*
253+
* Note, all off-by-default features must be enabled before anything
254+
* caches KVM_GET_SUPPORTED_CPUID, e.g. before using kvm_cpu_has().
255+
*/
252256
vm_xsave_require_permission(XSTATE_XTILE_DATA_BIT);
253257

254-
/* Create VM */
255-
vm = vm_create_with_one_vcpu(&vcpu, guest_code);
256-
258+
TEST_REQUIRE(kvm_cpu_has(X86_FEATURE_XFD));
257259
TEST_REQUIRE(kvm_cpu_has(X86_FEATURE_XSAVE));
258260
TEST_REQUIRE(kvm_cpu_has(X86_FEATURE_AMX_TILE));
259261
TEST_REQUIRE(kvm_cpu_has(X86_FEATURE_XTILECFG));
260262
TEST_REQUIRE(kvm_cpu_has(X86_FEATURE_XTILEDATA));
261263

264+
/* Create VM */
265+
vm = vm_create_with_one_vcpu(&vcpu, guest_code);
266+
262267
TEST_ASSERT(kvm_cpu_has_p(X86_PROPERTY_XSTATE_MAX_SIZE),
263268
"KVM should enumerate max XSAVE size when XSAVE is supported");
264269
xsave_restore_size = kvm_cpu_property(X86_PROPERTY_XSTATE_MAX_SIZE);

0 commit comments

Comments
 (0)