qemu/hw/xen/xen_backend.c
<<
>>
Prefs
   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, see <http://www.gnu.org/licenses/>.
  16 *
  17 *  Contributions after 2012-01-13 are licensed under the terms of the
  18 *  GNU GPL, version 2 or (at your option) any later version.
  19 */
  20
  21/*
  22 * TODO: add some xenbus / xenstore concepts overview here.
  23 */
  24
  25#include "qemu/osdep.h"
  26#include <sys/signal.h>
  27
  28#include "hw/hw.h"
  29#include "hw/sysbus.h"
  30#include "hw/boards.h"
  31#include "qemu/log.h"
  32#include "qapi/error.h"
  33#include "hw/xen/xen_backend.h"
  34#include "hw/xen/xen_pvdev.h"
  35#include "monitor/qdev.h"
  36
  37#include <xen/grant_table.h>
  38
  39DeviceState *xen_sysdev;
  40BusState *xen_sysbus;
  41
  42/* ------------------------------------------------------------- */
  43
  44/* public */
  45struct xs_handle *xenstore = NULL;
  46const char *xen_protocol;
  47
  48/* private */
  49static int debug;
  50
  51int xenstore_write_be_str(struct XenDevice *xendev, const char *node, const char *val)
  52{
  53    return xenstore_write_str(xendev->be, node, val);
  54}
  55
  56int xenstore_write_be_int(struct XenDevice *xendev, const char *node, int ival)
  57{
  58    return xenstore_write_int(xendev->be, node, ival);
  59}
  60
  61int xenstore_write_be_int64(struct XenDevice *xendev, const char *node, int64_t ival)
  62{
  63    return xenstore_write_int64(xendev->be, node, ival);
  64}
  65
  66char *xenstore_read_be_str(struct XenDevice *xendev, const char *node)
  67{
  68    return xenstore_read_str(xendev->be, node);
  69}
  70
  71int xenstore_read_be_int(struct XenDevice *xendev, const char *node, int *ival)
  72{
  73    return xenstore_read_int(xendev->be, node, ival);
  74}
  75
  76char *xenstore_read_fe_str(struct XenDevice *xendev, const char *node)
  77{
  78    return xenstore_read_str(xendev->fe, node);
  79}
  80
  81int xenstore_read_fe_int(struct XenDevice *xendev, const char *node, int *ival)
  82{
  83    return xenstore_read_int(xendev->fe, node, ival);
  84}
  85
  86int xenstore_read_fe_uint64(struct XenDevice *xendev, const char *node,
  87                            uint64_t *uval)
  88{
  89    return xenstore_read_uint64(xendev->fe, node, uval);
  90}
  91
  92/* ------------------------------------------------------------- */
  93
  94int xen_be_set_state(struct XenDevice *xendev, enum xenbus_state state)
  95{
  96    int rc;
  97
  98    rc = xenstore_write_be_int(xendev, "state", state);
  99    if (rc < 0) {
 100        return rc;
 101    }
 102    xen_pv_printf(xendev, 1, "backend state: %s -> %s\n",
 103                  xenbus_strstate(xendev->be_state), xenbus_strstate(state));
 104    xendev->be_state = state;
 105    return 0;
 106}
 107
 108/*
 109 * get xen backend device, allocate a new one if it doesn't exist.
 110 */
 111static struct XenDevice *xen_be_get_xendev(const char *type, int dom, int dev,
 112                                           struct XenDevOps *ops)
 113{
 114    struct XenDevice *xendev;
 115
 116    xendev = xen_pv_find_xendev(type, dom, dev);
 117    if (xendev) {
 118        return xendev;
 119    }
 120
 121    /* init new xendev */
 122    xendev = g_malloc0(ops->size);
 123    object_initialize(&xendev->qdev, ops->size, TYPE_XENBACKEND);
 124    OBJECT(xendev)->free = g_free;
 125    qdev_set_parent_bus(DEVICE(xendev), xen_sysbus);
 126    qdev_set_id(DEVICE(xendev), g_strdup_printf("xen-%s-%d", type, dev));
 127    qdev_init_nofail(DEVICE(xendev));
 128    object_unref(OBJECT(xendev));
 129
 130    xendev->type  = type;
 131    xendev->dom   = dom;
 132    xendev->dev   = dev;
 133    xendev->ops   = ops;
 134
 135    snprintf(xendev->be, sizeof(xendev->be), "backend/%s/%d/%d",
 136             xendev->type, xendev->dom, xendev->dev);
 137    snprintf(xendev->name, sizeof(xendev->name), "%s-%d",
 138             xendev->type, xendev->dev);
 139
 140    xendev->debug      = debug;
 141    xendev->local_port = -1;
 142
 143    xendev->evtchndev = xenevtchn_open(NULL, 0);
 144    if (xendev->evtchndev == NULL) {
 145        xen_pv_printf(NULL, 0, "can't open evtchn device\n");
 146        qdev_unplug(DEVICE(xendev), NULL);
 147        return NULL;
 148    }
 149    qemu_set_cloexec(xenevtchn_fd(xendev->evtchndev));
 150
 151    if (ops->flags & DEVOPS_FLAG_NEED_GNTDEV) {
 152        xendev->gnttabdev = xengnttab_open(NULL, 0);
 153        if (xendev->gnttabdev == NULL) {
 154            xen_pv_printf(NULL, 0, "can't open gnttab device\n");
 155            xenevtchn_close(xendev->evtchndev);
 156            qdev_unplug(DEVICE(xendev), NULL);
 157            return NULL;
 158        }
 159    } else {
 160        xendev->gnttabdev = NULL;
 161    }
 162
 163    xen_pv_insert_xendev(xendev);
 164
 165    if (xendev->ops->alloc) {
 166        xendev->ops->alloc(xendev);
 167    }
 168
 169    return xendev;
 170}
 171
 172
 173/*
 174 * Sync internal data structures on xenstore updates.
 175 * Node specifies the changed field.  node = NULL means
 176 * update all fields (used for initialization).
 177 */
 178static void xen_be_backend_changed(struct XenDevice *xendev, const char *node)
 179{
 180    if (node == NULL  ||  strcmp(node, "online") == 0) {
 181        if (xenstore_read_be_int(xendev, "online", &xendev->online) == -1) {
 182            xendev->online = 0;
 183        }
 184    }
 185
 186    if (node) {
 187        xen_pv_printf(xendev, 2, "backend update: %s\n", node);
 188        if (xendev->ops->backend_changed) {
 189            xendev->ops->backend_changed(xendev, node);
 190        }
 191    }
 192}
 193
 194static void xen_be_frontend_changed(struct XenDevice *xendev, const char *node)
 195{
 196    int fe_state;
 197
 198    if (node == NULL  ||  strcmp(node, "state") == 0) {
 199        if (xenstore_read_fe_int(xendev, "state", &fe_state) == -1) {
 200            fe_state = XenbusStateUnknown;
 201        }
 202        if (xendev->fe_state != fe_state) {
 203            xen_pv_printf(xendev, 1, "frontend state: %s -> %s\n",
 204                          xenbus_strstate(xendev->fe_state),
 205                          xenbus_strstate(fe_state));
 206        }
 207        xendev->fe_state = fe_state;
 208    }
 209    if (node == NULL  ||  strcmp(node, "protocol") == 0) {
 210        g_free(xendev->protocol);
 211        xendev->protocol = xenstore_read_fe_str(xendev, "protocol");
 212        if (xendev->protocol) {
 213            xen_pv_printf(xendev, 1, "frontend protocol: %s\n",
 214                          xendev->protocol);
 215        }
 216    }
 217
 218    if (node) {
 219        xen_pv_printf(xendev, 2, "frontend update: %s\n", node);
 220        if (xendev->ops->frontend_changed) {
 221            xendev->ops->frontend_changed(xendev, node);
 222        }
 223    }
 224}
 225
 226/* ------------------------------------------------------------- */
 227/* Check for possible state transitions and perform them.        */
 228
 229/*
 230 * Initial xendev setup.  Read frontend path, register watch for it.
 231 * Should succeed once xend finished setting up the backend device.
 232 *
 233 * Also sets initial state (-> Initializing) when done.  Which
 234 * only affects the xendev->be_state variable as xenbus should
 235 * already be put into that state by xend.
 236 */
 237static int xen_be_try_setup(struct XenDevice *xendev)
 238{
 239    char token[XEN_BUFSIZE];
 240    int be_state;
 241
 242    if (xenstore_read_be_int(xendev, "state", &be_state) == -1) {
 243        xen_pv_printf(xendev, 0, "reading backend state failed\n");
 244        return -1;
 245    }
 246
 247    if (be_state != XenbusStateInitialising) {
 248        xen_pv_printf(xendev, 0, "initial backend state is wrong (%s)\n",
 249                      xenbus_strstate(be_state));
 250        return -1;
 251    }
 252
 253    xendev->fe = xenstore_read_be_str(xendev, "frontend");
 254    if (xendev->fe == NULL) {
 255        xen_pv_printf(xendev, 0, "reading frontend path failed\n");
 256        return -1;
 257    }
 258
 259    /* setup frontend watch */
 260    snprintf(token, sizeof(token), "fe:%p", xendev);
 261    if (!xs_watch(xenstore, xendev->fe, token)) {
 262        xen_pv_printf(xendev, 0, "watching frontend path (%s) failed\n",
 263                      xendev->fe);
 264        return -1;
 265    }
 266    xen_be_set_state(xendev, XenbusStateInitialising);
 267
 268    xen_be_backend_changed(xendev, NULL);
 269    xen_be_frontend_changed(xendev, NULL);
 270    return 0;
 271}
 272
 273/*
 274 * Try initialize xendev.  Prepare everything the backend can do
 275 * without synchronizing with the frontend.  Fakes hotplug-status.  No
 276 * hotplug involved here because this is about userspace drivers, thus
 277 * there are kernel backend devices which could invoke hotplug.
 278 *
 279 * Goes to InitWait on success.
 280 */
 281static int xen_be_try_init(struct XenDevice *xendev)
 282{
 283    int rc = 0;
 284
 285    if (!xendev->online) {
 286        xen_pv_printf(xendev, 1, "not online\n");
 287        return -1;
 288    }
 289
 290    if (xendev->ops->init) {
 291        rc = xendev->ops->init(xendev);
 292    }
 293    if (rc != 0) {
 294        xen_pv_printf(xendev, 1, "init() failed\n");
 295        return rc;
 296    }
 297
 298    xenstore_write_be_str(xendev, "hotplug-status", "connected");
 299    xen_be_set_state(xendev, XenbusStateInitWait);
 300    return 0;
 301}
 302
 303/*
 304 * Try to initialise xendev.  Depends on the frontend being ready
 305 * for it (shared ring and evtchn info in xenstore, state being
 306 * Initialised or Connected).
 307 *
 308 * Goes to Connected on success.
 309 */
 310static int xen_be_try_initialise(struct XenDevice *xendev)
 311{
 312    int rc = 0;
 313
 314    if (xendev->fe_state != XenbusStateInitialised  &&
 315        xendev->fe_state != XenbusStateConnected) {
 316        if (xendev->ops->flags & DEVOPS_FLAG_IGNORE_STATE) {
 317            xen_pv_printf(xendev, 2, "frontend not ready, ignoring\n");
 318        } else {
 319            xen_pv_printf(xendev, 2, "frontend not ready (yet)\n");
 320            return -1;
 321        }
 322    }
 323
 324    if (xendev->ops->initialise) {
 325        rc = xendev->ops->initialise(xendev);
 326    }
 327    if (rc != 0) {
 328        xen_pv_printf(xendev, 0, "initialise() failed\n");
 329        return rc;
 330    }
 331
 332    xen_be_set_state(xendev, XenbusStateConnected);
 333    return 0;
 334}
 335
 336/*
 337 * Try to let xendev know that it is connected.  Depends on the
 338 * frontend being Connected.  Note that this may be called more
 339 * than once since the backend state is not modified.
 340 */
 341static void xen_be_try_connected(struct XenDevice *xendev)
 342{
 343    if (!xendev->ops->connected) {
 344        return;
 345    }
 346
 347    if (xendev->fe_state != XenbusStateConnected) {
 348        if (xendev->ops->flags & DEVOPS_FLAG_IGNORE_STATE) {
 349            xen_pv_printf(xendev, 2, "frontend not ready, ignoring\n");
 350        } else {
 351            xen_pv_printf(xendev, 2, "frontend not ready (yet)\n");
 352            return;
 353        }
 354    }
 355
 356    xendev->ops->connected(xendev);
 357}
 358
 359/*
 360 * Teardown connection.
 361 *
 362 * Goes to Closed when done.
 363 */
 364static void xen_be_disconnect(struct XenDevice *xendev, enum xenbus_state state)
 365{
 366    if (xendev->be_state != XenbusStateClosing &&
 367        xendev->be_state != XenbusStateClosed  &&
 368        xendev->ops->disconnect) {
 369        xendev->ops->disconnect(xendev);
 370    }
 371    if (xendev->be_state != state) {
 372        xen_be_set_state(xendev, state);
 373    }
 374}
 375
 376/*
 377 * Try to reset xendev, for reconnection by another frontend instance.
 378 */
 379static int xen_be_try_reset(struct XenDevice *xendev)
 380{
 381    if (xendev->fe_state != XenbusStateInitialising) {
 382        return -1;
 383    }
 384
 385    xen_pv_printf(xendev, 1, "device reset (for re-connect)\n");
 386    xen_be_set_state(xendev, XenbusStateInitialising);
 387    return 0;
 388}
 389
 390/*
 391 * state change dispatcher function
 392 */
 393void xen_be_check_state(struct XenDevice *xendev)
 394{
 395    int rc = 0;
 396
 397    /* frontend may request shutdown from almost anywhere */
 398    if (xendev->fe_state == XenbusStateClosing ||
 399        xendev->fe_state == XenbusStateClosed) {
 400        xen_be_disconnect(xendev, xendev->fe_state);
 401        return;
 402    }
 403
 404    /* check for possible backend state transitions */
 405    for (;;) {
 406        switch (xendev->be_state) {
 407        case XenbusStateUnknown:
 408            rc = xen_be_try_setup(xendev);
 409            break;
 410        case XenbusStateInitialising:
 411            rc = xen_be_try_init(xendev);
 412            break;
 413        case XenbusStateInitWait:
 414            rc = xen_be_try_initialise(xendev);
 415            break;
 416        case XenbusStateConnected:
 417            /* xendev->be_state doesn't change */
 418            xen_be_try_connected(xendev);
 419            rc = -1;
 420            break;
 421        case XenbusStateClosed:
 422            rc = xen_be_try_reset(xendev);
 423            break;
 424        default:
 425            rc = -1;
 426        }
 427        if (rc != 0) {
 428            break;
 429        }
 430    }
 431}
 432
 433/* ------------------------------------------------------------- */
 434
 435static int xenstore_scan(const char *type, int dom, struct XenDevOps *ops)
 436{
 437    struct XenDevice *xendev;
 438    char path[XEN_BUFSIZE], token[XEN_BUFSIZE];
 439    char **dev = NULL;
 440    unsigned int cdev, j;
 441
 442    /* setup watch */
 443    snprintf(token, sizeof(token), "be:%p:%d:%p", type, dom, ops);
 444    snprintf(path, sizeof(path), "backend/%s/%d", type, dom);
 445    if (!xs_watch(xenstore, path, token)) {
 446        xen_pv_printf(NULL, 0, "xen be: watching backend path (%s) failed\n",
 447                      path);
 448        return -1;
 449    }
 450
 451    /* look for backends */
 452    dev = xs_directory(xenstore, 0, path, &cdev);
 453    if (!dev) {
 454        return 0;
 455    }
 456    for (j = 0; j < cdev; j++) {
 457        xendev = xen_be_get_xendev(type, dom, atoi(dev[j]), ops);
 458        if (xendev == NULL) {
 459            continue;
 460        }
 461        xen_be_check_state(xendev);
 462    }
 463    free(dev);
 464    return 0;
 465}
 466
 467void xenstore_update_be(char *watch, char *type, int dom,
 468                        struct XenDevOps *ops)
 469{
 470    struct XenDevice *xendev;
 471    char path[XEN_BUFSIZE], *bepath;
 472    unsigned int len, dev;
 473
 474    len = snprintf(path, sizeof(path), "backend/%s/%d", type, dom);
 475    if (strncmp(path, watch, len) != 0) {
 476        return;
 477    }
 478    if (sscanf(watch+len, "/%u/%255s", &dev, path) != 2) {
 479        strcpy(path, "");
 480        if (sscanf(watch+len, "/%u", &dev) != 1) {
 481            dev = -1;
 482        }
 483    }
 484    if (dev == -1) {
 485        return;
 486    }
 487
 488    xendev = xen_be_get_xendev(type, dom, dev, ops);
 489    if (xendev != NULL) {
 490        bepath = xs_read(xenstore, 0, xendev->be, &len);
 491        if (bepath == NULL) {
 492            xen_pv_del_xendev(xendev);
 493        } else {
 494            free(bepath);
 495            xen_be_backend_changed(xendev, path);
 496            xen_be_check_state(xendev);
 497        }
 498    }
 499}
 500
 501void xenstore_update_fe(char *watch, struct XenDevice *xendev)
 502{
 503    char *node;
 504    unsigned int len;
 505
 506    len = strlen(xendev->fe);
 507    if (strncmp(xendev->fe, watch, len) != 0) {
 508        return;
 509    }
 510    if (watch[len] != '/') {
 511        return;
 512    }
 513    node = watch + len + 1;
 514
 515    xen_be_frontend_changed(xendev, node);
 516    xen_be_check_state(xendev);
 517}
 518/* -------------------------------------------------------------------- */
 519
 520int xen_be_init(void)
 521{
 522    xenstore = xs_daemon_open();
 523    if (!xenstore) {
 524        xen_pv_printf(NULL, 0, "can't connect to xenstored\n");
 525        return -1;
 526    }
 527
 528    qemu_set_fd_handler(xs_fileno(xenstore), xenstore_update, NULL, NULL);
 529
 530    if (xen_xc == NULL || xen_fmem == NULL) {
 531        /* Check if xen_init() have been called */
 532        goto err;
 533    }
 534
 535    xen_sysdev = qdev_create(NULL, TYPE_XENSYSDEV);
 536    qdev_init_nofail(xen_sysdev);
 537    xen_sysbus = qbus_create(TYPE_XENSYSBUS, DEVICE(xen_sysdev), "xen-sysbus");
 538    qbus_set_bus_hotplug_handler(xen_sysbus, &error_abort);
 539
 540    return 0;
 541
 542err:
 543    qemu_set_fd_handler(xs_fileno(xenstore), NULL, NULL, NULL);
 544    xs_daemon_close(xenstore);
 545    xenstore = NULL;
 546
 547    return -1;
 548}
 549
 550static void xen_set_dynamic_sysbus(void)
 551{
 552    Object *machine = qdev_get_machine();
 553    ObjectClass *oc = object_get_class(machine);
 554    MachineClass *mc = MACHINE_CLASS(oc);
 555
 556    mc->has_dynamic_sysbus = true;
 557}
 558
 559int xen_be_register(const char *type, struct XenDevOps *ops)
 560{
 561    char path[50];
 562    int rc;
 563
 564    if (ops->backend_register) {
 565        rc = ops->backend_register();
 566        if (rc) {
 567            return rc;
 568        }
 569    }
 570
 571    snprintf(path, sizeof(path), "device-model/%u/backends/%s", xen_domid,
 572             type);
 573    xenstore_mkdir(path, XS_PERM_NONE);
 574
 575    return xenstore_scan(type, xen_domid, ops);
 576}
 577
 578void xen_be_register_common(void)
 579{
 580    xen_set_dynamic_sysbus();
 581
 582    xen_be_register("console", &xen_console_ops);
 583    xen_be_register("vkbd", &xen_kbdmouse_ops);
 584    xen_be_register("qdisk", &xen_blkdev_ops);
 585#ifdef CONFIG_VIRTFS
 586    xen_be_register("9pfs", &xen_9pfs_ops);
 587#endif
 588#ifdef CONFIG_USB_LIBUSB
 589    xen_be_register("qusb", &xen_usb_ops);
 590#endif
 591}
 592
 593int xen_be_bind_evtchn(struct XenDevice *xendev)
 594{
 595    if (xendev->local_port != -1) {
 596        return 0;
 597    }
 598    xendev->local_port = xenevtchn_bind_interdomain
 599        (xendev->evtchndev, xendev->dom, xendev->remote_port);
 600    if (xendev->local_port == -1) {
 601        xen_pv_printf(xendev, 0, "xenevtchn_bind_interdomain failed\n");
 602        return -1;
 603    }
 604    xen_pv_printf(xendev, 2, "bind evtchn port %d\n", xendev->local_port);
 605    qemu_set_fd_handler(xenevtchn_fd(xendev->evtchndev),
 606                        xen_pv_evtchn_event, NULL, xendev);
 607    return 0;
 608}
 609
 610
 611static Property xendev_properties[] = {
 612    DEFINE_PROP_END_OF_LIST(),
 613};
 614
 615static void xendev_class_init(ObjectClass *klass, void *data)
 616{
 617    DeviceClass *dc = DEVICE_CLASS(klass);
 618
 619    dc->props = xendev_properties;
 620    set_bit(DEVICE_CATEGORY_MISC, dc->categories);
 621    /* xen-backend devices can be plugged/unplugged dynamically */
 622    dc->user_creatable = true;
 623}
 624
 625static const TypeInfo xendev_type_info = {
 626    .name          = TYPE_XENBACKEND,
 627    .parent        = TYPE_XENSYSDEV,
 628    .class_init    = xendev_class_init,
 629    .instance_size = sizeof(struct XenDevice),
 630};
 631
 632static void xen_sysbus_class_init(ObjectClass *klass, void *data)
 633{
 634    HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(klass);
 635
 636    hc->unplug = qdev_simple_device_unplug_cb;
 637}
 638
 639static const TypeInfo xensysbus_info = {
 640    .name       = TYPE_XENSYSBUS,
 641    .parent     = TYPE_BUS,
 642    .class_init = xen_sysbus_class_init,
 643    .interfaces = (InterfaceInfo[]) {
 644        { TYPE_HOTPLUG_HANDLER },
 645        { }
 646    }
 647};
 648
 649static int xen_sysdev_init(SysBusDevice *dev)
 650{
 651    return 0;
 652}
 653
 654static Property xen_sysdev_properties[] = {
 655    {/* end of property list */},
 656};
 657
 658static void xen_sysdev_class_init(ObjectClass *klass, void *data)
 659{
 660    DeviceClass *dc = DEVICE_CLASS(klass);
 661    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
 662
 663    k->init = xen_sysdev_init;
 664    dc->props = xen_sysdev_properties;
 665    dc->bus_type = TYPE_XENSYSBUS;
 666}
 667
 668static const TypeInfo xensysdev_info = {
 669    .name          = TYPE_XENSYSDEV,
 670    .parent        = TYPE_SYS_BUS_DEVICE,
 671    .instance_size = sizeof(SysBusDevice),
 672    .class_init    = xen_sysdev_class_init,
 673};
 674
 675static void xenbe_register_types(void)
 676{
 677    type_register_static(&xensysbus_info);
 678    type_register_static(&xensysdev_info);
 679    type_register_static(&xendev_type_info);
 680}
 681
 682type_init(xenbe_register_types)
 683