Revision d94f9486

b/Makefile.target
561 561
endif
562 562

  
563 563
# xen backend driver support
564
XEN_OBJS := xen_machine_pv.o
564
XEN_OBJS := xen_machine_pv.o xen_backend.o
565 565
ifeq ($(CONFIG_XEN), yes)
566 566
  OBJS += $(XEN_OBJS)
567 567
  LIBS += $(XEN_LIBS)
b/hw/xen_backend.c
1
/*
2
 *  xen backend driver infrastructure
3
 *  (c) 2008 Gerd Hoffmann <kraxel@redhat.com>
4
 *
5
 *  This program is free software; you can redistribute it and/or modify
6
 *  it under the terms of the GNU General Public License as published by
7
 *  the Free Software Foundation; under version 2 of the License.
8
 *
9
 *  This program is distributed in the hope that it will be useful,
10
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
 *  GNU General Public License for more details.
13
 *
14
 *  You should have received a copy of the GNU General Public License along
15
 *  with this program; if not, write to the Free Software Foundation, Inc.,
16
 *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17
 */
18

  
19
/*
20
 * TODO: add some xenbus / xenstore concepts overview here.
21
 */
22

  
23
#include <stdio.h>
24
#include <stdlib.h>
25
#include <stdarg.h>
26
#include <string.h>
27
#include <unistd.h>
28
#include <fcntl.h>
29
#include <inttypes.h>
30
#include <sys/types.h>
31
#include <sys/stat.h>
32
#include <sys/mman.h>
33
#include <sys/signal.h>
34

  
35
#include <xs.h>
36
#include <xenctrl.h>
37
#include <xen/grant_table.h>
38

  
39
#include "hw.h"
40
#include "qemu-char.h"
41
#include "xen_backend.h"
42

  
43
/* ------------------------------------------------------------- */
44

  
45
/* public */
46
int xen_xc;
47
struct xs_handle *xenstore = NULL;
48

  
49
/* private */
50
static TAILQ_HEAD(XenDeviceHead, XenDevice) xendevs = TAILQ_HEAD_INITIALIZER(xendevs);
51
static int debug = 0;
52

  
53
/* ------------------------------------------------------------- */
54

  
55
int xenstore_write_str(const char *base, const char *node, const char *val)
56
{
57
    char abspath[XEN_BUFSIZE];
58

  
59
    snprintf(abspath, sizeof(abspath), "%s/%s", base, node);
60
    if (!xs_write(xenstore, 0, abspath, val, strlen(val)))
61
	return -1;
62
    return 0;
63
}
64

  
65
char *xenstore_read_str(const char *base, const char *node)
66
{
67
    char abspath[XEN_BUFSIZE];
68
    unsigned int len;
69
    char *str, *ret = NULL;
70

  
71
    snprintf(abspath, sizeof(abspath), "%s/%s", base, node);
72
    str = xs_read(xenstore, 0, abspath, &len);
73
    if (str != NULL) {
74
        /* move to qemu-allocated memory to make sure
75
         * callers can savely qemu_free() stuff. */
76
        ret = qemu_strdup(str);
77
        free(str);
78
    }
79
    return ret;
80
}
81

  
82
int xenstore_write_int(const char *base, const char *node, int ival)
83
{
84
    char val[32];
85

  
86
    snprintf(val, sizeof(val), "%d", ival);
87
    return xenstore_write_str(base, node, val);
88
}
89

  
90
int xenstore_read_int(const char *base, const char *node, int *ival)
91
{
92
    char *val;
93
    int rc = -1;
94

  
95
    val = xenstore_read_str(base, node);
96
    if (val && 1 == sscanf(val, "%d", ival))
97
	rc = 0;
98
    qemu_free(val);
99
    return rc;
100
}
101

  
102
int xenstore_write_be_str(struct XenDevice *xendev, const char *node, const char *val)
103
{
104
    return xenstore_write_str(xendev->be, node, val);
105
}
106

  
107
int xenstore_write_be_int(struct XenDevice *xendev, const char *node, int ival)
108
{
109
    return xenstore_write_int(xendev->be, node, ival);
110
}
111

  
112
char *xenstore_read_be_str(struct XenDevice *xendev, const char *node)
113
{
114
    return xenstore_read_str(xendev->be, node);
115
}
116

  
117
int xenstore_read_be_int(struct XenDevice *xendev, const char *node, int *ival)
118
{
119
    return xenstore_read_int(xendev->be, node, ival);
120
}
121

  
122
char *xenstore_read_fe_str(struct XenDevice *xendev, const char *node)
123
{
124
    return xenstore_read_str(xendev->fe, node);
125
}
126

  
127
int xenstore_read_fe_int(struct XenDevice *xendev, const char *node, int *ival)
128
{
129
    return xenstore_read_int(xendev->fe, node, ival);
130
}
131

  
132
/* ------------------------------------------------------------- */
133

  
134
const char *xenbus_strstate(enum xenbus_state state)
135
{
136
	static const char *const name[] = {
137
		[ XenbusStateUnknown      ] = "Unknown",
138
		[ XenbusStateInitialising ] = "Initialising",
139
		[ XenbusStateInitWait     ] = "InitWait",
140
		[ XenbusStateInitialised  ] = "Initialised",
141
		[ XenbusStateConnected    ] = "Connected",
142
		[ XenbusStateClosing      ] = "Closing",
143
		[ XenbusStateClosed	  ] = "Closed",
144
	};
145
	return (state < ARRAY_SIZE(name)) ? name[state] : "INVALID";
146
}
147

  
148
int xen_be_set_state(struct XenDevice *xendev, enum xenbus_state state)
149
{
150
    int rc;
151

  
152
    rc = xenstore_write_be_int(xendev, "state", state);
153
    if (rc < 0)
154
	return rc;
155
    xen_be_printf(xendev, 1, "backend state: %s -> %s\n",
156
		  xenbus_strstate(xendev->be_state), xenbus_strstate(state));
157
    xendev->be_state = state;
158
    return 0;
159
}
160

  
161
/* ------------------------------------------------------------- */
162

  
163
struct XenDevice *xen_be_find_xendev(const char *type, int dom, int dev)
164
{
165
    struct XenDevice *xendev;
166

  
167
    TAILQ_FOREACH(xendev, &xendevs, next) {
168
	if (xendev->dom != dom)
169
	    continue;
170
	if (xendev->dev != dev)
171
	    continue;
172
	if (strcmp(xendev->type, type) != 0)
173
	    continue;
174
	return xendev;
175
    }
176
    return NULL;
177
}
178

  
179
/*
180
 * get xen backend device, allocate a new one if it doesn't exist.
181
 */
