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 #pragma ident "%Z%%M% %I% %E% SMI" 57 58 #ifdef XPV_HVM_DRIVER 59 #include <sys/xpv_support.h> 60 #include <sys/hypervisor.h> 61 #else 62 #include <sys/hypervisor.h> 63 #include <sys/xen_mmu.h> 64 #include <sys/evtchn_impl.h> 65 #endif 66 #include <sys/gnttab.h> 67 #include <xen/sys/xenbus_impl.h> 68 #include <sys/cmn_err.h> 69 70 71 int 72 xenbus_watch_path(struct xenbus_device *dev, const char *path, 73 struct xenbus_watch *watch, 74 void (*callback)(struct xenbus_watch *, 75 const char **, unsigned int)) 76 { 77 int err; 78 79 watch->node = path; 80 watch->callback = callback; 81 82 err = register_xenbus_watch(watch); 83 84 if (err) { 85 watch->node = NULL; 86 watch->callback = NULL; 87 xenbus_dev_fatal(dev, err, "adding watch on %s", path); 88 } 89 90 return (err); 91 } 92 93 94 int 95 xenbus_watch_path2(struct xenbus_device *dev, const char *path, 96 const char *path2, struct xenbus_watch *watch, 97 void (*callback)(struct xenbus_watch *, 98 const char **, unsigned int)) 99 { 100 int err; 101 char *state; 102 103 state = kmem_alloc(strlen(path) + 1 + strlen(path2) + 1, KM_SLEEP); 104 (void) strcpy(state, path); 105 (void) strcat(state, "/"); 106 (void) strcat(state, path2); 107 108 err = xenbus_watch_path(dev, state, watch, callback); 109 if (err) 110 kmem_free(state, strlen(state) + 1); 111 return (err); 112 } 113 114 /* 115 * Returns 0 on success, -1 if no change was made, or an errno on failure. We 116 * check whether the state is currently set to the given value, and if not, 117 * then the state is set. We don't want to unconditionally write the given 118 * state, because we don't want to fire watches unnecessarily. Furthermore, if 119 * the node has gone, we don't write to it, as the device will be tearing down, 120 * and we don't want to resurrect that directory. 121 * 122 * XXPV: not clear that this is still safe if two threads are racing to update 123 * the state? 124 */ 125 int 126 xenbus_switch_state(struct xenbus_device *dev, xenbus_transaction_t xbt, 127 XenbusState state) 128 { 129 int current_state; 130 int err; 131 132 err = xenbus_scanf(xbt, dev->nodename, "state", "%d", ¤t_state); 133 134 /* XXPV: is this really the right thing to do? */ 135 if (err == ENOENT) 136 return (0); 137 if (err) 138 return (err); 139 140 err = -1; 141 142 if ((XenbusState)current_state != state) { 143 err = xenbus_printf(xbt, dev->nodename, "state", "%d", state); 144 if (err) 145 xenbus_dev_fatal(dev, err, "writing new state"); 146 } 147 148 return (err); 149 } 150 151 152 /* 153 * Return the path to the error node for the given device, or NULL on failure. 154 * If the value returned is non-NULL, then it is the caller's to kmem_free. 155 */ 156 static char * 157 error_path(struct xenbus_device *dev) 158 { 159 char *path_buffer; 160 161 path_buffer = kmem_alloc(strlen("error/") + strlen(dev->nodename) + 162 1, KM_SLEEP); 163 164 (void) strcpy(path_buffer, "error/"); 165 (void) strcpy(path_buffer + strlen("error/"), dev->nodename); 166 167 return (path_buffer); 168 } 169 170 static void 171 common_dev_error(struct xenbus_device *dev, int err, const char *fmt, 172 va_list ap) 173 { 174 int ret; 175 unsigned int len; 176 char *printf_buffer = NULL, *path_buffer = NULL; 177 178 #define PRINTF_BUFFER_SIZE 4096 179 printf_buffer = kmem_alloc(PRINTF_BUFFER_SIZE, KM_SLEEP); 180 181 (void) snprintf(printf_buffer, PRINTF_BUFFER_SIZE, "%d ", err); 182 len = strlen(printf_buffer); 183 ret = vsnprintf(printf_buffer+len, PRINTF_BUFFER_SIZE-len, fmt, ap); 184 185 ASSERT(len + ret <= PRINTF_BUFFER_SIZE-1); 186 dev->has_error = 1; 187 188 path_buffer = error_path(dev); 189 190 if (path_buffer == NULL) { 191 printf("xenbus: failed to write error node for %s (%s)\n", 192 dev->nodename, printf_buffer); 193 goto fail; 194 } 195 196 if (xenbus_write(NULL, path_buffer, "error", printf_buffer) != 0) { 197 printf("xenbus: failed to write error node for %s (%s)\n", 198 dev->nodename, printf_buffer); 199 goto fail; 200 } 201 202 fail: 203 if (printf_buffer) 204 kmem_free(printf_buffer, PRINTF_BUFFER_SIZE); 205 if (path_buffer) 206 kmem_free(path_buffer, strlen(path_buffer) + 1); 207 } 208 209 210 void 211 xenbus_dev_error(struct xenbus_device *dev, int err, const char *fmt, ...) 212 { 213 va_list ap; 214 215 va_start(ap, fmt); 216 common_dev_error(dev, err, fmt, ap); 217 va_end(ap); 218 } 219 220 221 void 222 xenbus_dev_fatal(struct xenbus_device *dev, int err, const char *fmt, ...) 223 { 224 va_list ap; 225 226 va_start(ap, fmt); 227 common_dev_error(dev, err, fmt, ap); 228 va_end(ap); 229 230 (void) xenbus_switch_state(dev, XBT_NULL, XenbusStateClosing); 231 } 232 233 /* Clear any error. */ 234 void 235 xenbus_dev_ok(struct xenbus_device *dev) 236 { 237 if (dev->has_error) { 238 if (xenbus_rm(NULL, dev->nodename, "error") != 0) 239 printf("xenbus: failed to clear error node for %s\n", 240 dev->nodename); 241 else 242 dev->has_error = 0; 243 } 244 } 245 246 int 247 xenbus_grant_ring(struct xenbus_device *dev, unsigned long ring_mfn) 248 { 249 int err = gnttab_grant_foreign_access(dev->otherend_id, ring_mfn, 0); 250 if (err < 0) 251 xenbus_dev_fatal(dev, err, "granting access to ring page"); 252 return (err); 253 } 254 255 256 int 257 xenbus_alloc_evtchn(struct xenbus_device *dev, int *port) 258 { 259 int err; 260 261 err = xen_alloc_unbound_evtchn(dev->otherend_id, port); 262 if (err) 263 xenbus_dev_fatal(dev, err, "allocating event channel"); 264 return (err); 265 } 266 267 268 XenbusState 269 xenbus_read_driver_state(const char *path) 270 { 271 XenbusState result; 272 273 int err = xenbus_gather(XBT_NULL, path, "state", "%d", &result, NULL); 274 if (err) 275 result = XenbusStateClosed; 276 277 return (result); 278 } 279 280 281 /* 282 * Local variables: 283 * c-file-style: "solaris" 284 * indent-tabs-mode: t 285 * c-indent-level: 8 286 * c-basic-offset: 8 287 * tab-width: 8 288 * End: 289 */ 290