Statistics
| Branch: | Revision:

root / hw / xen / xen_backend.c @ fd58922c

History | View | Annotate | Download (21.5 kB)

1 d94f9486 aliguori
/*
2 d94f9486 aliguori
 *  xen backend driver infrastructure
3 d94f9486 aliguori
 *  (c) 2008 Gerd Hoffmann <kraxel@redhat.com>
4 d94f9486 aliguori
 *
5 d94f9486 aliguori
 *  This program is free software; you can redistribute it and/or modify
6 d94f9486 aliguori
 *  it under the terms of the GNU General Public License as published by
7 d94f9486 aliguori
 *  the Free Software Foundation; under version 2 of the License.
8 d94f9486 aliguori
 *
9 d94f9486 aliguori
 *  This program is distributed in the hope that it will be useful,
10 d94f9486 aliguori
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11 d94f9486 aliguori
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 d94f9486 aliguori
 *  GNU General Public License for more details.
13 d94f9486 aliguori
 *
14 d94f9486 aliguori
 *  You should have received a copy of the GNU General Public License along
15 8167ee88 Blue Swirl
 *  with this program; if not, see <http://www.gnu.org/licenses/>.
16 6b620ca3 Paolo Bonzini
 *
17 6b620ca3 Paolo Bonzini
 *  Contributions after 2012-01-13 are licensed under the terms of the
18 6b620ca3 Paolo Bonzini
 *  GNU GPL, version 2 or (at your option) any later version.
19 d94f9486 aliguori
 */
20 d94f9486 aliguori
21 d94f9486 aliguori
/*
22 d94f9486 aliguori
 * TODO: add some xenbus / xenstore concepts overview here.
23 d94f9486 aliguori
 */