182
static struct XenDevice *xen_be_get_xendev(const char *type, int dom, int dev,
183
                                           struct XenDevOps *ops)
184
{
185
    struct XenDevice *xendev;
186
    char *dom0;
187

  
188
    xendev = xen_be_find_xendev(type, dom, dev);
189
    if (xendev)
190
	return xendev;
191

  
192
    /* init new xendev */
193
    xendev = qemu_mallocz(ops->size);
194
    xendev->type  = type;
195
    xendev->dom   = dom;
196
    xendev->dev   = dev;
197
    xendev->ops   = ops;
198

  
199
    dom0 = xs_get_domain_path(xenstore, 0);
200
    snprintf(xendev->be, sizeof(xendev->be), "%s/backend/%s/%d/%d",
201
	     dom0, xendev->type, xendev->dom, xendev->dev);
202
    snprintf(xendev->name, sizeof(xendev->name), "%s-%d",
203
	     xendev->type, xendev->dev);
204
    free(dom0);
205

  
206
    xendev->debug      = debug;
207
    xendev->local_port = -1;
208

  
209
    xendev->evtchndev = xc_evtchn_open();
210
    if (xendev->evtchndev < 0) {
211
	xen_be_printf(NULL, 0, "can't open evtchn device\n");
212
	qemu_free(xendev);
213
	return NULL;
214
    }
215
    fcntl(xc_evtchn_fd(xendev->evtchndev), F_SETFD, FD_CLOEXEC);
216

  
217
    if (ops->flags & DEVOPS_FLAG_NEED_GNTDEV) {
218
	xendev->gnttabdev = xc_gnttab_open();
219
	if (xendev->gnttabdev < 0) {
220
	    xen_be_printf(NULL, 0, "can't open gnttab device\n");
221
	    xc_evtchn_close(xendev->evtchndev);
222
	    qemu_free(xendev);
223
	    return NULL;
224
	}
225
    } else {
226
	xendev->gnttabdev = -1;
227
    }
228

  
229
    TAILQ_INSERT_TAIL(&xendevs, xendev, next);
230

  
231
    if (xendev->ops->alloc)
232
	xendev->ops->alloc(xendev);
233

  
234
    return xendev;
235
}
236

  
237
/*
238
 * release xen backend device.
239
 */
