| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: xbdback_xenbus.c,v 1.55.2.1 2012/06/05 15:36:00 jdc Exp $ */ | | 1 | /* $NetBSD: xbdback_xenbus.c,v 1.55.2.1.4.1 2013/11/07 20:18:50 snj Exp $ */ |
2 | | | 2 | |
3 | /* | | 3 | /* |
4 | * Copyright (c) 2006 Manuel Bouyer. | | 4 | * Copyright (c) 2006 Manuel Bouyer. |
5 | * | | 5 | * |
6 | * Redistribution and use in source and binary forms, with or without | | 6 | * Redistribution and use in source and binary forms, with or without |
7 | * modification, are permitted provided that the following conditions | | 7 | * modification, are permitted provided that the following conditions |
8 | * are met: | | 8 | * are met: |
9 | * 1. Redistributions of source code must retain the above copyright | | 9 | * 1. Redistributions of source code must retain the above copyright |
10 | * notice, this list of conditions and the following disclaimer. | | 10 | * notice, this list of conditions and the following disclaimer. |
11 | * 2. Redistributions in binary form must reproduce the above copyright | | 11 | * 2. Redistributions in binary form must reproduce the above copyright |
12 | * notice, this list of conditions and the following disclaimer in the | | 12 | * notice, this list of conditions and the following disclaimer in the |
13 | * documentation and/or other materials provided with the distribution. | | 13 | * documentation and/or other materials provided with the distribution. |
14 | * | | 14 | * |
| @@ -16,27 +16,27 @@ | | | @@ -16,27 +16,27 @@ |
16 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | | 16 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
17 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | | 17 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
18 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | | 18 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
19 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | | 19 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
20 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | | 20 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
21 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | | 21 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
22 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | | 22 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | | 23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
24 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | | 24 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
25 | * | | 25 | * |
26 | */ | | 26 | */ |
27 | | | 27 | |
28 | #include <sys/cdefs.h> | | 28 | #include <sys/cdefs.h> |
29 | __KERNEL_RCSID(0, "$NetBSD: xbdback_xenbus.c,v 1.55.2.1 2012/06/05 15:36:00 jdc Exp $"); | | 29 | __KERNEL_RCSID(0, "$NetBSD: xbdback_xenbus.c,v 1.55.2.1.4.1 2013/11/07 20:18:50 snj Exp $"); |
30 | | | 30 | |
31 | #include <sys/atomic.h> | | 31 | #include <sys/atomic.h> |
32 | #include <sys/buf.h> | | 32 | #include <sys/buf.h> |
33 | #include <sys/condvar.h> | | 33 | #include <sys/condvar.h> |
34 | #include <sys/conf.h> | | 34 | #include <sys/conf.h> |
35 | #include <sys/disk.h> | | 35 | #include <sys/disk.h> |
36 | #include <sys/device.h> | | 36 | #include <sys/device.h> |
37 | #include <sys/fcntl.h> | | 37 | #include <sys/fcntl.h> |
38 | #include <sys/kauth.h> | | 38 | #include <sys/kauth.h> |
39 | #include <sys/kernel.h> | | 39 | #include <sys/kernel.h> |
40 | #include <sys/kmem.h> | | 40 | #include <sys/kmem.h> |
41 | #include <sys/kthread.h> | | 41 | #include <sys/kthread.h> |
42 | #include <sys/malloc.h> | | 42 | #include <sys/malloc.h> |
| @@ -521,88 +521,95 @@ xbdback_xenbus_destroy(void *arg) | | | @@ -521,88 +521,95 @@ xbdback_xenbus_destroy(void *arg) |
521 | | | 521 | |
522 | static int | | 522 | static int |
523 | xbdback_connect(struct xbdback_instance *xbdi) | | 523 | xbdback_connect(struct xbdback_instance *xbdi) |
524 | { | | 524 | { |
525 | int len, err; | | 525 | int len, err; |
526 | struct gnttab_map_grant_ref grop; | | 526 | struct gnttab_map_grant_ref grop; |
527 | struct gnttab_unmap_grant_ref ungrop; | | 527 | struct gnttab_unmap_grant_ref ungrop; |
528 | evtchn_op_t evop; | | 528 | evtchn_op_t evop; |
529 | u_long ring_ref, revtchn; | | 529 | u_long ring_ref, revtchn; |
530 | char *xsproto; | | 530 | char *xsproto; |
531 | const char *proto; | | 531 | const char *proto; |
532 | struct xenbus_device *xbusd = xbdi->xbdi_xbusd; | | 532 | struct xenbus_device *xbusd = xbdi->xbdi_xbusd; |
533 | | | 533 | |
| | | 534 | XENPRINTF(("xbdback %s: connect\n", xbusd->xbusd_path)); |
534 | /* read comunication informations */ | | 535 | /* read comunication informations */ |
535 | err = xenbus_read_ul(NULL, xbusd->xbusd_otherend, | | 536 | err = xenbus_read_ul(NULL, xbusd->xbusd_otherend, |
536 | "ring-ref", &ring_ref, 10); | | 537 | "ring-ref", &ring_ref, 10); |
537 | if (err) { | | 538 | if (err) { |
538 | xenbus_dev_fatal(xbusd, err, "reading %s/ring-ref", | | 539 | xenbus_dev_fatal(xbusd, err, "reading %s/ring-ref", |
539 | xbusd->xbusd_otherend); | | 540 | xbusd->xbusd_otherend); |
540 | return -1; | | 541 | return -1; |
541 | } | | 542 | } |
| | | 543 | XENPRINTF(("xbdback %s: connect ring-ref %lu\n", xbusd->xbusd_path, ring_ref)); |
542 | err = xenbus_read_ul(NULL, xbusd->xbusd_otherend, | | 544 | err = xenbus_read_ul(NULL, xbusd->xbusd_otherend, |
543 | "event-channel", &revtchn, 10); | | 545 | "event-channel", &revtchn, 10); |
544 | if (err) { | | 546 | if (err) { |
545 | xenbus_dev_fatal(xbusd, err, "reading %s/event-channel", | | 547 | xenbus_dev_fatal(xbusd, err, "reading %s/event-channel", |
546 | xbusd->xbusd_otherend); | | 548 | xbusd->xbusd_otherend); |
547 | return -1; | | 549 | return -1; |
548 | } | | 550 | } |
| | | 551 | XENPRINTF(("xbdback %s: connect revtchn %lu\n", xbusd->xbusd_path, revtchn)); |
549 | err = xenbus_read(NULL, xbusd->xbusd_otherend, "protocol", | | 552 | err = xenbus_read(NULL, xbusd->xbusd_otherend, "protocol", |
550 | &len, &xsproto); | | 553 | &len, &xsproto); |
551 | if (err) { | | 554 | if (err) { |
552 | xbdi->xbdi_proto = XBDIP_NATIVE; | | 555 | xbdi->xbdi_proto = XBDIP_NATIVE; |
553 | proto = "unspecified"; | | 556 | proto = "unspecified"; |
| | | 557 | XENPRINTF(("xbdback %s: connect no xsproto\n", xbusd->xbusd_path)); |
554 | } else { | | 558 | } else { |
| | | 559 | XENPRINTF(("xbdback %s: connect xsproto %s\n", xbusd->xbusd_path, xsproto)); |
555 | if (strcmp(xsproto, XEN_IO_PROTO_ABI_NATIVE) == 0) { | | 560 | if (strcmp(xsproto, XEN_IO_PROTO_ABI_NATIVE) == 0) { |
556 | xbdi->xbdi_proto = XBDIP_NATIVE; | | 561 | xbdi->xbdi_proto = XBDIP_NATIVE; |
557 | proto = XEN_IO_PROTO_ABI_NATIVE; | | 562 | proto = XEN_IO_PROTO_ABI_NATIVE; |
558 | } else if (strcmp(xsproto, XEN_IO_PROTO_ABI_X86_32) == 0) { | | 563 | } else if (strcmp(xsproto, XEN_IO_PROTO_ABI_X86_32) == 0) { |
559 | xbdi->xbdi_proto = XBDIP_32; | | 564 | xbdi->xbdi_proto = XBDIP_32; |
560 | proto = XEN_IO_PROTO_ABI_X86_32; | | 565 | proto = XEN_IO_PROTO_ABI_X86_32; |
561 | } else if (strcmp(xsproto, XEN_IO_PROTO_ABI_X86_64) == 0) { | | 566 | } else if (strcmp(xsproto, XEN_IO_PROTO_ABI_X86_64) == 0) { |
562 | xbdi->xbdi_proto = XBDIP_64; | | 567 | xbdi->xbdi_proto = XBDIP_64; |
563 | proto = XEN_IO_PROTO_ABI_X86_64; | | 568 | proto = XEN_IO_PROTO_ABI_X86_64; |
564 | } else { | | 569 | } else { |
565 | aprint_error("xbd domain %d: unknown proto %s\n", | | 570 | aprint_error("xbd domain %d: unknown proto %s\n", |
566 | xbdi->xbdi_domid, xsproto); | | 571 | xbdi->xbdi_domid, xsproto); |
567 | free(xsproto, M_DEVBUF); | | 572 | free(xsproto, M_DEVBUF); |
568 | return -1; | | 573 | return -1; |
569 | } | | 574 | } |
| | | 575 | free(xsproto, M_DEVBUF); |
570 | } | | 576 | } |
571 | free(xsproto, M_DEVBUF); | | | |
572 | | | 577 | |
573 | /* allocate VA space and map rings */ | | 578 | /* allocate VA space and map rings */ |
574 | xbdi->xbdi_ring_va = uvm_km_alloc(kernel_map, PAGE_SIZE, 0, | | 579 | xbdi->xbdi_ring_va = uvm_km_alloc(kernel_map, PAGE_SIZE, 0, |
575 | UVM_KMF_VAONLY); | | 580 | UVM_KMF_VAONLY); |
576 | if (xbdi->xbdi_ring_va == 0) { | | 581 | if (xbdi->xbdi_ring_va == 0) { |
577 | xenbus_dev_fatal(xbusd, ENOMEM, | | 582 | xenbus_dev_fatal(xbusd, ENOMEM, |
578 | "can't get VA for ring", xbusd->xbusd_otherend); | | 583 | "can't get VA for ring", xbusd->xbusd_otherend); |
579 | return -1; | | 584 | return -1; |
580 | } | | 585 | } |
| | | 586 | XENPRINTF(("xbdback %s: connect va 0x%" PRIxVADDR "\n", xbusd->xbusd_path, xbdi->xbdi_ring_va)); |
581 | | | 587 | |
582 | grop.host_addr = xbdi->xbdi_ring_va; | | 588 | grop.host_addr = xbdi->xbdi_ring_va; |
583 | grop.flags = GNTMAP_host_map; | | 589 | grop.flags = GNTMAP_host_map; |
584 | grop.ref = ring_ref; | | 590 | grop.ref = ring_ref; |
585 | grop.dom = xbdi->xbdi_domid; | | 591 | grop.dom = xbdi->xbdi_domid; |
586 | err = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, | | 592 | err = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, |
587 | &grop, 1); | | 593 | &grop, 1); |
588 | if (err || grop.status) { | | 594 | if (err || grop.status) { |
589 | aprint_error("xbdback %s: can't map grant ref: %d/%d\n", | | 595 | aprint_error("xbdback %s: can't map grant ref: %d/%d\n", |
590 | xbusd->xbusd_path, err, grop.status); | | 596 | xbusd->xbusd_path, err, grop.status); |
591 | xenbus_dev_fatal(xbusd, EINVAL, | | 597 | xenbus_dev_fatal(xbusd, EINVAL, |
592 | "can't map ring", xbusd->xbusd_otherend); | | 598 | "can't map ring", xbusd->xbusd_otherend); |
593 | goto err; | | 599 | goto err; |
594 | } | | 600 | } |
595 | xbdi->xbdi_ring_handle = grop.handle; | | 601 | xbdi->xbdi_ring_handle = grop.handle; |
| | | 602 | XENPRINTF(("xbdback %s: connect grhandle %d\n", xbusd->xbusd_path, grop.handle)); |
596 | | | 603 | |
597 | switch(xbdi->xbdi_proto) { | | 604 | switch(xbdi->xbdi_proto) { |
598 | case XBDIP_NATIVE: | | 605 | case XBDIP_NATIVE: |
599 | { | | 606 | { |
600 | blkif_sring_t *sring = (void *)xbdi->xbdi_ring_va; | | 607 | blkif_sring_t *sring = (void *)xbdi->xbdi_ring_va; |
601 | BACK_RING_INIT(&xbdi->xbdi_ring.ring_n, sring, PAGE_SIZE); | | 608 | BACK_RING_INIT(&xbdi->xbdi_ring.ring_n, sring, PAGE_SIZE); |
602 | break; | | 609 | break; |
603 | } | | 610 | } |
604 | case XBDIP_32: | | 611 | case XBDIP_32: |
605 | { | | 612 | { |
606 | blkif_x86_32_sring_t *sring = (void *)xbdi->xbdi_ring_va; | | 613 | blkif_x86_32_sring_t *sring = (void *)xbdi->xbdi_ring_va; |
607 | BACK_RING_INIT(&xbdi->xbdi_ring.ring_32, sring, PAGE_SIZE); | | 614 | BACK_RING_INIT(&xbdi->xbdi_ring.ring_32, sring, PAGE_SIZE); |
608 | break; | | 615 | break; |
| @@ -617,26 +624,27 @@ xbdback_connect(struct xbdback_instance | | | @@ -617,26 +624,27 @@ xbdback_connect(struct xbdback_instance |
617 | | | 624 | |
618 | evop.cmd = EVTCHNOP_bind_interdomain; | | 625 | evop.cmd = EVTCHNOP_bind_interdomain; |
619 | evop.u.bind_interdomain.remote_dom = xbdi->xbdi_domid; | | 626 | evop.u.bind_interdomain.remote_dom = xbdi->xbdi_domid; |
620 | evop.u.bind_interdomain.remote_port = revtchn; | | 627 | evop.u.bind_interdomain.remote_port = revtchn; |
621 | err = HYPERVISOR_event_channel_op(&evop); | | 628 | err = HYPERVISOR_event_channel_op(&evop); |
622 | if (err) { | | 629 | if (err) { |
623 | aprint_error("blkback %s: " | | 630 | aprint_error("blkback %s: " |
624 | "can't get event channel: %d\n", | | 631 | "can't get event channel: %d\n", |
625 | xbusd->xbusd_otherend, err); | | 632 | xbusd->xbusd_otherend, err); |
626 | xenbus_dev_fatal(xbusd, err, | | 633 | xenbus_dev_fatal(xbusd, err, |
627 | "can't bind event channel", xbusd->xbusd_otherend); | | 634 | "can't bind event channel", xbusd->xbusd_otherend); |
628 | goto err2; | | 635 | goto err2; |
629 | } | | 636 | } |
| | | 637 | XENPRINTF(("xbdback %s: connect evchannel %d\n", xbusd->xbusd_path, xbdi->xbdi_evtchn)); |
630 | xbdi->xbdi_evtchn = evop.u.bind_interdomain.local_port; | | 638 | xbdi->xbdi_evtchn = evop.u.bind_interdomain.local_port; |
631 | | | 639 | |
632 | event_set_handler(xbdi->xbdi_evtchn, xbdback_evthandler, | | 640 | event_set_handler(xbdi->xbdi_evtchn, xbdback_evthandler, |
633 | xbdi, IPL_BIO, xbdi->xbdi_name); | | 641 | xbdi, IPL_BIO, xbdi->xbdi_name); |
634 | aprint_verbose("xbd backend domain %d handle %#x (%d) " | | 642 | aprint_verbose("xbd backend domain %d handle %#x (%d) " |
635 | "using event channel %d, protocol %s\n", xbdi->xbdi_domid, | | 643 | "using event channel %d, protocol %s\n", xbdi->xbdi_domid, |
636 | xbdi->xbdi_handle, xbdi->xbdi_handle, xbdi->xbdi_evtchn, proto); | | 644 | xbdi->xbdi_handle, xbdi->xbdi_handle, xbdi->xbdi_evtchn, proto); |
637 | | | 645 | |
638 | /* enable the xbdback event handler machinery */ | | 646 | /* enable the xbdback event handler machinery */ |
639 | xbdi->xbdi_status = WAITING; | | 647 | xbdi->xbdi_status = WAITING; |
640 | hypervisor_enable_event(xbdi->xbdi_evtchn); | | 648 | hypervisor_enable_event(xbdi->xbdi_evtchn); |
641 | hypervisor_notify_via_evtchn(xbdi->xbdi_evtchn); | | 649 | hypervisor_notify_via_evtchn(xbdi->xbdi_evtchn); |
642 | | | 650 | |
| @@ -756,26 +764,27 @@ xbdback_backend_changed(struct xenbus_wa | | | @@ -756,26 +764,27 @@ xbdback_backend_changed(struct xenbus_wa |
756 | return; | | 764 | return; |
757 | } | | 765 | } |
758 | xbdi->xbdi_dev = dev; | | 766 | xbdi->xbdi_dev = dev; |
759 | err = xenbus_read(NULL, xbusd->xbusd_path, "mode", NULL, &mode); | | 767 | err = xenbus_read(NULL, xbusd->xbusd_path, "mode", NULL, &mode); |
760 | if (err) { | | 768 | if (err) { |
761 | printf("xbdback: failed to read %s/mode: %d\n", | | 769 | printf("xbdback: failed to read %s/mode: %d\n", |
762 | xbusd->xbusd_path, err); | | 770 | xbusd->xbusd_path, err); |
763 | return; | | 771 | return; |
764 | } | | 772 | } |
765 | if (mode[0] == 'w') | | 773 | if (mode[0] == 'w') |
766 | xbdi->xbdi_ro = false; | | 774 | xbdi->xbdi_ro = false; |
767 | else | | 775 | else |
768 | xbdi->xbdi_ro = true; | | 776 | xbdi->xbdi_ro = true; |
| | | 777 | free(mode, M_DEVBUF); |
769 | major = major(xbdi->xbdi_dev); | | 778 | major = major(xbdi->xbdi_dev); |
770 | devname = devsw_blk2name(major); | | 779 | devname = devsw_blk2name(major); |
771 | if (devname == NULL) { | | 780 | if (devname == NULL) { |
772 | printf("xbdback %s: unknown device 0x%"PRIx64"\n", | | 781 | printf("xbdback %s: unknown device 0x%"PRIx64"\n", |
773 | xbusd->xbusd_path, xbdi->xbdi_dev); | | 782 | xbusd->xbusd_path, xbdi->xbdi_dev); |
774 | return; | | 783 | return; |
775 | } | | 784 | } |
776 | xbdi->xbdi_bdevsw = bdevsw_lookup(xbdi->xbdi_dev); | | 785 | xbdi->xbdi_bdevsw = bdevsw_lookup(xbdi->xbdi_dev); |
777 | if (xbdi->xbdi_bdevsw == NULL) { | | 786 | if (xbdi->xbdi_bdevsw == NULL) { |
778 | printf("xbdback %s: no bdevsw for device 0x%"PRIx64"\n", | | 787 | printf("xbdback %s: no bdevsw for device 0x%"PRIx64"\n", |
779 | xbusd->xbusd_path, xbdi->xbdi_dev); | | 788 | xbusd->xbusd_path, xbdi->xbdi_dev); |
780 | return; | | 789 | return; |
781 | } | | 790 | } |