24 d94f9486 aliguori
25 d94f9486 aliguori
#include <stdio.h>
26 d94f9486 aliguori
#include <stdlib.h>
27 d94f9486 aliguori
#include <stdarg.h>
28 d94f9486 aliguori
#include <string.h>
29 d94f9486 aliguori
#include <unistd.h>
30 d94f9486 aliguori
#include <fcntl.h>
31 d94f9486 aliguori
#include <inttypes.h>
32 d94f9486 aliguori
#include <sys/types.h>
33 d94f9486 aliguori
#include <sys/stat.h>
34 d94f9486 aliguori
#include <sys/mman.h>
35 d94f9486 aliguori
#include <sys/signal.h>
36 d94f9486 aliguori
37 83c9f4ca Paolo Bonzini
#include "hw/hw.h"
38 dccfcd0e Paolo Bonzini
#include "sysemu/char.h"
39 1de7afc9 Paolo Bonzini
#include "qemu/log.h"
40 0d09e41a Paolo Bonzini
#include "hw/xen/xen_backend.h"
41 d94f9486 aliguori
42 b41f6719 Anthony PERARD
#include <xen/grant_table.h>
43 b41f6719 Anthony PERARD
44 d94f9486 aliguori
/* ------------------------------------------------------------- */
45 d94f9486 aliguori
46 d94f9486 aliguori
/* public */
47 d5b93ddf Anthony PERARD
XenXC xen_xc = XC_HANDLER_INITIAL_VALUE;
48 d5b93ddf Anthony PERARD
XenGnttab xen_xcg = XC_HANDLER_INITIAL_VALUE;
49 d94f9486 aliguori
struct xs_handle *xenstore = NULL;
50 2c8b24a3 aliguori
const char *xen_protocol;
51 d94f9486 aliguori
52 d94f9486 aliguori
/* private */
53 72cf2d4f Blue Swirl
static QTAILQ_HEAD(XenDeviceHead, XenDevice) xendevs = QTAILQ_HEAD_INITIALIZER(xendevs);
54 d94f9486 aliguori
static int debug = 0;
55 d94f9486 aliguori
56 d94f9486 aliguori
/* ------------------------------------------------------------- */
57 d94f9486 aliguori
58 d94f9486 aliguori
int xenstore_write_str(const char *base, const char *node, const char *val)
59 d94f9486 aliguori
{
60 d94f9486 aliguori
    char abspath[XEN_BUFSIZE];
61 d94f9486 aliguori
62 d94f9486 aliguori
    snprintf(abspath, sizeof(abspath), "%s/%s", base, node);
63 209cd7ab Anthony PERARD
    if (!xs_write(xenstore, 0, abspath, val, strlen(val))) {
64 209cd7ab Anthony PERARD
        return -1;
65 209cd7ab Anthony PERARD
    }
66 d94f9486 aliguori
    return 0;
67 d94f9486 aliguori
}
68 d94f9486 aliguori
69 d94f9486 aliguori
char *xenstore_read_str(const char *base, const char *node)
70 d94f9486 aliguori
{
71 d94f9486 aliguori
    char abspath[XEN_BUFSIZE];
72 d94f9486 aliguori
    unsigned int len;
73 d94f9486 aliguori
    char *str, *ret = NULL;
74 d94f9486 aliguori
75 d94f9486 aliguori
    snprintf(abspath, sizeof(abspath), "%s/%s", base, node);
76 d94f9486 aliguori
    str = xs_read(xenstore, 0, abspath, &len);
77 d94f9486 aliguori
    if (str != NULL) {
78 d94f9486 aliguori
        /* move to qemu-allocated memory to make sure
79 7267c094 Anthony Liguori
         * callers can savely g_free() stuff. */
80 7267c094 Anthony Liguori
        ret = g_strdup(str);
81 d94f9486 aliguori
        free(str);
82 d94f9486 aliguori
    }
83 d94f9486 aliguori
    return ret;
84 d94f9486 aliguori
}
85 d94f9486 aliguori
86 d94f9486 aliguori
int xenstore_write_int(const char *base, const char *node, int ival)
87 d94f9486 aliguori
{
88 10bb3c62 Felipe Franciosi
    char val[12];
89 d94f9486 aliguori
90 d94f9486 aliguori
    snprintf(val, sizeof(val), "%d", ival);
91 d94f9486 aliguori
    return xenstore_write_str(base, node, val);
92 d94f9486 aliguori
}
93 d94f9486 aliguori
94 10bb3c62 Felipe Franciosi
int xenstore_write_int64(const char *base, const char *node, int64_t ival)
95 10bb3c62 Felipe Franciosi
{
96 10bb3c62 Felipe Franciosi
    char val[21];
97 10bb3c62 Felipe Franciosi
98 10bb3c62 Felipe Franciosi
    snprintf(val, sizeof(val), "%"PRId64, ival);
99 10bb3c62 Felipe Franciosi
    return xenstore_write_str(base, node, val);
100 10bb3c62 Felipe Franciosi
}
101 10bb3c62 Felipe Franciosi
102 d94f9486 aliguori
int xenstore_read_int(const char *base, const char *node, int *ival)
103 d94f9486 aliguori
{
104 d94f9486 aliguori
    char *val;
105 d94f9486 aliguori
    int rc = -1;
106 d94f9486 aliguori
107 d94f9486 aliguori
    val = xenstore_read_str(base, node);
108 209cd7ab Anthony PERARD
    if (val && 1 == sscanf(val, "%d", ival)) {
109 209cd7ab Anthony PERARD
        rc = 0;
110 209cd7ab Anthony PERARD
    }
111 7267c094 Anthony Liguori
    g_free(val);
112 d94f9486 aliguori
    return rc;
113 d94f9486 aliguori
}
114 d94f9486 aliguori
115 d94f9486 aliguori
int xenstore_write_be_str(struct XenDevice *xendev, const char *node, const char *val)
116 d94f9486 aliguori
{
117 d94f9486 aliguori
    return xenstore_write_str(xendev->be, node, val);
118 d94f9486 aliguori
}
119 d94f9486 aliguori
120 d94f9486 aliguori
int xenstore_write_be_int(struct XenDevice *xendev, const char *node, int ival)
121 d94f9486 aliguori
{
122 d94f9486 aliguori
    return xenstore_write_int(xendev->be, node, ival);
123 d94f9486 aliguori
}
124 d94f9486 aliguori
125 10bb3c62 Felipe Franciosi
int xenstore_write_be_int64(struct XenDevice *xendev, const char *node, int64_t ival)
126 10bb3c62 Felipe Franciosi
{
127 10bb3c62 Felipe Franciosi
    return xenstore_write_int64(xendev->be, node, ival);
128 10bb3c62 Felipe Franciosi
}
129 10bb3c62 Felipe Franciosi
130 d94f9486 aliguori
char *xenstore_read_be_str(struct XenDevice *xendev, const char *node)
131 d94f9486 aliguori
{
132 d94f9486 aliguori
    return xenstore_read_str(xendev->be, node);
133 d94f9486 aliguori
}
134 d94f9486 aliguori
135 d94f9486 aliguori
int xenstore_read_be_int(struct XenDevice *xendev, const char *node, int *ival)
136 d94f9486 aliguori
{
137 d94f9486 aliguori
    return xenstore_read_int(xendev->be, node, ival);
138 d94f9486 aliguori
}
139 d94f9486 aliguori
140 d94f9486 aliguori
char *xenstore_read_fe_str(struct XenDevice *xendev, const char *node)
141 d94f9486 aliguori
{
142 d94f9486 aliguori
    return xenstore_read_str(xendev->fe, node);
143 d94f9486 aliguori
}
144 d94f9486 aliguori
145 d94f9486 aliguori
int xenstore_read_fe_int(struct XenDevice *xendev, const char *node, int *ival)
146 d94f9486 aliguori
{
147 d94f9486 aliguori
    return xenstore_read_int(xendev->fe, node, ival);
148 d94f9486 aliguori
}
149 d94f9486 aliguori
150 d94f9486 aliguori
/* ------------------------------------------------------------- */
151 d94f9486 aliguori
152 d94f9486 aliguori
const char *xenbus_strstate(enum xenbus_state state)
153 d94f9486 aliguori
{
154 209cd7ab Anthony PERARD
    static const char *const name[] = {
155 209cd7ab Anthony PERARD
        [ XenbusStateUnknown      ] = "Unknown",
156 209cd7ab Anthony PERARD
        [ XenbusStateInitialising ] = "Initialising",
157 209cd7ab Anthony PERARD
        [ XenbusStateInitWait     ] = "InitWait",
158 209cd7ab Anthony PERARD
        [ XenbusStateInitialised  ] = "Initialised",
159 209cd7ab Anthony PERARD
        [ XenbusStateConnected    ] = "Connected",
160 209cd7ab Anthony PERARD
        [ XenbusStateClosing      ] = "Closing",
161 209cd7ab Anthony PERARD
        [ XenbusStateClosed       ] = "Closed",
162 209cd7ab Anthony PERARD
    };
163 209cd7ab Anthony PERARD
    return (state < ARRAY_SIZE(name)) ? name[state] : "INVALID";
164 d94f9486 aliguori
}
165 d94f9486 aliguori
166 d94f9486 aliguori
int xen_be_set_state(struct XenDevice *xendev, enum xenbus_state state)
167 d94f9486 aliguori
{
168 d94f9486 aliguori
    int rc;
169 d94f9486 aliguori
170 d94f9486 aliguori
    rc = xenstore_write_be_int(xendev, "state", state);
171 209cd7ab Anthony PERARD
    if (rc < 0) {
172 209cd7ab Anthony PERARD
        return rc;
173 209cd7ab Anthony PERARD
    }
174 d94f9486 aliguori
    xen_be_printf(xendev, 1, "backend state: %s -> %s\n",
175 209cd7ab Anthony PERARD
                  xenbus_strstate(xendev->be_state), xenbus_strstate(state));
176 d94f9486 aliguori
    xendev->be_state = state;
177 d94f9486 aliguori
    return 0;
178 d94f9486 aliguori
}
179 d94f9486 aliguori
180 d94f9486 aliguori
/* ------------------------------------------------------------- */
181 d94f9486 aliguori
182 d94f9486 aliguori
struct XenDevice *xen_be_find_xendev(const char *type, int dom, int dev)
183 d94f9486 aliguori
{
184 d94f9486 aliguori
    struct XenDevice *xendev;
185 d94f9486 aliguori
186 72cf2d4f Blue Swirl
    QTAILQ_FOREACH(xendev, &xendevs, next) {
187 209cd7ab Anthony PERARD
        if (xendev->dom != dom) {
188 209cd7ab Anthony PERARD
            continue;
189 209cd7ab Anthony PERARD
        }
190 209cd7ab Anthony PERARD
        if (xendev->dev != dev) {
191 209cd7ab Anthony PERARD
            continue;
192 209cd7ab Anthony PERARD
        }
193 209cd7ab Anthony PERARD
        if (strcmp(xendev->type, type) != 0) {
194 209cd7ab Anthony PERARD
            continue;
195 209cd7ab Anthony PERARD
        }
196 209cd7ab Anthony PERARD
        return xendev;
197 d94f9486 aliguori
    }
198 d94f9486 aliguori
    return NULL;
199 d94f9486 aliguori
}
200 d94f9486 aliguori
201 d94f9486 aliguori
/*
202 d94f9486 aliguori
 * get xen backend device, allocate a new one if it doesn't exist.
203 d94f9486 aliguori
 */