240
static struct XenDevice *xen_be_del_xendev(int dom, int dev)
241
{
242
    struct XenDevice *xendev, *xnext;
243

  
244
    /*
245
     * This is pretty much like TAILQ_FOREACH(xendev, &xendevs, next) but
246
     * we save the next pointer in xnext because we might free xendev.
247
     */
248
    xnext = xendevs.tqh_first;
249
    while (xnext) {
250
        xendev = xnext;
251
        xnext = xendev->next.tqe_next;
252

  
253
	if (xendev->dom != dom)
254
	    continue;
255
	if (xendev->dev != dev && dev != -1)
256
	    continue;
257

  
258
	if (xendev->ops->free)
259
	    xendev->ops->free(xendev);
260

  
261
	if (xendev->fe) {
262
	    char token[XEN_BUFSIZE];
263
	    snprintf(token, sizeof(token), "fe:%p", xendev);
264
	    xs_unwatch(xenstore, xendev->fe, token);
265
	    qemu_free(xendev->fe);
266
	}
267

  
268
	if (xendev->evtchndev >= 0)
269
	    xc_evtchn_close(xendev->evtchndev);
270
	if (xendev->gnttabdev >= 0)
271
	    xc_gnttab_close(xendev->gnttabdev);
272

  
273
	TAILQ_REMOVE(&xendevs, xendev, next);
274
	qemu_free(xendev);
275
    }
276
    return NULL;
277
}
278

  
279
/*
280
 * Sync internal data structures on xenstore updates.
281
 * Node specifies the changed field.  node = NULL means
282
 * update all fields (used for initialization).
283
 */
284
static void xen_be_backend_changed(struct XenDevice *xendev, const char *node)
285
{
286
    if (node == NULL  ||  strcmp(node, "online") == 0) {
287
	if (xenstore_read_be_int(xendev, "online", &xendev->online) == -1)
288
	    xendev->online = 0;
289
    }
290

  
291
    if (node) {
292
	xen_be_printf(xendev, 2, "backend update: %s\n", node);
293
	if (xendev->ops->backend_changed)
294
	    xendev->ops->backend_changed(xendev, node);
295
    }
296
}
297

  
298
static void xen_be_frontend_changed(struct XenDevice *xendev, const char *node)
299
{
300
    int fe_state;
301

  
302
    if (node == NULL  ||  strcmp(node, "state") == 0) {
303
	if (xenstore_read_fe_int(xendev, "state", &fe_state) == -1)
304
	    fe_state = XenbusStateUnknown;
305
	if (xendev->fe_state != fe_state)
306
	    xen_be_printf(xendev, 1, "frontend state: %s -> %s\n",
307
			  xenbus_strstate(xendev->fe_state),
308
			  xenbus_strstate(fe_state));
309
	xendev->fe_state = fe_state;
310
    }
311
    if (node == NULL  ||  strcmp(node, "protocol") == 0) {
312
	qemu_free(xendev->protocol);
313
	xendev->protocol = xenstore_read_fe_str(xendev, "protocol");
314
	if (xendev->protocol)
315
	    xen_be_printf(xendev, 1, "frontend protocol: %s\n", xendev->protocol);
316
    }
317

  
318
    if (node) {
319
	xen_be_printf(xendev, 2, "frontend update: %s\n", node);
320
	if (xendev->ops->frontend_changed)
321
	    xendev->ops->frontend_changed(xendev, node);
322
    }
323
}
324

  
325
/* ------------------------------------------------------------- */
326
/* Check for possible state transitions and perform them.        */
327

  
328
/*
329
 * Initial xendev setup.  Read frontend path, register watch for it.
330
 * Should succeed once xend finished setting up the backend device.
331
 *
332
 * Also sets initial state (-> Initializing) when done.  Which
333
 * only affects the xendev->be_state variable as xenbus should
334
 * already be put into that state by xend.
335
 */
