Skip to content

Commit 1c3c87d

Browse files
committed
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.
2 parents 80583d0 + 1b2658e commit 1c3c87d

14 files changed

Lines changed: 73 additions & 167 deletions

tools/testing/selftests/kvm/Makefile

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,6 @@ TEST_GEN_PROGS_x86_64 += x86_64/hyperv_svm_test
8686
TEST_GEN_PROGS_x86_64 += x86_64/hyperv_tlb_flush
8787
TEST_GEN_PROGS_x86_64 += x86_64/kvm_clock_test
8888
TEST_GEN_PROGS_x86_64 += x86_64/kvm_pv_test
89-
TEST_GEN_PROGS_x86_64 += x86_64/mmio_warning_test
9089
TEST_GEN_PROGS_x86_64 += x86_64/monitor_mwait_test
9190
TEST_GEN_PROGS_x86_64 += x86_64/nested_exceptions_test
9291
TEST_GEN_PROGS_x86_64 += x86_64/platform_info_test
@@ -226,7 +225,7 @@ else
226225
LINUX_TOOL_ARCH_INCLUDE = $(top_srcdir)/tools/arch/$(ARCH)/include
227226
endif
228227
CFLAGS += -Wall -Wstrict-prototypes -Wuninitialized -O2 -g -std=gnu99 \
229-
-Wno-gnu-variable-sized-type-not-at-end -MD\
228+
-Wno-gnu-variable-sized-type-not-at-end -MD -MP \
230229
-fno-builtin-memcmp -fno-builtin-memcpy -fno-builtin-memset \
231230
-fno-builtin-strnlen \
232231
-fno-stack-protector -fno-PIE -I$(LINUX_TOOL_INCLUDE) \

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

Lines changed: 45 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,13 @@ static inline bool kvm_has_cap(long cap)
267267
#define __KVM_SYSCALL_ERROR(_name, _ret) \
268268
"%s failed, rc: %i errno: %i (%s)", (_name), (_ret), errno, strerror(errno)
269269

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

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