204 d94f9486 aliguori
static struct XenDevice *xen_be_get_xendev(const char *type, int dom, int dev,
205 d94f9486 aliguori
                                           struct XenDevOps *ops)
206 d94f9486 aliguori
{
207 d94f9486 aliguori
    struct XenDevice *xendev;
208 d94f9486 aliguori
    char *dom0;
209 d94f9486 aliguori
210 d94f9486 aliguori
    xendev = xen_be_find_xendev(type, dom, dev);
211 209cd7ab Anthony PERARD
    if (xendev) {
212 209cd7ab Anthony PERARD
        return xendev;
213 209cd7ab Anthony PERARD
    }
214 d94f9486 aliguori
215 d94f9486 aliguori
    /* init new xendev */
216 7267c094 Anthony Liguori
    xendev = g_malloc0(ops->size);
217 d94f9486 aliguori
    xendev->type  = type;
218 d94f9486 aliguori
    xendev->dom   = dom;
219 d94f9486 aliguori
    xendev->dev   = dev;
220 d94f9486 aliguori
    xendev->ops   = ops;
221 d94f9486 aliguori
222 d94f9486 aliguori
    dom0 = xs_get_domain_path(xenstore, 0);
223 d94f9486 aliguori
    snprintf(xendev->be, sizeof(xendev->be), "%s/backend/%s/%d/%d",
224 209cd7ab Anthony PERARD
             dom0, xendev->type, xendev->dom, xendev->dev);
225 d94f9486 aliguori
    snprintf(xendev->name, sizeof(xendev->name), "%s-%d",
226 209cd7ab Anthony PERARD
             xendev->type, xendev->dev);
227 d94f9486 aliguori
    free(dom0);
228 d94f9486 aliguori
229 d94f9486 aliguori
    xendev->debug      = debug;
230 d94f9486 aliguori
    xendev->local_port = -1;
231 d94f9486 aliguori
232 d5b93ddf Anthony PERARD
    xendev->evtchndev = xen_xc_evtchn_open(NULL, 0);
233 d5b93ddf Anthony PERARD
    if (xendev->evtchndev == XC_HANDLER_INITIAL_VALUE) {
234 209cd7ab Anthony PERARD
        xen_be_printf(NULL, 0, "can't open evtchn device\n");
235 7267c094 Anthony Liguori
        g_free(xendev);
236 209cd7ab Anthony PERARD
        return NULL;
237 d94f9486 aliguori
    }
238 d94f9486 aliguori
    fcntl(xc_evtchn_fd(xendev->evtchndev), F_SETFD, FD_CLOEXEC);
239 d94f9486 aliguori
240 d94f9486 aliguori
    if (ops->flags & DEVOPS_FLAG_NEED_GNTDEV) {
241 d5b93ddf Anthony PERARD
        xendev->gnttabdev = xen_xc_gnttab_open(NULL, 0);
242 d5b93ddf Anthony PERARD
        if (xendev->gnttabdev == XC_HANDLER_INITIAL_VALUE) {
243 209cd7ab Anthony PERARD
            xen_be_printf(NULL, 0, "can't open gnttab device\n");
244 209cd7ab Anthony PERARD
            xc_evtchn_close(xendev->evtchndev);
245 7267c094 Anthony Liguori
            g_free(xendev);
246 209cd7ab Anthony PERARD
            return NULL;
247 209cd7ab Anthony PERARD
        }
248 d94f9486 aliguori
    } else {
249 d5b93ddf Anthony PERARD
        xendev->gnttabdev = XC_HANDLER_INITIAL_VALUE;
250 d94f9486 aliguori
    }
251 d94f9486 aliguori
252 72cf2d4f Blue Swirl
    QTAILQ_INSERT_TAIL(&xendevs, xendev, next);
253 d94f9486 aliguori
254 209cd7ab Anthony PERARD
    if (xendev->ops->alloc) {
255 209cd7ab Anthony PERARD
        xendev->ops->alloc(xendev);
256 209cd7ab Anthony PERARD
    }
257 d94f9486 aliguori
258 d94f9486 aliguori
    return xendev;
259 d94f9486 aliguori
}
260 d94f9486 aliguori
261 d94f9486 aliguori
/*
262 d94f9486 aliguori
 * release xen backend device.
263 d94f9486 aliguori
 */
264 d94f9486 aliguori
static struct XenDevice *xen_be_del_xendev(int dom, int dev)
265 d94f9486 aliguori
{
266 d94f9486 aliguori
    struct XenDevice *xendev, *xnext;
267 d94f9486 aliguori
268 d94f9486 aliguori
    /*
269 72cf2d4f Blue Swirl
     * This is pretty much like QTAILQ_FOREACH(xendev, &xendevs, next) but
270 d94f9486 aliguori
     * we save the next pointer in xnext because we might free xendev.
271 d94f9486 aliguori
     */
272 d94f9486 aliguori
    xnext = xendevs.tqh_first;
273 d94f9486 aliguori
    while (xnext) {
274 d94f9486 aliguori
        xendev = xnext;
275 d94f9486 aliguori
        xnext = xendev->next.tqe_next;
276 d94f9486 aliguori
277 209cd7ab Anthony PERARD
        if (xendev->dom != dom) {
278 209cd7ab Anthony PERARD
            continue;
279 209cd7ab Anthony PERARD
        }
280 209cd7ab Anthony PERARD
        if (xendev->dev != dev && dev != -1) {
281 209cd7ab Anthony PERARD
            continue;
282 209cd7ab Anthony PERARD
        }
283 209cd7ab Anthony PERARD
284 209cd7ab Anthony PERARD
        if (xendev->ops->free) {
285 209cd7ab Anthony PERARD
            xendev->ops->free(xendev);
286 209cd7ab Anthony PERARD
        }
287 209cd7ab Anthony PERARD
288 209cd7ab Anthony PERARD
        if (xendev->fe) {
289 209cd7ab Anthony PERARD
            char token[XEN_BUFSIZE];
290 209cd7ab Anthony PERARD
            snprintf(token, sizeof(token), "fe:%p", xendev);
291 209cd7ab Anthony PERARD
            xs_unwatch(xenstore, xendev->fe, token);
292 7267c094 Anthony Liguori
            g_free(xendev->fe);
293 209cd7ab Anthony PERARD
        }
294 209cd7ab Anthony PERARD
295 d5b93ddf Anthony PERARD
        if (xendev->evtchndev != XC_HANDLER_INITIAL_VALUE) {
296 209cd7ab Anthony PERARD
            xc_evtchn_close(xendev->evtchndev);
297 209cd7ab Anthony PERARD
        }
298 d5b93ddf Anthony PERARD
        if (xendev->gnttabdev != XC_HANDLER_INITIAL_VALUE) {
299 209cd7ab Anthony PERARD
            xc_gnttab_close(xendev->gnttabdev);
300 209cd7ab Anthony PERARD
        }
301 209cd7ab Anthony PERARD
302 209cd7ab Anthony PERARD
        QTAILQ_REMOVE(&xendevs, xendev, next);
303 7267c094 Anthony Liguori
        g_free(xendev);
304 d94f9486 aliguori
    }
305 d94f9486 aliguori
    return NULL;
306 d94f9486 aliguori
}
307 d94f9486 aliguori
308 d94f9486 aliguori
/*
309 d94f9486 aliguori
 * Sync internal data structures on xenstore updates.
310 d94f9486 aliguori
 * Node specifies the changed field.  node = NULL means
311 d94f9486 aliguori
 * update all fields (used for initialization).
312 d94f9486 aliguori
 */
