1 /******************************************************************************
4 * Driver for receiving and demuxing event-channel signals.
6 * Copyright (c) 2004-2005, K A Fraser
7 * Multi-process extensions Copyright (c) 2004, Steven Smith
8 * FreeBSD port Copyright (c) 2014, Roger Pau Monné
9 * Fetched from git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
10 * File: drivers/xen/evtchn.c
11 * Git commit: 0dc0064add422bc0ef5165ebe9ece3052bbd457d
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License version 2
15 * as published by the Free Software Foundation; or, when distributed
16 * separately from the Linux kernel or incorporated into other
17 * software packages, subject to the following license:
19 * Permission is hereby granted, free of charge, to any person obtaining a copy
20 * of this source file (the "Software"), to deal in the Software without
21 * restriction, including without limitation the rights to use, copy, modify,
22 * merge, publish, distribute, sublicense, and/or sell copies of the Software,
23 * and to permit persons to whom the Software is furnished to do so, subject to
24 * the following conditions:
26 * The above copyright notice and this permission notice shall be included in
27 * all copies or substantial portions of the Software.
29 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
30 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
31 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
32 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
33 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
34 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
38 #include <sys/cdefs.h>
39 __FBSDID("$FreeBSD$");
41 #include <sys/param.h>
42 #include <sys/systm.h>
45 #include <sys/malloc.h>
46 #include <sys/kernel.h>
48 #include <sys/mutex.h>
50 #include <sys/selinfo.h>
53 #include <sys/fcntl.h>
54 #include <sys/ioccom.h>
57 #include <sys/module.h>
58 #include <sys/filio.h>
59 #include <sys/vnode.h>
61 #include <machine/intr_machdep.h>
62 #include <machine/xen/synch_bitops.h>
64 #include <xen/xen-os.h>
65 #include <xen/evtchn.h>
66 #include <xen/xen_intr.h>
68 #include <xen/evtchn/evtchnvar.h>
70 MALLOC_DEFINE(M_EVTCHN, "evtchn_dev", "Xen event channel user-space device");
74 static int evtchn_cmp(struct user_evtchn *u1, struct user_evtchn *u2);
76 RB_HEAD(evtchn_tree, user_evtchn);
78 struct per_user_data {
79 struct mtx bind_mutex; /* serialize bind/unbind operations */
80 struct evtchn_tree evtchns;
82 /* Notification ring, accessed via /dev/xen/evtchn. */
83 #define EVTCHN_RING_SIZE (PAGE_SIZE / sizeof(evtchn_port_t))
84 #define EVTCHN_RING_MASK(_i) ((_i)&(EVTCHN_RING_SIZE-1))
86 unsigned int ring_cons, ring_prod, ring_overflow;
87 struct sx ring_cons_mutex; /* protect against concurrent readers */
88 struct mtx ring_prod_mutex; /* product against concurrent interrupts */
89 struct selinfo ev_rsel;
93 RB_ENTRY(user_evtchn) node;
94 struct per_user_data *user;
96 xen_intr_handle_t handle;
100 RB_GENERATE_STATIC(evtchn_tree, user_evtchn, node, evtchn_cmp);
102 static device_t evtchn_dev;
104 static d_read_t evtchn_read;
105 static d_write_t evtchn_write;
106 static d_ioctl_t evtchn_ioctl;
107 static d_poll_t evtchn_poll;
108 static d_open_t evtchn_open;
110 static void evtchn_release(void *arg);
112 static struct cdevsw evtchn_devsw = {
113 .d_version = D_VERSION,
114 .d_open = evtchn_open,
115 .d_read = evtchn_read,
116 .d_write = evtchn_write,
117 .d_ioctl = evtchn_ioctl,
118 .d_poll = evtchn_poll,
122 /*------------------------- Red-black tree helpers ---------------------------*/
124 evtchn_cmp(struct user_evtchn *u1, struct user_evtchn *u2)
127 return (u1->port - u2->port);
130 static struct user_evtchn *
131 find_evtchn(struct per_user_data *u, evtchn_port_t port)
133 struct user_evtchn tmp = {
137 return (RB_FIND(evtchn_tree, &u->evtchns, &tmp));
140 /*--------------------------- Interrupt handlers -----------------------------*/
142 evtchn_filter(void *arg)
144 struct user_evtchn *evtchn;
148 if (!evtchn->enabled && bootverbose) {
149 device_printf(evtchn_dev,
150 "Received upcall for disabled event channel %d\n",
154 evtchn_mask_port(evtchn->port);
155 evtchn->enabled = false;
157 return (FILTER_SCHEDULE_THREAD);
161 evtchn_interrupt(void *arg)
163 struct user_evtchn *evtchn;
164 struct per_user_data *u;
170 * Protect against concurrent events using this handler
173 mtx_lock(&u->ring_prod_mutex);
174 if ((u->ring_prod - u->ring_cons) < EVTCHN_RING_SIZE) {
175 u->ring[EVTCHN_RING_MASK(u->ring_prod)] = evtchn->port;
176 wmb(); /* Ensure ring contents visible */
177 if (u->ring_cons == u->ring_prod++) {
179 selwakeup(&u->ev_rsel);
182 u->ring_overflow = 1;
183 mtx_unlock(&u->ring_prod_mutex);
186 /*------------------------- Character device methods -------------------------*/
188 evtchn_open(struct cdev *dev, int flag, int otyp, struct thread *td)
190 struct per_user_data *u;
193 u = malloc(sizeof(*u), M_EVTCHN, M_WAITOK | M_ZERO);
194 u->ring = malloc(PAGE_SIZE, M_EVTCHN, M_WAITOK | M_ZERO);
196 /* Initialize locks */
197 mtx_init(&u->bind_mutex, "evtchn_bind_mutex", NULL, MTX_DEF);
198 sx_init(&u->ring_cons_mutex, "evtchn_ringc_sx");
199 mtx_init(&u->ring_prod_mutex, "evtchn_ringp_mutex", NULL, MTX_DEF);
201 /* Initialize red-black tree. */
202 RB_INIT(&u->evtchns);
204 /* Assign the allocated per_user_data to this open instance. */
205 error = devfs_set_cdevpriv(u, evtchn_release);
207 mtx_destroy(&u->bind_mutex);
208 mtx_destroy(&u->ring_prod_mutex);
209 sx_destroy(&u->ring_cons_mutex);
210 free(u->ring, M_EVTCHN);
218 evtchn_release(void *arg)
220 struct per_user_data *u;
221 struct user_evtchn *evtchn, *tmp;
225 seldrain(&u->ev_rsel);
227 RB_FOREACH_SAFE(evtchn, evtchn_tree, &u->evtchns, tmp) {
228 xen_intr_unbind(&evtchn->handle);
230 RB_REMOVE(evtchn_tree, &u->evtchns, evtchn);
231 free(evtchn, M_EVTCHN);
234 mtx_destroy(&u->bind_mutex);
235 mtx_destroy(&u->ring_prod_mutex);
236 sx_destroy(&u->ring_cons_mutex);
237 free(u->ring, M_EVTCHN);
242 evtchn_read(struct cdev *dev, struct uio *uio, int ioflag)
245 unsigned int c, p, bytes1 = 0, bytes2 = 0;
246 struct per_user_data *u;
248 error = devfs_get_cdevpriv((void **)&u);
252 /* Whole number of ports. */
253 count = uio->uio_resid;
254 count &= ~(sizeof(evtchn_port_t)-1);
259 if (count > PAGE_SIZE)
262 sx_xlock(&u->ring_cons_mutex);
264 if (u->ring_overflow) {
274 if (ioflag & IO_NDELAY) {
279 error = sx_sleep(u, &u->ring_cons_mutex, PCATCH, "evtchw", 0);
280 if ((error != 0) && (error != EWOULDBLOCK))
284 /* Byte lengths of two chunks. Chunk split (if any) is at ring wrap. */
285 if (((c ^ p) & EVTCHN_RING_SIZE) != 0) {
286 bytes1 = (EVTCHN_RING_SIZE - EVTCHN_RING_MASK(c)) *
287 sizeof(evtchn_port_t);
288 bytes2 = EVTCHN_RING_MASK(p) * sizeof(evtchn_port_t);
290 bytes1 = (p - c) * sizeof(evtchn_port_t);
294 /* Truncate chunks according to caller's maximum byte count. */
295 if (bytes1 > count) {
298 } else if ((bytes1 + bytes2) > count) {
299 bytes2 = count - bytes1;
303 rmb(); /* Ensure that we see the port before we copy it. */
305 if (uiomove(&u->ring[EVTCHN_RING_MASK(c)], bytes1, uio) ||
306 ((bytes2 != 0) && uiomove(&u->ring[0], bytes2, uio)))
309 u->ring_cons += (bytes1 + bytes2) / sizeof(evtchn_port_t);
313 sx_xunlock(&u->ring_cons_mutex);
318 evtchn_write(struct cdev *dev, struct uio *uio, int ioflag)
322 struct per_user_data *u;
324 error = devfs_get_cdevpriv((void **)&u);
328 kbuf = malloc(PAGE_SIZE, M_EVTCHN, M_WAITOK);
330 count = uio->uio_resid;
331 /* Whole number of ports. */
332 count &= ~(sizeof(evtchn_port_t)-1);
338 if (count > PAGE_SIZE)
341 error = uiomove(kbuf, count, uio);
345 mtx_lock(&u->bind_mutex);
347 for (i = 0; i < (count/sizeof(evtchn_port_t)); i++) {
348 evtchn_port_t port = kbuf[i];
349 struct user_evtchn *evtchn;
351 evtchn = find_evtchn(u, port);
352 if (evtchn && !evtchn->enabled) {
353 evtchn->enabled = true;
354 evtchn_unmask_port(evtchn->port);
358 mtx_unlock(&u->bind_mutex);
362 free(kbuf, M_EVTCHN);
367 evtchn_bind_user_port(struct per_user_data *u, struct user_evtchn *evtchn)
371 evtchn->port = xen_intr_port(evtchn->handle);
373 evtchn->enabled = true;
374 mtx_lock(&u->bind_mutex);
375 RB_INSERT(evtchn_tree, &u->evtchns, evtchn);
376 mtx_unlock(&u->bind_mutex);
377 error = xen_intr_add_handler(device_get_nameunit(evtchn_dev),
378 evtchn_filter, evtchn_interrupt, evtchn,
379 INTR_TYPE_MISC | INTR_MPSAFE, evtchn->handle);
381 xen_intr_unbind(&evtchn->handle);
382 mtx_lock(&u->bind_mutex);
383 RB_REMOVE(evtchn_tree, &u->evtchns, evtchn);
384 mtx_unlock(&u->bind_mutex);
385 free(evtchn, M_EVTCHN);
391 evtchn_ioctl(struct cdev *dev, unsigned long cmd, caddr_t arg,
392 int mode, struct thread *td __unused)
394 struct per_user_data *u;
397 error = devfs_get_cdevpriv((void **)&u);
402 case IOCTL_EVTCHN_BIND_VIRQ: {
403 struct ioctl_evtchn_bind_virq *bind;
404 struct user_evtchn *evtchn;
406 evtchn = malloc(sizeof(*evtchn), M_EVTCHN, M_WAITOK | M_ZERO);
408 bind = (struct ioctl_evtchn_bind_virq *)arg;
410 error = xen_intr_bind_virq(evtchn_dev, bind->virq, 0,
411 NULL, NULL, NULL, 0, &evtchn->handle);
413 free(evtchn, M_EVTCHN);
416 error = evtchn_bind_user_port(u, evtchn);
419 bind->port = evtchn->port;
423 case IOCTL_EVTCHN_BIND_INTERDOMAIN: {
424 struct ioctl_evtchn_bind_interdomain *bind;
425 struct user_evtchn *evtchn;
427 evtchn = malloc(sizeof(*evtchn), M_EVTCHN, M_WAITOK | M_ZERO);
429 bind = (struct ioctl_evtchn_bind_interdomain *)arg;
431 error = xen_intr_bind_remote_port(evtchn_dev,
432 bind->remote_domain, bind->remote_port, NULL,
433 NULL, NULL, 0, &evtchn->handle);
435 free(evtchn, M_EVTCHN);
438 error = evtchn_bind_user_port(u, evtchn);
441 bind->port = evtchn->port;
445 case IOCTL_EVTCHN_BIND_UNBOUND_PORT: {
446 struct ioctl_evtchn_bind_unbound_port *bind;
447 struct user_evtchn *evtchn;
449 evtchn = malloc(sizeof(*evtchn), M_EVTCHN, M_WAITOK | M_ZERO);
451 bind = (struct ioctl_evtchn_bind_unbound_port *)arg;
453 error = xen_intr_alloc_and_bind_local_port(evtchn_dev,
454 bind->remote_domain, NULL, NULL, NULL, 0, &evtchn->handle);
456 free(evtchn, M_EVTCHN);
459 error = evtchn_bind_user_port(u, evtchn);
462 bind->port = evtchn->port;
466 case IOCTL_EVTCHN_UNBIND: {
467 struct ioctl_evtchn_unbind *unbind;
468 struct user_evtchn *evtchn;
470 unbind = (struct ioctl_evtchn_unbind *)arg;
472 mtx_lock(&u->bind_mutex);
473 evtchn = find_evtchn(u, unbind->port);
474 if (evtchn == NULL) {
478 RB_REMOVE(evtchn_tree, &u->evtchns, evtchn);
479 mtx_unlock(&u->bind_mutex);
481 xen_intr_unbind(&evtchn->handle);
482 free(evtchn, M_EVTCHN);
487 case IOCTL_EVTCHN_NOTIFY: {
488 struct ioctl_evtchn_notify *notify;
489 struct user_evtchn *evtchn;
491 notify = (struct ioctl_evtchn_notify *)arg;
493 mtx_lock(&u->bind_mutex);
494 evtchn = find_evtchn(u, notify->port);
495 if (evtchn == NULL) {
500 xen_intr_signal(evtchn->handle);
501 mtx_unlock(&u->bind_mutex);
506 case IOCTL_EVTCHN_RESET: {
507 /* Initialise the ring to empty. Clear errors. */
508 sx_xlock(&u->ring_cons_mutex);
509 mtx_lock(&u->ring_prod_mutex);
510 u->ring_cons = u->ring_prod = u->ring_overflow = 0;
511 mtx_unlock(&u->ring_prod_mutex);
512 sx_xunlock(&u->ring_cons_mutex);
519 /* Handled in an upper layer */
532 evtchn_poll(struct cdev *dev, int events, struct thread *td)
534 struct per_user_data *u;
537 error = devfs_get_cdevpriv((void **)&u);
541 /* we can always write */
542 mask = events & (POLLOUT | POLLWRNORM);
544 mtx_lock(&u->ring_prod_mutex);
545 if (events & (POLLIN | POLLRDNORM)) {
546 if (u->ring_cons != u->ring_prod) {
547 mask |= events & (POLLIN | POLLRDNORM);
549 /* Record that someone is waiting */
550 selrecord(td, &u->ev_rsel);
553 mtx_unlock(&u->ring_prod_mutex);
558 /*------------------ Private Device Attachment Functions --------------------*/
560 evtchn_identify(driver_t *driver, device_t parent)
563 KASSERT((xen_domain()),
564 ("Trying to attach evtchn device on non Xen domain"));
566 evtchn_dev = BUS_ADD_CHILD(parent, 0, "evtchn", 0);
567 if (evtchn_dev == NULL)
568 panic("unable to attach evtchn user-space device");
572 evtchn_probe(device_t dev)
575 device_set_desc(dev, "Xen event channel user-space device");
576 return (BUS_PROBE_NOWILDCARD);
580 evtchn_attach(device_t dev)
583 make_dev_credf(MAKEDEV_ETERNAL, &evtchn_devsw, 0, NULL, UID_ROOT,
584 GID_WHEEL, 0600, "xen/evtchn");
588 /*-------------------- Private Device Attachment Data -----------------------*/
589 static device_method_t evtchn_methods[] = {
590 DEVMETHOD(device_identify, evtchn_identify),
591 DEVMETHOD(device_probe, evtchn_probe),
592 DEVMETHOD(device_attach, evtchn_attach),
597 static driver_t evtchn_driver = {
603 devclass_t evtchn_devclass;
605 DRIVER_MODULE(evtchn, xenpv, evtchn_driver, evtchn_devclass, 0, 0);
606 MODULE_DEPEND(evtchn, xenpv, 1, 1, 1);