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