313 d94f9486 aliguori
static void xen_be_backend_changed(struct XenDevice *xendev, const char *node)
314 d94f9486 aliguori
{
315 d94f9486 aliguori
    if (node == NULL  ||  strcmp(node, "online") == 0) {
316 209cd7ab Anthony PERARD
        if (xenstore_read_be_int(xendev, "online", &xendev->online) == -1) {
317 209cd7ab Anthony PERARD
            xendev->online = 0;
318 209cd7ab Anthony PERARD
        }
319 d94f9486 aliguori
    }
320 d94f9486 aliguori
321 d94f9486 aliguori
    if (node) {
322 209cd7ab Anthony PERARD
        xen_be_printf(xendev, 2, "backend update: %s\n", node);
323 209cd7ab Anthony PERARD
        if (xendev->ops->backend_changed) {
324 209cd7ab Anthony PERARD
            xendev->ops->backend_changed(xendev, node);
325 209cd7ab Anthony PERARD
        }
326 d94f9486 aliguori
    }
327 d94f9486 aliguori
}
328 d94f9486 aliguori
329 d94f9486 aliguori
static void xen_be_frontend_changed(struct XenDevice *xendev, const char *node)
330 d94f9486 aliguori
{
331 d94f9486 aliguori
    int fe_state;
332 d94f9486 aliguori
333 d94f9486 aliguori
    if (node == NULL  ||  strcmp(node, "state") == 0) {
334 209cd7ab Anthony PERARD
        if (xenstore_read_fe_int(xendev, "state", &fe_state) == -1) {
335 209cd7ab Anthony PERARD
            fe_state = XenbusStateUnknown;
336 209cd7ab Anthony PERARD
        }
337 209cd7ab Anthony PERARD
        if (xendev->fe_state != fe_state) {
338 209cd7ab Anthony PERARD
            xen_be_printf(xendev, 1, "frontend state: %s -> %s\n",
339 209cd7ab Anthony PERARD
                          xenbus_strstate(xendev->fe_state),
340 209cd7ab Anthony PERARD
                          xenbus_strstate(fe_state));
341 209cd7ab Anthony PERARD
        }
342 209cd7ab Anthony PERARD
        xendev->fe_state = fe_state;
343 d94f9486 aliguori
    }
344 d94f9486 aliguori
    if (node == NULL  ||  strcmp(node, "protocol") == 0) {
345 7267c094 Anthony Liguori
        g_free(xendev->protocol);
346 209cd7ab Anthony PERARD
        xendev->protocol = xenstore_read_fe_str(xendev, "protocol");
347 209cd7ab Anthony PERARD
        if (xendev->protocol) {
348 209cd7ab Anthony PERARD
            xen_be_printf(xendev, 1, "frontend protocol: %s\n", xendev->protocol);
349 209cd7ab Anthony PERARD
        }
350 d94f9486 aliguori
    }
351 d94f9486 aliguori
352 d94f9486 aliguori
    if (node) {
353 209cd7ab Anthony PERARD
        xen_be_printf(xendev, 2, "frontend update: %s\n", node);
354 209cd7ab Anthony PERARD
        if (xendev->ops->frontend_changed) {
355 209cd7ab Anthony PERARD
            xendev->ops->frontend_changed(xendev, node);
356 209cd7ab Anthony PERARD
        }
357 d94f9486 aliguori
    }
358 d94f9486 aliguori
}
359 d94f9486 aliguori
360 d94f9486 aliguori
/* ------------------------------------------------------------- */
361 d94f9486 aliguori
/* Check for possible state transitions and perform them.        */
362 d94f9486 aliguori
363 d94f9486 aliguori
/*
364 d94f9486 aliguori
 * Initial xendev setup.  Read frontend path, register watch for it.
365 d94f9486 aliguori
 * Should succeed once xend finished setting up the backend device.
366 d94f9486 aliguori
 *
367 d94f9486 aliguori
 * Also sets initial state (-> Initializing) when done.  Which
368 d94f9486 aliguori
 * only affects the xendev->be_state variable as xenbus should
369 d94f9486 aliguori
 * already be put into that state by xend.
370 d94f9486 aliguori
 */
371 d94f9486 aliguori
static int xen_be_try_setup(struct XenDevice *xendev)
372 d94f9486 aliguori
{
373 d94f9486 aliguori
    char token[XEN_BUFSIZE];
374 d94f9486 aliguori
    int be_state;
375 d94f9486 aliguori
376 d94f9486 aliguori
    if (xenstore_read_be_int(xendev, "state", &be_state) == -1) {
377 209cd7ab Anthony PERARD
        xen_be_printf(xendev, 0, "reading backend state failed\n");
378 209cd7ab Anthony PERARD
        return -1;
379 d94f9486 aliguori
    }
380 d94f9486 aliguori
381 d94f9486 aliguori
    if (be_state != XenbusStateInitialising) {
382 209cd7ab Anthony PERARD
        xen_be_printf(xendev, 0, "initial backend state is wrong (%s)\n",
383 209cd7ab Anthony PERARD
                      xenbus_strstate(be_state));
384 209cd7ab Anthony PERARD
        return -1;
385 d94f9486 aliguori
    }
386 d94f9486 aliguori
387 d94f9486 aliguori
    xendev->fe = xenstore_read_be_str(xendev, "frontend");
388 d94f9486 aliguori
    if (xendev->fe == NULL) {
389 209cd7ab Anthony PERARD
        xen_be_printf(xendev, 0, "reading frontend path failed\n");
390 209cd7ab Anthony PERARD
        return -1;
391 d94f9486 aliguori
    }
392 d94f9486 aliguori
393 d94f9486 aliguori
    /* setup frontend watch */
394 d94f9486 aliguori
    snprintf(token, sizeof(token), "fe:%p", xendev);
395 d94f9486 aliguori
    if (!xs_watch(xenstore, xendev->fe, token)) {
396 209cd7ab Anthony PERARD
        xen_be_printf(xendev, 0, "watching frontend path (%s) failed\n",
397 209cd7ab Anthony PERARD
                      xendev->fe);
398 209cd7ab Anthony PERARD
        return -1;
399 d94f9486 aliguori
    }
400 d94f9486 aliguori
    xen_be_set_state(xendev, XenbusStateInitialising);
401 d94f9486 aliguori
402 d94f9486 aliguori
    xen_be_backend_changed(xendev, NULL);
403 d94f9486 aliguori
    xen_be_frontend_changed(xendev, NULL);
404 d94f9486 aliguori
    return 0;
405 d94f9486 aliguori
}
406 d94f9486 aliguori
407 d94f9486 aliguori
/*
408 d94f9486 aliguori
 * Try initialize xendev.  Prepare everything the backend can do
409 d94f9486 aliguori
 * without synchronizing with the frontend.  Fakes hotplug-status.  No
410 d94f9486 aliguori
 * hotplug involved here because this is about userspace drivers, thus
411 d94f9486 aliguori
 * there are kernel backend devices which could invoke hotplug.
412 d94f9486 aliguori
 *
413 d94f9486 aliguori
 * Goes to InitWait on success.
414 d94f9486 aliguori
 */