336
static int xen_be_try_setup(struct XenDevice *xendev)
337
{
338
    char token[XEN_BUFSIZE];
339
    int be_state;
340

  
341
    if (xenstore_read_be_int(xendev, "state", &be_state) == -1) {
342
	xen_be_printf(xendev, 0, "reading backend state failed\n");
343
	return -1;
344
    }
345

  
346
    if (be_state != XenbusStateInitialising) {
347
	xen_be_printf(xendev, 0, "initial backend state is wrong (%s)\n",
348
		      xenbus_strstate(be_state));
349
	return -1;
350
    }
351

  
352
    xendev->fe = xenstore_read_be_str(xendev, "frontend");
353
    if (xendev->fe == NULL) {
354
	xen_be_printf(xendev, 0, "reading frontend path failed\n");
355
	return -1;
356
    }
357

  
358
    /* setup frontend watch */
359
    snprintf(token, sizeof(token), "fe:%p", xendev);
360
    if (!xs_watch(xenstore, xendev->fe, token)) {
361
	xen_be_printf(xendev, 0, "watching frontend path (%s) failed\n",
362
		      xendev->fe);
363
	return -1;
364
    }
365
    xen_be_set_state(xendev, XenbusStateInitialising);
366

  
367
    xen_be_backend_changed(xendev, NULL);
368
    xen_be_frontend_changed(xendev, NULL);
369
    return 0;
370
}
371

  
372
/*
373
 * Try initialize xendev.  Prepare everything the backend can do
374
 * without synchronizing with the frontend.  Fakes hotplug-status.  No
375
 * hotplug involved here because this is about userspace drivers, thus
376
 * there are kernel backend devices which could invoke hotplug.
377
 *
378
 * Goes to InitWait on success.
379
 */
380
static int xen_be_try_init(struct XenDevice *xendev)
381
{
382
    int rc = 0;
383

  
384
    if (!xendev->online) {
385
	xen_be_printf(xendev, 1, "not online\n");
386
	return -1;
387
    }
388

  
389
    if (xendev->ops->init)
390
	rc = xendev->ops->init(xendev);
391
    if (rc != 0) {
392
	xen_be_printf(xendev, 1, "init() failed\n");
393
	return rc;
394
    }
395

  
396
    xenstore_write_be_str(xendev, "hotplug-status", "connected");
397
    xen_be_set_state(xendev, XenbusStateInitWait);
398
    return 0;
399
}
400

  
401
/*
402
 * Try to connect xendev.  Depends on the frontend being ready
403
 * for it (shared ring and evtchn info in xenstore, state being
404
 * Initialised or Connected).
405
 *
406
 * Goes to Connected on success.
407
 */
408
static int xen_be_try_connect(struct XenDevice *xendev)
409
{
410
    int rc = 0;
411

  
412
    if (xendev->fe_state != XenbusStateInitialised  &&
413
	xendev->fe_state != XenbusStateConnected) {
414
	if (xendev->ops->flags & DEVOPS_FLAG_IGNORE_STATE) {
415
	    xen_be_printf(xendev, 2, "frontend not ready, ignoring\n");
416
	} else {
417
	    xen_be_printf(xendev, 2, "frontend not ready (yet)\n");
418
	    return -1;
419
	}
420
    }
421

  
422
    if (xendev->ops->connect)
423
	rc = xendev->ops->connect(xendev);
424
    if (rc != 0) {
425
	xen_be_printf(xendev, 0, "connect() failed\n");
426
	return rc;
427
    }
428

  
429
    xen_be_set_state(xendev, XenbusStateConnected);
430
    return 0;
431
}
432

  
433
/*
434
 * Teardown connection.
435
 *
436
 * Goes to Closed when done.
437
 */
