1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* 28 * Client-facing interface for the Xenbus driver. In other words, the 29 * interface between the Xenbus and the device-specific code, be it the 30 * frontend or the backend of that driver. 31 * 32 * Copyright (C) 2005 XenSource Ltd 33 * 34 * This file may be distributed separately from the Linux kernel, or 35 * incorporated into other software packages, subject to the following license: 36 * 37 * Permission is hereby granted, free of charge, to any person obtaining a copy 38 * of this source file (the "Software"), to deal in the Software without 39 * restriction, including without limitation the rights to use, copy, modify, 40 * merge, publish, distribute, sublicense, and/or sell copies of the Software, 41 * and to permit persons to whom the Software is furnished to do so, subject to 42 * the following conditions: 43 * 44 * The above copyright notice and this permission notice shall be included in 45 * all copies or substantial portions of the Software. 46 * 47 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 48 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 49 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 50 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 51 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 52 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 53 * IN THE SOFTWARE. 54 */ 55 56 #ifdef XPV_HVM_DRIVER 57 #include <sys/xpv_support.h> 58 #include <sys/hypervisor.h> 59 #else 60 #include <sys/hypervisor.h> 61 #include <sys/xen_mmu.h> 62 #include <sys/evtchn_impl.h> 63 #endif 64 #include <sys/gnttab.h> 65 #include <xen/sys/xenbus_impl.h> 66 #include <sys/cmn_err.h> 67 68 69 int 70 xenbus_watch_path(struct xenbus_device *dev, const char *path, 71 struct xenbus_watch *watch, 72 void (*callback)(struct xenbus_watch *, 73 const char **, unsigned int)) 74 { 75 int err; 76 77 watch->node = path; 78 watch->callback = callback; 79 80 err = register_xenbus_watch(watch); 81 82 if (err) { 83 watch->node = NULL; 84 watch->callback = NULL; 85 xenbus_dev_fatal(dev, err, "adding watch on %s", path); 86 } 87 88 return (err); 89 } 90 91 92 int 93 xenbus_watch_path2(struct xenbus_device *dev, const char *path, 94 const char *path2, struct xenbus_watch *watch, 95 void (*callback)(struct xenbus_watch *, 96 const char **, unsigned int)) 97 { 98 int err; 99 char *state; 100 101 state = kmem_alloc(strlen(path) + 1 + strlen(path2) + 1, KM_SLEEP); 102 (void) strcpy(state, path); 103 (void) strcat(state, "/"); 104 (void) strcat(state, path2); 105 106 err = xenbus_watch_path(dev, state, watch, callback); 107 if (err) 108 kmem_free(state, strlen(state) + 1); 109 return (err); 110 } 111 112 /* 113 * Returns 0 on success, -1 if no change was made, or an errno on failure. We 114 * check whether the state is currently set to the given value, and if not, 115 * then the state is set. We don't want to unconditionally write the given 116 * state, because we don't want to fire watches unnecessarily. Furthermore, if 117 * the node has gone, we don't write to it, as the device will be tearing down, 118 * and we don't want to resurrect that directory. 119 * 120 * XXPV: not clear that this is still safe if two threads are racing to update 121 * the state? 122 */ 123 int 124 xenbus_switch_state(struct xenbus_device *dev, xenbus_transaction_t xbt, 125 XenbusState state) 126 { 127 int current_state; 128 int err; 129 130 err = xenbus_scanf(xbt, dev->nodename, "state", "%d", ¤t_state); 131 132 /* XXPV: is this really the right thing to do? */ 133 if (err == ENOENT) 134 return (0); 135 if (err) 136 return (err); 137 138 err = -1; 139 140 if ((XenbusState)current_state != state) { 141 err = xenbus_printf(xbt, dev->nodename, "state", "%d", state); 142 if (err) 143 xenbus_dev_fatal(dev, err, "writing new state"); 144 } 145 146 return (err); 147 } 148 149 150 /* 151 * Return the path to the error node for the given device, or NULL on failure. 152 * If the value returned is non-NULL, then it is the caller's to kmem_free. 153 */ 154 static char * 155 error_path(struct xenbus_device *dev) 156 { 157 char *path_buffer; 158 159 path_buffer = kmem_alloc(strlen("error/") + strlen(dev->nodename) + 160 1, KM_SLEEP); 161 162 (void) strcpy(path_buffer, "error/"); 163 (void) strcpy(path_buffer + strlen("error/"), dev->nodename); 164 165 return (path_buffer); 166 } 167 168 static void 169 common_dev_error(struct xenbus_device *dev, int err, const char *fmt, 170 va_list ap) 171 { 172 int ret; 173 unsigned int len; 174 char *printf_buffer = NULL, *path_buffer = NULL; 175 176 #define PRINTF_BUFFER_SIZE 4096 177 printf_buffer = kmem_alloc(PRINTF_BUFFER_SIZE, KM_SLEEP); 178 179 (void) snprintf(printf_buffer, PRINTF_BUFFER_SIZE, "%d ", err); 180 len = strlen(printf_buffer); 181 ret = vsnprintf(printf_buffer+len, PRINTF_BUFFER_SIZE-len, fmt, ap); 182 183 ASSERT(len + ret <= PRINTF_BUFFER_SIZE-1); 184 dev->has_error = 1; 185 186 path_buffer = error_path(dev); 187 188 if (path_buffer == NULL) { 189 printf("xenbus: failed to write error node for %s (%s)\n", 190 dev->nodename, printf_buffer); 191 goto fail; 192 } 193 194 if (xenbus_write(0, path_buffer, "error", printf_buffer) != 0) { 195 printf("xenbus: failed to write error node for %s (%s)\n", 196 dev->nodename, printf_buffer); 197 goto fail; 198 } 199 200 fail: 201 if (printf_buffer) 202 kmem_free(printf_buffer, PRINTF_BUFFER_SIZE); 203 if (path_buffer) 204 kmem_free(path_buffer, strlen(path_buffer) + 1); 205 } 206 207 208 void 209 xenbus_dev_error(struct xenbus_device *dev, int err, const char *fmt, ...) 210 { 211 va_list ap; 212 213 va_start(ap, fmt); 214 common_dev_error(dev, err, fmt, ap); 215 va_end(ap); 216 } 217 218 219 void 220 xenbus_dev_fatal(struct xenbus_device *dev, int err, const char *fmt, ...) 221 { 222 va_list ap; 223 224 va_start(ap, fmt); 225 common_dev_error(dev, err, fmt, ap); 226 va_end(ap); 227 228 (void) xenbus_switch_state(dev, XBT_NULL, XenbusStateClosing); 229 } 230 231 /* Clear any error. */ 232 void 233 xenbus_dev_ok(struct xenbus_device *dev) 234 { 235 if (dev->has_error) { 236 if (xenbus_rm(0, dev->nodename, "error") != 0) 237 printf("xenbus: failed to clear error node for %s\n", 238 dev->nodename); 239 else 240 dev->has_error = 0; 241 } 242 } 243 244 int 245 xenbus_grant_ring(struct xenbus_device *dev, unsigned long ring_mfn) 246 { 247 int err = gnttab_grant_foreign_access(dev->otherend_id, ring_mfn, 0); 248 if (err < 0) 249 xenbus_dev_fatal(dev, err, "granting access to ring page"); 250 return (err); 251 } 252 253 254 int 255 xenbus_alloc_evtchn(struct xenbus_device *dev, int *port) 256 { 257 int err; 258 259 err = xen_alloc_unbound_evtchn(dev->otherend_id, port); 260 if (err) 261 xenbus_dev_fatal(dev, err, "allocating event channel"); 262 return (err); 263 } 264 265 266 XenbusState 267 xenbus_read_driver_state(const char *path) 268 { 269 XenbusState result; 270 271 int err = xenbus_gather(XBT_NULL, path, "state", "%d", &result, NULL); 272 if (err) 273 result = XenbusStateClosed; 274 275 return (result); 276 } 277 278 279 /* 280 * Local variables: 281 * c-file-style: "solaris" 282 * indent-tabs-mode: t 283 * c-indent-level: 8 284 * c-basic-offset: 8 285 * tab-width: 8 286 * End: 287 */ 288