Commit 1c3c87d7 authored by Paolo Bonzini's avatar Paolo Bonzini
Browse files

Merge tag 'kvm-x86-selftests-6.7-rcN' of https://github.com/kvm-x86/linux into HEAD

KVM selftests fixes for 6.8 merge window:

 - Fix an annoying goof where the NX hugepage test prints out garbage
   instead of the magic token needed to run the text.

 - Fix build errors when a header is delete/moved due to a missing flag
   in the Makefile.

 - Detect if KVM bugged/killed a selftest's VM and print out a helpful
   message instead of complaining that a random ioctl() failed.

 - Annotate the guest printf/assert helpers with __printf(), and fix the
   various bugs that were lurking due to lack of said annotation.

A small subset of these was included in 6.7-rc as well.
parents 80583d0c 1b2658e4
Loading
Loading
Loading
Loading
+1 −2
Original line number Diff line number Diff line
@@ -86,7 +86,6 @@ TEST_GEN_PROGS_x86_64 += x86_64/hyperv_svm_test
TEST_GEN_PROGS_x86_64 += x86_64/hyperv_tlb_flush
TEST_GEN_PROGS_x86_64 += x86_64/kvm_clock_test
TEST_GEN_PROGS_x86_64 += x86_64/kvm_pv_test
TEST_GEN_PROGS_x86_64 += x86_64/mmio_warning_test
TEST_GEN_PROGS_x86_64 += x86_64/monitor_mwait_test
TEST_GEN_PROGS_x86_64 += x86_64/nested_exceptions_test
TEST_GEN_PROGS_x86_64 += x86_64/platform_info_test
@@ -226,7 +225,7 @@ else
LINUX_TOOL_ARCH_INCLUDE = $(top_srcdir)/tools/arch/$(ARCH)/include
endif
CFLAGS += -Wall -Wstrict-prototypes -Wuninitialized -O2 -g -std=gnu99 \
	-Wno-gnu-variable-sized-type-not-at-end -MD\
	-Wno-gnu-variable-sized-type-not-at-end -MD -MP \
	-fno-builtin-memcmp -fno-builtin-memcpy -fno-builtin-memset \
	-fno-builtin-strnlen \
	-fno-stack-protector -fno-PIE -I$(LINUX_TOOL_INCLUDE) \
+45 −20
Original line number Diff line number Diff line
@@ -267,6 +267,13 @@ static inline bool kvm_has_cap(long cap)
#define __KVM_SYSCALL_ERROR(_name, _ret) \
	"%s failed, rc: %i errno: %i (%s)", (_name), (_ret), errno, strerror(errno)

/*
 * Use the "inner", double-underscore macro when reporting errors from within
 * other macros so that the name of ioctl() and not its literal numeric value
 * is printed on error.  The "outer" macro is strongly preferred when reporting
 * errors "directly", i.e. without an additional layer of macros, as it reduces
 * the probability of passing in the wrong string.
 */
#define __KVM_IOCTL_ERROR(_name, _ret)	__KVM_SYSCALL_ERROR(_name, _ret)
#define KVM_IOCTL_ERROR(_ioctl, _ret) __KVM_IOCTL_ERROR(#_ioctl, _ret)

@@ -279,17 +286,13 @@ static inline bool kvm_has_cap(long cap)
#define __kvm_ioctl(kvm_fd, cmd, arg)				\
	kvm_do_ioctl(kvm_fd, cmd, arg)


