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 = ˚ 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