Split the core of __vm_xsave_require_permission() into a new helper, vm_xsave_request_permission(), which returns false instead of skipping the test if KVM doesn't support the requested dynamic XSAVE feature, or if the request for permission is denied. This allows tests to opt into dynamic features opportunistically, e.g. to exercise additional KVM paths when AMX is available, while retaining the sanity check that the request is made before KVM_GET_SUPPORTED_CPUID is first queried. Like vm_xsave_require_permission(), wrap the new helper in a macro that stringifies the feature mask for use in assertion messages. Use __kvm_device_attr_get() instead of open-coding KVM_GET_DEVICE_ATTR. No functional change intended for existing users, other than collapsing the reasons for skipping into a single message. Signed-off-by: Jim Mattson --- .../selftests/kvm/include/x86/processor.h | 4 +++ .../testing/selftests/kvm/lib/x86/processor.c | 33 ++++++++++++------- 2 files changed, 26 insertions(+), 11 deletions(-) diff --git a/tools/testing/selftests/kvm/include/x86/processor.h b/tools/testing/selftests/kvm/include/x86/processor.h index 6e6f70035508..6e9db81187c3 100644 --- a/tools/testing/selftests/kvm/include/x86/processor.h +++ b/tools/testing/selftests/kvm/include/x86/processor.h @@ -1530,8 +1530,12 @@ static inline void cli(void) asm volatile ("cli"); } +bool __vm_xsave_request_permission(u64 xfeature, const char *name); void __vm_xsave_require_permission(u64 xfeature, const char *name); +#define vm_xsave_request_permission(xfeature) \ + __vm_xsave_request_permission(xfeature, #xfeature) + #define vm_xsave_require_permission(xfeature) \ __vm_xsave_require_permission(xfeature, #xfeature) diff --git a/tools/testing/selftests/kvm/lib/x86/processor.c b/tools/testing/selftests/kvm/lib/x86/processor.c index d31fa81ea075..12092e59b390 100644 --- a/tools/testing/selftests/kvm/lib/x86/processor.c +++ b/tools/testing/selftests/kvm/lib/x86/processor.c @@ -975,16 +975,18 @@ u64 kvm_get_feature_msr(u64 msr_index) return buffer.entry.data; } -void __vm_xsave_require_permission(u64 xfeature, const char *name) +/* + * Request permission for guests to use the dynamic XSAVE feature @xfeature. + * Returns false, without skipping the test, if KVM doesn't support the + * feature or if the request is denied. Must be called before + * KVM_GET_SUPPORTED_CPUID is first queried, as KVM enumerates dynamic + * features only if userspace has permission to use them. + */ +bool __vm_xsave_request_permission(u64 xfeature, const char *name) { int kvm_fd; u64 bitmask; long rc; - struct kvm_device_attr attr = { - .group = 0, - .attr = KVM_X86_XCOMP_GUEST_SUPP, - .addr = (unsigned long) &bitmask, - }; TEST_ASSERT(!kvm_supported_cpuid, "kvm_get_supported_cpuid() cannot be used before ARCH_REQ_XCOMP_GUEST_PERM"); @@ -993,24 +995,33 @@ void __vm_xsave_require_permission(u64 xfeature, const char *name) "Dynamic XFeatures must be enabled one at a time"); kvm_fd = open_kvm_dev_path_or_exit(); - rc = __kvm_ioctl(kvm_fd, KVM_GET_DEVICE_ATTR, &attr); + rc = __kvm_device_attr_get(kvm_fd, 0, KVM_X86_XCOMP_GUEST_SUPP, &bitmask); close(kvm_fd); if (rc == -1 && (errno == ENXIO || errno == EINVAL)) - __TEST_REQUIRE(0, "KVM_X86_XCOMP_GUEST_SUPP not supported"); + return false; TEST_ASSERT(rc == 0, "KVM_GET_DEVICE_ATTR(0, KVM_X86_XCOMP_GUEST_SUPP) error: %ld", rc); - __TEST_REQUIRE(bitmask & xfeature, - "Required XSAVE feature '%s' not supported", name); + if (!(bitmask & xfeature)) + return false; - TEST_REQUIRE(!syscall(SYS_arch_prctl, ARCH_REQ_XCOMP_GUEST_PERM, ilog2(xfeature))); + if (syscall(SYS_arch_prctl, ARCH_REQ_XCOMP_GUEST_PERM, ilog2(xfeature))) + return false; rc = syscall(SYS_arch_prctl, ARCH_GET_XCOMP_GUEST_PERM, &bitmask); TEST_ASSERT(rc == 0, "prctl(ARCH_GET_XCOMP_GUEST_PERM) error: %ld", rc); TEST_ASSERT(bitmask & xfeature, "'%s' (0x%lx) not permitted after prctl(ARCH_REQ_XCOMP_GUEST_PERM) permitted=0x%lx", name, xfeature, bitmask); + return true; +} + +void __vm_xsave_require_permission(u64 xfeature, const char *name) +{ + __TEST_REQUIRE(__vm_xsave_request_permission(xfeature, name), + "Dynamic XSAVE feature '%s' not supported or not permitted", + name); } void vcpu_init_cpuid(struct kvm_vcpu *vcpu, const struct kvm_cpuid2 *cpuid) -- 2.56.0.212.g129ede20d9-goog