438
static void xen_be_disconnect(struct XenDevice *xendev, enum xenbus_state state)
439
{
440
    if (xendev->be_state != XenbusStateClosing &&
441
        xendev->be_state != XenbusStateClosed  &&
442
        xendev->ops->disconnect)
443
	xendev->ops->disconnect(xendev);
444
    if (xendev->be_state != state)
445
        xen_be_set_state(xendev, state);
446
}
447

  
448
/*
449
 * Try to reset xendev, for reconnection by another frontend instance.
450
 */
451
static int xen_be_try_reset(struct XenDevice *xendev)
452
{
453
    if (xendev->fe_state != XenbusStateInitialising)
454
        return -1;
455

  
456
    xen_be_printf(xendev, 1, "device reset (for re-connect)\n");
457
    xen_be_set_state(xendev, XenbusStateInitialising);
458
    return 0;
459
}
460

  
461
/*
462
 * state change dispatcher function
463
 */
464
void xen_be_check_state(struct XenDevice *xendev)
465
{
466
    int rc = 0;
467

  
468
    /* frontend may request shutdown from almost anywhere */
469
    if (xendev->fe_state == XenbusStateClosing ||
470
	xendev->fe_state == XenbusStateClosed) {
471
	xen_be_disconnect(xendev, xendev->fe_state);
472
	return;
473
    }
474

  
475
    /* check for possible backend state transitions */
476
    for (;;) {
477
	switch (xendev->be_state) {
478
	case XenbusStateUnknown:
479
	    rc = xen_be_try_setup(xendev);
480
	    break;
481
	case XenbusStateInitialising:
482
	    rc = xen_be_try_init(xendev);
483
	    break;
484
	case XenbusStateInitWait:
485
	    rc = xen_be_try_connect(xendev);
486
	    break;
487
        case XenbusStateClosed:
488
            rc = xen_be_try_reset(xendev);
489
            break;
490
	default:
491
	    rc = -1;
492
	}
493
	if (rc != 0)
494
	    break;
495
    }
496
}
497

  
498
/* ------------------------------------------------------------- */
499

  
500
static int xenstore_scan(const char *type, int dom, struct XenDevOps *ops)
501
{
502
    struct XenDevice *xendev;
503
    char path[XEN_BUFSIZE], token[XEN_BUFSIZE];
504
    char **dev = NULL, *dom0;
505
    unsigned int cdev, j;
506

  
507
    /* setup watch */
508
    dom0 = xs_get_domain_path(xenstore, 0);
509
    snprintf(token, sizeof(token), "be:%p:%d:%p", type, dom, ops);
510
    snprintf(path, sizeof(path), "%s/backend/%s/%d", dom0, type, dom);
511
    free(dom0);
512
    if (!xs_watch(xenstore, path, token)) {
513
	xen_be_printf(NULL, 0, "xen be: watching backend path (%s) failed\n", path);
514
	return -1;
515
    }
516

  
517
    /* look for backends */
518
    dev = xs_directory(xenstore, 0, path, &cdev);
519
    if (!dev)
520
	return 0;
521
    for (j = 0; j < cdev; j++) {
522
	xendev = xen_be_get_xendev(type, dom, atoi(dev[j]), ops);
523
	if (xendev == NULL)
524
	    continue;
525
	xen_be_check_state(xendev);
526
    }
527
    free(dev);
528
    return 0;
529
}
530

  
531
static void xenstore_update_be(char *watch, char *type, int dom,
532
			       struct XenDevOps *ops)