415 d94f9486 aliguori
static int xen_be_try_init(struct XenDevice *xendev)
416 d94f9486 aliguori
{
417 d94f9486 aliguori
    int rc = 0;
418 d94f9486 aliguori
419 d94f9486 aliguori
    if (!xendev->online) {
420 209cd7ab Anthony PERARD
        xen_be_printf(xendev, 1, "not online\n");
421 209cd7ab Anthony PERARD
        return -1;
422 d94f9486 aliguori
    }
423 d94f9486 aliguori
424 209cd7ab Anthony PERARD
    if (xendev->ops->init) {
425 209cd7ab Anthony PERARD
        rc = xendev->ops->init(xendev);
426 209cd7ab Anthony PERARD
    }
427 d94f9486 aliguori
    if (rc != 0) {
428 209cd7ab Anthony PERARD
        xen_be_printf(xendev, 1, "init() failed\n");
429 209cd7ab Anthony PERARD
        return rc;
430 d94f9486 aliguori
    }
431 d94f9486 aliguori
432 d94f9486 aliguori
    xenstore_write_be_str(xendev, "hotplug-status", "connected");
433 d94f9486 aliguori
    xen_be_set_state(xendev, XenbusStateInitWait);
434 d94f9486 aliguori
    return 0;
435 d94f9486 aliguori
}
436 d94f9486 aliguori
437 d94f9486 aliguori
/*
438 384087b2 John Haxby
 * Try to initialise xendev.  Depends on the frontend being ready
439 d94f9486 aliguori
 * for it (shared ring and evtchn info in xenstore, state being
440 d94f9486 aliguori
 * Initialised or Connected).
441 d94f9486 aliguori
 *
442 d94f9486 aliguori
 * Goes to Connected on success.
443 d94f9486 aliguori
 */
444 384087b2 John Haxby
static int xen_be_try_initialise(struct XenDevice *xendev)
445 d94f9486 aliguori
{
446 d94f9486 aliguori
    int rc = 0;
447 d94f9486 aliguori
448 d94f9486 aliguori
    if (xendev->fe_state != XenbusStateInitialised  &&
449 209cd7ab Anthony PERARD
        xendev->fe_state != XenbusStateConnected) {
450 209cd7ab Anthony PERARD
        if (xendev->ops->flags & DEVOPS_FLAG_IGNORE_STATE) {
451 209cd7ab Anthony PERARD
            xen_be_printf(xendev, 2, "frontend not ready, ignoring\n");
452 209cd7ab Anthony PERARD
        } else {
453 209cd7ab Anthony PERARD
            xen_be_printf(xendev, 2, "frontend not ready (yet)\n");
454 209cd7ab Anthony PERARD
            return -1;
455 209cd7ab Anthony PERARD
        }
456 d94f9486 aliguori
    }
457 d94f9486 aliguori
458 384087b2 John Haxby
    if (xendev->ops->initialise) {
459 384087b2 John Haxby
        rc = xendev->ops->initialise(xendev);
460 209cd7ab Anthony PERARD
    }
461 d94f9486 aliguori
    if (rc != 0) {
462 384087b2 John Haxby
        xen_be_printf(xendev, 0, "initialise() failed\n");
463 209cd7ab Anthony PERARD
        return rc;
464 d94f9486 aliguori
    }
465 d94f9486 aliguori
466 d94f9486 aliguori
    xen_be_set_state(xendev, XenbusStateConnected);
467 d94f9486 aliguori
    return 0;
468 d94f9486 aliguori
}
469 d94f9486 aliguori
470 d94f9486 aliguori
/*
471 384087b2 John Haxby
 * Try to let xendev know that it is connected.  Depends on the
472 384087b2 John Haxby
 * frontend being Connected.  Note that this may be called more
473 384087b2 John Haxby
 * than once since the backend state is not modified.
474 384087b2 John Haxby
 */
475 384087b2 John Haxby
static void xen_be_try_connected(struct XenDevice *xendev)
476 384087b2 John Haxby
{
477 384087b2 John Haxby
    if (!xendev->ops->connected) {
478 384087b2 John Haxby
        return;
479 384087b2 John Haxby
    }
480 384087b2 John Haxby
481 384087b2 John Haxby
    if (xendev->fe_state != XenbusStateConnected) {
482 384087b2 John Haxby
        if (xendev->ops->flags & DEVOPS_FLAG_IGNORE_STATE) {
483 384087b2 John Haxby
            xen_be_printf(xendev, 2, "frontend not ready, ignoring\n");
484 384087b2 John Haxby
        } else {
485 384087b2 John Haxby
            xen_be_printf(xendev, 2, "frontend not ready (yet)\n");
486 384087b2 John Haxby
            return;
487 384087b2 John Haxby
        }
488 384087b2 John Haxby
    }
489 384087b2 John Haxby
490 384087b2 John Haxby
    xendev->ops->connected(xendev);
491 384087b2 John Haxby
}
492 384087b2 John Haxby
493 384087b2 John Haxby
/*
494 d94f9486 aliguori
 * Teardown connection.
495 d94f9486 aliguori
 *
496 d94f9486 aliguori
 * Goes to Closed when done.
497 d94f9486 aliguori
 */
