1/******************************************************************************
2 * evtchn.c
3 *
4 * Xenolinux driver for receiving and demuxing event-channel signals.
5 *
6 * Copyright (c) 2004, K A Fraser
7 */
8
9#include <sys/cdefs.h>
10__FBSDID("$FreeBSD$");
11
12#include <sys/param.h>
13#include <sys/systm.h>
14#include <sys/uio.h>
15#include <sys/bus.h>
16#include <sys/malloc.h>
17#include <sys/kernel.h>
18#include <sys/lock.h>
19#include <sys/mutex.h>
20#include <sys/selinfo.h>
21#include <sys/poll.h>
22#include <sys/conf.h>
23#include <sys/fcntl.h>
24#include <sys/ioccom.h>
25
26#include <machine/xen/xen-os.h>
27#include <xen/xen_intr.h>
28#include <machine/bus.h>
29#include <sys/rman.h>
30#include <machine/resource.h>
31#include <machine/xen/synch_bitops.h>
32#include <xen/hypervisor.h>
33#include <xen/evtchn.h>
34
35
36typedef struct evtchn_sotfc {
37
38	struct selinfo  ev_rsel;
39} evtchn_softc_t;
40
41
42#ifdef linuxcrap
43/* NB. This must be shared amongst drivers if more things go in /dev/xen */
44static devfs_handle_t xen_dev_dir;
45#endif
46
47/* Only one process may open /dev/xen/evtchn at any time. */
48static unsigned long evtchn_dev_inuse;
49
50/* Notification ring, accessed via /dev/xen/evtchn. */
51
52#define EVTCHN_RING_SIZE     2048  /* 2048 16-bit entries */
53
54#define EVTCHN_RING_MASK(_i) ((_i)&(EVTCHN_RING_SIZE-1))
55static uint16_t *ring;
56static unsigned int ring_cons, ring_prod, ring_overflow;
57
58/* Which ports is user-space bound to? */
59static uint32_t bound_ports[32];
60
61/* Unique address for processes to sleep on */
62static void *evtchn_waddr = &ring;
63
64static struct mtx lock, upcall_lock;
65
66static d_read_t      evtchn_read;
67static d_write_t     evtchn_write;
68static d_ioctl_t     evtchn_ioctl;
69static d_poll_t      evtchn_poll;
70static d_open_t      evtchn_open;
71static d_close_t     evtchn_close;
72
73
74void
75evtchn_device_upcall(int port)
76{
77	mtx_lock(&upcall_lock);
78
79	mask_evtchn(port);
80	clear_evtchn(port);
81
82	if ( ring != NULL ) {
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++ ) {
86				wakeup(evtchn_waddr);
87			}
88		}
89		else {
90			ring_overflow = 1;
91		}
92	}
93
94	mtx_unlock(&upcall_lock);
95}
96
97static void
98__evtchn_reset_buffer_ring(void)
99{
100	/* Initialise the ring to empty. Clear errors. */
101	ring_cons = ring_prod = ring_overflow = 0;
102}
103
104static int
105evtchn_read(struct cdev *dev, struct uio *uio, int ioflag)
106{
107	int rc;
108	unsigned int count, c, p, sst = 0, bytes1 = 0, bytes2 = 0;
109	count = uio->uio_resid;
110
111	count &= ~1; /* even number of bytes */
112
113	if ( count == 0 )
114	{
115		rc = 0;
116		goto out;
117	}
118
119	if ( count > PAGE_SIZE )
120		count = PAGE_SIZE;
121
122	for ( ; ; ) {
123		if ( (c = ring_cons) != (p = ring_prod) )
124			break;
125
126		if ( ring_overflow ) {
127			rc = EFBIG;
128			goto out;
129		}
130
131		if (sst != 0) {
132			rc = EINTR;
133			goto out;
134		}
135
136		/* PCATCH == check for signals before and after sleeping
137		 * PWAIT == priority of waiting on resource
138		 */
139		sst = tsleep(evtchn_waddr, PWAIT|PCATCH, "evchwt", 10);
140	}
141
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);
146	}
147	else {
148		bytes1 = (p - c) * sizeof(uint16_t);
149		bytes2 = 0;
150	}
151
152	/* Truncate chunks according to caller's maximum byte count. */
153	if ( bytes1 > count ) {
154		bytes1 = count;
155		bytes2 = 0;
156	}
157	else if ( (bytes1 + bytes2) > count ) {
158		bytes2 = count - bytes1;
159	}
160
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)
165		 */
166	{
167		rc = EFAULT;
168		goto out;
169	}
170
171	ring_cons += (bytes1 + bytes2) / sizeof(uint16_t);
172
173	rc = bytes1 + bytes2;
174
175 out:
176
177	return rc;
178}
179
180static int
181evtchn_write(struct cdev *dev, struct uio *uio, int ioflag)
182{
183	int  rc, i, count;
184
185	count = uio->uio_resid;
186
187	uint16_t *kbuf = (uint16_t *)malloc(PAGE_SIZE, M_DEVBUF, M_WAITOK);
188
189
190	if ( kbuf == NULL )
191		return ENOMEM;
192
193	count &= ~1; /* even number of bytes */
194
195	if ( count == 0 ) {
196		rc = 0;
197		goto out;
198	}
199
200	if ( count > PAGE_SIZE )
201		count = PAGE_SIZE;
202
203	if ( uiomove(kbuf, count, uio) != 0 ) {
204		rc = EFAULT;
205		goto out;
206	}
207
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);
213
214	rc = count;
215
216 out:
217	free(kbuf, M_DEVBUF);
218	return rc;
219}
220
221static int
222evtchn_ioctl(struct cdev *dev, unsigned long cmd, caddr_t arg,
223	     int mode, struct thread *td __unused)
224{
225	int rc = 0;
226
227	mtx_lock_spin(&lock);
228
229	switch ( cmd )
230	{
231	case EVTCHN_RESET:
232		__evtchn_reset_buffer_ring();
233		break;
234	case EVTCHN_BIND:
235		if ( !synch_test_and_set_bit((uintptr_t)arg, &bound_ports[0]) )
236			unmask_evtchn((uintptr_t)arg);
237		else
238			rc = EINVAL;
239		break;
240	case EVTCHN_UNBIND:
241		if ( synch_test_and_clear_bit((uintptr_t)arg, &bound_ports[0]) )
242			mask_evtchn((uintptr_t)arg);
243		else
244			rc = EINVAL;
245		break;
246	default:
247		rc = ENOSYS;
248		break;
249	}
250
251	mtx_unlock_spin(&lock);
252
253	return rc;
254}
255
256static int
257evtchn_poll(struct cdev *dev, int poll_events, struct thread *td)
258{
259
260	evtchn_softc_t *sc;
261	unsigned int mask = POLLOUT | POLLWRNORM;
262
263	sc = dev->si_drv1;
264
265	if ( ring_cons != ring_prod )
266		mask |= POLLIN | POLLRDNORM;
267	else if ( ring_overflow )
268		mask = POLLERR;
269	else
270		selrecord(td, &sc->ev_rsel);
271
272
273	return mask;
274}
275
276
277static int
278evtchn_open(struct cdev *dev, int flag, int otyp, struct thread *td)
279{
280	uint16_t *_ring;
281
282	if (flag & O_NONBLOCK)
283		return EBUSY;
284
285	if ( synch_test_and_set_bit(0, &evtchn_dev_inuse) )
286		return EBUSY;
287
288	if ( (_ring = (uint16_t *)malloc(PAGE_SIZE, M_DEVBUF, M_WAITOK)) == NULL )
289		return ENOMEM;
290
291	mtx_lock_spin(&lock);
292	ring = _ring;
293	__evtchn_reset_buffer_ring();
294	mtx_unlock_spin(&lock);
295
296
297	return 0;
298}
299
300static int
301evtchn_close(struct cdev *dev, int flag, int otyp, struct thread *td __unused)
302{
303	int i;
304
305	if (ring != NULL) {
306		free(ring, M_DEVBUF);
307		ring = NULL;
308	}
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]) )
312			mask_evtchn(i);
313	mtx_unlock_spin(&lock);
314
315	evtchn_dev_inuse = 0;
316
317	return 0;
318}
319
320static struct cdevsw evtchn_devsw = {
321	.d_version =	D_VERSION,
322	.d_open =	evtchn_open,
323	.d_close =	evtchn_close,
324	.d_read =	evtchn_read,
325	.d_write =	evtchn_write,
326	.d_ioctl =	evtchn_ioctl,
327	.d_poll =	evtchn_poll,
328	.d_name =	"evtchn",
329};
330
331
332/* XXX  - if this device is ever supposed to support use by more than one process
333 * this global static will have to go away
334 */
335static struct cdev *evtchn_dev;
336
337
338
339static int
340evtchn_dev_init(void *dummy __unused)
341{
342	/* XXX I believe we don't need these leaving them here for now until we
343	 * have some semblance of it working
344	 */
345	mtx_init(&upcall_lock, "evtchup", NULL, MTX_DEF);
346
347	/* (DEVFS) create '/dev/misc/evtchn'. */
348	evtchn_dev = make_dev(&evtchn_devsw, 0, UID_ROOT, GID_WHEEL, 0600, "xen/evtchn");
349
350	mtx_init(&lock, "evch", NULL, MTX_SPIN | MTX_NOWITNESS);
351
352	evtchn_dev->si_drv1 = malloc(sizeof(evtchn_softc_t), M_DEVBUF, M_WAITOK);
353	bzero(evtchn_dev->si_drv1, sizeof(evtchn_softc_t));
354
355	/* XXX I don't think we need any of this rubbish */
356#if 0
357	if ( err != 0 )
358	{
359		printk(KERN_ALERT "Could not register /dev/misc/evtchn\n");
360		return err;
361	}
362
363	/* (DEVFS) create directory '/dev/xen'. */
364	xen_dev_dir = devfs_mk_dir(NULL, "xen", NULL);
365
366	/* (DEVFS) &link_dest[pos] == '../misc/evtchn'. */
367	pos = devfs_generate_path(evtchn_miscdev.devfs_handle,
368				  &link_dest[3],
369				  sizeof(link_dest) - 3);
370	if ( pos >= 0 )
371		strncpy(&link_dest[pos], "../", 3);
372	/* (DEVFS) symlink '/dev/xen/evtchn' -> '../misc/evtchn'. */
373	(void)devfs_mk_symlink(xen_dev_dir,
374			       "evtchn",
375			       DEVFS_FL_DEFAULT,
376			       &link_dest[pos],
377			       &symlink_handle,
378			       NULL);
379
380	/* (DEVFS) automatically destroy the symlink with its destination. */
381	devfs_auto_unregister(evtchn_miscdev.devfs_handle, symlink_handle);
382#endif
383	if (bootverbose)
384		printf("Event-channel device installed.\n");
385
386	return 0;
387}
388
389SYSINIT(evtchn_dev_init, SI_SUB_DRIVERS, SI_ORDER_FIRST, evtchn_dev_init, NULL);
390
391
392