Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/tools/testing/selftests/kvm/irqfd_test.c
38189 views
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
struct kvm_vcpu *unused;
93
int r, i;
94
95
TEST_REQUIRE(kvm_arch_has_default_irqchip());
96
97
/*
98
* Create "full" VMs, as KVM_IRQFD requires an in-kernel IRQ chip. Also
99
* create an unused vCPU as certain architectures (like arm64) need to
100
* complete IRQ chip initialization after all possible vCPUs for a VM
101
* have been created.
102
*/
103
vm1 = vm_create_with_one_vcpu(&unused, NULL);
104
vm2 = vm_create_with_one_vcpu(&unused, NULL);
105
106
WRITE_ONCE(__eventfd, kvm_new_eventfd());
107
108
kvm_irqfd(vm1, 10, __eventfd, 0);
109
110
r = __kvm_irqfd(vm1, 11, __eventfd, 0);
111
TEST_ASSERT(r && errno == EBUSY,
112
"Wanted EBUSY, r = %d, errno = %d", r, errno);
113
114
r = __kvm_irqfd(vm2, 12, __eventfd, 0);
115
TEST_ASSERT(r && errno == EBUSY,
116
"Wanted EBUSY, r = %d, errno = %d", r, errno);
117
118
/*
119
* De-assign all eventfds, along with multiple eventfds that were never
120
* assigned. KVM's ABI is that de-assign is allowed so long as the
121
* eventfd itself is valid.
122
*/
123
kvm_irqfd(vm1, 11, READ_ONCE(__eventfd), KVM_IRQFD_FLAG_DEASSIGN);
124
kvm_irqfd(vm1, 12, READ_ONCE(__eventfd), KVM_IRQFD_FLAG_DEASSIGN);
125
kvm_irqfd(vm1, 13, READ_ONCE(__eventfd), KVM_IRQFD_FLAG_DEASSIGN);
126
kvm_irqfd(vm1, 14, READ_ONCE(__eventfd), KVM_IRQFD_FLAG_DEASSIGN);
127
kvm_irqfd(vm1, 10, READ_ONCE(__eventfd), KVM_IRQFD_FLAG_DEASSIGN);
128
129
close(__eventfd);
130
131
pthread_create(&racing_thread, NULL, secondary_irqfd_juggler, vm2);
132
133
for (i = 0; i < 10000; i++) {
134
WRITE_ONCE(__eventfd, kvm_new_eventfd());
135
136
juggle_eventfd_primary(vm1, __eventfd);
137
juggle_eventfd_primary(vm2, __eventfd);
138
close(__eventfd);
139
}
140
141
WRITE_ONCE(done, true);
142
pthread_join(racing_thread, NULL);
143
}
144
145