#define _kvm_ioctl(kvm_fd, cmd, name, arg)			\
#define kvm_ioctl(kvm_fd, cmd, arg)				\
({								\
	int ret = __kvm_ioctl(kvm_fd, cmd, arg);		\
								\
	TEST_ASSERT(!ret, __KVM_IOCTL_ERROR(name, ret));	\
	TEST_ASSERT(!ret, __KVM_IOCTL_ERROR(#cmd, ret));	\
})

#define kvm_ioctl(kvm_fd, cmd, arg) \
	_kvm_ioctl(kvm_fd, cmd, #cmd, arg)

static __always_inline void static_assert_is_vm(struct kvm_vm *vm) { }

#define __vm_ioctl(vm, cmd, arg)				\
@@ -298,17 +301,42 @@ static __always_inline void static_assert_is_vm(struct kvm_vm *vm) { }
	kvm_do_ioctl((vm)->fd, cmd, arg);			\
})

#define _vm_ioctl(vm, cmd, name, arg)				\
/*
 * Assert that a VM or vCPU ioctl() succeeded, with extra magic to detect if
 * the ioctl() failed because KVM killed/bugged the VM.  To detect a dead VM,
 * probe KVM_CAP_USER_MEMORY, which (a) has been supported by KVM since before
 * selftests existed and (b) should never outright fail, i.e. is supposed to
 * return 0 or 1.  If KVM kills a VM, KVM returns -EIO for all ioctl()s for the
 * VM and its vCPUs, including KVM_CHECK_EXTENSION.
 */
#define __TEST_ASSERT_VM_VCPU_IOCTL(cond, name, ret, vm)				\
do {											\
	int __errno = errno;								\
											\
	static_assert_is_vm(vm);							\
											\
	if (cond)									\
		break;									\
											\
	if (errno == EIO &&								\
	    __vm_ioctl(vm, KVM_CHECK_EXTENSION, (void *)KVM_CAP_USER_MEMORY) < 0) {	\
		TEST_ASSERT(errno == EIO, "KVM killed the VM, should return -EIO");	\
		TEST_FAIL("KVM killed/bugged the VM, check the kernel log for clues");	\
	}										\
	errno = __errno;								\
	TEST_ASSERT(cond, __KVM_IOCTL_ERROR(name, ret));				\
} while (0)

#define TEST_ASSERT_VM_VCPU_IOCTL(cond, cmd, ret, vm)		\
	__TEST_ASSERT_VM_VCPU_IOCTL(cond, #cmd, ret, vm)

#define vm_ioctl(vm, cmd, arg)					\
({								\
	int ret = __vm_ioctl(vm, cmd, arg);			\
								\
	TEST_ASSERT(!ret, __KVM_IOCTL_ERROR(name, ret));	\
	__TEST_ASSERT_VM_VCPU_IOCTL(!ret, #cmd, ret, vm);		\
})

#define vm_ioctl(vm, cmd, arg)					\
	_vm_ioctl(vm, cmd, #cmd, arg)


static __always_inline void static_assert_is_vcpu(struct kvm_vcpu *vcpu) { }

#define __vcpu_ioctl(vcpu, cmd, arg)				\
@@ -317,16 +345,13 @@ static __always_inline void static_assert_is_vcpu(struct kvm_vcpu *vcpu) { }
	kvm_do_ioctl((vcpu)->fd, cmd, arg);			\
})

#define _vcpu_ioctl(vcpu, cmd, name, arg)			\
#define vcpu_ioctl(vcpu, cmd, arg)				\
({								\
	int ret = __vcpu_ioctl(vcpu, cmd, arg);			\
								\
	TEST_ASSERT(!ret, __KVM_IOCTL_ERROR(name, ret));	\
	__TEST_ASSERT_VM_VCPU_IOCTL(!ret, #cmd, ret, (vcpu)->vm);	\
})

#define vcpu_ioctl(vcpu, cmd, arg)				\
	_vcpu_ioctl(vcpu, cmd, #cmd, arg)

/*
 * Looks up and returns the value corresponding to the capability
 * (KVM_CAP_*) given by cap.
@@ -335,7 +360,7 @@ static inline int vm_check_cap(struct kvm_vm *vm, long cap)
{
	int ret =  __vm_ioctl(vm, KVM_CHECK_EXTENSION, (void *)cap);

	TEST_ASSERT(ret >= 0, KVM_IOCTL_ERROR(KVM_CHECK_EXTENSION, ret));
	TEST_ASSERT_VM_VCPU_IOCTL(ret >= 0, KVM_CHECK_EXTENSION, ret, vm);
	return ret;
}

@@ -442,7 +467,7 @@ static inline int vm_get_stats_fd(struct kvm_vm *vm)
{
	int fd = __vm_ioctl(vm, KVM_GET_STATS_FD, NULL);

	TEST_ASSERT(fd >= 0, KVM_IOCTL_ERROR(KVM_GET_STATS_FD, fd));
	TEST_ASSERT_VM_VCPU_IOCTL(fd >= 0, KVM_GET_STATS_FD, fd, vm);
	return fd;
}

@@ -684,7 +709,7 @@ static inline int vcpu_get_stats_fd(struct kvm_vcpu *vcpu)
{
	int fd = __vcpu_ioctl(vcpu, KVM_GET_STATS_FD, NULL);

	TEST_ASSERT(fd >= 0, KVM_IOCTL_ERROR(KVM_GET_STATS_FD, fd));
	TEST_ASSERT_VM_VCPU_IOCTL(fd >= 0, KVM_CHECK_EXTENSION, fd, vcpu->vm);
	return fd;
}

+1 −1
Original line number Diff line number Diff line
@@ -191,7 +191,7 @@ static inline uint32_t atoi_non_negative(const char *name, const char *num_str)
}

int guest_vsnprintf(char *buf, int n, const char *fmt, va_list args);
int guest_snprintf(char *buf, int n, const char *fmt, ...);
__printf(3, 4) int guest_snprintf(char *buf, int n, const char *fmt, ...);

char *strdup_printf(const char *fmt, ...) __attribute__((format(printf, 1, 2), nonnull(1)));

+4 −3
Original line number Diff line number Diff line
@@ -34,9 +34,10 @@ void ucall_arch_do_ucall(vm_vaddr_t uc);
void *ucall_arch_get_ucall(struct kvm_vcpu *vcpu);

void ucall(uint64_t cmd, int nargs, ...);
void ucall_fmt(uint64_t cmd, const char *fmt, ...);
void ucall_assert(uint64_t cmd, const char *exp, const char *file,
		  unsigned int line, const char *fmt, ...);
__printf(2, 3) void ucall_fmt(uint64_t cmd, const char *fmt, ...);
__printf(5, 6) void ucall_assert(uint64_t cmd, const char *exp,
				 const char *file, unsigned int line,
				 const char *fmt, ...);
uint64_t get_ucall(struct kvm_vcpu *vcpu, struct ucall *uc);
void ucall_init(struct kvm_vm *vm, vm_paddr_t mmio_gpa);
int ucall_nr_pages_required(uint64_t page_size);
+1 −1
Original line number Diff line number Diff line
@@ -1271,7 +1271,7 @@ struct kvm_vcpu *__vm_vcpu_add(struct kvm_vm *vm, uint32_t vcpu_id)
	vcpu->vm = vm;
	vcpu->id = vcpu_id;
	vcpu->fd = __vm_ioctl(vm, KVM_CREATE_VCPU, (void *)(unsigned long)vcpu_id);
	TEST_ASSERT(vcpu->fd >= 0, KVM_IOCTL_ERROR(KVM_CREATE_VCPU, vcpu->fd));
	TEST_ASSERT_VM_VCPU_IOCTL(vcpu->fd >= 0, KVM_CREATE_VCPU, vcpu->fd, vm);

	TEST_ASSERT(vcpu_mmap_sz() >= sizeof(*vcpu->run), "vcpu mmap size "
		"smaller than expected, vcpu_mmap_sz: %i expected_min: %zi",
Loading