498 d94f9486 aliguori
static void xen_be_disconnect(struct XenDevice *xendev, enum xenbus_state state)
499 d94f9486 aliguori
{
500 d94f9486 aliguori
    if (xendev->be_state != XenbusStateClosing &&
501 d94f9486 aliguori
        xendev->be_state != XenbusStateClosed  &&
502 209cd7ab Anthony PERARD
        xendev->ops->disconnect) {
503 209cd7ab Anthony PERARD
        xendev->ops->disconnect(xendev);
504 209cd7ab Anthony PERARD
    }
505 209cd7ab Anthony PERARD
    if (xendev->be_state != state) {
506 d94f9486 aliguori
        xen_be_set_state(xendev, state);
507 209cd7ab Anthony PERARD
    }
508 d94f9486 aliguori
}
509 d94f9486 aliguori
510 d94f9486 aliguori
/*
511 d94f9486 aliguori
 * Try to reset xendev, for reconnection by another frontend instance.
512 d94f9486 aliguori
 */
513 d94f9486 aliguori
static int xen_be_try_reset(struct XenDevice *xendev)
514 d94f9486 aliguori
{
515 209cd7ab Anthony PERARD
    if (xendev->fe_state != XenbusStateInitialising) {
516 d94f9486 aliguori
        return -1;
517 209cd7ab Anthony PERARD
    }
518 d94f9486 aliguori
519 d94f9486 aliguori
    xen_be_printf(xendev, 1, "device reset (for re-connect)\n");
520 d94f9486 aliguori
    xen_be_set_state(xendev, XenbusStateInitialising);
521 d94f9486 aliguori
    return 0;
522 d94f9486 aliguori
}
523 d94f9486 aliguori
524 d94f9486 aliguori
/*
525 d94f9486 aliguori
 * state change dispatcher function
526 d94f9486 aliguori
 */
527 d94f9486 aliguori
void xen_be_check_state(struct XenDevice *xendev)
528 d94f9486 aliguori
{
529 d94f9486 aliguori
    int rc = 0;
530 d94f9486 aliguori
531 d94f9486 aliguori
    /* frontend may request shutdown from almost anywhere */
532 d94f9486 aliguori
    if (xendev->fe_state == XenbusStateClosing ||
533 209cd7ab Anthony PERARD
        xendev->fe_state == XenbusStateClosed) {
534 209cd7ab Anthony PERARD
        xen_be_disconnect(xendev, xendev->fe_state);
535 209cd7ab Anthony PERARD
        return;
536 d94f9486 aliguori
    }
537 d94f9486 aliguori
538 d94f9486 aliguori
    /* check for possible backend state transitions */
539 d94f9486 aliguori
    for (;;) {
540 209cd7ab Anthony PERARD
        switch (xendev->be_state) {
541 209cd7ab Anthony PERARD
        case XenbusStateUnknown:
542 209cd7ab Anthony PERARD
            rc = xen_be_try_setup(xendev);
543 209cd7ab Anthony PERARD
            break;
544 209cd7ab Anthony PERARD
        case XenbusStateInitialising:
545 209cd7ab Anthony PERARD
            rc = xen_be_try_init(xendev);
546 209cd7ab Anthony PERARD
            break;
547 209cd7ab Anthony PERARD
        case XenbusStateInitWait:
548 384087b2 John Haxby
            rc = xen_be_try_initialise(xendev);
549 384087b2 John Haxby
            break;
550 384087b2 John Haxby
        case XenbusStateConnected:
551 384087b2 John Haxby
            /* xendev->be_state doesn't change */
552 384087b2 John Haxby
            xen_be_try_connected(xendev);
553 384087b2 John Haxby
            rc = -1;
554 209cd7ab Anthony PERARD
            break;
555 d94f9486 aliguori
        case XenbusStateClosed:
556 d94f9486 aliguori
            rc = xen_be_try_reset(xendev);
557 d94f9486 aliguori
            break;
558 209cd7ab Anthony PERARD
        default:
559 209cd7ab Anthony PERARD
            rc = -1;
560 209cd7ab Anthony PERARD
        }
561 209cd7ab Anthony PERARD
        if (rc != 0) {
562 209cd7ab Anthony PERARD
            break;
563 209cd7ab Anthony PERARD
        }
564 d94f9486 aliguori
    }
565 d94f9486 aliguori
}
566 d94f9486 aliguori
567 d94f9486 aliguori
/* ------------------------------------------------------------- */
568 d94f9486 aliguori
569 d94f9486 aliguori
static int xenstore_scan(const char *type, int dom, struct XenDevOps *ops)
570 d94f9486 aliguori
{
571 d94f9486 aliguori
    struct XenDevice *xendev;
572 d94f9486 aliguori
    char path[XEN_BUFSIZE], token[XEN_BUFSIZE];
573 d94f9486 aliguori
    char **dev = NULL, *dom0;
574 d94f9486 aliguori
    unsigned int cdev, j;
575 d94f9486 aliguori
576 d94f9486 aliguori
    /* setup watch */
577 d94f9486 aliguori
    dom0 = xs_get_domain_path(xenstore, 0);
578 d94f9486 aliguori
    snprintf(token, sizeof(token), "be:%p:%d:%p", type, dom, ops);
579 d94f9486 aliguori
    snprintf(path, sizeof(path), "%s/backend/%s/%d", dom0, type, dom);
580 d94f9486 aliguori
    free(dom0);
581 d94f9486 aliguori
    if (!xs_watch(xenstore, path, token)) {
582 209cd7ab Anthony PERARD
        xen_be_printf(NULL, 0, "xen be: watching backend path (%s) failed\n", path);
583 209cd7ab Anthony PERARD
        return -1;
584 d94f9486 aliguori
    }
585 d94f9486 aliguori
586 d94f9486 aliguori
    /* look for backends */
587 d94f9486 aliguori
    dev = xs_directory(xenstore, 0, path, &cdev);
588 209cd7ab Anthony PERARD
    if (!dev) {
589 209cd7ab Anthony PERARD
        return 0;
590 209cd7ab Anthony PERARD
    }
591 d94f9486 aliguori
    for (j = 0; j < cdev; j++) {
592 209cd7ab Anthony PERARD
        xendev = xen_be_get_xendev(type, dom, atoi(dev[j]), ops);
593 209cd7ab Anthony PERARD
        if (xendev == NULL) {
594 209cd7ab Anthony PERARD
            continue;
595 209cd7ab Anthony PERARD
        }
596 209cd7ab Anthony PERARD
        xen_be_check_state(xendev);
597 d94f9486 aliguori
    }
598 d94f9486 aliguori
    free(dev);
599 d94f9486 aliguori
    return 0;
600 d94f9486 aliguori
}
601 d94f9486 aliguori
602 d94f9486 aliguori
static void xenstore_update_be(char *watch, char *type, int dom,
603 209cd7ab Anthony PERARD
                               struct XenDevOps *ops)