282-
283-
#define _kvm_ioctl(kvm_fd, cmd, name, arg) \
289+
#define kvm_ioctl(kvm_fd, cmd, arg) \
284290
({ \
285291
int ret = __kvm_ioctl(kvm_fd, cmd, arg); \
286292
\
287-
TEST_ASSERT(!ret, __KVM_IOCTL_ERROR(name, ret)); \
293+
TEST_ASSERT(!ret, __KVM_IOCTL_ERROR(#cmd, ret)); \
288294
})
289295

290-
#define kvm_ioctl(kvm_fd, cmd, arg) \
291-
_kvm_ioctl(kvm_fd, cmd, #cmd, arg)
292-
293296
static __always_inline void static_assert_is_vm(struct kvm_vm *vm) { }
294297

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

301-
#define _vm_ioctl(vm, cmd, name, arg) \
304+
/*
305+
* Assert that a VM or vCPU ioctl() succeeded, with extra magic to detect if
306+
* the ioctl() failed because KVM killed/bugged the VM. To detect a dead VM,
307+
* probe KVM_CAP_USER_MEMORY, which (a) has been supported by KVM since before
308+
* selftests existed and (b) should never outright fail, i.e. is supposed to
309+
* return 0 or 1. If KVM kills a VM, KVM returns -EIO for all ioctl()s for the
310+
* VM and its vCPUs, including KVM_CHECK_EXTENSION.
311+
*/
312+
#define __TEST_ASSERT_VM_VCPU_IOCTL(cond, name, ret, vm) \
313+
do { \
314+
int __errno = errno; \
315+
\
316+
static_assert_is_vm(vm); \
317+
\
318+
if (cond) \
319+
break; \
320+
\
321+
if (errno == EIO && \
322+
__vm_ioctl(vm, KVM_CHECK_EXTENSION, (void *)KVM_CAP_USER_MEMORY) < 0) { \
323+
TEST_ASSERT(errno == EIO, "KVM killed the VM, should return -EIO"); \
324+
TEST_FAIL("KVM killed/bugged the VM, check the kernel log for clues"); \
325+
} \
326+
errno = __errno; \
327+
TEST_ASSERT(cond, __KVM_IOCTL_ERROR(name, ret)); \
328+
} while (0)
329+
330+
#define TEST_ASSERT_VM_VCPU_IOCTL(cond, cmd, ret, vm) \
331+
__TEST_ASSERT_VM_VCPU_IOCTL(cond, #cmd, ret, vm)
332+
333+
#define vm_ioctl(vm, cmd, arg) \
302334
({ \
303335
int ret = __vm_ioctl(vm, cmd, arg); \
304336
\
305-
TEST_ASSERT(!ret, __KVM_IOCTL_ERROR(name, ret)); \
337+
__TEST_ASSERT_VM_VCPU_IOCTL(!ret, #cmd, ret, vm); \
306338
})
307339

308-
#define vm_ioctl(vm, cmd, arg) \
309-
_vm_ioctl(vm, cmd, #cmd, arg)
310-
311-
312340
static __always_inline void static_assert_is_vcpu(struct kvm_vcpu *vcpu) { }
313341

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

320-
#define _vcpu_ioctl(vcpu, cmd, name, arg) \
348+
#define vcpu_ioctl(vcpu, cmd, arg) \
321349
({ \
322350
int ret = __vcpu_ioctl(vcpu, cmd, arg); \
323351
\
324-
TEST_ASSERT(!ret, __KVM_IOCTL_ERROR(name, ret)); \
352+
__TEST_ASSERT_VM_VCPU_IOCTL(!ret, #cmd, ret, (vcpu)->vm); \
325353
})
326354

327-
#define vcpu_ioctl(vcpu, cmd, arg) \
328-
_vcpu_ioctl(vcpu, cmd, #cmd, arg)
329-
330355
/*
331356
* Looks up and returns the value corresponding to the capability
332357
* (KVM_CAP_*) given by cap.
@@ -335,7 +360,7 @@ static inline int vm_check_cap(struct kvm_vm *vm, long cap)
335360
{
336361
int ret = __vm_ioctl(vm, KVM_CHECK_EXTENSION, (void *)cap);
337362

338-
TEST_ASSERT(ret >= 0, KVM_IOCTL_ERROR(KVM_CHECK_EXTENSION, ret));
363+
TEST_ASSERT_VM_VCPU_IOCTL(ret >= 0, KVM_CHECK_EXTENSION, ret, vm);
339364
return ret;
340365
}
341366

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

445-
TEST_ASSERT(fd >= 0, KVM_IOCTL_ERROR(KVM_GET_STATS_FD, fd));
470+
TEST_ASSERT_VM_VCPU_IOCTL(fd >= 0, KVM_GET_STATS_FD, fd, vm);
446471
return fd;
447472
}
448473

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

687-
TEST_ASSERT(fd >= 0, KVM_IOCTL_ERROR(KVM_GET_STATS_FD, fd));
712+
TEST_ASSERT_VM_VCPU_IOCTL(fd >= 0, KVM_CHECK_EXTENSION, fd, vcpu->vm);
688713
return fd;
689714
}
690715

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ static inline uint32_t atoi_non_negative(const char *name, const char *num_str)
191191
}
192192

193193
int guest_vsnprintf(char *buf, int n, const char *fmt, va_list args);
194-
int guest_snprintf(char *buf, int n, const char *fmt, ...);
194+
__printf(3, 4) int guest_snprintf(char *buf, int n, const char *fmt, ...);
195195

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

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

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,10 @@ void ucall_arch_do_ucall(vm_vaddr_t uc);
3434
void *ucall_arch_get_ucall(struct kvm_vcpu *vcpu);
3535

3636
void ucall(uint64_t cmd, int nargs, ...);
37-
void ucall_fmt(uint64_t cmd, const char *fmt, ...);
38-
void ucall_assert(uint64_t cmd, const char *exp, const char *file,
39-
unsigned int line, const char *fmt, ...);
37+
__printf(2, 3) void ucall_fmt(uint64_t cmd, const char *fmt, ...);
38+
__printf(5, 6) void ucall_assert(uint64_t cmd, const char *exp,
39+
const char *file, unsigned int line,
40+
const char *fmt, ...);
4041
uint64_t get_ucall(struct kvm_vcpu *vcpu, struct ucall *uc);
4142
void ucall_init(struct kvm_vm *vm, vm_paddr_t mmio_gpa);
4243
int ucall_nr_pages_required(uint64_t page_size);

tools/testing/selftests/kvm/lib/kvm_util.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1271,7 +1271,7 @@ struct kvm_vcpu *__vm_vcpu_add(struct kvm_vm *vm, uint32_t vcpu_id)
12711271
vcpu->vm = vm;
12721272
vcpu->id = vcpu_id;
12731273
vcpu->fd = __vm_ioctl(vm, KVM_CREATE_VCPU, (void *)(unsigned long)vcpu_id);
1274-
TEST_ASSERT(vcpu->fd >= 0, KVM_IOCTL_ERROR(KVM_CREATE_VCPU, vcpu->fd));
1274+
TEST_ASSERT_VM_VCPU_IOCTL(vcpu->fd >= 0, KVM_CREATE_VCPU, vcpu->fd, vm);
12751275

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

tools/testing/selftests/kvm/set_memory_region_test.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -157,17 +157,17 @@ static void guest_code_move_memory_region(void)
157157
*/
158158
val = guest_spin_on_val(0);
159159
__GUEST_ASSERT(val == 1 || val == MMIO_VAL,
160-
"Expected '1' or MMIO ('%llx'), got '%llx'", MMIO_VAL, val);
160+
"Expected '1' or MMIO ('%lx'), got '%lx'", MMIO_VAL, val);
161161

162162
/* Spin until the misaligning memory region move completes. */
163163
val = guest_spin_on_val(MMIO_VAL);
164164
__GUEST_ASSERT(val == 1 || val == 0,
165-
"Expected '0' or '1' (no MMIO), got '%llx'", val);
165+
"Expected '0' or '1' (no MMIO), got '%lx'", val);
166166

167167
/* Spin until the memory region starts to get re-aligned. */
168168
val = guest_spin_on_val(0);
169169
__GUEST_ASSERT(val == 1 || val == MMIO_VAL,
170-
"Expected '1' or MMIO ('%llx'), got '%llx'", MMIO_VAL, val);
170+
"Expected '1' or MMIO ('%lx'), got '%lx'", MMIO_VAL, val);
171171

172172
/* Spin until the re-aligning memory region move completes. */
173173
val = guest_spin_on_val(MMIO_VAL);

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

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -55,18 +55,18 @@ static void guest_msr(struct msr_data *msr)
5555
if (msr->fault_expected)
5656
__GUEST_ASSERT(vector == GP_VECTOR,
5757
"Expected #GP on %sMSR(0x%x), got vector '0x%x'",
58-
msr->idx, msr->write ? "WR" : "RD", vector);
58+
msr->write ? "WR" : "RD", msr->idx, vector);
5959
else
6060
__GUEST_ASSERT(!vector,
6161
"Expected success on %sMSR(0x%x), got vector '0x%x'",
62-
msr->idx, msr->write ? "WR" : "RD", vector);
62+
msr->write ? "WR" : "RD", msr->idx, vector);
6363

6464
if (vector || is_write_only_msr(msr->idx))
6565
goto done;
6666

6767
if (msr->write)
6868
__GUEST_ASSERT(!vector,
69-
"WRMSR(0x%x) to '0x%llx', RDMSR read '0x%llx'",
69+
"WRMSR(0x%x) to '0x%lx', RDMSR read '0x%lx'",
7070
msr->idx, msr->write_val, msr_val);
7171

7272
/* Invariant TSC bit appears when TSC invariant control MSR is written to */
@@ -102,11 +102,11 @@ static void guest_hcall(vm_vaddr_t pgs_gpa, struct hcall_data *hcall)
102102
vector = __hyperv_hypercall(hcall->control, input, output, &res);
103103
if (hcall->ud_expected) {
104104
__GUEST_ASSERT(vector == UD_VECTOR,
105-
"Expected #UD for control '%u', got vector '0x%x'",
105+
"Expected #UD for control '%lu', got vector '0x%x'",
106106
hcall->control, vector);
107107
} else {
108108
__GUEST_ASSERT(!vector,
109-
"Expected no exception for control '%u', got vector '0x%x'",
109+
"Expected no exception for control '%lu', got vector '0x%x'",
110110
hcall->control, vector);
111111
GUEST_ASSERT_EQ(res, hcall->expect);
112112
}

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

Lines changed: 0 additions & 121 deletions
This file was deleted.

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

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,12 @@ do { \
2727
\
2828
if (fault_wanted) \
2929
__GUEST_ASSERT((vector) == UD_VECTOR, \
30-
"Expected #UD on " insn " for testcase '0x%x', got '0x%x'", vector); \
30+
"Expected #UD on " insn " for testcase '0x%x', got '0x%x'", \
31+
testcase, vector); \
3132
else \
3233
__GUEST_ASSERT(!(vector), \
33-
"Expected success on " insn " for testcase '0x%x', got '0x%x'", vector); \
34+
"Expected success on " insn " for testcase '0x%x', got '0x%x'", \
35+
testcase, vector); \
3436
} while (0)
3537

3638
static void guest_monitor_wait(int testcase)

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -259,7 +259,7 @@ int main(int argc, char **argv)
259259
__TEST_REQUIRE(token == MAGIC_TOKEN,
260260
"This test must be run with the magic token %d.\n"
261261
"This is done by nx_huge_pages_test.sh, which\n"
262-
"also handles environment setup for the test.");
262+
"also handles environment setup for the test.", MAGIC_TOKEN);
263263

264264
run_test(reclaim_period_ms, false, reboot_permissions);
265265
run_test(reclaim_period_ms, true, reboot_permissions);

0 commit comments

Comments
 (0)