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