604 d94f9486 aliguori
{
605 d94f9486 aliguori
    struct XenDevice *xendev;
606 77ba8fef Stefano Stabellini
    char path[XEN_BUFSIZE], *dom0, *bepath;
607 d94f9486 aliguori
    unsigned int len, dev;
608 d94f9486 aliguori
609 d94f9486 aliguori
    dom0 = xs_get_domain_path(xenstore, 0);
610 d94f9486 aliguori
    len = snprintf(path, sizeof(path), "%s/backend/%s/%d", dom0, type, dom);
611 d94f9486 aliguori
    free(dom0);
612 209cd7ab Anthony PERARD
    if (strncmp(path, watch, len) != 0) {
613 209cd7ab Anthony PERARD
        return;
614 209cd7ab Anthony PERARD
    }
615 d94f9486 aliguori
    if (sscanf(watch+len, "/%u/%255s", &dev, path) != 2) {
616 209cd7ab Anthony PERARD
        strcpy(path, "");
617 209cd7ab Anthony PERARD
        if (sscanf(watch+len, "/%u", &dev) != 1) {
618 209cd7ab Anthony PERARD
            dev = -1;
619 209cd7ab Anthony PERARD
        }
620 209cd7ab Anthony PERARD
    }
621 209cd7ab Anthony PERARD
    if (dev == -1) {
622 209cd7ab Anthony PERARD
        return;
623 d94f9486 aliguori
    }
624 d94f9486 aliguori
625 d94f9486 aliguori
    xendev = xen_be_get_xendev(type, dom, dev, ops);
626 d94f9486 aliguori
    if (xendev != NULL) {
627 77ba8fef Stefano Stabellini
        bepath = xs_read(xenstore, 0, xendev->be, &len);
628 77ba8fef Stefano Stabellini
        if (bepath == NULL) {
629 77ba8fef Stefano Stabellini
            xen_be_del_xendev(dom, dev);
630 77ba8fef Stefano Stabellini
        } else {
631 77ba8fef Stefano Stabellini
            free(bepath);
632 77ba8fef Stefano Stabellini
            xen_be_backend_changed(xendev, path);
633 77ba8fef Stefano Stabellini
            xen_be_check_state(xendev);
634 77ba8fef Stefano Stabellini
        }
635 d94f9486 aliguori
    }
636 d94f9486 aliguori
}
637 d94f9486 aliguori
638 d94f9486 aliguori
static void xenstore_update_fe(char *watch, struct XenDevice *xendev)
639 d94f9486 aliguori
{
640 d94f9486 aliguori
    char *node;
641 d94f9486 aliguori
    unsigned int len;
642 d94f9486 aliguori
643 d94f9486 aliguori
    len = strlen(xendev->fe);
644 209cd7ab Anthony PERARD
    if (strncmp(xendev->fe, watch, len) != 0) {
645 209cd7ab Anthony PERARD
        return;
646 209cd7ab Anthony PERARD
    }
647 209cd7ab Anthony PERARD
    if (watch[len] != '/') {
648 209cd7ab Anthony PERARD
        return;
649 209cd7ab Anthony PERARD
    }
650 d94f9486 aliguori
    node = watch + len + 1;
651 d94f9486 aliguori
652 d94f9486 aliguori
    xen_be_frontend_changed(xendev, node);
653 d94f9486 aliguori
    xen_be_check_state(xendev);
654 d94f9486 aliguori
}
655 d94f9486 aliguori
656 d94f9486 aliguori
static void xenstore_update(void *unused)
657 d94f9486 aliguori
{
658 d94f9486 aliguori
    char **vec = NULL;
659 d94f9486 aliguori
    intptr_t type, ops, ptr;
660 d94f9486 aliguori
    unsigned int dom, count;
661 d94f9486 aliguori
662 d94f9486 aliguori
    vec = xs_read_watch(xenstore, &count);
663 209cd7ab Anthony PERARD
    if (vec == NULL) {
664 209cd7ab Anthony PERARD
        goto cleanup;
665 209cd7ab Anthony PERARD
    }
666 d94f9486 aliguori
667 d94f9486 aliguori
    if (sscanf(vec[XS_WATCH_TOKEN], "be:%" PRIxPTR ":%d:%" PRIxPTR,
668 209cd7ab Anthony PERARD
               &type, &dom, &ops) == 3) {
669 209cd7ab Anthony PERARD
        xenstore_update_be(vec[XS_WATCH_PATH], (void*)type, dom, (void*)ops);
670 209cd7ab Anthony PERARD
    }
671 209cd7ab Anthony PERARD
    if (sscanf(vec[XS_WATCH_TOKEN], "fe:%" PRIxPTR, &ptr) == 1) {
672 209cd7ab Anthony PERARD
        xenstore_update_fe(vec[XS_WATCH_PATH], (void*)ptr);
673 209cd7ab Anthony PERARD
    }
674 d94f9486 aliguori
675 d94f9486 aliguori
cleanup:
676 834fac78 Jean-Christophe DUBOIS
    free(vec);
677 d94f9486 aliguori
}
678 d94f9486 aliguori
679 d94f9486 aliguori
static void xen_be_evtchn_event(void *opaque)
680 d94f9486 aliguori
{
681 d94f9486 aliguori
    struct XenDevice *xendev = opaque;
682 d94f9486 aliguori
    evtchn_port_t port;
683 d94f9486 aliguori
684 d94f9486 aliguori
    port = xc_evtchn_pending(xendev->evtchndev);
685 d94f9486 aliguori
    if (port != xendev->local_port) {
686 209cd7ab Anthony PERARD
        xen_be_printf(xendev, 0, "xc_evtchn_pending returned %d (expected %d)\n",
687 209cd7ab Anthony PERARD
                      port, xendev->local_port);
688 209cd7ab Anthony PERARD
        return;
689 d94f9486 aliguori
    }
690 d94f9486 aliguori
    xc_evtchn_unmask(xendev->evtchndev, port);
691 d94f9486 aliguori
692 209cd7ab Anthony PERARD
    if (xendev->ops->event) {
693 209cd7ab Anthony PERARD
        xendev->ops->event(xendev);
694 209cd7ab Anthony PERARD
    }
695 d94f9486 aliguori
}
696 d94f9486 aliguori
697 d94f9486 aliguori
/* -------------------------------------------------------------------- */
698 d94f9486 aliguori
699 d94f9486 aliguori
int xen_be_init(void)
700 d94f9486 aliguori
{
701 d94f9486 aliguori
    xenstore = xs_daemon_open();
702 d94f9486 aliguori
    if (!xenstore) {
703 209cd7ab Anthony PERARD
        xen_be_printf(NULL, 0, "can't connect to xenstored\n");
704 209cd7ab Anthony PERARD
        return -1;
705 d94f9486 aliguori
    }
706 d94f9486 aliguori
707 209cd7ab Anthony PERARD
    if (qemu_set_fd_handler(xs_fileno(xenstore), xenstore_update, NULL, NULL) < 0) {
708 209cd7ab Anthony PERARD
        goto err;
709 209cd7ab Anthony PERARD
    }
710 d94f9486 aliguori
711 d5b93ddf Anthony PERARD
    if (xen_xc == XC_HANDLER_INITIAL_VALUE) {
712 3285cf4f Anthony PERARD
        /* Check if xen_init() have been called */
713 209cd7ab Anthony PERARD
        goto err;
714 d94f9486 aliguori
    }
715 d94f9486 aliguori
    return 0;
716 d94f9486 aliguori
717 d94f9486 aliguori
err:
718 d94f9486 aliguori
    qemu_set_fd_handler(xs_fileno(xenstore), NULL, NULL, NULL);
719 d94f9486 aliguori
    xs_daemon_close(xenstore);
720 d94f9486 aliguori
    xenstore = NULL;
721 d94f9486 aliguori
722 d94f9486 aliguori
    return -1;
723 d94f9486 aliguori
}
724 d94f9486 aliguori
725 d94f9486 aliguori
int xen_be_register(const char *type, struct XenDevOps *ops)
726 d94f9486 aliguori
{
727 d94f9486 aliguori
    return xenstore_scan(type, xen_domid, ops);
728 d94f9486 aliguori
}
729 d94f9486 aliguori
730 d94f9486 aliguori
int xen_be_bind_evtchn(struct XenDevice *xendev)
731 d94f9486 aliguori
{
732 209cd7ab Anthony PERARD
    if (xendev->local_port != -1) {
733 209cd7ab Anthony PERARD
        return 0;
734 209cd7ab Anthony PERARD
    }
735 d94f9486 aliguori
    xendev->local_port = xc_evtchn_bind_interdomain
736 209cd7ab Anthony PERARD
        (xendev->evtchndev, xendev->dom, xendev->remote_port);
737 d94f9486 aliguori
    if (xendev->local_port == -1) {
738 209cd7ab Anthony PERARD
        xen_be_printf(xendev, 0, "xc_evtchn_bind_interdomain failed\n");
739 209cd7ab Anthony PERARD
        return -1;
740 d94f9486 aliguori
    }
741 d94f9486 aliguori
    xen_be_printf(xendev, 2, "bind evtchn port %d\n", xendev->local_port);
742 d94f9486 aliguori
    qemu_set_fd_handler(xc_evtchn_fd(xendev->evtchndev),
743 209cd7ab Anthony PERARD
                        xen_be_evtchn_event, NULL, xendev);
744 d94f9486 aliguori
    return 0;
745 d94f9486 aliguori
}
746 d94f9486 aliguori
747 d94f9486 aliguori
void xen_be_unbind_evtchn(struct XenDevice *xendev)
748 d94f9486 aliguori
{
749 209cd7ab Anthony PERARD
    if (xendev->local_port == -1) {
750 209cd7ab Anthony PERARD
        return;
751 209cd7ab Anthony PERARD
    }
752 d94f9486 aliguori
    qemu_set_fd_handler(xc_evtchn_fd(xendev->evtchndev), NULL, NULL, NULL);
753 d94f9486 aliguori
    xc_evtchn_unbind(xendev->evtchndev, xendev->local_port);
754 d94f9486 aliguori
    xen_be_printf(xendev, 2, "unbind evtchn port %d\n", xendev->local_port);
755 d94f9486 aliguori
    xendev->local_port = -1;
756 d94f9486 aliguori
}
757 d94f9486 aliguori
758 d94f9486 aliguori
int xen_be_send_notify(struct XenDevice *xendev)
759 d94f9486 aliguori
{
760 d94f9486 aliguori
    return xc_evtchn_notify(xendev->evtchndev, xendev->local_port);
761 d94f9486 aliguori
}
762 d94f9486 aliguori
763 d94f9486 aliguori
/*
764 d94f9486 aliguori
 * msg_level:
765 d94f9486 aliguori
 *  0 == errors (stderr + logfile).
766 d94f9486 aliguori
 *  1 == informative debug messages (logfile only).
767 d94f9486 aliguori
 *  2 == noisy debug messages (logfile only).
768 d94f9486 aliguori
 *  3 == will flood your log (logfile only).
769 d94f9486 aliguori
 */
