diff mbox

[v5,3/5] libxl: add new pvusb backend "qusb" provided by qemu

Message ID 1459339558-29183-4-git-send-email-jgross@suse.com (mailing list archive)
State New, archived
Headers show

Commit Message

Juergen Gross March 30, 2016, 12:05 p.m. UTC
Add a new pvusb backend type "qusb" which is provided by qemu. It can
be selected either by specifying the type directly in the configuration
or it is selected automatically by libxl in case there is no "usbback"
driver loaded.

Signed-off-by: Juergen Gross <jgross@suse.com>
---
V4: bail out in case of usbback_is_loaded() error as requested by
    Chun Yan Liu
---
 docs/man/xl.cfg.pod.5                |  11 +++-
 tools/libxl/libxl_device.c           |   3 +-
 tools/libxl/libxl_dm.c               |   8 +++
 tools/libxl/libxl_internal.h         |   1 +
 tools/libxl/libxl_pvusb.c            | 116 ++++++++++++++++++++++++++++-------
 tools/libxl/libxl_types.idl          |   1 +
 tools/libxl/libxl_types_internal.idl |   1 +
 7 files changed, 115 insertions(+), 26 deletions(-)

Comments

Wei Liu March 30, 2016, 2:19 p.m. UTC | #1
On Wed, Mar 30, 2016 at 02:05:56PM +0200, Juergen Gross wrote:
> Add a new pvusb backend type "qusb" which is provided by qemu. It can
> be selected either by specifying the type directly in the configuration
> or it is selected automatically by libxl in case there is no "usbback"
> driver loaded.
> 
> Signed-off-by: Juergen Gross <jgross@suse.com>
> ---
> V4: bail out in case of usbback_is_loaded() error as requested by
>     Chun Yan Liu
> ---
[...]
>  /* Add usbctrl information to xenstore.
>   *
> - * Adding a usb controller will add a new 'vusb' device in xenstore, and
> - * add corresponding frontend, backend information to it. According to
> - * "update_json", decide wether to update json config file.
> + * Adding a usb controller will add a new 'qusb' or 'vusb' device in xenstore,
> + * and add corresponding frontend, backend information to it. According to
> + * "update_json", decide whether to update json config file.
>   */
>  static int libxl__device_usbctrl_add_xenstore(libxl__gc *gc, uint32_t domid,
>                                                libxl_device_usbctrl *usbctrl,
> @@ -121,6 +144,15 @@ static int libxl__device_usbctrl_add_xenstore(libxl__gc *gc, uint32_t domid,
>  
>          DEVICE_ADD(usbctrl, usbctrls, domid, &usbctrl_saved,
>                     COMPARE_USBCTRL, &d_config);
> +
> +        if (usbctrl->type == LIBXL_USBCTRL_TYPE_QUSB) {
> +            if (!libxl__query_qemu_backend(gc, domid, usbctrl->backend_domid,
> +                                           "qusb", false)) {

This needs to be sorted out.

And this is maybe a rather dumb question: the xenstore paths for qusb
and kernel backend are the same? What is the likelihood that one
deviates from the other? Note that this is not suggesting that you
over-engineer current code, it's just something that needs clarifying.

Wei.
Juergen Gross March 30, 2016, 2:34 p.m. UTC | #2
On 30/03/16 16:19, Wei Liu wrote:
> On Wed, Mar 30, 2016 at 02:05:56PM +0200, Juergen Gross wrote:
>> Add a new pvusb backend type "qusb" which is provided by qemu. It can
>> be selected either by specifying the type directly in the configuration
>> or it is selected automatically by libxl in case there is no "usbback"
>> driver loaded.
>>
>> Signed-off-by: Juergen Gross <jgross@suse.com>
>> ---
>> V4: bail out in case of usbback_is_loaded() error as requested by
>>     Chun Yan Liu
>> ---
> [...]
>>  /* Add usbctrl information to xenstore.
>>   *
>> - * Adding a usb controller will add a new 'vusb' device in xenstore, and
>> - * add corresponding frontend, backend information to it. According to
>> - * "update_json", decide wether to update json config file.
>> + * Adding a usb controller will add a new 'qusb' or 'vusb' device in xenstore,
>> + * and add corresponding frontend, backend information to it. According to
>> + * "update_json", decide whether to update json config file.
>>   */
>>  static int libxl__device_usbctrl_add_xenstore(libxl__gc *gc, uint32_t domid,
>>                                                libxl_device_usbctrl *usbctrl,
>> @@ -121,6 +144,15 @@ static int libxl__device_usbctrl_add_xenstore(libxl__gc *gc, uint32_t domid,
>>  
>>          DEVICE_ADD(usbctrl, usbctrls, domid, &usbctrl_saved,
>>                     COMPARE_USBCTRL, &d_config);
>> +
>> +        if (usbctrl->type == LIBXL_USBCTRL_TYPE_QUSB) {
>> +            if (!libxl__query_qemu_backend(gc, domid, usbctrl->backend_domid,
>> +                                           "qusb", false)) {
> 
> This needs to be sorted out.

What do you mean?

> And this is maybe a rather dumb question: the xenstore paths for qusb
> and kernel backend are the same? What is the likelihood that one
> deviates from the other? Note that this is not suggesting that you
> over-engineer current code, it's just something that needs clarifying.

There is an existing pvusb kernel backend implementation in kernel-xen
of openSUSE and SLE. The port of that implementation hasn't been
accepted in Linux upstream as it was regarded to fit better in qemu.

So the qemu base backend is designed in a way to be compatible to the
already existing kernel backend. Future enhancements will be made on the
qemu based backend only (as far as SUSE is involved).

So the frontend related Xenstore paths are the same, while the backend
paths are different ("vusb" vs. "qusb"). And yes, I've tested the same
domU with both backends.


Juergen
Wei Liu March 30, 2016, 2:38 p.m. UTC | #3
On Wed, Mar 30, 2016 at 04:34:20PM +0200, Juergen Gross wrote:
> On 30/03/16 16:19, Wei Liu wrote:
> > On Wed, Mar 30, 2016 at 02:05:56PM +0200, Juergen Gross wrote:
> >> Add a new pvusb backend type "qusb" which is provided by qemu. It can
> >> be selected either by specifying the type directly in the configuration
> >> or it is selected automatically by libxl in case there is no "usbback"
> >> driver loaded.
> >>
> >> Signed-off-by: Juergen Gross <jgross@suse.com>
> >> ---
> >> V4: bail out in case of usbback_is_loaded() error as requested by
> >>     Chun Yan Liu
> >> ---
> > [...]
> >>  /* Add usbctrl information to xenstore.
> >>   *
> >> - * Adding a usb controller will add a new 'vusb' device in xenstore, and
> >> - * add corresponding frontend, backend information to it. According to
> >> - * "update_json", decide wether to update json config file.
> >> + * Adding a usb controller will add a new 'qusb' or 'vusb' device in xenstore,
> >> + * and add corresponding frontend, backend information to it. According to
> >> + * "update_json", decide whether to update json config file.
> >>   */
> >>  static int libxl__device_usbctrl_add_xenstore(libxl__gc *gc, uint32_t domid,
> >>                                                libxl_device_usbctrl *usbctrl,
> >> @@ -121,6 +144,15 @@ static int libxl__device_usbctrl_add_xenstore(libxl__gc *gc, uint32_t domid,
> >>  
> >>          DEVICE_ADD(usbctrl, usbctrls, domid, &usbctrl_saved,
> >>                     COMPARE_USBCTRL, &d_config);
> >> +
> >> +        if (usbctrl->type == LIBXL_USBCTRL_TYPE_QUSB) {
> >> +            if (!libxl__query_qemu_backend(gc, domid, usbctrl->backend_domid,
> >> +                                           "qusb", false)) {
> > 
> > This needs to be sorted out.
> 
> What do you mean?
> 

Nothing -- it just meant it depends on a previous patch.

> > And this is maybe a rather dumb question: the xenstore paths for qusb
> > and kernel backend are the same? What is the likelihood that one
> > deviates from the other? Note that this is not suggesting that you
> > over-engineer current code, it's just something that needs clarifying.
> 
> There is an existing pvusb kernel backend implementation in kernel-xen
> of openSUSE and SLE. The port of that implementation hasn't been
> accepted in Linux upstream as it was regarded to fit better in qemu.
> 
> So the qemu base backend is designed in a way to be compatible to the
> already existing kernel backend. Future enhancements will be made on the
> qemu based backend only (as far as SUSE is involved).
> 
> So the frontend related Xenstore paths are the same, while the backend
> paths are different ("vusb" vs. "qusb"). And yes, I've tested the same
> domU with both backends.
> 

Cool, that makes sense.

Wei.

> 
> Juergen
>
Wei Liu March 30, 2016, 4:16 p.m. UTC | #4
On Wed, Mar 30, 2016 at 04:34:20PM +0200, Juergen Gross wrote:
> On 30/03/16 16:19, Wei Liu wrote:
> > On Wed, Mar 30, 2016 at 02:05:56PM +0200, Juergen Gross wrote:
> >> Add a new pvusb backend type "qusb" which is provided by qemu. It can
> >> be selected either by specifying the type directly in the configuration
> >> or it is selected automatically by libxl in case there is no "usbback"
> >> driver loaded.
> >>
> >> Signed-off-by: Juergen Gross <jgross@suse.com>
> >> ---
> >> V4: bail out in case of usbback_is_loaded() error as requested by
> >>     Chun Yan Liu
> >> ---
> > [...]
> >>  /* Add usbctrl information to xenstore.
> >>   *
> >> - * Adding a usb controller will add a new 'vusb' device in xenstore, and
> >> - * add corresponding frontend, backend information to it. According to
> >> - * "update_json", decide wether to update json config file.
> >> + * Adding a usb controller will add a new 'qusb' or 'vusb' device in xenstore,
> >> + * and add corresponding frontend, backend information to it. According to
> >> + * "update_json", decide whether to update json config file.
> >>   */
> >>  static int libxl__device_usbctrl_add_xenstore(libxl__gc *gc, uint32_t domid,
> >>                                                libxl_device_usbctrl *usbctrl,
> >> @@ -121,6 +144,15 @@ static int libxl__device_usbctrl_add_xenstore(libxl__gc *gc, uint32_t domid,
> >>  
> >>          DEVICE_ADD(usbctrl, usbctrls, domid, &usbctrl_saved,
> >>                     COMPARE_USBCTRL, &d_config);
> >> +
> >> +        if (usbctrl->type == LIBXL_USBCTRL_TYPE_QUSB) {
> >> +            if (!libxl__query_qemu_backend(gc, domid, usbctrl->backend_domid,
> >> +                                           "qusb", false)) {
> > 
> > This needs to be sorted out.
> 
> What do you mean?
> 
> > And this is maybe a rather dumb question: the xenstore paths for qusb
> > and kernel backend are the same? What is the likelihood that one
> > deviates from the other? Note that this is not suggesting that you
> > over-engineer current code, it's just something that needs clarifying.
> 
> There is an existing pvusb kernel backend implementation in kernel-xen
> of openSUSE and SLE. The port of that implementation hasn't been
> accepted in Linux upstream as it was regarded to fit better in qemu.
> 
> So the qemu base backend is designed in a way to be compatible to the
> already existing kernel backend. Future enhancements will be made on the
> qemu based backend only (as far as SUSE is involved).
> 
> So the frontend related Xenstore paths are the same, while the backend
> paths are different ("vusb" vs. "qusb"). And yes, I've tested the same
> domU with both backends.
> 

I forgot to ask -- When you repost, can you add such information to
commit message? Thanks.

> 
> Juergen
>
Juergen Gross March 30, 2016, 5:09 p.m. UTC | #5
On 30/03/16 18:16, Wei Liu wrote:
> On Wed, Mar 30, 2016 at 04:34:20PM +0200, Juergen Gross wrote:
>> On 30/03/16 16:19, Wei Liu wrote:
>>> On Wed, Mar 30, 2016 at 02:05:56PM +0200, Juergen Gross wrote:
>>>> Add a new pvusb backend type "qusb" which is provided by qemu. It can
>>>> be selected either by specifying the type directly in the configuration
>>>> or it is selected automatically by libxl in case there is no "usbback"
>>>> driver loaded.
>>>>
>>>> Signed-off-by: Juergen Gross <jgross@suse.com>
>>>> ---
>>>> V4: bail out in case of usbback_is_loaded() error as requested by
>>>>     Chun Yan Liu
>>>> ---
>>> [...]
>>>>  /* Add usbctrl information to xenstore.
>>>>   *
>>>> - * Adding a usb controller will add a new 'vusb' device in xenstore, and
>>>> - * add corresponding frontend, backend information to it. According to
>>>> - * "update_json", decide wether to update json config file.
>>>> + * Adding a usb controller will add a new 'qusb' or 'vusb' device in xenstore,
>>>> + * and add corresponding frontend, backend information to it. According to
>>>> + * "update_json", decide whether to update json config file.
>>>>   */
>>>>  static int libxl__device_usbctrl_add_xenstore(libxl__gc *gc, uint32_t domid,
>>>>                                                libxl_device_usbctrl *usbctrl,
>>>> @@ -121,6 +144,15 @@ static int libxl__device_usbctrl_add_xenstore(libxl__gc *gc, uint32_t domid,
>>>>  
>>>>          DEVICE_ADD(usbctrl, usbctrls, domid, &usbctrl_saved,
>>>>                     COMPARE_USBCTRL, &d_config);
>>>> +
>>>> +        if (usbctrl->type == LIBXL_USBCTRL_TYPE_QUSB) {
>>>> +            if (!libxl__query_qemu_backend(gc, domid, usbctrl->backend_domid,
>>>> +                                           "qusb", false)) {
>>>
>>> This needs to be sorted out.
>>
>> What do you mean?
>>
>>> And this is maybe a rather dumb question: the xenstore paths for qusb
>>> and kernel backend are the same? What is the likelihood that one
>>> deviates from the other? Note that this is not suggesting that you
>>> over-engineer current code, it's just something that needs clarifying.
>>
>> There is an existing pvusb kernel backend implementation in kernel-xen
>> of openSUSE and SLE. The port of that implementation hasn't been
>> accepted in Linux upstream as it was regarded to fit better in qemu.
>>
>> So the qemu base backend is designed in a way to be compatible to the
>> already existing kernel backend. Future enhancements will be made on the
>> qemu based backend only (as far as SUSE is involved).
>>
>> So the frontend related Xenstore paths are the same, while the backend
>> paths are different ("vusb" vs. "qusb"). And yes, I've tested the same
>> domU with both backends.
>>
> 
> I forgot to ask -- When you repost, can you add such information to
> commit message? Thanks.

Sure.


Juergen
diff mbox

Patch

diff --git a/docs/man/xl.cfg.pod.5 b/docs/man/xl.cfg.pod.5
index ec739cc..a4cc1b3 100644
--- a/docs/man/xl.cfg.pod.5
+++ b/docs/man/xl.cfg.pod.5
@@ -737,8 +737,15 @@  Possible B<KEY>s are:
 
 =item B<type=TYPE>
 
-Specifies the usb controller type.  Currently only 'pv' and 'auto'
-are supported.
+Specifies the usb controller type.
+
+"pv" denotes a kernel based pvusb backend.
+
+"qusb" specifies a qemu base backend for pvusb.
+
+"auto" (the default) determines whether a kernel based backend is installed.
+If this is the case, "pv" is selected, "qusb" will be selected if no kernel
+backend is currently available.
 
 =item B<version=VERSION>
 
diff --git a/tools/libxl/libxl_device.c b/tools/libxl/libxl_device.c
index 4ced9b6..eba3087 100644
--- a/tools/libxl/libxl_device.c
+++ b/tools/libxl/libxl_device.c
@@ -680,7 +680,8 @@  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)
+                if (dev->backend_kind == LIBXL__DEVICE_KIND_VUSB ||
+                    dev->backend_kind == LIBXL__DEVICE_KIND_QUSB)
                     libxl__initiate_device_usbctrl_remove(egc, aodev);
                 else
                     libxl__initiate_device_generic_remove(egc, aodev);
diff --git a/tools/libxl/libxl_dm.c b/tools/libxl/libxl_dm.c
index 7d9abbe..8f5c4e6 100644
--- a/tools/libxl/libxl_dm.c
+++ b/tools/libxl/libxl_dm.c
@@ -2166,6 +2166,14 @@  int libxl__need_xenpv_qemu(libxl__gc *gc, libxl_domain_config *d_config)
         }
     }
 
+    for (i = 0; i < d_config->num_usbctrls; i++) {
+       if (d_config->usbctrls[i].type == LIBXL_USBCTRL_TYPE_QUSB &&
+           d_config->usbctrls[i].backend_domid == domid) {
+            ret = 1;
+            goto out;
+        }
+    }
+
 out:
     return ret;
 }
diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
index c06ffc0..20b6122 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -487,6 +487,7 @@  typedef struct {
 #define QEMU_BACKEND(dev) (\
     (dev)->backend_kind == LIBXL__DEVICE_KIND_QDISK || \
     (dev)->backend_kind == LIBXL__DEVICE_KIND_VFB || \
+    (dev)->backend_kind == LIBXL__DEVICE_KIND_QUSB || \
     (dev)->backend_kind == LIBXL__DEVICE_KIND_VKBD)
 
 #define XC_PCI_BDF             "0x%x, 0x%x, 0x%x, 0x%x"
diff --git a/tools/libxl/libxl_pvusb.c b/tools/libxl/libxl_pvusb.c
index 5f92628..68e5673 100644
--- a/tools/libxl/libxl_pvusb.c
+++ b/tools/libxl/libxl_pvusb.c
@@ -22,6 +22,21 @@ 
 
 #define USBHUB_CLASS_CODE 9
 
+static int usbback_is_loaded(libxl__gc *gc)
+{
+    int r;
+    struct stat st;
+
+    r = lstat(SYSFS_USBBACK_DRIVER, &st);
+
+    if (r == 0)
+        return 1;
+    if (r < 0 && errno == ENOENT)
+        return 0;
+    LOGE(ERROR, "Accessing %s", SYSFS_USBBACK_DRIVER);
+    return ERROR_FAIL;
+}
+
 static int libxl__device_usbctrl_setdefault(libxl__gc *gc, uint32_t domid,
                                             libxl_device_usbctrl *usbctrl)
 {
@@ -36,7 +51,11 @@  static int libxl__device_usbctrl_setdefault(libxl__gc *gc, uint32_t domid,
 
     if (usbctrl->type == LIBXL_USBCTRL_TYPE_AUTO) {
         if (domtype == LIBXL_DOMAIN_TYPE_PV) {
-            usbctrl->type = LIBXL_USBCTRL_TYPE_PV;
+            rc = usbback_is_loaded(gc);
+            if (rc < 0)
+                goto out;
+            usbctrl->type = rc ? LIBXL_USBCTRL_TYPE_PV
+                               : LIBXL_USBCTRL_TYPE_QUSB;
         } else if (domtype == LIBXL_DOMAIN_TYPE_HVM) {
             /* FIXME: See if we can detect PV frontend */
             usbctrl->type = LIBXL_USBCTRL_TYPE_DEVICEMODEL;
@@ -45,6 +64,8 @@  static int libxl__device_usbctrl_setdefault(libxl__gc *gc, uint32_t domid,
 
     rc = libxl__resolve_domid(gc, usbctrl->backend_domname,
                               &usbctrl->backend_domid);
+
+out:
     return rc;
 }
 
@@ -54,7 +75,9 @@  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    = LIBXL__DEVICE_KIND_VUSB;
+    device->backend_kind    = (usbctrl->type == LIBXL_USBCTRL_TYPE_PV)
+                              ? LIBXL__DEVICE_KIND_VUSB
+                              : LIBXL__DEVICE_KIND_QUSB;
     device->devid           = usbctrl->devid;
     device->domid           = domid;
     device->kind            = LIBXL__DEVICE_KIND_VUSB;
@@ -64,9 +87,9 @@  int libxl__device_from_usbctrl(libxl__gc *gc, uint32_t domid,
 
 /* Add usbctrl information to xenstore.
  *
- * Adding a usb controller will add a new 'vusb' device in xenstore, and
- * add corresponding frontend, backend information to it. According to
- * "update_json", decide wether to update json config file.
+ * Adding a usb controller will add a new 'qusb' or 'vusb' device in xenstore,
+ * and add corresponding frontend, backend information to it. According to
+ * "update_json", decide whether to update json config file.
  */
 static int libxl__device_usbctrl_add_xenstore(libxl__gc *gc, uint32_t domid,
                                               libxl_device_usbctrl *usbctrl,
@@ -121,6 +144,15 @@  static int libxl__device_usbctrl_add_xenstore(libxl__gc *gc, uint32_t domid,
 
         DEVICE_ADD(usbctrl, usbctrls, domid, &usbctrl_saved,
                    COMPARE_USBCTRL, &d_config);
+
+        if (usbctrl->type == LIBXL_USBCTRL_TYPE_QUSB) {
+            if (!libxl__query_qemu_backend(gc, domid, usbctrl->backend_domid,
+                                           "qusb", false)) {
+                LOG(ERROR, "backend type not supported by device model");
+                rc = ERROR_FAIL;
+                goto out;
+            }
+        }
     }
 
     for (;;) {
@@ -159,6 +191,18 @@  out:
     return rc;
 }
 
+static char *pvusb_get_device_type(libxl_usbctrl_type type)
+{
+    switch (type) {
+    case LIBXL_USBCTRL_TYPE_PV:
+        return "vusb";
+    case LIBXL_USBCTRL_TYPE_QUSB:
+        return "qusb";
+    default:
+        return NULL;
+    }
+}
+
 /* AO operation to add a usb controller.
  *
  * Generally, it does:
@@ -190,7 +234,8 @@  void libxl__device_usbctrl_add(libxl__egc *egc, uint32_t domid,
         }
     }
 
-    if (usbctrl->type != LIBXL_USBCTRL_TYPE_PV) {
+    if (usbctrl->type != LIBXL_USBCTRL_TYPE_PV &&
+        usbctrl->type != LIBXL_USBCTRL_TYPE_QUSB) {
         LOG(ERROR, "Unsupported USB controller type");
         rc = ERROR_FAIL;
         goto out;
@@ -252,7 +297,8 @@  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) {
+    if (usbctrlinfo.type != LIBXL_USBCTRL_TYPE_PV &&
+        usbctrlinfo.type != LIBXL_USBCTRL_TYPE_QUSB) {
         LOG(ERROR, "Unsupported USB controller type");
         rc = ERROR_FAIL;
         goto out;
@@ -293,6 +339,7 @@  static const char *vusb_be_from_xs_fe(libxl__gc *gc, const char *fe_path,
     const char *be_path;
     int r;
     uint32_t be_domid, fe_domid;
+    char be_type[16];
 
     r = libxl__xs_read_checked(gc, XBT_NULL, GCSPRINTF("%s/backend", fe_path),
                                &be_path);
@@ -300,10 +347,10 @@  static const char *vusb_be_from_xs_fe(libxl__gc *gc, const char *fe_path,
 
     /* Check to see that it has the proper form, and that fe_domid ==
      * target domid */
-    r = sscanf(be_path, "/local/domain/%d/backend/vusb/%d",
-               &be_domid, &fe_domid);
+    r = sscanf(be_path, "/local/domain/%d/backend/%15[^/]/%d",
+               &be_domid, be_type, &fe_domid);
 
-    if (r != 2 || fe_domid != tgt_domid) {
+    if (r != 3 || fe_domid != tgt_domid) {
         LOG(ERROR, "Malformed backend, refusing to use");
         return NULL;
     }
@@ -740,8 +787,9 @@  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/vusb/%d/%d/port/%d",
+            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);
             rc = libxl__xs_read_checked(gc, XBT_NULL, path, &tmp);
             if (rc) goto out;
@@ -883,11 +931,12 @@  out:
 
 /* Add usb information to xenstore
  *
- * Adding a usb device won't create new 'vusb' device, but only write
+ * Adding a usb device won't create new 'qusb'/'vusb' device, but only write
  * the device busid to the controller:port in xenstore.
  */
 static int libxl__device_usbdev_add_xenstore(libxl__gc *gc, uint32_t domid,
                                              libxl_device_usbdev *usbdev,
+                                             libxl_usbctrl_type type,
                                              bool update_json)
 {
     char *be_path, *busid;
@@ -931,8 +980,9 @@  static int libxl__device_usbdev_add_xenstore(libxl__gc *gc, uint32_t domid,
             if (rc) goto out;
         }
 
-        be_path = GCSPRINTF("%s/backend/vusb/%d/%d/port/%d",
+        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);
 
         LOG(DEBUG, "Adding usb device %s to xenstore: controller %d, port %d",
@@ -956,12 +1006,14 @@  out:
 }
 
 static int libxl__device_usbdev_remove_xenstore(libxl__gc *gc, uint32_t domid,
-                                                libxl_device_usbdev *usbdev)
+                                                libxl_device_usbdev *usbdev,
+                                                libxl_usbctrl_type type)
 {
     char *be_path;
 
-    be_path = GCSPRINTF("%s/backend/vusb/%d/%d/port/%d",
+    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);
 
     LOG(DEBUG, "Removing usb device from xenstore: controller %d, port %d",
@@ -971,12 +1023,14 @@  static int libxl__device_usbdev_remove_xenstore(libxl__gc *gc, uint32_t domid,
 }
 
 static char *usbdev_busid_from_ctrlport(libxl__gc *gc, uint32_t domid,
-                                        libxl_device_usbdev *usbdev)
+                                        libxl_device_usbdev *usbdev,
+                                        libxl_usbctrl_type type)
 {
     return libxl__xs_read(gc, XBT_NULL,
-                          GCSPRINTF("%s/backend/vusb/%d/%d/port/%d",
+                          GCSPRINTF("%s/backend/%s/%d/%d/port/%d",
                               libxl__xs_get_dompath(gc, LIBXL_TOOLSTACK_DOMID),
-                          domid, usbdev->ctrl, usbdev->port));
+                              pvusb_get_device_type(type),
+                              domid, usbdev->ctrl, usbdev->port));
 }
 
 /* get original driver path of usb interface, stored in @drvpath */
@@ -1333,15 +1387,25 @@  static int do_usbdev_add(libxl__gc *gc, uint32_t domid,
             goto out;
         }
 
-        rc = libxl__device_usbdev_add_xenstore(gc, domid, usbdev, update_json);
+        rc = libxl__device_usbdev_add_xenstore(gc, domid, usbdev,
+                                               LIBXL_USBCTRL_TYPE_PV,
+                                               update_json);
         if (rc) goto out;
 
         rc = usbback_dev_assign(gc, busid);
         if (rc) {
-            libxl__device_usbdev_remove_xenstore(gc, domid, usbdev);
+            libxl__device_usbdev_remove_xenstore(gc, domid, usbdev,
+                                                 LIBXL_USBCTRL_TYPE_PV);
             goto out;
         }
         break;
+    case LIBXL_USBCTRL_TYPE_QUSB:
+        rc = libxl__device_usbdev_add_xenstore(gc, domid, usbdev,
+                                               LIBXL_USBCTRL_TYPE_QUSB,
+                                               update_json);
+        if (rc) goto out;
+
+        break;
     case LIBXL_USBCTRL_TYPE_DEVICEMODEL:
     default:
         LOG(ERROR, "Unsupported usb controller type");
@@ -1458,7 +1522,7 @@  static int do_usbdev_remove(libxl__gc *gc, uint32_t domid,
 
     switch (usbctrlinfo.type) {
     case LIBXL_USBCTRL_TYPE_PV:
-        busid = usbdev_busid_from_ctrlport(gc, domid, usbdev);
+        busid = usbdev_busid_from_ctrlport(gc, domid, usbdev, usbctrlinfo.type);
         if (!busid) {
             rc = ERROR_FAIL;
             goto out;
@@ -1483,7 +1547,8 @@  static int do_usbdev_remove(libxl__gc *gc, uint32_t domid,
             goto out;
         }
 
-        rc = libxl__device_usbdev_remove_xenstore(gc, domid, usbdev);
+        rc = libxl__device_usbdev_remove_xenstore(gc, domid, usbdev,
+                                                  LIBXL_USBCTRL_TYPE_PV);
         if (rc) {
             LOG(ERROR, "Error removing device from guest."
                 " Try running usbdev-detach again.");
@@ -1499,6 +1564,12 @@  static int do_usbdev_remove(libxl__gc *gc, uint32_t domid,
         }
 
         break;
+    case LIBXL_USBCTRL_TYPE_QUSB:
+        rc = libxl__device_usbdev_remove_xenstore(gc, domid, usbdev,
+                                                  LIBXL_USBCTRL_TYPE_QUSB);
+        if (rc) goto out;
+
+        break;
     case LIBXL_USBCTRL_TYPE_DEVICEMODEL:
     default:
         LOG(ERROR, "Unsupported usb controller type");
@@ -1583,7 +1654,6 @@  int libxl_ctrlport_to_device_usbdev(libxl_ctx *ctx,
     dompath = libxl__xs_get_dompath(gc, domid);
 
     fe_path = GCSPRINTF("%s/device/vusb/%d", dompath, ctrl);
-
     be_path = vusb_be_from_xs_fe(gc, fe_path, domid);
     if (!be_path) {
         rc = ERROR_FAIL;
diff --git a/tools/libxl/libxl_types.idl b/tools/libxl/libxl_types.idl
index 59b183c..304aa11 100644
--- a/tools/libxl/libxl_types.idl
+++ b/tools/libxl/libxl_types.idl
@@ -618,6 +618,7 @@  libxl_usbctrl_type = Enumeration("usbctrl_type", [
     (0, "AUTO"),
     (1, "PV"),
     (2, "DEVICEMODEL"),
+    (3, "QUSB"),
     ])
 
 libxl_usbdev_type = Enumeration("usbdev_type", [
diff --git a/tools/libxl/libxl_types_internal.idl b/tools/libxl/libxl_types_internal.idl
index 696f5f8..177f9b7 100644
--- a/tools/libxl/libxl_types_internal.idl
+++ b/tools/libxl/libxl_types_internal.idl
@@ -23,6 +23,7 @@  libxl__device_kind = Enumeration("device_kind", [
     (7, "CONSOLE"),
     (8, "VTPM"),
     (9, "VUSB"),
+    (10, "QUSB"),
     ])
 
 libxl__console_backend = Enumeration("console_backend", [