1#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 2 3#include <linux/slab.h> 4#include <linux/types.h> 5#include <linux/mm.h> 6#include <linux/fs.h> 7#include <linux/miscdevice.h> 8#include <linux/module.h> 9#include <linux/capability.h> 10 11#include <xen/xen.h> 12#include <xen/page.h> 13#include <xen/xenbus.h> 14#include <xen/xenbus_dev.h> 15#include <xen/grant_table.h> 16#include <xen/events.h> 17#include <asm/xen/hypervisor.h> 18 19#include "xenbus_comms.h" 20 21MODULE_LICENSE("GPL"); 22 23static int xenbus_backend_open(struct inode *inode, struct file *filp) 24{ 25 if (!capable(CAP_SYS_ADMIN)) 26 return -EPERM; 27 28 return nonseekable_open(inode, filp); 29} 30 31static long xenbus_alloc(domid_t domid) 32{ 33 struct evtchn_alloc_unbound arg; 34 int err = -EEXIST; 35 36 xs_suspend(); 37 38 /* If xenstored_ready is nonzero, that means we have already talked to 39 * xenstore and set up watches. These watches will be restored by 40 * xs_resume, but that requires communication over the port established 41 * below that is not visible to anyone until the ioctl returns. 42 * 43 * This can be resolved by splitting the ioctl into two parts 44 * (postponing the resume until xenstored is active) but this is 45 * unnecessarily complex for the intended use where xenstored is only 46 * started once - so return -EEXIST if it's already running. 47 */ 48 if (xenstored_ready) 49 goto out_err; 50 51 gnttab_grant_foreign_access_ref(GNTTAB_RESERVED_XENSTORE, domid, 52 virt_to_mfn(xen_store_interface), 0 /* writable */); 53 54 arg.dom = DOMID_SELF; 55 arg.remote_dom = domid; 56 57 err = HYPERVISOR_event_channel_op(EVTCHNOP_alloc_unbound, &arg); 58 if (err) 59 goto out_err; 60 61 if (xen_store_evtchn > 0) 62 xb_deinit_comms(); 63 64 xen_store_evtchn = arg.port; 65 66 xs_resume(); 67 68 return arg.port; 69 70 out_err: 71 xs_suspend_cancel(); 72 return err; 73} 74 75static long xenbus_backend_ioctl(struct file *file, unsigned int cmd, 76 unsigned long data) 77{ 78 if (!capable(CAP_SYS_ADMIN)) 79 return -EPERM; 80 81 switch (cmd) { 82 case IOCTL_XENBUS_BACKEND_EVTCHN: 83 if (xen_store_evtchn > 0) 84 return xen_store_evtchn; 85 return -ENODEV; 86 case IOCTL_XENBUS_BACKEND_SETUP: 87 return xenbus_alloc(data); 88 default: 89 return -ENOTTY; 90 } 91} 92 93static int xenbus_backend_mmap(struct file *file, struct vm_area_struct *vma) 94{ 95 size_t size = vma->vm_end - vma->vm_start; 96 97 if (!capable(CAP_SYS_ADMIN)) 98 return -EPERM; 99 100 if ((size > PAGE_SIZE) || (vma->vm_pgoff != 0)) 101 return -EINVAL; 102 103 if (remap_pfn_range(vma, vma->vm_start, 104 virt_to_pfn(xen_store_interface), 105 size, vma->vm_page_prot)) 106 return -EAGAIN; 107 108 return 0; 109} 110 111static const struct file_operations xenbus_backend_fops = { 112 .open = xenbus_backend_open, 113 .mmap = xenbus_backend_mmap, 114 .unlocked_ioctl = xenbus_backend_ioctl, 115}; 116 117static struct miscdevice xenbus_backend_dev = { 118 .minor = MISC_DYNAMIC_MINOR, 119 .name = "xen/xenbus_backend", 120 .fops = &xenbus_backend_fops, 121}; 122 123static int __init xenbus_backend_init(void) 124{ 125 int err; 126 127 if (!xen_initial_domain()) 128 return -ENODEV; 129 130 err = misc_register(&xenbus_backend_dev); 131 if (err) 132 pr_err("Could not register xenbus backend device\n"); 133 return err; 134} 135 136static void __exit xenbus_backend_exit(void) 137{ 138 misc_deregister(&xenbus_backend_dev); 139} 140 141module_init(xenbus_backend_init); 142module_exit(xenbus_backend_exit); 143