Merge to Fedora kernel-2.6.18-1.2224_FC5 patched with stable patch-2.6.18.1-vs2.0...
[linux-2.6.git] / drivers / xen / evtchn / evtchn.c
1 /******************************************************************************
2  * evtchn.c
3  * 
4  * Driver for receiving and demuxing event-channel signals.
5  * 
6  * Copyright (c) 2004-2005, K A Fraser
7  * Multi-process extensions Copyright (c) 2004, Steven Smith
8  * 
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License version 2
11  * as published by the Free Software Foundation; or, when distributed
12  * separately from the Linux kernel or incorporated into other
13  * software packages, subject to the following license:
14  * 
15  * Permission is hereby granted, free of charge, to any person obtaining a copy
16  * of this source file (the "Software"), to deal in the Software without
17  * restriction, including without limitation the rights to use, copy, modify,
18  * merge, publish, distribute, sublicense, and/or sell copies of the Software,
19  * and to permit persons to whom the Software is furnished to do so, subject to
20  * the following conditions:
21  * 
22  * The above copyright notice and this permission notice shall be included in
23  * all copies or substantial portions of the Software.
24  * 
25  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
26  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
27  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
28  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
29  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
30  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
31  * IN THE SOFTWARE.
32  */
33
34 #include <linux/module.h>
35 #include <linux/kernel.h>
36 #include <linux/sched.h>
37 #include <linux/slab.h>
38 #include <linux/string.h>
39 #include <linux/errno.h>
40 #include <linux/fs.h>
41 #include <linux/errno.h>
42 #include <linux/miscdevice.h>
43 #include <linux/major.h>
44 #include <linux/proc_fs.h>
45 #include <linux/stat.h>
46 #include <linux/poll.h>
47 #include <linux/irq.h>
48 #include <linux/init.h>
49 #include <linux/gfp.h>
50 #include <xen/evtchn.h>
51 #include <xen/public/evtchn.h>
52
53 struct per_user_data {
54         /* Notification ring, accessed via /dev/xen/evtchn. */
55 #define EVTCHN_RING_SIZE     (PAGE_SIZE / sizeof(evtchn_port_t))
56 #define EVTCHN_RING_MASK(_i) ((_i)&(EVTCHN_RING_SIZE-1))
57         evtchn_port_t *ring;
58         unsigned int ring_cons, ring_prod, ring_overflow;
59
60         /* Processes wait on this queue when ring is empty. */
61         wait_queue_head_t evtchn_wait;
62         struct fasync_struct *evtchn_async_queue;
63 };
64
65 /* Who's bound to each port? */
66 static struct per_user_data *port_user[NR_EVENT_CHANNELS];
67 static spinlock_t port_user_lock;
68
69 void evtchn_device_upcall(int port)
70 {
71         struct per_user_data *u;
72
73         spin_lock(&port_user_lock);
74
75         mask_evtchn(port);
76         clear_evtchn(port);
77
78         if ((u = port_user[port]) != NULL) {
79                 if ((u->ring_prod - u->ring_cons) < EVTCHN_RING_SIZE) {
80                         u->ring[EVTCHN_RING_MASK(u->ring_prod)] = port;
81                         if (u->ring_cons == u->ring_prod++) {
82                                 wake_up_interruptible(&u->evtchn_wait);
83                                 kill_fasync(&u->evtchn_async_queue,
84                                             SIGIO, POLL_IN);
85                         }
86                 } else {
87                         u->ring_overflow = 1;
88                 }
89         }
90
91         spin_unlock(&port_user_lock);
92 }
93
94 static ssize_t evtchn_read(struct file *file, char __user *buf,
95                            size_t count, loff_t *ppos)
96 {
97         int rc;
98         unsigned int c, p, bytes1 = 0, bytes2 = 0;
99         struct per_user_data *u = file->private_data;
100
101         /* Whole number of ports. */
102         count &= ~(sizeof(evtchn_port_t)-1);
103
104         if (count == 0)
105                 return 0;
106
107         if (count > PAGE_SIZE)
108                 count = PAGE_SIZE;
109
110         for (;;) {
111                 if (u->ring_overflow)
112                         return -EFBIG;
113
114                 if ((c = u->ring_cons) != (p = u->ring_prod))
115                         break;
116
117                 if (file->f_flags & O_NONBLOCK)
118                         return -EAGAIN;
119
120                 rc = wait_event_interruptible(
121                         u->evtchn_wait, u->ring_cons != u->ring_prod);
122                 if (rc)
123                         return rc;
124         }
125
126         /* Byte lengths of two chunks. Chunk split (if any) is at ring wrap. */
127         if (((c ^ p) & EVTCHN_RING_SIZE) != 0) {
128                 bytes1 = (EVTCHN_RING_SIZE - EVTCHN_RING_MASK(c)) *
129                         sizeof(evtchn_port_t);
130                 bytes2 = EVTCHN_RING_MASK(p) * sizeof(evtchn_port_t);
131         } else {
132                 bytes1 = (p - c) * sizeof(evtchn_port_t);
133                 bytes2 = 0;
134         }
135
136         /* Truncate chunks according to caller's maximum byte count. */
137         if (bytes1 > count) {
138                 bytes1 = count;
139                 bytes2 = 0;
140         } else if ((bytes1 + bytes2) > count) {
141                 bytes2 = count - bytes1;
142         }
143
144         if (copy_to_user(buf, &u->ring[EVTCHN_RING_MASK(c)], bytes1) ||
145             ((bytes2 != 0) &&
146              copy_to_user(&buf[bytes1], &u->ring[0], bytes2)))
147                 return -EFAULT;
148
149         u->ring_cons += (bytes1 + bytes2) / sizeof(evtchn_port_t);
150
151         return bytes1 + bytes2;
152 }
153
154 static ssize_t evtchn_write(struct file *file, const char __user *buf,
155                             size_t count, loff_t *ppos)
156 {
157         int  rc, i;
158         evtchn_port_t *kbuf = (evtchn_port_t *)__get_free_page(GFP_KERNEL);
159         struct per_user_data *u = file->private_data;
160
161         if (kbuf == NULL)
162                 return -ENOMEM;
163
164         /* Whole number of ports. */
165         count &= ~(sizeof(evtchn_port_t)-1);
166
167         if (count == 0) {
168                 rc = 0;
169                 goto out;
170         }
171
172         if (count > PAGE_SIZE)
173                 count = PAGE_SIZE;
174
175         if (copy_from_user(kbuf, buf, count) != 0) {
176                 rc = -EFAULT;
177                 goto out;
178         }
179
180         spin_lock_irq(&port_user_lock);
181         for (i = 0; i < (count/sizeof(evtchn_port_t)); i++)
182                 if ((kbuf[i] < NR_EVENT_CHANNELS) && (port_user[kbuf[i]] == u))
183                         unmask_evtchn(kbuf[i]);
184         spin_unlock_irq(&port_user_lock);
185
186         rc = count;
187
188  out:
189         free_page((unsigned long)kbuf);
190         return rc;
191 }
192
193 static void evtchn_bind_to_user(struct per_user_data *u, int port)
194 {
195         spin_lock_irq(&port_user_lock);
196         BUG_ON(port_user[port] != NULL);
197         port_user[port] = u;
198         unmask_evtchn(port);
199         spin_unlock_irq(&port_user_lock);
200 }
201
202 static int evtchn_ioctl(struct inode *inode, struct file *file,
203                         unsigned int cmd, unsigned long arg)
204 {
205         int rc;
206         struct per_user_data *u = file->private_data;
207         void __user *uarg = (void __user *) arg;
208
209         switch (cmd) {
210         case IOCTL_EVTCHN_BIND_VIRQ: {
211                 struct ioctl_evtchn_bind_virq bind;
212                 struct evtchn_bind_virq bind_virq;
213
214                 rc = -EFAULT;
215                 if (copy_from_user(&bind, uarg, sizeof(bind)))
216                         break;
217
218                 bind_virq.virq = bind.virq;
219                 bind_virq.vcpu = 0;
220                 rc = HYPERVISOR_event_channel_op(EVTCHNOP_bind_virq,
221                                                  &bind_virq);
222                 if (rc != 0)
223                         break;
224
225                 rc = bind_virq.port;
226                 evtchn_bind_to_user(u, rc);
227                 break;
228         }
229
230         case IOCTL_EVTCHN_BIND_INTERDOMAIN: {
231                 struct ioctl_evtchn_bind_interdomain bind;
232                 struct evtchn_bind_interdomain bind_interdomain;
233
234                 rc = -EFAULT;
235                 if (copy_from_user(&bind, uarg, sizeof(bind)))
236                         break;
237
238                 bind_interdomain.remote_dom  = bind.remote_domain;
239                 bind_interdomain.remote_port = bind.remote_port;
240                 rc = HYPERVISOR_event_channel_op(EVTCHNOP_bind_interdomain,
241                                                  &bind_interdomain);
242                 if (rc != 0)
243                         break;
244
245                 rc = bind_interdomain.local_port;
246                 evtchn_bind_to_user(u, rc);
247                 break;
248         }
249
250         case IOCTL_EVTCHN_BIND_UNBOUND_PORT: {
251                 struct ioctl_evtchn_bind_unbound_port bind;
252                 struct evtchn_alloc_unbound alloc_unbound;
253
254                 rc = -EFAULT;
255                 if (copy_from_user(&bind, uarg, sizeof(bind)))
256                         break;
257
258                 alloc_unbound.dom        = DOMID_SELF;
259                 alloc_unbound.remote_dom = bind.remote_domain;
260                 rc = HYPERVISOR_event_channel_op(EVTCHNOP_alloc_unbound,
261                                                  &alloc_unbound);
262                 if (rc != 0)
263                         break;
264
265                 rc = alloc_unbound.port;
266                 evtchn_bind_to_user(u, rc);
267                 break;
268         }
269
270         case IOCTL_EVTCHN_UNBIND: {
271                 struct ioctl_evtchn_unbind unbind;
272                 struct evtchn_close close;
273                 int ret;
274
275                 rc = -EFAULT;
276                 if (copy_from_user(&unbind, uarg, sizeof(unbind)))
277                         break;
278
279                 rc = -EINVAL;
280                 if (unbind.port >= NR_EVENT_CHANNELS)
281                         break;
282
283                 spin_lock_irq(&port_user_lock);
284     
285                 rc = -ENOTCONN;
286                 if (port_user[unbind.port] != u) {
287                         spin_unlock_irq(&port_user_lock);
288                         break;
289                 }
290
291                 port_user[unbind.port] = NULL;
292                 mask_evtchn(unbind.port);
293
294                 spin_unlock_irq(&port_user_lock);
295
296                 close.port = unbind.port;
297                 ret = HYPERVISOR_event_channel_op(EVTCHNOP_close, &close);
298                 BUG_ON(ret);
299
300                 rc = 0;
301                 break;
302         }
303
304         case IOCTL_EVTCHN_NOTIFY: {
305                 struct ioctl_evtchn_notify notify;
306
307                 rc = -EFAULT;
308                 if (copy_from_user(&notify, uarg, sizeof(notify)))
309                         break;
310
311                 if (notify.port >= NR_EVENT_CHANNELS) {
312                         rc = -EINVAL;
313                 } else if (port_user[notify.port] != u) {
314                         rc = -ENOTCONN;
315                 } else {
316                         notify_remote_via_evtchn(notify.port);
317                         rc = 0;
318                 }
319                 break;
320         }
321
322         case IOCTL_EVTCHN_RESET: {
323                 /* Initialise the ring to empty. Clear errors. */
324                 spin_lock_irq(&port_user_lock);
325                 u->ring_cons = u->ring_prod = u->ring_overflow = 0;
326                 spin_unlock_irq(&port_user_lock);
327                 rc = 0;
328                 break;
329         }
330
331         default:
332                 rc = -ENOSYS;
333                 break;
334         }
335
336         return rc;
337 }
338
339 static unsigned int evtchn_poll(struct file *file, poll_table *wait)
340 {
341         unsigned int mask = POLLOUT | POLLWRNORM;
342         struct per_user_data *u = file->private_data;
343
344         poll_wait(file, &u->evtchn_wait, wait);
345         if (u->ring_cons != u->ring_prod)
346                 mask |= POLLIN | POLLRDNORM;
347         if (u->ring_overflow)
348                 mask = POLLERR;
349         return mask;
350 }
351
352 static int evtchn_fasync(int fd, struct file *filp, int on)
353 {
354         struct per_user_data *u = filp->private_data;
355         return fasync_helper(fd, filp, on, &u->evtchn_async_queue);
356 }
357
358 static int evtchn_open(struct inode *inode, struct file *filp)
359 {
360         struct per_user_data *u;
361
362         if ((u = kmalloc(sizeof(*u), GFP_KERNEL)) == NULL)
363                 return -ENOMEM;
364
365         memset(u, 0, sizeof(*u));
366         init_waitqueue_head(&u->evtchn_wait);
367
368         u->ring = (evtchn_port_t *)__get_free_page(GFP_KERNEL);
369         if (u->ring == NULL) {
370                 kfree(u);
371                 return -ENOMEM;
372         }
373
374         filp->private_data = u;
375
376         return 0;
377 }
378
379 static int evtchn_release(struct inode *inode, struct file *filp)
380 {
381         int i;
382         struct per_user_data *u = filp->private_data;
383         struct evtchn_close close;
384
385         spin_lock_irq(&port_user_lock);
386
387         free_page((unsigned long)u->ring);
388
389         for (i = 0; i < NR_EVENT_CHANNELS; i++) {
390                 int ret;
391                 if (port_user[i] != u)
392                         continue;
393
394                 port_user[i] = NULL;
395                 mask_evtchn(i);
396
397                 close.port = i;
398                 ret = HYPERVISOR_event_channel_op(EVTCHNOP_close, &close);
399                 BUG_ON(ret);
400         }
401
402         spin_unlock_irq(&port_user_lock);
403
404         kfree(u);
405
406         return 0;
407 }
408
409 static struct file_operations evtchn_fops = {
410         .owner   = THIS_MODULE,
411         .read    = evtchn_read,
412         .write   = evtchn_write,
413         .ioctl   = evtchn_ioctl,
414         .poll    = evtchn_poll,
415         .fasync  = evtchn_fasync,
416         .open    = evtchn_open,
417         .release = evtchn_release,
418 };
419
420 static struct miscdevice evtchn_miscdev = {
421         .minor        = MISC_DYNAMIC_MINOR,
422         .name         = "evtchn",
423         .fops         = &evtchn_fops,
424 };
425
426 static int __init evtchn_init(void)
427 {
428         int err;
429
430         if (!is_running_on_xen())
431                 return -ENODEV;
432
433         spin_lock_init(&port_user_lock);
434         memset(port_user, 0, sizeof(port_user));
435
436         /* Create '/dev/misc/evtchn'. */
437         err = misc_register(&evtchn_miscdev);
438         if (err != 0) {
439                 printk(KERN_ALERT "Could not register /dev/misc/evtchn\n");
440                 return err;
441         }
442
443         printk("Event-channel device installed.\n");
444
445         return 0;
446 }
447
448 static void evtchn_cleanup(void)
449 {
450         misc_deregister(&evtchn_miscdev);
451 }
452
453 module_init(evtchn_init);
454 module_exit(evtchn_cleanup);
455
456 MODULE_LICENSE("Dual BSD/GPL");