1 // SPDX-License-Identifier: GPL-2.0-only 2 #include <errno.h> 3 #include <pthread.h> 4 #include <stdio.h> 5 #include <stdlib.h> 6 #include <string.h> 7 #include <signal.h> 8 #include <stdint.h> 9 #include <sys/sysinfo.h> 10 11 #include "kvm_util.h" 12 13 static struct kvm_vm *vm1; 14 static struct kvm_vm *vm2; 15 static int __eventfd; 16 static bool done; 17 18 /* 19 * KVM de-assigns based on eventfd *and* GSI, but requires unique eventfds when 20 * assigning (the API isn't symmetrical). Abuse the oddity and use a per-task 21 * GSI base to avoid false failures due to cross-task de-assign, i.e. so that 22 * the secondary doesn't de-assign the primary's eventfd and cause assign to 23 * unexpectedly succeed on the primary. 24 */ 25 #define GSI_BASE_PRIMARY 0x20 26 #define GSI_BASE_SECONDARY 0x30 27 28 static void juggle_eventfd_secondary(struct kvm_vm *vm, int eventfd) 29 { 30 int r, i; 31 32 /* 33 * The secondary task can encounter EBADF since the primary can close 34 * the eventfd at any time. And because the primary can recreate the 35 * eventfd, at the safe fd in the file table, the secondary can also 36 * encounter "unexpected" success, e.g. if the close+recreate happens 37 * between the first and second assignments. The secondary's role is 38 * mostly to antagonize KVM, not to detect bugs. 39 */ 40 for (i = 0; i < 2; i++) { 41 r = __kvm_irqfd(vm, GSI_BASE_SECONDARY, eventfd, 0); 42 TEST_ASSERT(!r || errno == EBUSY || errno == EBADF, 43 "Wanted success, EBUSY, or EBADF, r = %d, errno = %d", 44 r, errno); 45 46 /* De-assign should succeed unless the eventfd was closed. */ 47 r = __kvm_irqfd(vm, GSI_BASE_SECONDARY + i, eventfd, KVM_IRQFD_FLAG_DEASSIGN); 48 TEST_ASSERT(!r || errno == EBADF, 49 "De-assign should succeed unless the fd was closed"); 50 } 51 } 52 53 static void *secondary_irqfd_juggler(void *ign) 54 { 55 while (!READ_ONCE(done)) { 56 juggle_eventfd_secondary(vm1, READ_ONCE(__eventfd)); 57 juggle_eventfd_secondary(vm2, READ_ONCE(__eventfd)); 58 } 59 60 return NULL; 61 } 62 63 static void juggle_eventfd_primary(struct kvm_vm *vm, int eventfd) 64 { 65 int r1, r2; 66 67 /* 68 * At least one of the assigns should fail. KVM disallows assigning a 69 * single eventfd to multiple GSIs (or VMs), so it's possible that both 70 * assignments can fail, too. 71 */ 72 r1 = __kvm_irqfd(vm, GSI_BASE_PRIMARY, eventfd, 0); 73 TEST_ASSERT(!r1 || errno == EBUSY, 74 "Wanted success or EBUSY, r = %d, errno = %d", r1, errno); 75 76 r2 = __kvm_irqfd(vm, GSI_BASE_PRIMARY + 1, eventfd, 0); 77 TEST_ASSERT(r1 || (r2 && errno == EBUSY), 78 "Wanted failure (EBUSY), r1 = %d, r2 = %d, errno = %d", 79 r1, r2, errno); 80 81 /* 82 * De-assign should always succeed, even if the corresponding assign 83 * failed. 84 */ 85 kvm_irqfd(vm, GSI_BASE_PRIMARY, eventfd, KVM_IRQFD_FLAG_DEASSIGN); 86 kvm_irqfd(vm, GSI_BASE_PRIMARY + 1, eventfd, KVM_IRQFD_FLAG_DEASSIGN); 87 } 88 89 int main(int argc, char *argv[]) 90 { 91 pthread_t racing_thread; 92 int r, i; 93 94 /* Create "full" VMs, as KVM_IRQFD requires an in-kernel IRQ chip. */ 95 vm1 = vm_create(1); 96 vm2 = vm_create(1); 97 98 WRITE_ONCE(__eventfd, kvm_new_eventfd()); 99 100 kvm_irqfd(vm1, 10, __eventfd, 0); 101 102 r = __kvm_irqfd(vm1, 11, __eventfd, 0); 103 TEST_ASSERT(r && errno == EBUSY, 104 "Wanted EBUSY, r = %d, errno = %d", r, errno); 105 106 r = __kvm_irqfd(vm2, 12, __eventfd, 0); 107 TEST_ASSERT(r && errno == EBUSY, 108 "Wanted EBUSY, r = %d, errno = %d", r, errno); 109 110 /* 111 * De-assign all eventfds, along with multiple eventfds that were never 112 * assigned. KVM's ABI is that de-assign is allowed so long as the 113 * eventfd itself is valid. 114 */ 115 kvm_irqfd(vm1, 11, READ_ONCE(__eventfd), KVM_IRQFD_FLAG_DEASSIGN); 116 kvm_irqfd(vm1, 12, READ_ONCE(__eventfd), KVM_IRQFD_FLAG_DEASSIGN); 117 kvm_irqfd(vm1, 13, READ_ONCE(__eventfd), KVM_IRQFD_FLAG_DEASSIGN); 118 kvm_irqfd(vm1, 14, READ_ONCE(__eventfd), KVM_IRQFD_FLAG_DEASSIGN); 119 kvm_irqfd(vm1, 10, READ_ONCE(__eventfd), KVM_IRQFD_FLAG_DEASSIGN); 120 121 close(__eventfd); 122 123 pthread_create(&racing_thread, NULL, secondary_irqfd_juggler, vm2); 124 125 for (i = 0; i < 10000; i++) { 126 WRITE_ONCE(__eventfd, kvm_new_eventfd()); 127 128 juggle_eventfd_primary(vm1, __eventfd); 129 juggle_eventfd_primary(vm2, __eventfd); 130 close(__eventfd); 131 } 132 133 WRITE_ONCE(done, true); 134 pthread_join(racing_thread, NULL); 135 } 136