]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/xen/evtchn/evtchn_dev.c
MFV r355071: libbsdxml (expat) 2.2.9.
[FreeBSD/FreeBSD.git] / sys / dev / xen / evtchn / evtchn_dev.c
1 /******************************************************************************
2  * evtchn.c
3  *
4  * Driver for receiving and demuxing event-channel signals.
5  *
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
12  *
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:
18  *
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:
25  *
26  * The above copyright notice and this permission notice shall be included in
27  * all copies or substantial portions of the Software.
28  *
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
35  * IN THE SOFTWARE.
36  */
37
38 #include <sys/cdefs.h>
39 __FBSDID("$FreeBSD$");
40
41 #include <sys/param.h>
42 #include <sys/systm.h>
43 #include <sys/uio.h>
44 #include <sys/bus.h>
45 #include <sys/malloc.h>
46 #include <sys/kernel.h>
47 #include <sys/lock.h>
48 #include <sys/mutex.h>
49 #include <sys/sx.h>
50 #include <sys/selinfo.h>
51 #include <sys/poll.h>
52 #include <sys/conf.h>
53 #include <sys/fcntl.h>
54 #include <sys/ioccom.h>
55 #include <sys/rman.h>
56 #include <sys/tree.h>
57 #include <sys/module.h>
58 #include <sys/filio.h>
59 #include <sys/vnode.h>
60
61 #include <machine/intr_machdep.h>
62 #include <machine/xen/synch_bitops.h>
63
64 #include <xen/xen-os.h>
65 #include <xen/evtchn.h>
66 #include <xen/xen_intr.h>
67
68 #include <xen/evtchn/evtchnvar.h>
69
70 MALLOC_DEFINE(M_EVTCHN, "evtchn_dev", "Xen event channel user-space device");
71
72 struct user_evtchn;
73
74 static int evtchn_cmp(struct user_evtchn *u1, struct user_evtchn *u2);
75
76 RB_HEAD(evtchn_tree, user_evtchn);
77
78 struct per_user_data {
79         struct mtx bind_mutex; /* serialize bind/unbind operations */
80         struct evtchn_tree evtchns;
81
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))
85         evtchn_port_t *ring;
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;
90 };
91
92 struct user_evtchn {
93         RB_ENTRY(user_evtchn) node;
94         struct per_user_data *user;
95         evtchn_port_t port;
96         xen_intr_handle_t handle;
97         bool enabled;
98 };
99
100 RB_GENERATE_STATIC(evtchn_tree, user_evtchn, node, evtchn_cmp);
101
102 static device_t evtchn_dev;
103
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;
109
110 static void evtchn_release(void *arg);
111
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,
119         .d_name = "evtchn",
120 };
121
122 /*------------------------- Red-black tree helpers ---------------------------*/
123 static int
124 evtchn_cmp(struct user_evtchn *u1, struct user_evtchn *u2)
125 {
126
127         return (u1->port - u2->port);
128 }
129
130 static struct user_evtchn *
131 find_evtchn(struct per_user_data *u, evtchn_port_t port)
132 {
133         struct user_evtchn tmp = {
134                 .port = port,
135         };
136
137         return (RB_FIND(evtchn_tree, &u->evtchns, &tmp));
138 }
139
140 /*--------------------------- Interrupt handlers -----------------------------*/
141 static int
142 evtchn_filter(void *arg)
143 {
144         struct user_evtchn *evtchn;
145
146         evtchn = arg;
147
148         if (!evtchn->enabled && bootverbose) {
149                 device_printf(evtchn_dev,
150                     "Received upcall for disabled event channel %d\n",
151                     evtchn->port);
152         }
153
154         evtchn_mask_port(evtchn->port);
155         evtchn->enabled = false;
156
157         return (FILTER_SCHEDULE_THREAD);
158 }
159
160 static void
161 evtchn_interrupt(void *arg)
162 {
163         struct user_evtchn *evtchn;
164         struct per_user_data *u;
165
166         evtchn = arg;
167         u = evtchn->user;
168
169         /*
170          * Protect against concurrent events using this handler
171          * on different CPUs.
172          */
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++) {
178                         wakeup(u);
179                         selwakeup(&u->ev_rsel);
180                 }
181         } else
182                 u->ring_overflow = 1;
183         mtx_unlock(&u->ring_prod_mutex);
184 }
185
186 /*------------------------- Character device methods -------------------------*/
187 static int
188 evtchn_open(struct cdev *dev, int flag, int otyp, struct thread *td)
189 {
190         struct per_user_data *u;
191         int error;
192
193         u = malloc(sizeof(*u), M_EVTCHN, M_WAITOK | M_ZERO);
194         u->ring = malloc(PAGE_SIZE, M_EVTCHN, M_WAITOK | M_ZERO);
195
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);
200
201         /* Initialize red-black tree. */
202         RB_INIT(&u->evtchns);
203
204         /* Assign the allocated per_user_data to this open instance. */
205         error = devfs_set_cdevpriv(u, evtchn_release);
206         if (error != 0) {
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);
211                 free(u, M_EVTCHN);
212         }
213
214         return (error);
215 }
216
217 static void
218 evtchn_release(void *arg)
219 {
220         struct per_user_data *u;
221         struct user_evtchn *evtchn, *tmp;
222
223         u = arg;
224
225         seldrain(&u->ev_rsel);
226
227         RB_FOREACH_SAFE(evtchn, evtchn_tree, &u->evtchns, tmp) {
228                 xen_intr_unbind(&evtchn->handle);
229
230                 RB_REMOVE(evtchn_tree, &u->evtchns, evtchn);
231                 free(evtchn, M_EVTCHN);
232         }
233
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);
238         free(u, M_EVTCHN);
239 }
240
241 static int
242 evtchn_read(struct cdev *dev, struct uio *uio, int ioflag)
243 {
244         int error, count;
245         unsigned int c, p, bytes1 = 0, bytes2 = 0;
246         struct per_user_data *u;
247
248         error = devfs_get_cdevpriv((void **)&u);
249         if (error != 0)
250                 return (EINVAL);
251
252         /* Whole number of ports. */
253         count = uio->uio_resid;
254         count &= ~(sizeof(evtchn_port_t)-1);
255
256         if (count == 0)
257                 return (0);
258
259         if (count > PAGE_SIZE)
260                 count = PAGE_SIZE;
261
262         sx_xlock(&u->ring_cons_mutex);
263         for (;;) {
264                 error = EFBIG;
265                 if (u->ring_overflow)
266                         goto unlock_out;
267
268                 c = u->ring_cons;
269                 p = u->ring_prod;
270                 if (c != p)
271                         break;
272
273                 if (ioflag & IO_NDELAY) {
274                         sx_xunlock(&u->ring_cons_mutex);
275                         return (EWOULDBLOCK);
276                 }
277
278                 error = sx_sleep(u, &u->ring_cons_mutex, PCATCH, "evtchw", 0);
279                 if ((error != 0) && (error != EWOULDBLOCK))
280                         return (error);
281         }
282
283         /* Byte lengths of two chunks. Chunk split (if any) is at ring wrap. */
284         if (((c ^ p) & EVTCHN_RING_SIZE) != 0) {
285                 bytes1 = (EVTCHN_RING_SIZE - EVTCHN_RING_MASK(c)) *
286                     sizeof(evtchn_port_t);
287                 bytes2 = EVTCHN_RING_MASK(p) * sizeof(evtchn_port_t);
288         } else {
289                 bytes1 = (p - c) * sizeof(evtchn_port_t);
290                 bytes2 = 0;
291         }
292
293         /* Truncate chunks according to caller's maximum byte count. */
294         if (bytes1 > count) {
295                 bytes1 = count;
296                 bytes2 = 0;
297         } else if ((bytes1 + bytes2) > count) {
298                 bytes2 = count - bytes1;
299         }
300
301         error = EFAULT;
302         rmb(); /* Ensure that we see the port before we copy it. */
303
304         if (uiomove(&u->ring[EVTCHN_RING_MASK(c)], bytes1, uio) ||
305             ((bytes2 != 0) && uiomove(&u->ring[0], bytes2, uio)))
306                 goto unlock_out;
307
308         u->ring_cons += (bytes1 + bytes2) / sizeof(evtchn_port_t);
309         error = 0;
310
311 unlock_out:
312         sx_xunlock(&u->ring_cons_mutex);
313         return (error);
314 }
315
316 static int
317 evtchn_write(struct cdev *dev, struct uio *uio, int ioflag)
318 {
319         int error, i, count;
320         evtchn_port_t *kbuf;
321         struct per_user_data *u;
322
323         error = devfs_get_cdevpriv((void **)&u);
324         if (error != 0)
325                 return (EINVAL);
326
327         kbuf = malloc(PAGE_SIZE, M_EVTCHN, M_WAITOK);
328
329         count = uio->uio_resid;
330         /* Whole number of ports. */
331         count &= ~(sizeof(evtchn_port_t)-1);
332
333         error = 0;
334         if (count == 0)
335                 goto out;
336
337         if (count > PAGE_SIZE)
338                 count = PAGE_SIZE;
339
340         error = uiomove(kbuf, count, uio);
341         if (error != 0)
342                 goto out;
343
344         mtx_lock(&u->bind_mutex);
345
346         for (i = 0; i < (count/sizeof(evtchn_port_t)); i++) {
347                 evtchn_port_t port = kbuf[i];
348                 struct user_evtchn *evtchn;
349
350                 evtchn = find_evtchn(u, port);
351                 if (evtchn && !evtchn->enabled) {
352                         evtchn->enabled = true;
353                         evtchn_unmask_port(evtchn->port);
354                 }
355         }
356
357         mtx_unlock(&u->bind_mutex);
358         error = 0;
359
360 out:
361         free(kbuf, M_EVTCHN);
362         return (error);
363 }
364
365 static inline int
366 evtchn_bind_user_port(struct per_user_data *u, struct user_evtchn *evtchn)
367 {
368         int error;
369
370         evtchn->port = xen_intr_port(evtchn->handle);
371         evtchn->user = u;
372         evtchn->enabled = true;
373         mtx_lock(&u->bind_mutex);
374         RB_INSERT(evtchn_tree, &u->evtchns, evtchn);
375         mtx_unlock(&u->bind_mutex);
376         error = xen_intr_add_handler(device_get_nameunit(evtchn_dev),
377             evtchn_filter, evtchn_interrupt, evtchn,
378             INTR_TYPE_MISC | INTR_MPSAFE, evtchn->handle);
379         if (error != 0) {
380                 xen_intr_unbind(&evtchn->handle);
381                 mtx_lock(&u->bind_mutex);
382                 RB_REMOVE(evtchn_tree, &u->evtchns, evtchn);
383                 mtx_unlock(&u->bind_mutex);
384                 free(evtchn, M_EVTCHN);
385         }
386         return (error);
387 }
388
389 static int
390 evtchn_ioctl(struct cdev *dev, unsigned long cmd, caddr_t arg,
391     int mode, struct thread *td __unused)
392 {
393         struct per_user_data *u;
394         int error;
395
396         error = devfs_get_cdevpriv((void **)&u);
397         if (error != 0)
398                 return (EINVAL);
399
400         switch (cmd) {
401         case IOCTL_EVTCHN_BIND_VIRQ: {
402                 struct ioctl_evtchn_bind_virq *bind;
403                 struct user_evtchn *evtchn;
404
405                 evtchn = malloc(sizeof(*evtchn), M_EVTCHN, M_WAITOK | M_ZERO);
406
407                 bind = (struct ioctl_evtchn_bind_virq *)arg;
408
409                 error = xen_intr_bind_virq(evtchn_dev, bind->virq, 0,
410                     NULL, NULL, NULL, 0, &evtchn->handle);
411                 if (error != 0) {
412                         free(evtchn, M_EVTCHN);
413                         break;
414                 }
415                 error = evtchn_bind_user_port(u, evtchn);
416                 if (error != 0)
417                         break;
418                 bind->port = evtchn->port;
419                 break;
420         }
421
422         case IOCTL_EVTCHN_BIND_INTERDOMAIN: {
423                 struct ioctl_evtchn_bind_interdomain *bind;
424                 struct user_evtchn *evtchn;
425
426                 evtchn = malloc(sizeof(*evtchn), M_EVTCHN, M_WAITOK | M_ZERO);
427
428                 bind = (struct ioctl_evtchn_bind_interdomain *)arg;
429
430                 error = xen_intr_bind_remote_port(evtchn_dev,
431                     bind->remote_domain, bind->remote_port, NULL,
432                     NULL, NULL, 0, &evtchn->handle);
433                 if (error != 0) {
434                         free(evtchn, M_EVTCHN);
435                         break;
436                 }
437                 error = evtchn_bind_user_port(u, evtchn);
438                 if (error != 0)
439                         break;
440                 bind->port = evtchn->port;
441                 break;
442         }
443
444         case IOCTL_EVTCHN_BIND_UNBOUND_PORT: {
445                 struct ioctl_evtchn_bind_unbound_port *bind;
446                 struct user_evtchn *evtchn;
447
448                 evtchn = malloc(sizeof(*evtchn), M_EVTCHN, M_WAITOK | M_ZERO);
449
450                 bind = (struct ioctl_evtchn_bind_unbound_port *)arg;
451
452                 error = xen_intr_alloc_and_bind_local_port(evtchn_dev,
453                     bind->remote_domain, NULL, NULL, NULL, 0, &evtchn->handle);
454                 if (error != 0) {
455                         free(evtchn, M_EVTCHN);
456                         break;
457                 }
458                 error = evtchn_bind_user_port(u, evtchn);
459                 if (error != 0)
460                         break;
461                 bind->port = evtchn->port;
462                 break;
463         }
464
465         case IOCTL_EVTCHN_UNBIND: {
466                 struct ioctl_evtchn_unbind *unbind;
467                 struct user_evtchn *evtchn;
468
469                 unbind = (struct ioctl_evtchn_unbind *)arg;
470
471                 mtx_lock(&u->bind_mutex);
472                 evtchn = find_evtchn(u, unbind->port);
473                 if (evtchn == NULL) {
474                         error = ENOTCONN;
475                         break;
476                 }
477                 RB_REMOVE(evtchn_tree, &u->evtchns, evtchn);
478                 mtx_unlock(&u->bind_mutex);
479
480                 xen_intr_unbind(&evtchn->handle);
481                 free(evtchn, M_EVTCHN);
482                 error = 0;
483                 break;
484         }
485
486         case IOCTL_EVTCHN_NOTIFY: {
487                 struct ioctl_evtchn_notify *notify;
488                 struct user_evtchn *evtchn;
489
490                 notify = (struct ioctl_evtchn_notify *)arg;
491
492                 mtx_lock(&u->bind_mutex);
493                 evtchn = find_evtchn(u, notify->port);
494                 if (evtchn == NULL) {
495                         error = ENOTCONN;
496                         break;
497                 }
498
499                 xen_intr_signal(evtchn->handle);
500                 mtx_unlock(&u->bind_mutex);
501                 error = 0;
502                 break;
503         }
504
505         case IOCTL_EVTCHN_RESET: {
506                 /* Initialise the ring to empty. Clear errors. */
507                 sx_xlock(&u->ring_cons_mutex);
508                 mtx_lock(&u->ring_prod_mutex);
509                 u->ring_cons = u->ring_prod = u->ring_overflow = 0;
510                 mtx_unlock(&u->ring_prod_mutex);
511                 sx_xunlock(&u->ring_cons_mutex);
512                 error = 0;
513                 break;
514         }
515
516         case FIONBIO:
517         case FIOASYNC:
518                 /* Handled in an upper layer */
519                 error = 0;
520                 break;
521
522         default:
523                 error = ENOTTY;
524                 break;
525         }
526
527         return (error);
528 }
529
530 static int
531 evtchn_poll(struct cdev *dev, int events, struct thread *td)
532 {
533         struct per_user_data *u;
534         int error, mask;
535
536         error = devfs_get_cdevpriv((void **)&u);
537         if (error != 0)
538                 return (POLLERR);
539
540         /* we can always write */
541         mask = events & (POLLOUT | POLLWRNORM);
542
543         mtx_lock(&u->ring_prod_mutex);
544         if (events & (POLLIN | POLLRDNORM)) {
545                 if (u->ring_cons != u->ring_prod) {
546                         mask |= events & (POLLIN | POLLRDNORM);
547                 } else {
548                         /* Record that someone is waiting */
549                         selrecord(td, &u->ev_rsel);
550                 }
551         }
552         mtx_unlock(&u->ring_prod_mutex);
553
554         return (mask);
555 }
556
557 /*------------------ Private Device Attachment Functions  --------------------*/
558 static void
559 evtchn_identify(driver_t *driver, device_t parent)
560 {
561
562         KASSERT((xen_domain()),
563             ("Trying to attach evtchn device on non Xen domain"));
564
565         evtchn_dev = BUS_ADD_CHILD(parent, 0, "evtchn", 0);
566         if (evtchn_dev == NULL)
567                 panic("unable to attach evtchn user-space device");
568 }
569
570 static int
571 evtchn_probe(device_t dev)
572 {
573
574         device_set_desc(dev, "Xen event channel user-space device");
575         return (BUS_PROBE_NOWILDCARD);
576 }
577
578 static int
579 evtchn_attach(device_t dev)
580 {
581
582         make_dev_credf(MAKEDEV_ETERNAL, &evtchn_devsw, 0, NULL, UID_ROOT,
583             GID_WHEEL, 0600, "xen/evtchn");
584         return (0);
585 }
586
587 /*-------------------- Private Device Attachment Data  -----------------------*/
588 static device_method_t evtchn_methods[] = {
589         DEVMETHOD(device_identify, evtchn_identify),
590         DEVMETHOD(device_probe, evtchn_probe),
591         DEVMETHOD(device_attach, evtchn_attach),
592
593         DEVMETHOD_END
594 };
595
596 static driver_t evtchn_driver = {
597         "evtchn",
598         evtchn_methods,
599         0,
600 };
601
602 devclass_t evtchn_devclass;
603
604 DRIVER_MODULE(evtchn, xenpv, evtchn_driver, evtchn_devclass, 0, 0);
605 MODULE_DEPEND(evtchn, xenpv, 1, 1, 1);