1 /******************************************************************************
4 * Xenolinux driver for receiving and demuxing event-channel signals.
6 * Copyright (c) 2004, K A Fraser
10 __FBSDID("$FreeBSD$");
12 #include <sys/param.h>
13 #include <sys/systm.h>
16 #include <sys/malloc.h>
17 #include <sys/kernel.h>
19 #include <sys/mutex.h>
20 #include <sys/selinfo.h>
23 #include <sys/fcntl.h>
24 #include <sys/ioccom.h>
26 #include <machine/cpufunc.h>
27 #include <machine/intr_machdep.h>
28 #include <machine/xen-os.h>
29 #include <xen/xen_intr.h>
30 #include <machine/bus.h>
32 #include <machine/resource.h>
33 #include <machine/synch_bitops.h>
35 #include <xen/hypervisor.h>
38 typedef struct evtchn_sotfc {
40 struct selinfo ev_rsel;
45 /* NB. This must be shared amongst drivers if more things go in /dev/xen */
46 static devfs_handle_t xen_dev_dir;
49 /* Only one process may open /dev/xen/evtchn at any time. */
50 static unsigned long evtchn_dev_inuse;
52 /* Notification ring, accessed via /dev/xen/evtchn. */
54 #define EVTCHN_RING_SIZE 2048 /* 2048 16-bit entries */
56 #define EVTCHN_RING_MASK(_i) ((_i)&(EVTCHN_RING_SIZE-1))
57 static uint16_t *ring;
58 static unsigned int ring_cons, ring_prod, ring_overflow;
60 /* Which ports is user-space bound to? */
61 static uint32_t bound_ports[32];
63 /* Unique address for processes to sleep on */
64 static void *evtchn_waddr = ˚
66 static struct mtx lock, upcall_lock;
68 static d_read_t evtchn_read;
69 static d_write_t evtchn_write;
70 static d_ioctl_t evtchn_ioctl;
71 static d_poll_t evtchn_poll;
72 static d_open_t evtchn_open;
73 static d_close_t evtchn_close;
77 evtchn_device_upcall(int port)
79 mtx_lock(&upcall_lock);
85 if ( (ring_prod - ring_cons) < EVTCHN_RING_SIZE ) {
86 ring[EVTCHN_RING_MASK(ring_prod)] = (uint16_t)port;
87 if ( ring_cons == ring_prod++ ) {
96 mtx_unlock(&upcall_lock);
100 __evtchn_reset_buffer_ring(void)
102 /* Initialise the ring to empty. Clear errors. */
103 ring_cons = ring_prod = ring_overflow = 0;
107 evtchn_read(struct cdev *dev, struct uio *uio, int ioflag)
110 unsigned int count, c, p, sst = 0, bytes1 = 0, bytes2 = 0;
111 count = uio->uio_resid;
113 count &= ~1; /* even number of bytes */
121 if ( count > PAGE_SIZE )
125 if ( (c = ring_cons) != (p = ring_prod) )
128 if ( ring_overflow ) {
138 /* PCATCH == check for signals before and after sleeping
139 * PWAIT == priority of waiting on resource
141 sst = tsleep(evtchn_waddr, PWAIT|PCATCH, "evchwt", 10);
144 /* Byte lengths of two chunks. Chunk split (if any) is at ring wrap. */
145 if ( ((c ^ p) & EVTCHN_RING_SIZE) != 0 ) {
146 bytes1 = (EVTCHN_RING_SIZE - EVTCHN_RING_MASK(c)) * sizeof(uint16_t);
147 bytes2 = EVTCHN_RING_MASK(p) * sizeof(uint16_t);
150 bytes1 = (p - c) * sizeof(uint16_t);
154 /* Truncate chunks according to caller's maximum byte count. */
155 if ( bytes1 > count ) {
159 else if ( (bytes1 + bytes2) > count ) {
160 bytes2 = count - bytes1;
163 if ( uiomove(&ring[EVTCHN_RING_MASK(c)], bytes1, uio) ||
164 ((bytes2 != 0) && uiomove(&ring[0], bytes2, uio)))
165 /* keeping this around as its replacement is not equivalent
166 * copyout(&ring[0], &buf[bytes1], bytes2)
173 ring_cons += (bytes1 + bytes2) / sizeof(uint16_t);
175 rc = bytes1 + bytes2;
183 evtchn_write(struct cdev *dev, struct uio *uio, int ioflag)
187 count = uio->uio_resid;
189 uint16_t *kbuf = (uint16_t *)malloc(PAGE_SIZE, M_DEVBUF, M_WAITOK);
195 count &= ~1; /* even number of bytes */
202 if ( count > PAGE_SIZE )
205 if ( uiomove(kbuf, count, uio) != 0 ) {
210 mtx_lock_spin(&lock);
211 for ( i = 0; i < (count/2); i++ )
212 if ( test_bit(kbuf[i], &bound_ports[0]) )
213 unmask_evtchn(kbuf[i]);
214 mtx_unlock_spin(&lock);
219 free(kbuf, M_DEVBUF);
224 evtchn_ioctl(struct cdev *dev, unsigned long cmd, caddr_t arg,
225 int mode, struct thread *td __unused)
229 mtx_lock_spin(&lock);
234 __evtchn_reset_buffer_ring();
237 if ( !synch_test_and_set_bit((int)arg, &bound_ports[0]) )
238 unmask_evtchn((int)arg);
243 if ( synch_test_and_clear_bit((int)arg, &bound_ports[0]) )
244 mask_evtchn((int)arg);
253 mtx_unlock_spin(&lock);
259 evtchn_poll(struct cdev *dev, int poll_events, struct thread *td)
263 unsigned int mask = POLLOUT | POLLWRNORM;
267 if ( ring_cons != ring_prod )
268 mask |= POLLIN | POLLRDNORM;
269 else if ( ring_overflow )
272 selrecord(td, &sc->ev_rsel);
280 evtchn_open(struct cdev *dev, int flag, int otyp, struct thread *td)
284 if (flag & O_NONBLOCK)
287 if ( synch_test_and_set_bit(0, &evtchn_dev_inuse) )
290 if ( (_ring = (uint16_t *)malloc(PAGE_SIZE, M_DEVBUF, M_WAITOK)) == NULL )
293 mtx_lock_spin(&lock);
295 __evtchn_reset_buffer_ring();
296 mtx_unlock_spin(&lock);
303 evtchn_close(struct cdev *dev, int flag, int otyp, struct thread *td __unused)
307 mtx_lock_spin(&lock);
309 free(ring, M_DEVBUF);
312 for ( i = 0; i < NR_EVENT_CHANNELS; i++ )
313 if ( synch_test_and_clear_bit(i, &bound_ports[0]) )
315 mtx_unlock_spin(&lock);
317 evtchn_dev_inuse = 0;
322 static struct cdevsw evtchn_devsw = {
323 d_version: D_VERSION,
325 d_close: evtchn_close,
327 d_write: evtchn_write,
328 d_ioctl: evtchn_ioctl,
335 /* XXX - if this device is ever supposed to support use by more than one process
336 * this global static will have to go away
338 static struct cdev *evtchn_dev;
343 evtchn_init(void *dummy __unused)
345 /* XXX I believe we don't need these leaving them here for now until we
346 * have some semblance of it working
348 mtx_init(&upcall_lock, "evtchup", NULL, MTX_DEF);
350 /* (DEVFS) create '/dev/misc/evtchn'. */
351 evtchn_dev = make_dev(&evtchn_devsw, 0, UID_ROOT, GID_WHEEL, 0600, "xen/evtchn");
353 mtx_init(&lock, "evch", NULL, MTX_SPIN | MTX_NOWITNESS);
355 evtchn_dev->si_drv1 = malloc(sizeof(evtchn_softc_t), M_DEVBUF, M_WAITOK);
356 bzero(evtchn_dev->si_drv1, sizeof(evtchn_softc_t));
358 /* XXX I don't think we need any of this rubbish */
362 printk(KERN_ALERT "Could not register /dev/misc/evtchn\n");
366 /* (DEVFS) create directory '/dev/xen'. */
367 xen_dev_dir = devfs_mk_dir(NULL, "xen", NULL);
369 /* (DEVFS) &link_dest[pos] == '../misc/evtchn'. */
370 pos = devfs_generate_path(evtchn_miscdev.devfs_handle,
372 sizeof(link_dest) - 3);
374 strncpy(&link_dest[pos], "../", 3);
375 /* (DEVFS) symlink '/dev/xen/evtchn' -> '../misc/evtchn'. */
376 (void)devfs_mk_symlink(xen_dev_dir,
383 /* (DEVFS) automatically destroy the symlink with its destination. */
384 devfs_auto_unregister(evtchn_miscdev.devfs_handle, symlink_handle);
386 printk("Event-channel device installed.\n");
392 SYSINIT(evtchn_init, SI_SUB_DRIVERS, SI_ORDER_FIRST, evtchn_init, NULL);