533
{
534
    struct XenDevice *xendev;
535
    char path[XEN_BUFSIZE], *dom0;
536
    unsigned int len, dev;
537

  
538
    dom0 = xs_get_domain_path(xenstore, 0);
539
    len = snprintf(path, sizeof(path), "%s/backend/%s/%d", dom0, type, dom);
540
    free(dom0);
541
    if (strncmp(path, watch, len) != 0)
542
	return;
543
    if (sscanf(watch+len, "/%u/%255s", &dev, path) != 2) {
544
	strcpy(path, "");
545
	if (sscanf(watch+len, "/%u", &dev) != 1)
546
	    dev = -1;
547
    }
548
    if (dev == -1)
549
	return;
550

  
551
    if (0) {
552
	/* FIXME: detect devices being deleted from xenstore ... */
553
	xen_be_del_xendev(dom, dev);
554
    }
555

  
556
    xendev = xen_be_get_xendev(type, dom, dev, ops);
557
    if (xendev != NULL) {
558
	xen_be_backend_changed(xendev, path);
559
	xen_be_check_state(xendev);
560
    }
561
}
562

  
563
static void xenstore_update_fe(char *watch, struct XenDevice *xendev)
564
{
565
    char *node;
566
    unsigned int len;
567

  
568
    len = strlen(xendev->fe);
569
    if (strncmp(xendev->fe, watch, len) != 0)
570
	return;
571
    if (watch[len] != '/')
572
	return;
573
    node = watch + len + 1;
574

  
575
    xen_be_frontend_changed(xendev, node);
576
    xen_be_check_state(xendev);
577
}
578

  
579
static void xenstore_update(void *unused)
580
{
581
    char **vec = NULL;
582
    intptr_t type, ops, ptr;
583
    unsigned int dom, count;
584

  
585
    vec = xs_read_watch(xenstore, &count);
586
    if (vec == NULL)
587
	goto cleanup;
588

  
589
    if (sscanf(vec[XS_WATCH_TOKEN], "be:%" PRIxPTR ":%d:%" PRIxPTR,
590
               &type, &dom, &ops) == 3)
591
	xenstore_update_be(vec[XS_WATCH_PATH], (void*)type, dom, (void*)ops);
592
    if (sscanf(vec[XS_WATCH_TOKEN], "fe:%" PRIxPTR, &ptr) == 1)
593
	xenstore_update_fe(vec[XS_WATCH_PATH], (void*)ptr);
594

  
595
cleanup:
596
    qemu_free(vec);
597
}
598

  
599
static void xen_be_evtchn_event(void *opaque)
600
{
601
    struct XenDevice *xendev = opaque;
602
    evtchn_port_t port;
603

  
604
    port = xc_evtchn_pending(xendev->evtchndev);
605
    if (port != xendev->local_port) {
606
	xen_be_printf(xendev, 0, "xc_evtchn_pending returned %d (expected %d)\n",
607
		      port, xendev->local_port);
608
	return;
609
    }
610
    xc_evtchn_unmask(xendev->evtchndev, port);
611

  
612
    if (xendev->ops->event)
613
	xendev->ops->event(xendev);
614
}
615

  
616
/* -------------------------------------------------------------------- */
617

  
618
int xen_be_init(void)
619
{
620
    xenstore = xs_daemon_open();
621
    if (!xenstore) {
622
	xen_be_printf(NULL, 0, "can't connect to xenstored\n");
623
	return -1;
624
    }
625

  
626
    if (qemu_set_fd_handler(xs_fileno(xenstore), xenstore_update, NULL, NULL) < 0)
627
	goto err;
628

  
629
    xen_xc = xc_interface_open();
630
    if (xen_xc == -1) {
631
	xen_be_printf(NULL, 0, "can't open xen interface\n");
632
	goto err;
633
    }
634
    return 0;
635

  
636
err:
637
    qemu_set_fd_handler(xs_fileno(xenstore), NULL, NULL, NULL);
638
    xs_daemon_close(xenstore);
639
    xenstore = NULL;
640

  
641
    return -1;
642
}
643

  
644
int xen_be_register(const char *type, struct XenDevOps *ops)
645
{
646
    return xenstore_scan(type, xen_domid, ops);
647
}
648

  
649
int xen_be_bind_evtchn(struct XenDevice *xendev)
650
{
651
    if (xendev->local_port != -1)
652
	return 0;
653
    xendev->local_port = xc_evtchn_bind_interdomain
654
	(xendev->evtchndev, xendev->dom, xendev->remote_port);
655
    if (xendev->local_port == -1) {
656
	xen_be_printf(xendev, 0, "xc_evtchn_bind_interdomain failed\n");
657
	return -1;
658
    }
659
    xen_be_printf(xendev, 2, "bind evtchn port %d\n", xendev->local_port);
660
    qemu_set_fd_handler(xc_evtchn_fd(xendev->evtchndev),
661
			xen_be_evtchn_event, NULL, xendev);
662
    return 0;
663
}
664

  
665
void xen_be_unbind_evtchn(struct XenDevice *xendev)
666
{
667
    if (xendev->local_port == -1)
668
	return;
669
    qemu_set_fd_handler(xc_evtchn_fd(xendev->evtchndev), NULL, NULL, NULL);
670
    xc_evtchn_unbind(xendev->evtchndev, xendev->local_port);
671
    xen_be_printf(xendev, 2, "unbind evtchn port %d\n", xendev->local_port);
672
    xendev->local_port = -1;
673
}
674

  
675
int xen_be_send_notify(struct XenDevice *xendev)
676
{
677
    return xc_evtchn_notify(xendev->evtchndev, xendev->local_port);
678
}
679

  
680
/*
681
 * msg_level:
682
 *  0 == errors (stderr + logfile).
683
 *  1 == informative debug messages (logfile only).
684
 *  2 == noisy debug messages (logfile only).
685
 *  3 == will flood your log (logfile only).
686
 */
