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