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 1cc9098..3e7a102 100644
--- a/tools/libxl/libxl_device.c
+++ b/tools/libxl/libxl_device.c
@@ -811,8 +811,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,
>backend_domid);
@@ -75,9 +135,20 @@ static int libxl__device_from_usbctrl(libxl__gc *gc,
uint32_t domid,
{