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#include <sys/rman.h> 26 27#include <xen/xen-os.h> 28#include <xen/evtchn.h> 29#include <xen/xen_intr.h> 30 31#include <machine/bus.h> 32#include <machine/resource.h> 33#include <machine/xen/synch_bitops.h> 34 35#include <xen/evtchn/evtchnvar.h> 36 37typedef struct evtchn_sotfc { 38 39 struct selinfo ev_rsel; 40} evtchn_softc_t; 41 42/* Only one process may open /dev/xen/evtchn at any time. */ 43static unsigned long evtchn_dev_inuse; 44 45/* Notification ring, accessed via /dev/xen/evtchn. */ 46 47#define EVTCHN_RING_SIZE 2048 /* 2048 16-bit entries */ 48 49#define EVTCHN_RING_MASK(_i) ((_i)&(EVTCHN_RING_SIZE-1)) 50static uint16_t *ring; 51static unsigned int ring_cons, ring_prod, ring_overflow; 52 53/* Which ports is user-space bound to? */ 54static uint32_t bound_ports[32]; 55 56/* Unique address for processes to sleep on */ 57static void *evtchn_waddr = ˚ 58 59static struct mtx lock, upcall_lock; 60 61static d_read_t evtchn_read; 62static d_write_t evtchn_write; 63static d_ioctl_t evtchn_ioctl; 64static d_poll_t evtchn_poll; 65static d_open_t evtchn_open; 66static d_close_t evtchn_close; 67 68 69void 70evtchn_device_upcall(evtchn_port_t port) 71{ 72 mtx_lock(&upcall_lock); 73 74 evtchn_mask_port(port); 75 evtchn_clear_port(port); 76 77 if ( ring != NULL ) { 78 if ( (ring_prod - ring_cons) < EVTCHN_RING_SIZE ) { 79 ring[EVTCHN_RING_MASK(ring_prod)] = (uint16_t)port; 80 if ( ring_cons == ring_prod++ ) { 81 wakeup(evtchn_waddr); 82 } 83 } 84 else { 85 ring_overflow = 1; 86 } 87 } 88 89 mtx_unlock(&upcall_lock); 90} 91 92static void 93__evtchn_reset_buffer_ring(void) 94{ 95 /* Initialise the ring to empty. Clear errors. */ 96 ring_cons = ring_prod = ring_overflow = 0; 97} 98 99static int 100evtchn_read(struct cdev *dev, struct uio *uio, int ioflag) 101{ 102 int rc; 103 unsigned int count, c, p, sst = 0, bytes1 = 0, bytes2 = 0; 104 count = uio->uio_resid; 105 106 count &= ~1; /* even number of bytes */ 107 108 if ( count == 0 ) 109 { 110 rc = 0; 111 goto out; 112 } 113 114 if ( count > PAGE_SIZE ) 115 count = PAGE_SIZE; 116 117 for ( ; ; ) { 118 if ( (c = ring_cons) != (p = ring_prod) ) 119 break; 120 121 if ( ring_overflow ) { 122 rc = EFBIG; 123 goto out; 124 } 125 126 if (sst != 0) { 127 rc = EINTR; 128 goto out; 129 } 130 131 /* PCATCH == check for signals before and after sleeping 132 * PWAIT == priority of waiting on resource 133 */ 134 sst = tsleep(evtchn_waddr, PWAIT|PCATCH, "evchwt", 10); 135 } 136 137 /* Byte lengths of two chunks. Chunk split (if any) is at ring wrap. */ 138 if ( ((c ^ p) & EVTCHN_RING_SIZE) != 0 ) { 139 bytes1 = (EVTCHN_RING_SIZE - EVTCHN_RING_MASK(c)) * sizeof(uint16_t); 140 bytes2 = EVTCHN_RING_MASK(p) * sizeof(uint16_t); 141 } 142 else { 143 bytes1 = (p - c) * sizeof(uint16_t); 144 bytes2 = 0; 145 } 146 147 /* Truncate chunks according to caller's maximum byte count. */ 148 if ( bytes1 > count ) { 149 bytes1 = count; 150 bytes2 = 0; 151 } 152 else if ( (bytes1 + bytes2) > count ) { 153 bytes2 = count - bytes1; 154 } 155 156 if ( uiomove(&ring[EVTCHN_RING_MASK(c)], bytes1, uio) || 157 ((bytes2 != 0) && uiomove(&ring[0], bytes2, uio))) 158 /* keeping this around as its replacement is not equivalent 159 * copyout(&ring[0], &buf[bytes1], bytes2) 160 */ 161 { 162 rc = EFAULT; 163 goto out; 164 } 165 166 ring_cons += (bytes1 + bytes2) / sizeof(uint16_t); 167 168 rc = bytes1 + bytes2; 169 170 out: 171 172 return rc; 173} 174 175static int 176evtchn_write(struct cdev *dev, struct uio *uio, int ioflag) 177{ 178 int rc, i, count; 179 180 count = uio->uio_resid; 181 182 uint16_t *kbuf = (uint16_t *)malloc(PAGE_SIZE, M_DEVBUF, M_WAITOK); 183 184 185 if ( kbuf == NULL ) 186 return ENOMEM; 187 188 count &= ~1; /* even number of bytes */ 189 190 if ( count == 0 ) { 191 rc = 0; 192 goto out; 193 } 194 195 if ( count > PAGE_SIZE ) 196 count = PAGE_SIZE; 197 198 if ( uiomove(kbuf, count, uio) != 0 ) { 199 rc = EFAULT; 200 goto out; 201 } 202 203 mtx_lock_spin(&lock); 204 for ( i = 0; i < (count/2); i++ ) 205 if ( test_bit(kbuf[i], &bound_ports[0]) ) 206 evtchn_unmask_port(kbuf[i]); 207 mtx_unlock_spin(&lock); 208 209 rc = count; 210 211 out: 212 free(kbuf, M_DEVBUF); 213 return rc; 214} 215 216static int 217evtchn_ioctl(struct cdev *dev, unsigned long cmd, caddr_t arg, 218 int mode, struct thread *td __unused) 219{ 220 int rc = 0; 221 222#ifdef NOTYET 223 mtx_lock_spin(&lock); 224 225 switch ( cmd ) 226 { 227 case EVTCHN_RESET: 228 __evtchn_reset_buffer_ring(); 229 break; 230 case EVTCHN_BIND: 231 if ( !synch_test_and_set_bit((uintptr_t)arg, &bound_ports[0]) ) 232 unmask_evtchn((uintptr_t)arg); 233 else 234 rc = EINVAL; 235 break; 236 case EVTCHN_UNBIND: 237 if ( synch_test_and_clear_bit((uintptr_t)arg, &bound_ports[0]) ) 238 mask_evtchn((uintptr_t)arg); 239 else 240 rc = EINVAL; 241 break; 242 default: 243 rc = ENOSYS; 244 break; 245 } 246 247 mtx_unlock_spin(&lock); 248#endif 249 250 return rc; 251} 252 253static int 254evtchn_poll(struct cdev *dev, int poll_events, struct thread *td) 255{ 256 257 evtchn_softc_t *sc; 258 unsigned int mask = POLLOUT | POLLWRNORM; 259 260 sc = dev->si_drv1; 261 262 if ( ring_cons != ring_prod ) 263 mask |= POLLIN | POLLRDNORM; 264 else if ( ring_overflow ) 265 mask = POLLERR; 266 else 267 selrecord(td, &sc->ev_rsel); 268 269 270 return mask; 271} 272 273 274static int 275evtchn_open(struct cdev *dev, int flag, int otyp, struct thread *td) 276{ 277 uint16_t *_ring; 278 279 if (flag & O_NONBLOCK) 280 return EBUSY; 281 282 if ( synch_test_and_set_bit(0, &evtchn_dev_inuse) ) 283 return EBUSY; 284 285 if ( (_ring = (uint16_t *)malloc(PAGE_SIZE, M_DEVBUF, M_WAITOK)) == NULL ) 286 return ENOMEM; 287 288 mtx_lock_spin(&lock); 289 ring = _ring; 290 __evtchn_reset_buffer_ring(); 291 mtx_unlock_spin(&lock); 292 293 294 return 0; 295} 296 297static int 298evtchn_close(struct cdev *dev, int flag, int otyp, struct thread *td __unused) 299{ 300 int i; 301 302 if (ring != NULL) { 303 free(ring, M_DEVBUF); 304 ring = NULL; 305 } 306 mtx_lock_spin(&lock); 307 for ( i = 0; i < NR_EVENT_CHANNELS; i++ ) 308 if ( synch_test_and_clear_bit(i, &bound_ports[0]) ) 309 evtchn_mask_port(i); 310 mtx_unlock_spin(&lock); 311 312 evtchn_dev_inuse = 0; 313 314 return 0; 315} 316 317static struct cdevsw evtchn_devsw = { 318 .d_version = D_VERSION, 319 .d_open = evtchn_open, 320 .d_close = evtchn_close, 321 .d_read = evtchn_read, 322 .d_write = evtchn_write, 323 .d_ioctl = evtchn_ioctl, 324 .d_poll = evtchn_poll, 325 .d_name = "evtchn", 326}; 327 328 329/* XXX - if this device is ever supposed to support use by more than one process 330 * this global static will have to go away 331 */ 332static struct cdev *evtchn_dev; 333 334 335 336static int 337evtchn_dev_init(void *dummy __unused) 338{ 339 /* XXX I believe we don't need these leaving them here for now until we 340 * have some semblance of it working 341 */ 342 mtx_init(&upcall_lock, "evtchup", NULL, MTX_DEF); 343 344 /* (DEVFS) create '/dev/misc/evtchn'. */ 345 evtchn_dev = make_dev(&evtchn_devsw, 0, UID_ROOT, GID_WHEEL, 0600, "xen/evtchn"); 346 347 mtx_init(&lock, "evch", NULL, MTX_SPIN | MTX_NOWITNESS); 348 349 evtchn_dev->si_drv1 = malloc(sizeof(evtchn_softc_t), M_DEVBUF, M_WAITOK); 350 bzero(evtchn_dev->si_drv1, sizeof(evtchn_softc_t)); 351 352 if (bootverbose) 353 printf("Event-channel device installed.\n"); 354 355 return 0; 356} 357 358SYSINIT(evtchn_dev_init, SI_SUB_DRIVERS, SI_ORDER_FIRST, evtchn_dev_init, NULL); 359