687
void xen_be_printf(struct XenDevice *xendev, int msg_level, const char *fmt, ...)
688
{
689
    va_list args;
690

  
691
    if (xendev) {
692
        if (msg_level > xendev->debug)
693
            return;
694
        qemu_log("xen be: %s: ", xendev->name);
695
        if (msg_level == 0)
696
            fprintf(stderr, "xen be: %s: ", xendev->name);
697
    } else {
698
        if (msg_level > debug)
699
            return;
700
        qemu_log("xen be core: ");
701
        if (msg_level == 0)
702
            fprintf(stderr, "xen be core: ");
703
    }
704
    va_start(args, fmt);
705
    qemu_log_vprintf(fmt, args);
706
    va_end(args);
707
    if (msg_level == 0) {
708
        va_start(args, fmt);
709
        vfprintf(stderr, fmt, args);
710
        va_end(args);
711
    }
712
    qemu_log_flush();
713
}
b/hw/xen_backend.h
1
#ifndef QEMU_HW_XEN_BACKEND_H
2
#define QEMU_HW_XEN_BACKEND_H 1
3

  
4
#include "xen_common.h"
5

  
6
/* ------------------------------------------------------------- */
7

  
8
#define XEN_BUFSIZE 1024
9

  
10
struct XenDevice;
11

  
12
/* driver uses grant tables  ->  open gntdev device (xendev->gnttabdev) */
13
#define DEVOPS_FLAG_NEED_GNTDEV   1
14
/* don't expect frontend doing correct state transitions (aka console quirk) */
15
#define DEVOPS_FLAG_IGNORE_STATE  2
16

  
17
struct XenDevOps {
18
    size_t    size;
19
    uint32_t  flags;
20
    void      (*alloc)(struct XenDevice *xendev);
21
    int       (*init)(struct XenDevice *xendev);
22
    int       (*connect)(struct XenDevice *xendev);
23
    void      (*event)(struct XenDevice *xendev);
24
    void      (*disconnect)(struct XenDevice *xendev);
25
    int       (*free)(struct XenDevice *xendev);
26
    void      (*backend_changed)(struct XenDevice *xendev, const char *node);
27
    void      (*frontend_changed)(struct XenDevice *xendev, const char *node);
28
};
29

  
30
struct XenDevice {
31
    const char         *type;
32
    int                dom;
33
    int                dev;
34
    char               name[64];
35
    int                debug;
36

  
37
    enum xenbus_state  be_state;
38
    enum xenbus_state  fe_state;
39
    int                online;
40
    char               be[XEN_BUFSIZE];
41
    char               *fe;
42
    char               *protocol;
43
    int                remote_port;
44
    int                local_port;
45

  
46
    int                evtchndev;
47
    int                gnttabdev;
48

  
49
    struct XenDevOps   *ops;
50
    TAILQ_ENTRY(XenDevice) next;
51
};
52

  
53
/* ------------------------------------------------------------- */
54

  
55
/* variables */
56
extern int xen_xc;
57
extern struct xs_handle *xenstore;
58

  
59
/* xenstore helper functions */
60
int xenstore_write_str(const char *base, const char *node, const char *val);
61
int xenstore_write_int(const char *base, const char *node, int ival);
62
char *xenstore_read_str(const char *base, const char *node);
63
int xenstore_read_int(const char *base, const char *node, int *ival);
64

  
65
int xenstore_write_be_str(struct XenDevice *xendev, const char *node, const char *val);
66
int xenstore_write_be_int(struct XenDevice *xendev, const char *node, int ival);
67
char *xenstore_read_be_str(struct XenDevice *xendev, const char *node);
68
int xenstore_read_be_int(struct XenDevice *xendev, const char *node, int *ival);
69
char *xenstore_read_fe_str(struct XenDevice *xendev, const char *node);
70
int xenstore_read_fe_int(struct XenDevice *xendev, const char *node, int *ival);
71

  
72
const char *xenbus_strstate(enum xenbus_state state);
73
struct XenDevice *xen_be_find_xendev(const char *type, int dom, int dev);
74
void xen_be_check_state(struct XenDevice *xendev);
75

  
76
/* xen backend driver bits */
77
int xen_be_init(void);
78
int xen_be_register(const char *type, struct XenDevOps *ops);
79
int xen_be_set_state(struct XenDevice *xendev, enum xenbus_state state);
80
int xen_be_bind_evtchn(struct XenDevice *xendev);
81
void xen_be_unbind_evtchn(struct XenDevice *xendev);
82
int xen_be_send_notify(struct XenDevice *xendev);
83
void xen_be_printf(struct XenDevice *xendev, int msg_level, const char *fmt, ...)
84
    __attribute__ ((format(printf, 3, 4)));
