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