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