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
xenbus_watch_path(struct xenbus_device * dev,const char * path,struct xenbus_watch * watch,void (* callback)(struct xenbus_watch *,const char **,unsigned 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
xenbus_watch_path2(struct xenbus_device * dev,const char * path,const char * path2,struct xenbus_watch * watch,void (* callback)(struct xenbus_watch *,const char **,unsigned 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
xenbus_switch_state(struct xenbus_device * dev,xenbus_transaction_t xbt,XenbusState state)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 *
error_path(struct xenbus_device * dev)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
common_dev_error(struct xenbus_device * dev,int err,const char * fmt,va_list ap)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
xenbus_dev_error(struct xenbus_device * dev,int err,const char * fmt,...)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
xenbus_dev_fatal(struct xenbus_device * dev,int err,const char * fmt,...)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
xenbus_dev_ok(struct xenbus_device * dev)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
xenbus_grant_ring(struct xenbus_device * dev,unsigned long ring_mfn)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
xenbus_alloc_evtchn(struct xenbus_device * dev,int * port)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
xenbus_read_driver_state(const char * path)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