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