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