770 d94f9486 aliguori
void xen_be_printf(struct XenDevice *xendev, int msg_level, const char *fmt, ...)
771 d94f9486 aliguori
{
772 d94f9486 aliguori
    va_list args;
773 d94f9486 aliguori
774 d94f9486 aliguori
    if (xendev) {
775 209cd7ab Anthony PERARD
        if (msg_level > xendev->debug) {
776 d94f9486 aliguori
            return;
777 209cd7ab Anthony PERARD
        }
778 d94f9486 aliguori
        qemu_log("xen be: %s: ", xendev->name);
779 209cd7ab Anthony PERARD
        if (msg_level == 0) {
780 d94f9486 aliguori
            fprintf(stderr, "xen be: %s: ", xendev->name);
781 209cd7ab Anthony PERARD
        }
782 d94f9486 aliguori
    } else {
783 209cd7ab Anthony PERARD
        if (msg_level > debug) {
784 d94f9486 aliguori
            return;
785 209cd7ab Anthony PERARD
        }
786 d94f9486 aliguori
        qemu_log("xen be core: ");
787 209cd7ab Anthony PERARD
        if (msg_level == 0) {
788 d94f9486 aliguori
            fprintf(stderr, "xen be core: ");
789 209cd7ab Anthony PERARD
        }
790 d94f9486 aliguori
    }
791 d94f9486 aliguori
    va_start(args, fmt);
792 d94f9486 aliguori
    qemu_log_vprintf(fmt, args);
793 d94f9486 aliguori
    va_end(args);
794 d94f9486 aliguori
    if (msg_level == 0) {
795 d94f9486 aliguori
        va_start(args, fmt);
796 d94f9486 aliguori
        vfprintf(stderr, fmt, args);
797 d94f9486 aliguori
        va_end(args);
798 d94f9486 aliguori
    }
799 d94f9486 aliguori
    qemu_log_flush();
800 d94f9486 aliguori
}