evtchn_dev.c revision 186557
193885Sphantom/******************************************************************************
293885Sphantom * evtchn.c
393885Sphantom *
493885Sphantom * Xenolinux driver for receiving and demuxing event-channel signals.
593885Sphantom *
693885Sphantom * Copyright (c) 2004, K A Fraser
7174990Sache */
893885Sphantom
993885Sphantom#include <sys/cdefs.h>
1093885Sphantom__FBSDID("$FreeBSD: head/sys/xen/evtchn/evtchn_dev.c 186557 2008-12-29 06:31:03Z kmacy $");
1193885Sphantom
1293885Sphantom#include <sys/param.h>
1393885Sphantom#include <sys/systm.h>
1493885Sphantom#include <sys/uio.h>
1593885Sphantom#include <sys/bus.h>
1693885Sphantom#include <sys/malloc.h>
1793885Sphantom#include <sys/kernel.h>
1893885Sphantom#include <sys/lock.h>
1993885Sphantom#include <sys/mutex.h>
2093885Sphantom#include <sys/selinfo.h>
2193885Sphantom#include <sys/poll.h>
22174990Sache#include <sys/conf.h>
2393885Sphantom#include <sys/fcntl.h>
2493885Sphantom#include <sys/ioccom.h>
2593885Sphantom
2693885Sphantom#include <machine/cpufunc.h>
2793885Sphantom#include <machine/intr_machdep.h>
2893885Sphantom#include <machine/xen/xen-os.h>
2993885Sphantom#include <xen/xen_intr.h>
3093885Sphantom#include <machine/bus.h>
3193885Sphantom#include <sys/rman.h>
3293885Sphantom#include <machine/resource.h>
3393885Sphantom#include <machine/xen/synch_bitops.h>
3493885Sphantom#include <xen/hypervisor.h>
3593885Sphantom#include <xen/evtchn.h>
3693885Sphantom
37174990Sache
3893885Sphantomtypedef struct evtchn_sotfc {
3993885Sphantom
4093885Sphantom	struct selinfo  ev_rsel;
4193885Sphantom} evtchn_softc_t;
4293885Sphantom
4393885Sphantom
4493885Sphantom#ifdef linuxcrap
4593885Sphantom/* NB. This must be shared amongst drivers if more things go in /dev/xen */
4693885Sphantomstatic devfs_handle_t xen_dev_dir;
47174990Sache#endif
4893885Sphantom
4993885Sphantom/* Only one process may open /dev/xen/evtchn at any time. */
5093885Sphantomstatic unsigned long evtchn_dev_inuse;
5193885Sphantom
5293885Sphantom/* Notification ring, accessed via /dev/xen/evtchn. */
5393885Sphantom
5493885Sphantom#define EVTCHN_RING_SIZE     2048  /* 2048 16-bit entries */
5593885Sphantom
5693885Sphantom#define EVTCHN_RING_MASK(_i) ((_i)&(EVTCHN_RING_SIZE-1))
5793885Sphantomstatic uint16_t *ring;
5893885Sphantomstatic unsigned int ring_cons, ring_prod, ring_overflow;
5993885Sphantom
6093885Sphantom/* Which ports is user-space bound to? */
6193885Sphantomstatic uint32_t bound_ports[32];
6293885Sphantom
6393885Sphantom/* Unique address for processes to sleep on */
6493885Sphantomstatic void *evtchn_waddr = &ring;
6593885Sphantom
6693885Sphantomstatic struct mtx lock, upcall_lock;
6793885Sphantom
6893885Sphantomstatic d_read_t      evtchn_read;
6993885Sphantomstatic d_write_t     evtchn_write;
7093885Sphantomstatic d_ioctl_t     evtchn_ioctl;
7193885Sphantomstatic d_poll_t      evtchn_poll;
7293885Sphantomstatic d_open_t      evtchn_open;
7393885Sphantomstatic d_close_t     evtchn_close;
7493885Sphantom
7593885Sphantom
7693885Sphantomvoid
7793885Sphantomevtchn_device_upcall(int port)
7893885Sphantom{
7993885Sphantom	mtx_lock(&upcall_lock);
8093885Sphantom
81174990Sache	mask_evtchn(port);
8293885Sphantom	clear_evtchn(port);
8393885Sphantom
8493885Sphantom	if ( ring != NULL ) {
8593885Sphantom		if ( (ring_prod - ring_cons) < EVTCHN_RING_SIZE ) {
8693885Sphantom			ring[EVTCHN_RING_MASK(ring_prod)] = (uint16_t)port;
8793885Sphantom			if ( ring_cons == ring_prod++ ) {
8893885Sphantom				wakeup(evtchn_waddr);
8993885Sphantom			}
9093885Sphantom		}
9193885Sphantom		else {
9293885Sphantom			ring_overflow = 1;
9393885Sphantom		}
9493885Sphantom	}
9593885Sphantom
9693885Sphantom	mtx_unlock(&upcall_lock);
9793885Sphantom}
9893885Sphantom
9993885Sphantomstatic void
10093885Sphantom__evtchn_reset_buffer_ring(void)
10193885Sphantom{
10293885Sphantom	/* Initialise the ring to empty. Clear errors. */
10393885Sphantom	ring_cons = ring_prod = ring_overflow = 0;
104}
105
106static int
107evtchn_read(struct cdev *dev, struct uio *uio, int ioflag)
108{
109	int rc;
110	unsigned int count, c, p, sst = 0, bytes1 = 0, bytes2 = 0;
111	count = uio->uio_resid;
112
113	count &= ~1; /* even number of bytes */
114
115	if ( count == 0 )
116	{
117		rc = 0;
118		goto out;
119	}
120
121	if ( count > PAGE_SIZE )
122		count = PAGE_SIZE;
123
124	for ( ; ; ) {
125		if ( (c = ring_cons) != (p = ring_prod) )
126			break;
127
128		if ( ring_overflow ) {
129			rc = EFBIG;
130			goto out;
131		}
132
133		if (sst != 0) {
134			rc = EINTR;
135			goto out;
136		}
137
138		/* PCATCH == check for signals before and after sleeping
139		 * PWAIT == priority of waiting on resource
140		 */
141		sst = tsleep(evtchn_waddr, PWAIT|PCATCH, "evchwt", 10);
142	}
143
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);
148	}
149	else {
150		bytes1 = (p - c) * sizeof(uint16_t);
151		bytes2 = 0;
152	}
153
154	/* Truncate chunks according to caller's maximum byte count. */
155	if ( bytes1 > count ) {
156		bytes1 = count;
157		bytes2 = 0;
158	}
159	else if ( (bytes1 + bytes2) > count ) {
160		bytes2 = count - bytes1;
161	}
162
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)
167		 */
168	{
169		rc = EFAULT;
170		goto out;
171	}
172
173	ring_cons += (bytes1 + bytes2) / sizeof(uint16_t);
174
175	rc = bytes1 + bytes2;
176
177 out:
178
179	return rc;
180}
181
182static int
183evtchn_write(struct cdev *dev, struct uio *uio, int ioflag)
184{
185	int  rc, i, count;
186
187	count = uio->uio_resid;
188
189	uint16_t *kbuf = (uint16_t *)malloc(PAGE_SIZE, M_DEVBUF, M_WAITOK);
190
191
192	if ( kbuf == NULL )
193		return ENOMEM;
194
195	count &= ~1; /* even number of bytes */
196
197	if ( count == 0 ) {
198		rc = 0;
199		goto out;
200	}
201
202	if ( count > PAGE_SIZE )
203		count = PAGE_SIZE;
204
205	if ( uiomove(kbuf, count, uio) != 0 ) {
206		rc = EFAULT;
207		goto out;
208	}
209
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);
215
216	rc = count;
217
218 out:
219	free(kbuf, M_DEVBUF);
220	return rc;
221}
222
223static int
224evtchn_ioctl(struct cdev *dev, unsigned long cmd, caddr_t arg,
225	     int mode, struct thread *td __unused)
226{
227	int rc = 0;
228
229	mtx_lock_spin(&lock);
230
231	switch ( cmd )
232	{
233	case EVTCHN_RESET:
234		__evtchn_reset_buffer_ring();
235		break;
236	case EVTCHN_BIND:
237		if ( !synch_test_and_set_bit((int)arg, &bound_ports[0]) )
238			unmask_evtchn((int)arg);
239		else
240			rc = EINVAL;
241		break;
242	case EVTCHN_UNBIND:
243		if ( synch_test_and_clear_bit((int)arg, &bound_ports[0]) )
244			mask_evtchn((int)arg);
245		else
246			rc = EINVAL;
247		break;
248	default:
249		rc = ENOSYS;
250		break;
251	}
252
253	mtx_unlock_spin(&lock);
254
255	return rc;
256}
257
258static int
259evtchn_poll(struct cdev *dev, int poll_events, struct thread *td)
260{
261
262	evtchn_softc_t *sc;
263	unsigned int mask = POLLOUT | POLLWRNORM;
264
265	sc = dev->si_drv1;
266
267	if ( ring_cons != ring_prod )
268		mask |= POLLIN | POLLRDNORM;
269	else if ( ring_overflow )
270		mask = POLLERR;
271	else
272		selrecord(td, &sc->ev_rsel);
273
274
275	return mask;
276}
277
278
279static int
280evtchn_open(struct cdev *dev, int flag, int otyp, struct thread *td)
281{
282	uint16_t *_ring;
283
284	if (flag & O_NONBLOCK)
285		return EBUSY;
286
287	if ( synch_test_and_set_bit(0, &evtchn_dev_inuse) )
288		return EBUSY;
289
290	if ( (_ring = (uint16_t *)malloc(PAGE_SIZE, M_DEVBUF, M_WAITOK)) == NULL )
291		return ENOMEM;
292
293	mtx_lock_spin(&lock);
294	ring = _ring;
295	__evtchn_reset_buffer_ring();
296	mtx_unlock_spin(&lock);
297
298
299	return 0;
300}
301
302static int
303evtchn_close(struct cdev *dev, int flag, int otyp, struct thread *td __unused)
304{
305	int i;
306
307	mtx_lock_spin(&lock);
308	if (ring != NULL) {
309		free(ring, M_DEVBUF);
310		ring = NULL;
311	}
312	for ( i = 0; i < NR_EVENT_CHANNELS; i++ )
313		if ( synch_test_and_clear_bit(i, &bound_ports[0]) )
314			mask_evtchn(i);
315	mtx_unlock_spin(&lock);
316
317	evtchn_dev_inuse = 0;
318
319	return 0;
320}
321
322static struct cdevsw evtchn_devsw = {
323	d_version:   D_VERSION,
324	d_open:      evtchn_open,
325	d_close:     evtchn_close,
326	d_read:      evtchn_read,
327	d_write:     evtchn_write,
328	d_ioctl:     evtchn_ioctl,
329	d_poll:      evtchn_poll,
330	d_name:      "evtchn",
331	d_flags:     0,
332};
333
334
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
337 */
338static struct cdev *evtchn_dev;
339
340
341
342static int
343evtchn_dev_init(void *dummy __unused)
344{
345	/* XXX I believe we don't need these leaving them here for now until we
346	 * have some semblance of it working
347	 */
348	mtx_init(&upcall_lock, "evtchup", NULL, MTX_DEF);
349
350	/* (DEVFS) create '/dev/misc/evtchn'. */
351	evtchn_dev = make_dev(&evtchn_devsw, 0, UID_ROOT, GID_WHEEL, 0600, "xen/evtchn");
352
353	mtx_init(&lock, "evch", NULL, MTX_SPIN | MTX_NOWITNESS);
354
355	evtchn_dev->si_drv1 = malloc(sizeof(evtchn_softc_t), M_DEVBUF, M_WAITOK);
356	bzero(evtchn_dev->si_drv1, sizeof(evtchn_softc_t));
357
358	/* XXX I don't think we need any of this rubbish */
359#if 0
360	if ( err != 0 )
361	{
362		printk(KERN_ALERT "Could not register /dev/misc/evtchn\n");
363		return err;
364	}
365
366	/* (DEVFS) create directory '/dev/xen'. */
367	xen_dev_dir = devfs_mk_dir(NULL, "xen", NULL);
368
369	/* (DEVFS) &link_dest[pos] == '../misc/evtchn'. */
370	pos = devfs_generate_path(evtchn_miscdev.devfs_handle,
371				  &link_dest[3],
372				  sizeof(link_dest) - 3);
373	if ( pos >= 0 )
374		strncpy(&link_dest[pos], "../", 3);
375	/* (DEVFS) symlink '/dev/xen/evtchn' -> '../misc/evtchn'. */
376	(void)devfs_mk_symlink(xen_dev_dir,
377			       "evtchn",
378			       DEVFS_FL_DEFAULT,
379			       &link_dest[pos],
380			       &symlink_handle,
381			       NULL);
382
383	/* (DEVFS) automatically destroy the symlink with its destination. */
384	devfs_auto_unregister(evtchn_miscdev.devfs_handle, symlink_handle);
385#endif
386	printk("Event-channel device installed.\n");
387
388	return 0;
389}
390
391
392SYSINIT(evtchn_dev_init, SI_SUB_DRIVERS, SI_ORDER_FIRST, evtchn_dev_init, NULL);
393
394
395