xenbus_dev_backend.c revision e9f0fec3f5d406c500861da779d16a779a110055
1e9f0fec3f5d406c500861da779d16a779a110055Bastian Blank#include <linux/slab.h>
2e9f0fec3f5d406c500861da779d16a779a110055Bastian Blank#include <linux/types.h>
3e9f0fec3f5d406c500861da779d16a779a110055Bastian Blank#include <linux/mm.h>
4e9f0fec3f5d406c500861da779d16a779a110055Bastian Blank#include <linux/fs.h>
5e9f0fec3f5d406c500861da779d16a779a110055Bastian Blank#include <linux/miscdevice.h>
6e9f0fec3f5d406c500861da779d16a779a110055Bastian Blank#include <linux/module.h>
7e9f0fec3f5d406c500861da779d16a779a110055Bastian Blank#include <linux/capability.h>
8e9f0fec3f5d406c500861da779d16a779a110055Bastian Blank
9e9f0fec3f5d406c500861da779d16a779a110055Bastian Blank#include <xen/page.h>
10e9f0fec3f5d406c500861da779d16a779a110055Bastian Blank#include <xen/xenbus_dev.h>
11e9f0fec3f5d406c500861da779d16a779a110055Bastian Blank
12e9f0fec3f5d406c500861da779d16a779a110055Bastian Blank#include "xenbus_comms.h"
13e9f0fec3f5d406c500861da779d16a779a110055Bastian Blank
14e9f0fec3f5d406c500861da779d16a779a110055Bastian BlankMODULE_LICENSE("GPL");
15e9f0fec3f5d406c500861da779d16a779a110055Bastian Blank
16e9f0fec3f5d406c500861da779d16a779a110055Bastian Blankstatic int xenbus_backend_open(struct inode *inode, struct file *filp)
17e9f0fec3f5d406c500861da779d16a779a110055Bastian Blank{
18e9f0fec3f5d406c500861da779d16a779a110055Bastian Blank	if (!capable(CAP_SYS_ADMIN))
19e9f0fec3f5d406c500861da779d16a779a110055Bastian Blank		return -EPERM;
20e9f0fec3f5d406c500861da779d16a779a110055Bastian Blank
21e9f0fec3f5d406c500861da779d16a779a110055Bastian Blank	return nonseekable_open(inode, filp);
22e9f0fec3f5d406c500861da779d16a779a110055Bastian Blank}
23e9f0fec3f5d406c500861da779d16a779a110055Bastian Blank
24e9f0fec3f5d406c500861da779d16a779a110055Bastian Blankstatic long xenbus_backend_ioctl(struct file *file, unsigned int cmd, unsigned long data)
25e9f0fec3f5d406c500861da779d16a779a110055Bastian Blank{
26e9f0fec3f5d406c500861da779d16a779a110055Bastian Blank	if (!capable(CAP_SYS_ADMIN))
27e9f0fec3f5d406c500861da779d16a779a110055Bastian Blank		return -EPERM;
28e9f0fec3f5d406c500861da779d16a779a110055Bastian Blank
29e9f0fec3f5d406c500861da779d16a779a110055Bastian Blank	switch (cmd) {
30e9f0fec3f5d406c500861da779d16a779a110055Bastian Blank		case IOCTL_XENBUS_BACKEND_EVTCHN:
31e9f0fec3f5d406c500861da779d16a779a110055Bastian Blank			if (xen_store_evtchn > 0)
32e9f0fec3f5d406c500861da779d16a779a110055Bastian Blank				return xen_store_evtchn;
33e9f0fec3f5d406c500861da779d16a779a110055Bastian Blank			return -ENODEV;
34e9f0fec3f5d406c500861da779d16a779a110055Bastian Blank
35e9f0fec3f5d406c500861da779d16a779a110055Bastian Blank		default:
36e9f0fec3f5d406c500861da779d16a779a110055Bastian Blank			return -ENOTTY;
37e9f0fec3f5d406c500861da779d16a779a110055Bastian Blank	}
38e9f0fec3f5d406c500861da779d16a779a110055Bastian Blank}
39e9f0fec3f5d406c500861da779d16a779a110055Bastian Blank
40e9f0fec3f5d406c500861da779d16a779a110055Bastian Blankstatic int xenbus_backend_mmap(struct file *file, struct vm_area_struct *vma)
41e9f0fec3f5d406c500861da779d16a779a110055Bastian Blank{
42e9f0fec3f5d406c500861da779d16a779a110055Bastian Blank	size_t size = vma->vm_end - vma->vm_start;
43e9f0fec3f5d406c500861da779d16a779a110055Bastian Blank
44e9f0fec3f5d406c500861da779d16a779a110055Bastian Blank	if (!capable(CAP_SYS_ADMIN))
45e9f0fec3f5d406c500861da779d16a779a110055Bastian Blank		return -EPERM;
46e9f0fec3f5d406c500861da779d16a779a110055Bastian Blank
47e9f0fec3f5d406c500861da779d16a779a110055Bastian Blank	if ((size > PAGE_SIZE) || (vma->vm_pgoff != 0))
48e9f0fec3f5d406c500861da779d16a779a110055Bastian Blank		return -EINVAL;
49e9f0fec3f5d406c500861da779d16a779a110055Bastian Blank
50e9f0fec3f5d406c500861da779d16a779a110055Bastian Blank	if (remap_pfn_range(vma, vma->vm_start,
51e9f0fec3f5d406c500861da779d16a779a110055Bastian Blank			    virt_to_pfn(xen_store_interface),
52e9f0fec3f5d406c500861da779d16a779a110055Bastian Blank			    size, vma->vm_page_prot))
53e9f0fec3f5d406c500861da779d16a779a110055Bastian Blank		return -EAGAIN;
54e9f0fec3f5d406c500861da779d16a779a110055Bastian Blank
55e9f0fec3f5d406c500861da779d16a779a110055Bastian Blank	return 0;
56e9f0fec3f5d406c500861da779d16a779a110055Bastian Blank}
57e9f0fec3f5d406c500861da779d16a779a110055Bastian Blank
58e9f0fec3f5d406c500861da779d16a779a110055Bastian Blankconst struct file_operations xenbus_backend_fops = {
59e9f0fec3f5d406c500861da779d16a779a110055Bastian Blank	.open = xenbus_backend_open,
60e9f0fec3f5d406c500861da779d16a779a110055Bastian Blank	.mmap = xenbus_backend_mmap,
61e9f0fec3f5d406c500861da779d16a779a110055Bastian Blank	.unlocked_ioctl = xenbus_backend_ioctl,
62e9f0fec3f5d406c500861da779d16a779a110055Bastian Blank};
63e9f0fec3f5d406c500861da779d16a779a110055Bastian Blank
64e9f0fec3f5d406c500861da779d16a779a110055Bastian Blankstatic struct miscdevice xenbus_backend_dev = {
65e9f0fec3f5d406c500861da779d16a779a110055Bastian Blank	.minor = MISC_DYNAMIC_MINOR,
66e9f0fec3f5d406c500861da779d16a779a110055Bastian Blank	.name = "xen/xenbus_backend",
67e9f0fec3f5d406c500861da779d16a779a110055Bastian Blank	.fops = &xenbus_backend_fops,
68e9f0fec3f5d406c500861da779d16a779a110055Bastian Blank};
69e9f0fec3f5d406c500861da779d16a779a110055Bastian Blank
70e9f0fec3f5d406c500861da779d16a779a110055Bastian Blankstatic int __init xenbus_backend_init(void)
71e9f0fec3f5d406c500861da779d16a779a110055Bastian Blank{
72e9f0fec3f5d406c500861da779d16a779a110055Bastian Blank	int err;
73e9f0fec3f5d406c500861da779d16a779a110055Bastian Blank
74e9f0fec3f5d406c500861da779d16a779a110055Bastian Blank	if (!xen_initial_domain())
75e9f0fec3f5d406c500861da779d16a779a110055Bastian Blank		return -ENODEV;
76e9f0fec3f5d406c500861da779d16a779a110055Bastian Blank
77e9f0fec3f5d406c500861da779d16a779a110055Bastian Blank	err = misc_register(&xenbus_backend_dev);
78e9f0fec3f5d406c500861da779d16a779a110055Bastian Blank	if (err)
79e9f0fec3f5d406c500861da779d16a779a110055Bastian Blank		printk(KERN_ERR "Could not register xenbus backend device\n");
80e9f0fec3f5d406c500861da779d16a779a110055Bastian Blank	return err;
81e9f0fec3f5d406c500861da779d16a779a110055Bastian Blank}
82e9f0fec3f5d406c500861da779d16a779a110055Bastian Blank
83e9f0fec3f5d406c500861da779d16a779a110055Bastian Blankstatic void __exit xenbus_backend_exit(void)
84e9f0fec3f5d406c500861da779d16a779a110055Bastian Blank{
85e9f0fec3f5d406c500861da779d16a779a110055Bastian Blank	misc_deregister(&xenbus_backend_dev);
86e9f0fec3f5d406c500861da779d16a779a110055Bastian Blank}
87e9f0fec3f5d406c500861da779d16a779a110055Bastian Blank
88e9f0fec3f5d406c500861da779d16a779a110055Bastian Blankmodule_init(xenbus_backend_init);
89e9f0fec3f5d406c500861da779d16a779a110055Bastian Blankmodule_exit(xenbus_backend_exit);
90