@@ -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-
293296static __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-
312340static __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
0 commit comments