From patchwork Tue Sep 20 12:01:09 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Juergen Gross X-Patchwork-Id: 9341535 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 60BB2607D0 for ; Tue, 20 Sep 2016 12:04:04 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 4E87429624 for ; Tue, 20 Sep 2016 12:04:04 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 42B9129628; Tue, 20 Sep 2016 12:04:04 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-4.2 required=2.0 tests=BAYES_00, RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 15C6929625 for ; Tue, 20 Sep 2016 12:03:59 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.84_2) (envelope-from ) id 1bmJjj-00047D-Qx; Tue, 20 Sep 2016 12:01:19 +0000 Received: from mail6.bemta5.messagelabs.com ([195.245.231.135]) by lists.xenproject.org with esmtp (Exim 4.84_2) (envelope-from ) id 1bmJji-00046F-BB for xen-devel@lists.xen.org; Tue, 20 Sep 2016 12:01:18 +0000 Received: from [85.158.139.211] by server-4.bemta-5.messagelabs.com id 36/CA-12285-D0521E75; Tue, 20 Sep 2016 12:01:17 +0000 X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFrrBLMWRWlGSWpSXmKPExsVyuP0Ovy6P6sN wg1NbDC2WfFzM4sDocXT3b6YAxijWzLyk/IoE1ozF9w6zFtw5zVjx7lIbawPjrH7GLkZODgkB I4m3E/8xdTFycQgJLGSU6GnZzgqSYBNQldhw/RSYLSIgLXHt82WwBmaBYokF316AxYUF7CQOb T7EDGKzANWfX3wQLM4LFJ93+SsTxAI5ieszp4PZnAL2Egd7/4PVCwHVrJ79hnUCI/cCRoZVjB rFqUVlqUW6RkZ6SUWZ6RkluYmZObqGBqZ6uanFxYnpqTmJScV6yfm5mxiBPq5nYGDcwbin3e8 QoyQHk5Iorxzfg3AhvqT8lMqMxOKM+KLSnNTiQ4wyHBxKErziyg/DhQSLUtNTK9Iyc4DBBpOW 4OBREuFlAknzFhck5hZnpkOkTjEqSonz+oEkBEASGaV5cG2wAL/EKCslzMvIwMAgxFOQWpSbW YIq/4pRnINRSZjXFmQKT2ZeCdz0V0CLmYAWb/n5AGRxSSJCSqqBUazalj86t8PBcWOK0K90Hb dJJjKWa3v0Pu9fkZ29vF/u09Q53puO/NBi/nl1s/Hvw02P3/UrVbq8r9Y8H51Zqbbutti0oMp tqcpzPi/mkpxq/WdmcGf2uqXyTAf3ffy06e3V8LmsGux/51vs/cm9YOG26dODVE7xNQeFqvXG nD/8+XmMpvGHRiWW4oxEQy3mouJEAP6smuprAgAA X-Env-Sender: jgross@suse.com X-Msg-Ref: server-16.tower-206.messagelabs.com!1474372876!44592340!1 X-Originating-IP: [195.135.220.15] X-SpamReason: No, hits=0.0 required=7.0 tests= X-StarScan-Received: X-StarScan-Version: 8.84; banners=-,-,- X-VirusChecked: Checked Received: (qmail 537 invoked from network); 20 Sep 2016 12:01:16 -0000 Received: from mx2.suse.de (HELO mx2.suse.de) (195.135.220.15) by server-16.tower-206.messagelabs.com with DHE-RSA-CAMELLIA256-SHA encrypted SMTP; 20 Sep 2016 12:01:16 -0000 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (charybdis-ext.suse.de [195.135.220.254]) by mx2.suse.de (Postfix) with ESMTP id 33799AD9E; Tue, 20 Sep 2016 12:01:16 +0000 (UTC) From: Juergen Gross To: xen-devel@lists.xen.org Date: Tue, 20 Sep 2016 14:01:09 +0200 Message-Id: <1474372870-9408-4-git-send-email-jgross@suse.com> X-Mailer: git-send-email 2.6.6 In-Reply-To: <1474372870-9408-1-git-send-email-jgross@suse.com> References: <1474372870-9408-1-git-send-email-jgross@suse.com> Cc: George.Dunlap@eu.citrix.com, wei.liu2@citrix.com, ian.jackson@eu.citrix.com, Juergen Gross Subject: [Xen-devel] [PATCH v3 3/4] libxl: add HVM usb passthrough support X-BeenThere: xen-devel@lists.xen.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: xen-devel-bounces@lists.xen.org Sender: "Xen-devel" X-Virus-Scanned: ClamAV using ClamSMTP Add HVM usb passthrough support to libxl by using qemu's capability to emulate standard USB controllers. A USB controller is added via qmp command to the emulated hardware when a usbctrl device of type DEVICEMODEL is requested. Depending on the requested speed the appropriate hardware type is selected. A host USB device can then be added to the emulated USB controller via qmp command. Removing of the devices is done via qmp commands, too. Signed-off-by: Juergen Gross Acked-by: Wei Liu --- V3: renamed pvusb_get_port_path() to vusb_get_port_path() (George Dunlap) V2: code style issues (Wei Liu) adding some assert()s (Wei Liu) split out libxl__device_usbctrl_del_xenstore() (Wei Liu) --- tools/libxl/libxl_device.c | 3 +- tools/libxl/libxl_usb.c | 397 +++++++++++++++++++++++++++++++++++---------- tools/libxl/xl_cmdimpl.c | 4 +- 3 files changed, 311 insertions(+), 93 deletions(-) diff --git a/tools/libxl/libxl_device.c b/tools/libxl/libxl_device.c index f53f772..2acfb48 100644 --- a/tools/libxl/libxl_device.c +++ b/tools/libxl/libxl_device.c @@ -808,8 +808,7 @@ void libxl__devices_destroy(libxl__egc *egc, libxl__devices_remove_state *drs) aodev->action = LIBXL__DEVICE_ACTION_REMOVE; aodev->dev = dev; aodev->force = drs->force; - if (dev->backend_kind == LIBXL__DEVICE_KIND_VUSB || - dev->backend_kind == LIBXL__DEVICE_KIND_QUSB) + if (dev->kind == LIBXL__DEVICE_KIND_VUSB) libxl__initiate_device_usbctrl_remove(egc, aodev); else libxl__initiate_device_generic_remove(egc, aodev); diff --git a/tools/libxl/libxl_usb.c b/tools/libxl/libxl_usb.c index 2493464..76260b1 100644 --- a/tools/libxl/libxl_usb.c +++ b/tools/libxl/libxl_usb.c @@ -17,6 +17,7 @@ #include "libxl_internal.h" #include +#include #define USBBACK_INFO_PATH "/libxl/usbback" @@ -43,12 +44,6 @@ static int libxl__device_usbctrl_setdefault(libxl__gc *gc, uint32_t domid, int rc; libxl_domain_type domtype = libxl__domain_type(gc, domid); - if (!usbctrl->version) - usbctrl->version = 2; - - if (!usbctrl->ports) - usbctrl->ports = 8; - if (usbctrl->type == LIBXL_USBCTRL_TYPE_AUTO) { if (domtype == LIBXL_DOMAIN_TYPE_PV) { rc = usbback_is_loaded(gc); @@ -62,6 +57,71 @@ static int libxl__device_usbctrl_setdefault(libxl__gc *gc, uint32_t domid, } } + switch (usbctrl->type) { + case LIBXL_USBCTRL_TYPE_PV: + case LIBXL_USBCTRL_TYPE_QUSB: + if (!usbctrl->version) + usbctrl->version = 2; + if (usbctrl->version < 1 || usbctrl->version > 2) { + LOG(ERROR, + "USB version for paravirtualized devices must be 1 or 2"); + rc = ERROR_INVAL; + goto out; + } + if (!usbctrl->ports) + usbctrl->ports = 8; + if (usbctrl->ports < 1 || usbctrl->ports > USBIF_MAX_PORTNR) { + LOG(ERROR, "Number of ports for USB controller is limited to %u", + USBIF_MAX_PORTNR); + rc = ERROR_INVAL; + goto out; + } + break; + case LIBXL_USBCTRL_TYPE_DEVICEMODEL: + if (!usbctrl->version) + usbctrl->version = 2; + switch (usbctrl->version) { + case 1: + /* uhci controller in qemu has fixed number of ports. */ + if (usbctrl->ports && usbctrl->ports != 2) { + LOG(ERROR, + "Number of ports for USB controller of version 1 is always 2"); + rc = ERROR_INVAL; + goto out; + } + usbctrl->ports = 2; + break; + case 2: + /* ehci controller in qemu has fixed number of ports. */ + if (usbctrl->ports && usbctrl->ports != 6) { + LOG(ERROR, + "Number of ports for USB controller of version 2 is always 6"); + rc = ERROR_INVAL; + goto out; + } + usbctrl->ports = 6; + break; + case 3: + if (!usbctrl->ports) + usbctrl->ports = 8; + /* xhci controller in qemu supports up to 15 ports. */ + if (usbctrl->ports > 15) { + LOG(ERROR, + "Number of ports for USB controller of version 3 is limited to 15"); + rc = ERROR_INVAL; + goto out; + } + break; + default: + LOG(ERROR, "Illegal USB version"); + rc = ERROR_INVAL; + goto out; + } + break; + default: + break; + } + rc = libxl__resolve_domid(gc, usbctrl->backend_domname, &usbctrl->backend_domid); @@ -75,9 +135,20 @@ static int libxl__device_from_usbctrl(libxl__gc *gc, uint32_t domid, { device->backend_devid = usbctrl->devid; device->backend_domid = usbctrl->backend_domid; - device->backend_kind = (usbctrl->type == LIBXL_USBCTRL_TYPE_PV) - ? LIBXL__DEVICE_KIND_VUSB - : LIBXL__DEVICE_KIND_QUSB; + switch (usbctrl->type) { + case LIBXL_USBCTRL_TYPE_PV: + device->backend_kind = LIBXL__DEVICE_KIND_VUSB; + break; + case LIBXL_USBCTRL_TYPE_QUSB: + device->backend_kind = LIBXL__DEVICE_KIND_QUSB; + break; + case LIBXL_USBCTRL_TYPE_DEVICEMODEL: + device->backend_kind = LIBXL__DEVICE_KIND_NONE; + break; + default: + assert(0); /* can't really happen. */ + break; + } device->devid = usbctrl->devid; device->domid = domid; device->kind = LIBXL__DEVICE_KIND_VUSB; @@ -85,6 +156,35 @@ static int libxl__device_from_usbctrl(libxl__gc *gc, uint32_t domid, return 0; } +static const char *vusb_be_from_xs_libxl_type(libxl__gc *gc, + const char *libxl_path, + libxl_usbctrl_type type) +{ + const char *be_path = NULL, *tmp; + int r; + + if (type == LIBXL_USBCTRL_TYPE_AUTO) { + r = libxl__xs_read_checked(gc, XBT_NULL, + GCSPRINTF("%s/type", libxl_path), &tmp); + if (r || libxl_usbctrl_type_from_string(tmp, &type)) + goto out; + } + + if (type == LIBXL_USBCTRL_TYPE_DEVICEMODEL) { + be_path = libxl_path; + goto out; + } + + r = libxl__xs_read_checked(gc, XBT_NULL, + GCSPRINTF("%s/backend", libxl_path), + &be_path); + if (r) + be_path = NULL; + +out: + return be_path; +} + /* Add usbctrl information to xenstore. * * Adding a usb controller will add a new 'qusb' or 'vusb' device in xenstore, @@ -96,7 +196,7 @@ static int libxl__device_usbctrl_add_xenstore(libxl__gc *gc, uint32_t domid, bool update_json) { libxl__device *device; - flexarray_t *front; + flexarray_t *front = NULL; flexarray_t *back; xs_transaction_t t = XBT_NULL; int i, rc; @@ -112,13 +212,21 @@ static int libxl__device_usbctrl_add_xenstore(libxl__gc *gc, uint32_t domid, rc = libxl__device_from_usbctrl(gc, domid, usbctrl, device); if (rc) goto out; - front = flexarray_make(gc, 4, 1); back = flexarray_make(gc, 12, 1); - flexarray_append_pair(back, "frontend-id", GCSPRINTF("%d", domid)); - flexarray_append_pair(back, "online", "1"); - flexarray_append_pair(back, "state", - GCSPRINTF("%d", XenbusStateInitialising)); + if (device->backend_kind != LIBXL__DEVICE_KIND_NONE) { + front = flexarray_make(gc, 4, 1); + + flexarray_append_pair(back, "frontend-id", GCSPRINTF("%d", domid)); + flexarray_append_pair(back, "online", "1"); + flexarray_append_pair(back, "state", + GCSPRINTF("%d", XenbusStateInitialising)); + flexarray_append_pair(front, "backend-id", + GCSPRINTF("%d", usbctrl->backend_domid)); + flexarray_append_pair(front, "state", + GCSPRINTF("%d", XenbusStateInitialising)); + } + flexarray_append_pair(back, "type", (char *)libxl_usbctrl_type_to_string(usbctrl->type)); flexarray_append_pair(back, "usb-ver", GCSPRINTF("%d", usbctrl->version)); @@ -127,11 +235,6 @@ static int libxl__device_usbctrl_add_xenstore(libxl__gc *gc, uint32_t domid, for (i = 0; i < usbctrl->ports; i++) flexarray_append_pair(back, GCSPRINTF("port/%d", i + 1), ""); - flexarray_append_pair(front, "backend-id", - GCSPRINTF("%d", usbctrl->backend_domid)); - flexarray_append_pair(front, "state", - GCSPRINTF("%d", XenbusStateInitialising)); - if (update_json) { lock = libxl__lock_domain_userdata(gc, domid); if (!lock) { @@ -196,15 +299,7 @@ out: static const char *vusb_be_from_xs_libxl(libxl__gc *gc, const char *libxl_path) { - const char *be_path; - int r; - - r = libxl__xs_read_checked(gc, XBT_NULL, - GCSPRINTF("%s/backend", libxl_path), - &be_path); - if (r || !be_path) return NULL; - - return be_path; + return vusb_be_from_xs_libxl_type(gc, libxl_path, LIBXL_USBCTRL_TYPE_AUTO); } static void libxl__device_usbctrl_del_xenstore(libxl__gc *gc, uint32_t domid, @@ -216,7 +311,7 @@ static void libxl__device_usbctrl_del_xenstore(libxl__gc *gc, uint32_t domid, libxl_path = GCSPRINTF("%s/device/vusb/%d", libxl__xs_libxl_path(gc, domid), usbctrl->devid); - be_path = vusb_be_from_xs_libxl(gc, libxl_path); + be_path = vusb_be_from_xs_libxl_type(gc, libxl_path, usbctrl->type); for (;;) { rc = libxl__xs_transaction_start(gc, &t); @@ -247,6 +342,93 @@ static char *pvusb_get_device_type(libxl_usbctrl_type type) } } +/* Send qmp commands to create a usb controller in qemu. + * + * Depending on the speed (usbctrl->version) we create: + * - piix3-usb-uhci (version=1), always 2 ports + * - usb-ehci (version=2), always 6 ports + * - nec-usb-xhci (version=3), up to 15 ports + */ +static int libxl__device_usbctrl_add_hvm(libxl__gc *gc, uint32_t domid, + libxl_device_usbctrl *usbctrl) +{ + flexarray_t *qmp_args; + + qmp_args = flexarray_make(gc, 8, 1); + + switch (usbctrl->version) { + case 1: + flexarray_append_pair(qmp_args, "driver", "piix3-usb-uhci"); + break; + case 2: + flexarray_append_pair(qmp_args, "driver", "usb-ehci"); + break; + case 3: + flexarray_append_pair(qmp_args, "driver", "nec-usb-xhci"); + flexarray_append_pair(qmp_args, "p2", GCSPRINTF("%d", usbctrl->ports)); + flexarray_append_pair(qmp_args, "p3", GCSPRINTF("%d", usbctrl->ports)); + break; + default: + assert(0); /* Should not be possible. */ + break; + } + + flexarray_append_pair(qmp_args, "id", + GCSPRINTF("xenusb-%d", usbctrl->devid)); + + return libxl__qmp_run_command_flexarray(gc, domid, "device_add", qmp_args); +} + +/* Send qmp commands to delete a usb controller in qemu. */ +static int libxl__device_usbctrl_del_hvm(libxl__gc *gc, uint32_t domid, + int devid) +{ + flexarray_t *qmp_args; + + qmp_args = flexarray_make(gc, 2, 1); + flexarray_append_pair(qmp_args, "id", GCSPRINTF("xenusb-%d", devid)); + + return libxl__qmp_run_command_flexarray(gc, domid, "device_del", qmp_args); +} + +/* Send qmp commands to create a usb device in qemu. */ +static int libxl__device_usbdev_add_hvm(libxl__gc *gc, uint32_t domid, + libxl_device_usbdev *usbdev) +{ + flexarray_t *qmp_args; + + qmp_args = flexarray_make(gc, 12, 1); + flexarray_append_pair(qmp_args, "id", + GCSPRINTF("xenusb-%d-%d", + usbdev->u.hostdev.hostbus, + usbdev->u.hostdev.hostaddr)); + flexarray_append_pair(qmp_args, "driver", "usb-host"); + flexarray_append_pair(qmp_args, "bus", + GCSPRINTF("xenusb-%d.0", usbdev->ctrl)); + flexarray_append_pair(qmp_args, "port", GCSPRINTF("%d", usbdev->port)); + flexarray_append_pair(qmp_args, "hostbus", + GCSPRINTF("%d", usbdev->u.hostdev.hostbus)); + flexarray_append_pair(qmp_args, "hostaddr", + GCSPRINTF("%d", usbdev->u.hostdev.hostaddr)); + + return libxl__qmp_run_command_flexarray(gc, domid, "device_add", qmp_args); +} + +/* Send qmp commands to delete a usb device in qemu. */ +static int libxl__device_usbdev_del_hvm(libxl__gc *gc, uint32_t domid, + libxl_device_usbdev *usbdev) +{ + flexarray_t *qmp_args; + + qmp_args = flexarray_make(gc, 2, 1); + flexarray_append_pair(qmp_args, "id", + GCSPRINTF("xenusb-%d-%d", + usbdev->u.hostdev.hostbus, + usbdev->u.hostdev.hostaddr)); + + return libxl__qmp_run_command_flexarray(gc, domid, "device_del", qmp_args); +} + /* AO operation to add a usb controller. * * Generally, it does: @@ -278,13 +460,6 @@ static void libxl__device_usbctrl_add(libxl__egc *egc, uint32_t domid, } } - if (usbctrl->type != LIBXL_USBCTRL_TYPE_PV && - usbctrl->type != LIBXL_USBCTRL_TYPE_QUSB) { - LOG(ERROR, "Unsupported USB controller type"); - rc = ERROR_FAIL; - goto out; - } - rc = libxl__device_usbctrl_add_xenstore(gc, domid, usbctrl, aodev->update_json); if (rc) goto out; @@ -293,6 +468,12 @@ static void libxl__device_usbctrl_add(libxl__egc *egc, uint32_t domid, rc = libxl__device_from_usbctrl(gc, domid, usbctrl, device); if (rc) goto outrm; + if (device->backend_kind == LIBXL__DEVICE_KIND_NONE) { + rc = libxl__device_usbctrl_add_hvm(gc, domid, usbctrl); + if (rc) goto outrm; + goto out; + } + aodev->dev = device; aodev->action = LIBXL__DEVICE_ACTION_ADD; libxl__wait_device_connection(egc, aodev); @@ -347,13 +528,6 @@ void libxl__initiate_device_usbctrl_remove(libxl__egc *egc, rc = libxl_device_usbctrl_getinfo(CTX, domid, &usbctrl, &usbctrlinfo); if (rc) goto out; - if (usbctrlinfo.type != LIBXL_USBCTRL_TYPE_PV && - usbctrlinfo.type != LIBXL_USBCTRL_TYPE_QUSB) { - LOG(ERROR, "Unsupported USB controller type"); - rc = ERROR_FAIL; - goto out; - } - /* Remove usb devices first */ rc = libxl__device_usbdev_list_for_usbctrl(gc, domid, usbctrl_devid, &usbdevs, &num_usbdev); @@ -368,6 +542,13 @@ void libxl__initiate_device_usbctrl_remove(libxl__egc *egc, } } + if (usbctrlinfo.type == LIBXL_USBCTRL_TYPE_DEVICEMODEL) { + rc = libxl__device_usbctrl_del_hvm(gc, domid, usbctrl_devid); + if (!rc) + libxl__device_usbctrl_del_xenstore(gc, domid, &usbctrl); + goto out; + } + libxl_device_usbctrl_dispose(&usbctrl); libxl_usbctrlinfo_dispose(&usbctrlinfo); @@ -428,15 +609,20 @@ libxl_device_usbctrl_list(libxl_ctx *ctx, uint32_t domid, int *num) }) libxl_path = GCSPRINTF("%s/%s", libxl_vusbs_path, *entry); - be_path = READ_SUBPATH(libxl_path, "backend"); - if (!be_path) goto out; - ret = libxl__backendpath_parse_domid(gc, be_path, - &usbctrl->backend_domid); + libxl_usbctrl_type_from_string(READ_SUBPATH(libxl_path, "type"), + &usbctrl->type); + if (usbctrl->type == LIBXL_USBCTRL_TYPE_DEVICEMODEL) { + be_path = libxl_path; + ret = libxl__get_domid(gc, &usbctrl->backend_domid); + } else { + be_path = READ_SUBPATH(libxl_path, "backend"); + if (!be_path) goto out; + ret = libxl__backendpath_parse_domid(gc, be_path, + &usbctrl->backend_domid); + } if (ret) goto out; usbctrl->version = READ_SUBPATH_INT(be_path, "usb-ver"); usbctrl->ports = READ_SUBPATH_INT(be_path, "num-ports"); - libxl_usbctrl_type_from_string(READ_SUBPATH(libxl_path, "type"), - &usbctrl->type); #undef READ_SUBPATH #undef READ_SUBPATH_INT @@ -481,24 +667,33 @@ int libxl_device_usbctrl_getinfo(libxl_ctx *ctx, uint32_t domid, tmp ? atoi(tmp) : -1; \ }) - dompath = libxl__xs_get_dompath(gc, domid); - fe_path = GCSPRINTF("%s/device/vusb/%d", dompath, usbctrl->devid); libxl_dom_path = libxl__xs_libxl_path(gc, domid); libxl_path = GCSPRINTF("%s/device/vusb/%d", libxl_dom_path, usbctrl->devid); - be_path = READ_SUBPATH(libxl_path, "backend"); - usbctrlinfo->backend = libxl__strdup(NOGC, be_path); - rc = libxl__backendpath_parse_domid(gc, be_path, &usbctrl->backend_domid); - if (rc) goto out; - usbctrlinfo->state = READ_SUBPATH_INT(fe_path, "state"); - usbctrlinfo->evtch = READ_SUBPATH_INT(fe_path, "event-channel"); - usbctrlinfo->ref_urb = READ_SUBPATH_INT(fe_path, "urb-ring-ref"); - usbctrlinfo->ref_conn = READ_SUBPATH_INT(fe_path, "urb-ring-ref"); - usbctrlinfo->frontend = libxl__strdup(NOGC, fe_path); - usbctrlinfo->frontend_id = domid; - usbctrlinfo->ports = READ_SUBPATH_INT(be_path, "num-ports"); - usbctrlinfo->version = READ_SUBPATH_INT(be_path, "usb-ver");; - tmp = READ_SUBPATH(libxl_path, "type"); - libxl_usbctrl_type_from_string(tmp, &usbctrlinfo->type); + libxl_usbctrl_type_from_string(READ_SUBPATH(libxl_path, "type"), + &usbctrlinfo->type); + + if (usbctrlinfo->type != LIBXL_USBCTRL_TYPE_DEVICEMODEL) { + dompath = libxl__xs_get_dompath(gc, domid); + fe_path = GCSPRINTF("%s/device/vusb/%d", dompath, usbctrl->devid); + be_path = READ_SUBPATH(libxl_path, "backend"); + usbctrlinfo->backend = libxl__strdup(NOGC, be_path); + rc = libxl__backendpath_parse_domid(gc, be_path, + &usbctrl->backend_domid); + if (rc) goto out; + usbctrlinfo->state = READ_SUBPATH_INT(fe_path, "state"); + usbctrlinfo->evtch = READ_SUBPATH_INT(fe_path, "event-channel"); + usbctrlinfo->ref_urb = READ_SUBPATH_INT(fe_path, "urb-ring-ref"); + usbctrlinfo->ref_conn = READ_SUBPATH_INT(fe_path, "urb-ring-ref"); + usbctrlinfo->frontend = libxl__strdup(NOGC, fe_path); + usbctrlinfo->frontend_id = domid; + usbctrlinfo->ports = READ_SUBPATH_INT(be_path, "num-ports"); + usbctrlinfo->version = READ_SUBPATH_INT(be_path, "usb-ver"); + } else { + usbctrlinfo->ports = READ_SUBPATH_INT(libxl_path, "num-ports"); + usbctrlinfo->version = READ_SUBPATH_INT(libxl_path, "usb-ver"); + rc = libxl__get_domid(gc, &usbctrl->backend_domid); + if (rc) goto out; + } #undef READ_SUBPATH #undef READ_SUBPATH_INT @@ -790,6 +985,21 @@ libxl_device_usbdev_list(libxl_ctx *ctx, uint32_t domid, int *num) return usbdevs; } +static char *vusb_get_port_path(libxl__gc *gc, uint32_t domid, + libxl_usbctrl_type type, int ctrl, int port) +{ + char *path; + + if (type == LIBXL_USBCTRL_TYPE_DEVICEMODEL) + path = GCSPRINTF("%s/device/vusb", libxl__xs_libxl_path(gc, domid)); + else + path = GCSPRINTF("%s/backend/%s/%d", + libxl__xs_get_dompath(gc, LIBXL_TOOLSTACK_DOMID), + pvusb_get_device_type(type), domid); + + return GCSPRINTF("%s/%d/port/%d", path, ctrl, port); +} + /* find first unused controller:port and give that to usb device */ static int libxl__device_usbdev_set_default_usbctrl(libxl__gc *gc, uint32_t domid, @@ -809,10 +1019,8 @@ libxl__device_usbdev_set_default_usbctrl(libxl__gc *gc, uint32_t domid, for (j = 0; j < usbctrls[i].ports; j++) { const char *path, *tmp; - path = GCSPRINTF("%s/backend/%s/%d/%d/port/%d", - libxl__xs_get_dompath(gc, LIBXL_TOOLSTACK_DOMID), - pvusb_get_device_type(usbctrls[i].type), - domid, usbctrls[i].devid, j + 1); + path = vusb_get_port_path(gc, domid, usbctrls[i].type, + usbctrls[i].devid, j + 1); rc = libxl__xs_read_checked(gc, XBT_NULL, path, &tmp); if (rc) goto out; @@ -881,13 +1089,6 @@ static int libxl__device_usbdev_setdefault(libxl__gc *gc, } } - if (usbctrl->type != LIBXL_USBCTRL_TYPE_PV && - usbctrl->type != LIBXL_USBCTRL_TYPE_QUSB) { - LOG(ERROR, "Unsupported USB controller type"); - rc = ERROR_FAIL; - goto out; - } - rc = libxl__device_usbctrl_add_xenstore(gc, domid, usbctrl, update_json); if (rc) goto out; @@ -1013,10 +1214,8 @@ static int libxl__device_usbdev_add_xenstore(libxl__gc *gc, uint32_t domid, if (rc) goto out; } - be_path = GCSPRINTF("%s/backend/%s/%d/%d/port/%d", - libxl__xs_get_dompath(gc, LIBXL_TOOLSTACK_DOMID), - pvusb_get_device_type(type), - domid, usbdev->ctrl, usbdev->port); + be_path = vusb_get_port_path(gc, domid, type, usbdev->ctrl, + usbdev->port); LOG(DEBUG, "Adding usb device %s to xenstore: controller %d, port %d", busid, usbdev->ctrl, usbdev->port); @@ -1044,10 +1243,7 @@ static int libxl__device_usbdev_remove_xenstore(libxl__gc *gc, uint32_t domid, { char *be_path; - be_path = GCSPRINTF("%s/backend/%s/%d/%d/port/%d", - libxl__xs_get_dompath(gc, LIBXL_TOOLSTACK_DOMID), - pvusb_get_device_type(type), - domid, usbdev->ctrl, usbdev->port); + be_path = vusb_get_port_path(gc, domid, type, usbdev->ctrl, usbdev->port); LOG(DEBUG, "Removing usb device from xenstore: controller %d, port %d", usbdev->ctrl, usbdev->port); @@ -1060,10 +1256,8 @@ static char *usbdev_busid_from_ctrlport(libxl__gc *gc, uint32_t domid, libxl_usbctrl_type type) { return libxl__xs_read(gc, XBT_NULL, - GCSPRINTF("%s/backend/%s/%d/%d/port/%d", - libxl__xs_get_dompath(gc, LIBXL_TOOLSTACK_DOMID), - pvusb_get_device_type(type), - domid, usbdev->ctrl, usbdev->port)); + vusb_get_port_path(gc, domid, type, usbdev->ctrl, + usbdev->port)); } /* get original driver path of usb interface, stored in @drvpath */ @@ -1427,6 +1621,18 @@ static int do_usbdev_add(libxl__gc *gc, uint32_t domid, break; case LIBXL_USBCTRL_TYPE_DEVICEMODEL: + rc = libxl__device_usbdev_add_xenstore(gc, domid, usbdev, + LIBXL_USBCTRL_TYPE_DEVICEMODEL, + update_json); + if (rc) goto out; + + rc = libxl__device_usbdev_add_hvm(gc, domid, usbdev); + if (rc) { + libxl__device_usbdev_remove_xenstore(gc, domid, usbdev, + LIBXL_USBCTRL_TYPE_DEVICEMODEL); + goto out; + } + break; default: LOG(ERROR, "Unsupported usb controller type"); rc = ERROR_FAIL; @@ -1594,6 +1800,19 @@ static int do_usbdev_remove(libxl__gc *gc, uint32_t domid, break; case LIBXL_USBCTRL_TYPE_DEVICEMODEL: + rc = libxl__device_usbdev_remove_xenstore(gc, domid, usbdev, + LIBXL_USBCTRL_TYPE_DEVICEMODEL); + if (rc) goto out; + + rc = libxl__device_usbdev_del_hvm(gc, domid, usbdev); + if (rc) { + libxl__device_usbdev_add_xenstore(gc, domid, usbdev, + LIBXL_USBCTRL_TYPE_DEVICEMODEL, + false); + goto out; + } + + break; default: LOG(ERROR, "Unsupported usb controller type"); rc = ERROR_FAIL; diff --git a/tools/libxl/xl_cmdimpl.c b/tools/libxl/xl_cmdimpl.c index 62237d0..cb43c00 100644 --- a/tools/libxl/xl_cmdimpl.c +++ b/tools/libxl/xl_cmdimpl.c @@ -3728,14 +3728,14 @@ int main_usblist(int argc, char **argv) } for (i = 0; i < numctrl; ++i) { - printf("%-6s %-6s %-3s %-5s %-7s %-5s\n", + printf("%-6s %-12s %-3s %-5s %-7s %-5s\n", "Devid", "Type", "BE", "state", "usb-ver", "ports"); libxl_usbctrlinfo_init(&usbctrlinfo); if (!libxl_device_usbctrl_getinfo(ctx, domid, &usbctrls[i], &usbctrlinfo)) { - printf("%-6d %-6s %-3d %-5d %-7d %-5d\n", + printf("%-6d %-12s %-3d %-5d %-7d %-5d\n", usbctrlinfo.devid, libxl_usbctrl_type_to_string(usbctrlinfo.type), usbctrlinfo.backend_id, usbctrlinfo.state,