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/xen/xen-os.h>
27 #include <xen/xen_intr.h>
28 #include <machine/bus.h>
30 #include <machine/resource.h>
31 #include <machine/xen/synch_bitops.h>
32 #include <xen/hypervisor.h>
33 #include <xen/evtchn.h>
36 typedef struct evtchn_sotfc {
38 struct selinfo ev_rsel;
43 /* NB. This must be shared amongst drivers if more things go in /dev/xen */
44 static devfs_handle_t xen_dev_dir;
47 /* Only one process may open /dev/xen/evtchn at any time. */
48 static unsigned long evtchn_dev_inuse;
50 /* Notification ring, accessed via /dev/xen/evtchn. */
52 #define EVTCHN_RING_SIZE 2048 /* 2048 16-bit entries */
54 #define EVTCHN_RING_MASK(_i) ((_i)&(EVTCHN_RING_SIZE-1))
55 static uint16_t *ring;
56 static unsigned int ring_cons, ring_prod, ring_overflow;
58 /* Which ports is user-space bound to? */
59 static uint32_t bound_ports[32];
61 /* Unique address for processes to sleep on */
62 static void *evtchn_waddr = ˚
64 static struct mtx lock, upcall_lock;
66 static d_read_t evtchn_read;
67 static d_write_t evtchn_write;
68 static d_ioctl_t evtchn_ioctl;
69 static d_poll_t evtchn_poll;
70 static d_open_t evtchn_open;
71 static d_close_t evtchn_close;
75 evtchn_device_upcall(int port)
77 mtx_lock(&upcall_lock);
83 if ( (ring_prod - ring_cons) < EVTCHN_RING_SIZE ) {
84 ring[EVTCHN_RING_MASK(ring_prod)] = (uint16_t)port;
85 if ( ring_cons == ring_prod++ ) {
94 mtx_unlock(&upcall_lock);
98 __evtchn_reset_buffer_ring(void)
100 /* Initialise the ring to empty. Clear errors. */
101 ring_cons = ring_prod = ring_overflow = 0;
105 evtchn_read(struct cdev *dev, struct uio *uio, int ioflag)
108 unsigned int count, c, p, sst = 0, bytes1 = 0, bytes2 = 0;
109 count = uio->uio_resid;
111 count &= ~1; /* even number of bytes */
119 if ( count > PAGE_SIZE )
123 if ( (c = ring_cons) != (p = ring_prod) )
126 if ( ring_overflow ) {
136 /* PCATCH == check for signals before and after sleeping
137 * PWAIT == priority of waiting on resource
139 sst = tsleep(evtchn_waddr, PWAIT|PCATCH, "evchwt", 10);
142 /* Byte lengths of two chunks. Chunk split (if any) is at ring wrap. */
143 if ( ((c ^ p) & EVTCHN_RING_SIZE) != 0 ) {
144 bytes1 = (EVTCHN_RING_SIZE - EVTCHN_RING_MASK(c)) * sizeof(uint16_t);
145 bytes2 = EVTCHN_RING_MASK(p) * sizeof(uint16_t);
148 bytes1 = (p - c) * sizeof(uint16_t);
152 /* Truncate chunks according to caller's maximum byte count. */
153 if ( bytes1 > count ) {
157 else if ( (bytes1 + bytes2) > count ) {
158 bytes2 = count - bytes1;
161 if ( uiomove(&ring[EVTCHN_RING_MASK(c)], bytes1, uio) ||
162 ((bytes2 != 0) && uiomove(&ring[0], bytes2, uio)))
163 /* keeping this around as its replacement is not equivalent
164 * copyout(&ring[0], &buf[bytes1], bytes2)
171 ring_cons += (bytes1 + bytes2) / sizeof(uint16_t);
173 rc = bytes1 + bytes2;
181 evtchn_write(struct cdev *dev, struct uio *uio, int ioflag)
185 count = uio->uio_resid;
187 uint16_t *kbuf = (uint16_t *)malloc(PAGE_SIZE, M_DEVBUF, M_WAITOK);
193 count &= ~1; /* even number of bytes */
200 if ( count > PAGE_SIZE )
203 if ( uiomove(kbuf, count, uio) != 0 ) {
208 mtx_lock_spin(&lock);
209 for ( i = 0; i < (count/2); i++ )
210 if ( test_bit(kbuf[i], &bound_ports[0]) )
211 unmask_evtchn(kbuf[i]);
212 mtx_unlock_spin(&lock);
217 free(kbuf, M_DEVBUF);
222 evtchn_ioctl(struct cdev *dev, unsigned long cmd, caddr_t arg,
223 int mode, struct thread *td __unused)
227 mtx_lock_spin(&lock);
232 __evtchn_reset_buffer_ring();
235 if ( !synch_test_and_set_bit((uintptr_t)arg, &bound_ports[0]) )
236 unmask_evtchn((uintptr_t)arg);
241 if ( synch_test_and_clear_bit((uintptr_t)arg, &bound_ports[0]) )
242 mask_evtchn((uintptr_t)arg);
251 mtx_unlock_spin(&lock);
257 evtchn_poll(struct cdev *dev, int poll_events, struct thread *td)
261 unsigned int mask = POLLOUT | POLLWRNORM;
265 if ( ring_cons != ring_prod )
266 mask |= POLLIN | POLLRDNORM;
267 else if ( ring_overflow )
270 selrecord(td, &sc->ev_rsel);
278 evtchn_open(struct cdev *dev, int flag, int otyp, struct thread *td)
282 if (flag & O_NONBLOCK)
285 if ( synch_test_and_set_bit(0, &evtchn_dev_inuse) )
288 if ( (_ring = (uint16_t *)malloc(PAGE_SIZE, M_DEVBUF, M_WAITOK)) == NULL )
291 mtx_lock_spin(&lock);
293 __evtchn_reset_buffer_ring();
294 mtx_unlock_spin(&lock);
301 evtchn_close(struct cdev *dev, int flag, int otyp, struct thread *td __unused)
306 free(ring, M_DEVBUF);
309 mtx_lock_spin(&lock);
310 for ( i = 0; i < NR_EVENT_CHANNELS; i++ )
311 if ( synch_test_and_clear_bit(i, &bound_ports[0]) )
313 mtx_unlock_spin(&lock);
315 evtchn_dev_inuse = 0;
320 static struct cdevsw evtchn_devsw = {
321 d_version: D_VERSION,
323 d_close: evtchn_close,
325 d_write: evtchn_write,
326 d_ioctl: evtchn_ioctl,
333 /* XXX - if this device is ever supposed to support use by more than one process
334 * this global static will have to go away
336 static struct cdev *evtchn_dev;
341 evtchn_dev_init(void *dummy __unused)
343 /* XXX I believe we don't need these leaving them here for now until we
344 * have some semblance of it working
346 mtx_init(&upcall_lock, "evtchup", NULL, MTX_DEF);
348 /* (DEVFS) create '/dev/misc/evtchn'. */
349 evtchn_dev = make_dev(&evtchn_devsw, 0, UID_ROOT, GID_WHEEL, 0600, "xen/evtchn");
351 mtx_init(&lock, "evch", NULL, MTX_SPIN | MTX_NOWITNESS);
353 evtchn_dev->si_drv1 = malloc(sizeof(evtchn_softc_t), M_DEVBUF, M_WAITOK);
354 bzero(evtchn_dev->si_drv1, sizeof(evtchn_softc_t));
356 /* XXX I don't think we need any of this rubbish */
360 printk(KERN_ALERT "Could not register /dev/misc/evtchn\n");
364 /* (DEVFS) create directory '/dev/xen'. */
365 xen_dev_dir = devfs_mk_dir(NULL, "xen", NULL);
367 /* (DEVFS) &link_dest[pos] == '../misc/evtchn'. */
368 pos = devfs_generate_path(evtchn_miscdev.devfs_handle,
370 sizeof(link_dest) - 3);
372 strncpy(&link_dest[pos], "../", 3);
373 /* (DEVFS) symlink '/dev/xen/evtchn' -> '../misc/evtchn'. */
374 (void)devfs_mk_symlink(xen_dev_dir,
381 /* (DEVFS) automatically destroy the symlink with its destination. */
382 devfs_auto_unregister(evtchn_miscdev.devfs_handle, symlink_handle);
385 printf("Event-channel device installed.\n");
390 SYSINIT(evtchn_dev_init, SI_SUB_DRIVERS, SI_ORDER_FIRST, evtchn_dev_init, NULL);