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/cdefs.h> 28 #include <sys/types.h> 29 #include <sys/cdefs.h> 30 #include <sys/errno.h> 31 #include <sys/uio.h> 32 #include <sys/param.h> 33 #include <sys/systm.h> 34 #include <sys/proc.h> 35 #include <sys/kernel.h> 36 #include <sys/malloc.h> 37 #include <sys/conf.h> 38 #include <sys/module.h> 39 40 #include <xen/xen-os.h> 41 42 #include <xen/hypervisor.h> 43 #include <xen/xenstore/xenstorevar.h> 44 45 #include <vm/vm.h> 46 #include <vm/pmap.h> 47 48 #define XSD_READ_SIZE 20 49 50 static int xsd_dev_read(struct cdev *dev, struct uio *uio, int ioflag); 51 static int xsd_dev_mmap(struct cdev *dev, vm_ooffset_t offset, 52 vm_paddr_t *paddr, int nprot, vm_memattr_t *memattr); 53 54 static struct cdevsw xsd_dev_cdevsw = { 55 .d_version = D_VERSION, 56 .d_read = xsd_dev_read, 57 .d_mmap = xsd_dev_mmap, 58 .d_name = "xsd_dev", 59 }; 60 61 static int 62 xsd_dev_read(struct cdev *dev, struct uio *uio, int ioflag) 63 { 64 char evtchn[XSD_READ_SIZE]; 65 int error, len; 66 67 len = snprintf(evtchn, sizeof(evtchn), "%u", xs_evtchn()); 68 if (len < 0 || len > uio->uio_resid) 69 return (EINVAL); 70 71 error = uiomove(evtchn, len, uio); 72 if (error) 73 return (error); 74 75 return (0); 76 } 77 78 static int 79 xsd_dev_mmap(struct cdev *dev, vm_ooffset_t offset, vm_paddr_t *paddr, 80 int nprot, vm_memattr_t *memattr) 81 { 82 83 if (offset != 0) 84 return (EINVAL); 85 86 *paddr = xs_address(); 87 88 return (0); 89 } 90 91 /*------------------ Private Device Attachment Functions --------------------*/ 92 /** 93 * \brief Identify instances of this device type in the system. 94 * 95 * \param driver The driver performing this identify action. 96 * \param parent The NewBus parent device for any devices this method adds. 97 */ 98 static void 99 xsd_dev_identify(driver_t *driver __unused, device_t parent) 100 { 101 102 if (!xen_domain() || xs_initialized()) 103 return; 104 105 /* 106 * Only attach if xenstore is not available, because we are the 107 * domain that's supposed to run it. 108 */ 109 BUS_ADD_CHILD(parent, 0, driver->name, 0); 110 } 111 112 /** 113 * \brief Probe for the existence of the Xenstored device 114 * 115 * \param dev NewBus device_t for this instance. 116 * 117 * \return Always returns 0 indicating success. 118 */ 119 static int 120 xsd_dev_probe(device_t dev) 121 { 122 123 device_set_desc(dev, "Xenstored user-space device"); 124 return (BUS_PROBE_NOWILDCARD); 125 } 126 127 /** 128 * \brief Attach the Xenstored device. 129 * 130 * \param dev NewBus device_t for this instance. 131 * 132 * \return On success, 0. Otherwise an errno value indicating the 133 * type of failure. 134 */ 135 static int 136 xsd_dev_attach(device_t dev) 137 { 138 struct cdev *xsd_cdev; 139 140 xsd_cdev = make_dev(&xsd_dev_cdevsw, 0, UID_ROOT, GID_WHEEL, 0400, 141 "xen/xenstored"); 142 if (xsd_cdev == NULL) 143 return (EINVAL); 144 145 return (0); 146 } 147 148 /*-------------------- Private Device Attachment Data -----------------------*/ 149 static device_method_t xsd_dev_methods[] = { 150 /* Device interface */ 151 DEVMETHOD(device_identify, xsd_dev_identify), 152 DEVMETHOD(device_probe, xsd_dev_probe), 153 DEVMETHOD(device_attach, xsd_dev_attach), 154 155 DEVMETHOD_END 156 }; 157 158 DEFINE_CLASS_0(xsd_dev, xsd_dev_driver, xsd_dev_methods, 0); 159 160 DRIVER_MODULE(xsd_dev, xenpv, xsd_dev_driver, NULL, NULL); 161