1295634Sandrew/******************************************************************************
2295634Sandrew * evtchn.c
3295634Sandrew *
4295634Sandrew * Xenolinux driver for receiving and demuxing event-channel signals.
5295634Sandrew *
6295634Sandrew * Copyright (c) 2004, K A Fraser
7295634Sandrew */
8295634Sandrew
9295634Sandrew#include <sys/cdefs.h>
10295634Sandrew__FBSDID("$FreeBSD$");
11295634Sandrew
12295634Sandrew#include <sys/param.h>
13295634Sandrew#include <sys/systm.h>
14295634Sandrew#include <sys/uio.h>
15295634Sandrew#include <sys/bus.h>
16295634Sandrew#include <sys/malloc.h>
17295634Sandrew#include <sys/kernel.h>
18295634Sandrew#include <sys/lock.h>
19295634Sandrew#include <sys/mutex.h>
20295634Sandrew#include <sys/selinfo.h>
21295634Sandrew#include <sys/poll.h>
22295634Sandrew#include <sys/conf.h>
23295634Sandrew#include <sys/fcntl.h>
24295634Sandrew#include <sys/ioccom.h>
25295634Sandrew
26295634Sandrew#include <machine/xen/xen-os.h>
27295634Sandrew#include <xen/xen_intr.h>
28295634Sandrew#include <machine/bus.h>
29295634Sandrew#include <sys/rman.h>
30295634Sandrew#include <machine/resource.h>
31295634Sandrew#include <machine/xen/synch_bitops.h>
32295634Sandrew#include <xen/hypervisor.h>
33295634Sandrew#include <xen/evtchn.h>
34295634Sandrew
35295634Sandrew
36295634Sandrewtypedef struct evtchn_sotfc {
37295634Sandrew
38295634Sandrew	struct selinfo  ev_rsel;
39295634Sandrew} evtchn_softc_t;
40295634Sandrew
41295634Sandrew
42295634Sandrew#ifdef linuxcrap
43295634Sandrew/* NB. This must be shared amongst drivers if more things go in /dev/xen */
44295634Sandrewstatic devfs_handle_t xen_dev_dir;
45295634Sandrew#endif
46295634Sandrew
47295634Sandrew/* Only one process may open /dev/xen/evtchn at any time. */
48295634Sandrewstatic unsigned long evtchn_dev_inuse;
49295634Sandrew
50295634Sandrew/* Notification ring, accessed via /dev/xen/evtchn. */
51295634Sandrew
52295634Sandrew#define EVTCHN_RING_SIZE     2048  /* 2048 16-bit entries */
53295634Sandrew
54295634Sandrew#define EVTCHN_RING_MASK(_i) ((_i)&(EVTCHN_RING_SIZE-1))
55295634Sandrewstatic uint16_t *ring;
56295634Sandrewstatic unsigned int ring_cons, ring_prod, ring_overflow;
57295654Sandrew
58295634Sandrew/* Which ports is user-space bound to? */
59295654Sandrewstatic uint32_t bound_ports[32];
60295634Sandrew
61295634Sandrew/* Unique address for processes to sleep on */
62295634Sandrewstatic void *evtchn_waddr = &ring;
63295634Sandrew
64295634Sandrewstatic struct mtx lock, upcall_lock;
65295634Sandrew
66295634Sandrewstatic d_read_t      evtchn_read;
67295634Sandrewstatic d_write_t     evtchn_write;
68295634Sandrewstatic d_ioctl_t     evtchn_ioctl;
69295634Sandrewstatic d_poll_t      evtchn_poll;
70295634Sandrewstatic d_open_t      evtchn_open;
71295634Sandrewstatic d_close_t     evtchn_close;
72295634Sandrew
73295634Sandrew
74295634Sandrewvoid
75295634Sandrewevtchn_device_upcall(int port)
76295634Sandrew{
77295634Sandrew	mtx_lock(&upcall_lock);
78295634Sandrew
79295634Sandrew	mask_evtchn(port);
80295634Sandrew	clear_evtchn(port);
81295634Sandrew
82295634Sandrew	if ( ring != NULL ) {
83295634Sandrew		if ( (ring_prod - ring_cons) < EVTCHN_RING_SIZE ) {
84295634Sandrew			ring[EVTCHN_RING_MASK(ring_prod)] = (uint16_t)port;
85295634Sandrew			if ( ring_cons == ring_prod++ ) {
86295634Sandrew				wakeup(evtchn_waddr);
87295634Sandrew			}
88295634Sandrew		}
89295634Sandrew		else {
90295634Sandrew			ring_overflow = 1;
91295634Sandrew		}
92295634Sandrew	}
93295634Sandrew
94295634Sandrew	mtx_unlock(&upcall_lock);
95295634Sandrew}
96295634Sandrew
97295634Sandrewstatic void
98295634Sandrew__evtchn_reset_buffer_ring(void)
99295634Sandrew{
100295634Sandrew	/* Initialise the ring to empty. Clear errors. */
101295634Sandrew	ring_cons = ring_prod = ring_overflow = 0;
102295634Sandrew}
103295634Sandrew
104295634Sandrewstatic int
105295634Sandrewevtchn_read(struct cdev *dev, struct uio *uio, int ioflag)
106295634Sandrew{
107295634Sandrew	int rc;
108295634Sandrew	unsigned int count, c, p, sst = 0, bytes1 = 0, bytes2 = 0;
109295634Sandrew	count = uio->uio_resid;
110295634Sandrew
111295634Sandrew	count &= ~1; /* even number of bytes */
112295634Sandrew
113295634Sandrew	if ( count == 0 )
114295634Sandrew	{
115295634Sandrew		rc = 0;
116295634Sandrew		goto out;
117295634Sandrew	}
118295634Sandrew
119295634Sandrew	if ( count > PAGE_SIZE )
120295634Sandrew		count = PAGE_SIZE;
121295634Sandrew
122295634Sandrew	for ( ; ; ) {
123295634Sandrew		if ( (c = ring_cons) != (p = ring_prod) )
124295634Sandrew			break;
125295634Sandrew
126295634Sandrew		if ( ring_overflow ) {
127295634Sandrew			rc = EFBIG;
128295634Sandrew			goto out;
129295634Sandrew		}
130295634Sandrew
131295634Sandrew		if (sst != 0) {
132295634Sandrew			rc = EINTR;
133295634Sandrew			goto out;
134295634Sandrew		}
135295634Sandrew
136295634Sandrew		/* PCATCH == check for signals before and after sleeping
137295634Sandrew		 * PWAIT == priority of waiting on resource
138295634Sandrew		 */
139295634Sandrew		sst = tsleep(evtchn_waddr, PWAIT|PCATCH, "evchwt", 10);
140295634Sandrew	}
141295654Sandrew
142295634Sandrew	/* Byte lengths of two chunks. Chunk split (if any) is at ring wrap. */
143295634Sandrew	if ( ((c ^ p) & EVTCHN_RING_SIZE) != 0 ) {
144295634Sandrew		bytes1 = (EVTCHN_RING_SIZE - EVTCHN_RING_MASK(c)) * sizeof(uint16_t);
145295634Sandrew		bytes2 = EVTCHN_RING_MASK(p) * sizeof(uint16_t);
146295634Sandrew	}
147295634Sandrew	else {
148295634Sandrew		bytes1 = (p - c) * sizeof(uint16_t);
149295654Sandrew		bytes2 = 0;
150295654Sandrew	}
151295654Sandrew
152295654Sandrew	/* Truncate chunks according to caller's maximum byte count. */
153295654Sandrew	if ( bytes1 > count ) {
154295654Sandrew		bytes1 = count;
155295654Sandrew		bytes2 = 0;
156295654Sandrew	}
157295654Sandrew	else if ( (bytes1 + bytes2) > count ) {
158295634Sandrew		bytes2 = count - bytes1;
159295634Sandrew	}
160295634Sandrew
161295654Sandrew	if ( uiomove(&ring[EVTCHN_RING_MASK(c)], bytes1, uio) ||
162295634Sandrew	     ((bytes2 != 0) && uiomove(&ring[0], bytes2, uio)))
163295634Sandrew		/* keeping this around as its replacement is not equivalent
164295634Sandrew		 * copyout(&ring[0], &buf[bytes1], bytes2)
165295634Sandrew		 */
166295634Sandrew	{
167295634Sandrew		rc = EFAULT;
168295634Sandrew		goto out;
169295634Sandrew	}
170295634Sandrew
171295634Sandrew	ring_cons += (bytes1 + bytes2) / sizeof(uint16_t);
172295634Sandrew
173295634Sandrew	rc = bytes1 + bytes2;
174295634Sandrew
175295634Sandrew out:
176295634Sandrew
177295634Sandrew	return rc;
178295634Sandrew}
179295634Sandrew
180295634Sandrewstatic int
181295634Sandrewevtchn_write(struct cdev *dev, struct uio *uio, int ioflag)
182295634Sandrew{
183295634Sandrew	int  rc, i, count;
184295634Sandrew
185295634Sandrew	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