85

  
86
#endif /* QEMU_HW_XEN_BACKEND_H */
b/hw/xen_common.h
1
#ifndef QEMU_HW_XEN_COMMON_H
2
#define QEMU_HW_XEN_COMMON_H 1
3

  
4
#include <stddef.h>
5
#include <inttypes.h>
6

  
7
#include <xenctrl.h>
8
#include <xs.h>
9
#include <xen/io/xenbus.h>
10

  
11
#include "hw.h"
12
#include "xen.h"
13
#include "sys-queue.h"   /* BSD list implementation */
14

  
15
/*
16
 * tweaks needed to build with different xen versions
17
 *  0x00030205 -> 3.1.0
18
 *  0x00030207 -> 3.2.0
19
 *  0x00030208 -> unstable
20
 */
21
#include <xen/xen-compat.h>
22
#if __XEN_LATEST_INTERFACE_VERSION__ < 0x00030205
23
# define evtchn_port_or_error_t int
24
#endif
25
#if __XEN_LATEST_INTERFACE_VERSION__ < 0x00030207
26
# define xc_map_foreign_pages xc_map_foreign_batch
27
#endif
28
#if __XEN_LATEST_INTERFACE_VERSION__ < 0x00030208
29
# define xen_mb()  mb()
30
# define xen_rmb() rmb()
31
# define xen_wmb() wmb()
32
#endif
33

  
34
#endif /* QEMU_HW_XEN_COMMON_H */
b/hw/xen_machine_pv.c
26 26
#include "pc.h"
27 27
#include "sysemu.h"
28 28
#include "boards.h"
29
#include "xen.h"
29
#include "xen_backend.h"
30 30

  
31 31
uint32_t xen_domid;
32 32
enum xen_mode xen_mode = XEN_EMULATE;
......
50 50
    }
51 51
    env = cpu_init(cpu_model);
52 52
    env->halted = 1;
53

  
54
    /* Initialize backend core & drivers */
55
    if (xen_be_init() != 0) {
56
        fprintf(stderr, "%s: xen backend core setup failed\n", __FUNCTION__);
57
        exit(1);
58
    }
53 59
}
54 60

  
55 61
QEMUMachine xenpv_machine = {

Also available in: Unified diff