1 // SPDX-License-Identifier: GPL-2.0-only
3 * VFIO generic eventfd code for IRQFD support.
4 * Derived from drivers/vfio/pci/vfio_pci_intrs.c
6 * Copyright (C) 2012 Red Hat, Inc. All rights reserved.
7 * Author: Alex Williamson <alex.williamson@redhat.com>
10 #include <linux/vfio.h>
11 #include <linux/eventfd.h>
12 #include <linux/file.h>
13 #include <linux/module.h>
14 #include <linux/slab.h>
17 static struct workqueue_struct
*vfio_irqfd_cleanup_wq
;
18 static DEFINE_SPINLOCK(virqfd_lock
);
20 int __init
vfio_virqfd_init(void)
22 vfio_irqfd_cleanup_wq
=
23 create_singlethread_workqueue("vfio-irqfd-cleanup");
24 if (!vfio_irqfd_cleanup_wq
)
30 void vfio_virqfd_exit(void)
32 destroy_workqueue(vfio_irqfd_cleanup_wq
);
35 static void virqfd_deactivate(struct virqfd
*virqfd
)
37 queue_work(vfio_irqfd_cleanup_wq
, &virqfd
->shutdown
);
40 static int virqfd_wakeup(wait_queue_entry_t
*wait
, unsigned mode
, int sync
, void *key
)
42 struct virqfd
*virqfd
= container_of(wait
, struct virqfd
, wait
);
43 __poll_t flags
= key_to_poll(key
);
45 if (flags
& EPOLLIN
) {
47 eventfd_ctx_do_read(virqfd
->eventfd
, &cnt
);
49 /* An event has been signaled, call function */
50 if ((!virqfd
->handler
||
51 virqfd
->handler(virqfd
->opaque
, virqfd
->data
)) &&
53 schedule_work(&virqfd
->inject
);
56 if (flags
& EPOLLHUP
) {
58 spin_lock_irqsave(&virqfd_lock
, flags
);
61 * The eventfd is closing, if the virqfd has not yet been
62 * queued for release, as determined by testing whether the
63 * virqfd pointer to it is still valid, queue it now. As
64 * with kvm irqfds, we know we won't race against the virqfd
65 * going away because we hold the lock to get here.
67 if (*(virqfd
->pvirqfd
) == virqfd
) {
68 *(virqfd
->pvirqfd
) = NULL
;
69 virqfd_deactivate(virqfd
);
72 spin_unlock_irqrestore(&virqfd_lock
, flags
);
78 static void virqfd_ptable_queue_proc(struct file
*file
,
79 wait_queue_head_t
*wqh
, poll_table
*pt
)
81 struct virqfd
*virqfd
= container_of(pt
, struct virqfd
, pt
);
82 add_wait_queue(wqh
, &virqfd
->wait
);
85 static void virqfd_shutdown(struct work_struct
*work
)
87 struct virqfd
*virqfd
= container_of(work
, struct virqfd
, shutdown
);
90 eventfd_ctx_remove_wait_queue(virqfd
->eventfd
, &virqfd
->wait
, &cnt
);
91 flush_work(&virqfd
->inject
);
92 eventfd_ctx_put(virqfd
->eventfd
);
97 static void virqfd_inject(struct work_struct
*work
)
99 struct virqfd
*virqfd
= container_of(work
, struct virqfd
, inject
);
101 virqfd
->thread(virqfd
->opaque
, virqfd
->data
);
104 static void virqfd_flush_inject(struct work_struct
*work
)
106 struct virqfd
*virqfd
= container_of(work
, struct virqfd
, flush_inject
);
108 flush_work(&virqfd
->inject
);
111 int vfio_virqfd_enable(void *opaque
,
112 int (*handler
)(void *, void *),
113 void (*thread
)(void *, void *),
114 void *data
, struct virqfd
**pvirqfd
, int fd
)
116 struct eventfd_ctx
*ctx
;
117 struct virqfd
*virqfd
;
121 virqfd
= kzalloc(sizeof(*virqfd
), GFP_KERNEL_ACCOUNT
);
125 virqfd
->pvirqfd
= pvirqfd
;
126 virqfd
->opaque
= opaque
;
127 virqfd
->handler
= handler
;
128 virqfd
->thread
= thread
;
131 INIT_WORK(&virqfd
->shutdown
, virqfd_shutdown
);
132 INIT_WORK(&virqfd
->inject
, virqfd_inject
);
133 INIT_WORK(&virqfd
->flush_inject
, virqfd_flush_inject
);
135 CLASS(fd
, irqfd
)(fd
);
136 if (fd_empty(irqfd
)) {
141 ctx
= eventfd_ctx_fileget(fd_file(irqfd
));
147 virqfd
->eventfd
= ctx
;
150 * virqfds can be released by closing the eventfd or directly
151 * through ioctl. These are both done through a workqueue, so
152 * we update the pointer to the virqfd under lock to avoid
153 * pushing multiple jobs to release the same virqfd.
155 spin_lock_irq(&virqfd_lock
);
158 spin_unlock_irq(&virqfd_lock
);
164 spin_unlock_irq(&virqfd_lock
);
167 * Install our own custom wake-up handling so we are notified via
168 * a callback whenever someone signals the underlying eventfd.
170 init_waitqueue_func_entry(&virqfd
->wait
, virqfd_wakeup
);
171 init_poll_funcptr(&virqfd
->pt
, virqfd_ptable_queue_proc
);
173 events
= vfs_poll(fd_file(irqfd
), &virqfd
->pt
);
176 * Check if there was an event already pending on the eventfd
177 * before we registered and trigger it as if we didn't miss it.
179 if (events
& EPOLLIN
) {
180 if ((!handler
|| handler(opaque
, data
)) && thread
)
181 schedule_work(&virqfd
->inject
);
185 eventfd_ctx_put(ctx
);
191 EXPORT_SYMBOL_GPL(vfio_virqfd_enable
);
193 void vfio_virqfd_disable(struct virqfd
**pvirqfd
)
197 spin_lock_irqsave(&virqfd_lock
, flags
);
200 virqfd_deactivate(*pvirqfd
);
204 spin_unlock_irqrestore(&virqfd_lock
, flags
);
207 * Block until we know all outstanding shutdown jobs have completed.
208 * Even if we don't queue the job, flush the wq to be sure it's
211 flush_workqueue(vfio_irqfd_cleanup_wq
);
213 EXPORT_SYMBOL_GPL(vfio_virqfd_disable
);
215 void vfio_virqfd_flush_thread(struct virqfd
**pvirqfd
)
219 spin_lock_irqsave(&virqfd_lock
, flags
);
220 if (*pvirqfd
&& (*pvirqfd
)->thread
)
221 queue_work(vfio_irqfd_cleanup_wq
, &(*pvirqfd
)->flush_inject
);
222 spin_unlock_irqrestore(&virqfd_lock
, flags
);
224 flush_workqueue(vfio_irqfd_cleanup_wq
);
226 EXPORT_SYMBOL_GPL(vfio_virqfd_flush_thread
);