1 /* 2 * Copyright (c) 2014 Roger Pau Monné <roger.pau@citrix.com> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27 #include <sys/types.h> 28 #include <sys/cdefs.h> 29 #include <sys/errno.h> 30 #include <sys/uio.h> 31 #include <sys/param.h> 32 #include <sys/systm.h> 33 #include <sys/proc.h> 34 #include <sys/kernel.h> 35 #include <sys/malloc.h> 36 #include <sys/conf.h> 37 #include <sys/module.h> 38 39 #include <xen/xen-os.h> 40 41 #include <xen/hypervisor.h> 42 #include <xen/xenstore/xenstorevar.h> 43 44 #include <vm/vm.h> 45 #include <vm/pmap.h> 46 47 #define XSD_READ_SIZE 20 48 49 static int xsd_dev_read(struct cdev *dev, struct uio *uio, int ioflag); 50 static int xsd_dev_mmap(struct cdev *dev, vm_ooffset_t offset, 51 vm_paddr_t *paddr, int nprot, vm_memattr_t *memattr); 52 53 static struct cdevsw xsd_dev_cdevsw = { 54 .d_version = D_VERSION, 55 .d_read = xsd_dev_read, 56 .d_mmap = xsd_dev_mmap, 57 .d_name = "xsd_dev", 58 }; 59 60 static int 61 xsd_dev_read(struct cdev *dev, struct uio *uio, int ioflag) 62 { 63 char evtchn[XSD_READ_SIZE]; 64 int error, len; 65 66 len = snprintf(evtchn, sizeof(evtchn), "%u", xs_evtchn()); 67 if (len < 0 || len > uio->uio_resid) 68 return (EINVAL); 69 70 error = uiomove(evtchn, len, uio); 71 if (error) 72 return (error); 73 74 return (0); 75 } 76 77 static int 78 xsd_dev_mmap(struct cdev *dev, vm_ooffset_t offset, vm_paddr_t *paddr, 79 int nprot, vm_memattr_t *memattr) 80 { 81 82 if (offset != 0) 83 return (EINVAL); 84 85 *paddr = xs_address(); 86 87 return (0); 88 } 89 90 /*------------------ Private Device Attachment Functions --------------------*/ 91 /** 92 * \brief Identify instances of this device type in the system. 93 * 94 * \param driver The driver performing this identify action. 95 * \param parent The NewBus parent device for any devices this method adds. 96 */ 97 static void 98 xsd_dev_identify(driver_t *driver __unused, device_t parent) 99 { 100 101 if (!xen_domain() || xs_initialized()) 102 return; 103 104 /* 105 * Only attach if xenstore is not available, because we are the 106 * domain that's supposed to run it. 107 */ 108 BUS_ADD_CHILD(parent, 0, driver->name, 0); 109 } 110 111 /** 112 * \brief Probe for the existence of the Xenstored device 113 * 114 * \param dev NewBus device_t for this instance. 115 * 116 * \return Always returns 0 indicating success. 117 */ 118 static int 119 xsd_dev_probe(device_t dev) 120 { 121 122 device_set_desc(dev, "Xenstored user-space device"); 123 return (BUS_PROBE_NOWILDCARD); 124 } 125 126 /** 127 * \brief Attach the Xenstored device. 128 * 129 * \param dev NewBus device_t for this instance. 130 * 131 * \return On success, 0. Otherwise an errno value indicating the 132 * type of failure. 133 */ 134 static int 135 xsd_dev_attach(device_t dev) 136 { 137 struct cdev *xsd_cdev; 138 139 xsd_cdev = make_dev(&xsd_dev_cdevsw, 0, UID_ROOT, GID_WHEEL, 0400, 140 "xen/xenstored"); 141 if (xsd_cdev == NULL) 142 return (EINVAL); 143 144 return (0); 145 } 146 147 /*-------------------- Private Device Attachment Data -----------------------*/ 148 static device_method_t xsd_dev_methods[] = { 149 /* Device interface */ 150 DEVMETHOD(device_identify, xsd_dev_identify), 151 DEVMETHOD(device_probe, xsd_dev_probe), 152 DEVMETHOD(device_attach, xsd_dev_attach), 153 154 DEVMETHOD_END 155 }; 156 157 DEFINE_CLASS_0(xsd_dev, xsd_dev_driver, xsd_dev_methods, 0); 158 159 DRIVER_MODULE(xsd_dev, xenpv, xsd_dev_driver, NULL, NULL); 160