[libvirt] [PATCH 2/2] bhyve: add xhci tablet support

Roman Bogorodskiy bogorodskiy at gmail.com
Mon Mar 20 16:31:59 UTC 2017


Along with video and VNC support, bhyve has introduced USB tablet
support as an input device. This tablet is exposed to a guest
as a device on an XHCI controller.

At present, tablet is the only supported device on the XHCI controller
in bhyve, so to make things simple, it's allowed to only have a
single XHCI controller with a single tablet device.

In detail, this commit:

 - Introduce a new capability bit for XHCI support in bhyve
 - Add an XHCI controller and tabled support with 1:1 mapping
   between them
 - Add a couple of unit tests
---
 src/bhyve/bhyve_capabilities.c                     | 15 +++++++
 src/bhyve/bhyve_capabilities.h                     |  1 +
 src/bhyve/bhyve_command.c                          | 50 ++++++++++++++++++++++
 src/bhyve/bhyve_device.c                           |  4 +-
 .../bhyvexml2argv-input-xhci-tablet.args           |  9 ++++
 .../bhyvexml2argv-input-xhci-tablet.ldargs         |  3 ++
 .../bhyvexml2argv-input-xhci-tablet.xml            | 18 ++++++++
 .../bhyvexml2argv-xhci-multiple-controllers.xml    | 19 ++++++++
 .../bhyvexml2argv-xhci-multiple-devs.xml           | 19 ++++++++
 .../bhyvexml2argv-xhci-no-devs.xml                 | 17 ++++++++
 tests/bhyvexml2argvtest.c                          | 10 ++++-
 .../bhyvexml2xmlout-input-xhci-tablet.xml          | 31 ++++++++++++++
 tests/bhyvexml2xmltest.c                           |  3 ++
 13 files changed, 197 insertions(+), 2 deletions(-)
 create mode 100644 tests/bhyvexml2argvdata/bhyvexml2argv-input-xhci-tablet.args
 create mode 100644 tests/bhyvexml2argvdata/bhyvexml2argv-input-xhci-tablet.ldargs
 create mode 100644 tests/bhyvexml2argvdata/bhyvexml2argv-input-xhci-tablet.xml
 create mode 100644 tests/bhyvexml2argvdata/bhyvexml2argv-xhci-multiple-controllers.xml
 create mode 100644 tests/bhyvexml2argvdata/bhyvexml2argv-xhci-multiple-devs.xml
 create mode 100644 tests/bhyvexml2argvdata/bhyvexml2argv-xhci-no-devs.xml
 create mode 100644 tests/bhyvexml2xmloutdata/bhyvexml2xmlout-input-xhci-tablet.xml

diff --git a/src/bhyve/bhyve_capabilities.c b/src/bhyve/bhyve_capabilities.c
index f72fdea41..a34c596f0 100644
--- a/src/bhyve/bhyve_capabilities.c
+++ b/src/bhyve/bhyve_capabilities.c
@@ -286,6 +286,18 @@ bhyveProbeCapsFramebuffer(unsigned int *caps, char *binary)
                                       BHYVE_CAP_FBUF);
 }
 
+
+static int
+bhyveProbeCapsXHCIController(unsigned int *caps, char *binary)
+{
+    return bhyveProbeCapsDeviceHelper(caps, binary,
+                                      "-s",
+                                      "0,xhci",
+                                      "pci slot 0:0: unknown device \"xhci\"",
+                                      BHYVE_CAP_FBUF);
+}
+
+
 int
 virBhyveProbeCaps(unsigned int *caps)
 {
@@ -313,6 +325,9 @@ virBhyveProbeCaps(unsigned int *caps)
     if ((ret = bhyveProbeCapsFramebuffer(caps, binary)))
         goto out;
 
+    if ((ret = bhyveProbeCapsXHCIController(caps, binary)))
+        goto out;
+
  out:
     VIR_FREE(binary);
     return ret;
diff --git a/src/bhyve/bhyve_capabilities.h b/src/bhyve/bhyve_capabilities.h
index 3db4f1b88..3db51af02 100644
--- a/src/bhyve/bhyve_capabilities.h
+++ b/src/bhyve/bhyve_capabilities.h
@@ -45,6 +45,7 @@ typedef enum {
     BHYVE_CAP_NET_E1000 = 1 << 2,
     BHYVE_CAP_LPC_BOOTROM = 1 << 3,
     BHYVE_CAP_FBUF = 1 << 4,
+    BHYVE_CAP_XHCI = 1 << 5,
 } virBhyveCapsFlags;
 
 int virBhyveProbeGrubCaps(virBhyveGrubCapsFlags *caps);
diff --git a/src/bhyve/bhyve_command.c b/src/bhyve/bhyve_command.c
index ec7a71572..e0528ed77 100644
--- a/src/bhyve/bhyve_command.c
+++ b/src/bhyve/bhyve_command.c
@@ -249,6 +249,45 @@ bhyveBuildAHCIControllerArgStr(const virDomainDef *def,
 }
 
 static int
+bhyveBuildUSBControllerArgStr(const virDomainDef *def,
+                              virDomainControllerDefPtr controller,
+                              virCommandPtr cmd)
+{
+    size_t i;
+    int ndevices = 0;
+
+    for (i = 0; i < def->ninputs; i++) {
+        virDomainInputDefPtr input = def->inputs[i];
+
+        if (input->bus != VIR_DOMAIN_INPUT_BUS_USB) {
+            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                           _("only USB input devices are supported"));
+            return -1;
+        }
+
+        if (input->type != VIR_DOMAIN_INPUT_TYPE_TABLET) {
+            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                           _("only tablet input devices are supported"));
+            return -1;
+        }
+        ndevices++;
+    }
+
+    if (ndevices != 1) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                       _("only single input device is supported"));
+        return -1;
+    }
+
+    virCommandAddArg(cmd, "-s");
+    virCommandAddArgFormat(cmd, "%d:%d,xhci,tablet",
+                           controller->info.addr.pci.slot,
+                           controller->info.addr.pci.function);
+
+    return 0;
+}
+
+static int
 bhyveBuildVirtIODiskArgStr(const virDomainDef *def ATTRIBUTE_UNUSED,
                      virDomainDiskDefPtr disk,
                      virConnectPtr conn,
@@ -392,6 +431,7 @@ virBhyveProcessBuildBhyveCmd(virConnectPtr conn,
      */
     size_t i;
     bool add_lpc = false;
+    int nusbcontrollers = 0;
 
     virCommandPtr cmd = virCommandNew(BHYVE);
 
@@ -476,6 +516,16 @@ virBhyveProcessBuildBhyveCmd(virConnectPtr conn,
                 if (bhyveBuildAHCIControllerArgStr(def, controller, conn, cmd) < 0)
                     goto error;
                 break;
+        case VIR_DOMAIN_CONTROLLER_TYPE_USB:
+                if (++nusbcontrollers > 1) {
+                        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                                       "%s", _("only single USB controller is supported"));
+                        goto error;
+                }
+
+                if (bhyveBuildUSBControllerArgStr(def, controller, cmd) < 0)
+                    goto error;
+                break;
         }
     }
     for (i = 0; i < def->nnets; i++) {
diff --git a/src/bhyve/bhyve_device.c b/src/bhyve/bhyve_device.c
index a3a263b7e..fdfd512e1 100644
--- a/src/bhyve/bhyve_device.c
+++ b/src/bhyve/bhyve_device.c
@@ -106,7 +106,9 @@ bhyveAssignDevicePCISlots(virDomainDefPtr def,
 
     for (i = 0; i < def->ncontrollers; i++) {
         if ((def->controllers[i]->type == VIR_DOMAIN_CONTROLLER_TYPE_PCI) ||
-            (def->controllers[i]->type == VIR_DOMAIN_CONTROLLER_TYPE_SATA)) {
+            (def->controllers[i]->type == VIR_DOMAIN_CONTROLLER_TYPE_SATA) ||
+            ((def->controllers[i]->type == VIR_DOMAIN_CONTROLLER_TYPE_USB) &&
+             (def->controllers[i]->model == VIR_DOMAIN_CONTROLLER_MODEL_USB_NEC_XHCI))) {
             if (def->controllers[i]->model == VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT ||
                 !virDeviceInfoPCIAddressWanted(&def->controllers[i]->info))
                 continue;
diff --git a/tests/bhyvexml2argvdata/bhyvexml2argv-input-xhci-tablet.args b/tests/bhyvexml2argvdata/bhyvexml2argv-input-xhci-tablet.args
new file mode 100644
index 000000000..b1c0c94d0
--- /dev/null
+++ b/tests/bhyvexml2argvdata/bhyvexml2argv-input-xhci-tablet.args
@@ -0,0 +1,9 @@
+/usr/sbin/bhyve \
+-c 1 \
+-m 214 \
+-u \
+-H \
+-P \
+-s 0:0,hostbridge \
+-s 2:0,xhci,tablet \
+-s 3:0,ahci-hd,/tmp/freebsd.img bhyve
diff --git a/tests/bhyvexml2argvdata/bhyvexml2argv-input-xhci-tablet.ldargs b/tests/bhyvexml2argvdata/bhyvexml2argv-input-xhci-tablet.ldargs
new file mode 100644
index 000000000..32538b558
--- /dev/null
+++ b/tests/bhyvexml2argvdata/bhyvexml2argv-input-xhci-tablet.ldargs
@@ -0,0 +1,3 @@
+/usr/sbin/bhyveload \
+-m 214 \
+-d /tmp/freebsd.img bhyve
diff --git a/tests/bhyvexml2argvdata/bhyvexml2argv-input-xhci-tablet.xml b/tests/bhyvexml2argvdata/bhyvexml2argv-input-xhci-tablet.xml
new file mode 100644
index 000000000..95492e6cb
--- /dev/null
+++ b/tests/bhyvexml2argvdata/bhyvexml2argv-input-xhci-tablet.xml
@@ -0,0 +1,18 @@
+<domain type='bhyve'>
+  <name>bhyve</name>
+  <uuid>df3be7e7-a104-11e3-aeb0-50e5492bd3dc</uuid>
+  <memory>219136</memory>
+  <vcpu>1</vcpu>
+  <os>
+    <type>hvm</type>
+  </os>
+  <devices>
+    <disk type='file'>
+      <driver name='file' type='raw'/>
+      <source file='/tmp/freebsd.img'/>
+      <target dev='hda' bus='sata'/>
+    </disk>
+    <controller type='usb' model='nec-xhci'/>
+    <input type='tablet' bus='usb'/>
+  </devices>
+</domain>
diff --git a/tests/bhyvexml2argvdata/bhyvexml2argv-xhci-multiple-controllers.xml b/tests/bhyvexml2argvdata/bhyvexml2argv-xhci-multiple-controllers.xml
new file mode 100644
index 000000000..b3f259226
--- /dev/null
+++ b/tests/bhyvexml2argvdata/bhyvexml2argv-xhci-multiple-controllers.xml
@@ -0,0 +1,19 @@
+<domain type='bhyve'>
+  <name>bhyve</name>
+  <uuid>df3be7e7-a104-11e3-aeb0-50e5492bd3dc</uuid>
+  <memory>219136</memory>
+  <vcpu>1</vcpu>
+  <os>
+    <type>hvm</type>
+  </os>
+  <devices>
+    <disk type='file'>
+      <driver name='file' type='raw'/>
+      <source file='/tmp/freebsd.img'/>
+      <target dev='hda' bus='sata'/>
+    </disk>
+    <controller type='usb' model='nec-xhci'/>
+    <controller type='usb' model='nec-xhci'/>
+    <input type='tablet' bus='usb'/>
+  </devices>
+</domain>
diff --git a/tests/bhyvexml2argvdata/bhyvexml2argv-xhci-multiple-devs.xml b/tests/bhyvexml2argvdata/bhyvexml2argv-xhci-multiple-devs.xml
new file mode 100644
index 000000000..b0828f632
--- /dev/null
+++ b/tests/bhyvexml2argvdata/bhyvexml2argv-xhci-multiple-devs.xml
@@ -0,0 +1,19 @@
+<domain type='bhyve'>
+  <name>bhyve</name>
+  <uuid>df3be7e7-a104-11e3-aeb0-50e5492bd3dc</uuid>
+  <memory>219136</memory>
+  <vcpu>1</vcpu>
+  <os>
+    <type>hvm</type>
+  </os>
+  <devices>
+    <disk type='file'>
+      <driver name='file' type='raw'/>
+      <source file='/tmp/freebsd.img'/>
+      <target dev='hda' bus='sata'/>
+    </disk>
+    <controller type='usb' model='nec-xhci'/>
+    <input type='tablet' bus='usb'/>
+    <input type='tablet' bus='usb'/>
+  </devices>
+</domain>
diff --git a/tests/bhyvexml2argvdata/bhyvexml2argv-xhci-no-devs.xml b/tests/bhyvexml2argvdata/bhyvexml2argv-xhci-no-devs.xml
new file mode 100644
index 000000000..323063354
--- /dev/null
+++ b/tests/bhyvexml2argvdata/bhyvexml2argv-xhci-no-devs.xml
@@ -0,0 +1,17 @@
+<domain type='bhyve'>
+  <name>bhyve</name>
+  <uuid>df3be7e7-a104-11e3-aeb0-50e5492bd3dc</uuid>
+  <memory>219136</memory>
+  <vcpu>1</vcpu>
+  <os>
+    <type>hvm</type>
+  </os>
+  <devices>
+    <disk type='file'>
+      <driver name='file' type='raw'/>
+      <source file='/tmp/freebsd.img'/>
+      <target dev='hda' bus='sata'/>
+    </disk>
+    <controller type='usb' model='nec-xhci'/>
+  </devices>
+</domain>
diff --git a/tests/bhyvexml2argvtest.c b/tests/bhyvexml2argvtest.c
index 4cbc398b7..475e62666 100644
--- a/tests/bhyvexml2argvtest.c
+++ b/tests/bhyvexml2argvtest.c
@@ -167,7 +167,7 @@ mymain(void)
     driver.grubcaps = BHYVE_GRUB_CAP_CONSDEV;
     driver.bhyvecaps = BHYVE_CAP_RTC_UTC | BHYVE_CAP_AHCI32SLOT | \
                        BHYVE_CAP_NET_E1000 | BHYVE_CAP_LPC_BOOTROM | \
-                       BHYVE_CAP_FBUF;
+                       BHYVE_CAP_FBUF | BHYVE_CAP_XHCI;
 
     DO_TEST("base");
     DO_TEST("acpiapic");
@@ -207,6 +207,14 @@ mymain(void)
     DO_TEST("addr-no32devs-multiple-sata-disks");
     DO_TEST_FAILURE("addr-no32devs-more-than-32-sata-disks");
 
+    /* USB xhci tablet */
+    DO_TEST("input-xhci-tablet");
+    DO_TEST_FAILURE("xhci-multiple-controllers");
+    DO_TEST_FAILURE("xhci-no-devs");
+    DO_TEST_FAILURE("xhci-multiple-devs");
+    driver.bhyvecaps ^= BHYVE_CAP_XHCI;
+    DO_TEST_FAILURE("input-xhci-tablet");
+
     driver.grubcaps = 0;
 
     DO_TEST("serial-grub-nocons");
diff --git a/tests/bhyvexml2xmloutdata/bhyvexml2xmlout-input-xhci-tablet.xml b/tests/bhyvexml2xmloutdata/bhyvexml2xmlout-input-xhci-tablet.xml
new file mode 100644
index 000000000..797868e7f
--- /dev/null
+++ b/tests/bhyvexml2xmloutdata/bhyvexml2xmlout-input-xhci-tablet.xml
@@ -0,0 +1,31 @@
+<domain type='bhyve'>
+  <name>bhyve</name>
+  <uuid>df3be7e7-a104-11e3-aeb0-50e5492bd3dc</uuid>
+  <memory unit='KiB'>219136</memory>
+  <currentMemory unit='KiB'>219136</currentMemory>
+  <vcpu placement='static'>1</vcpu>
+  <os>
+    <type arch='x86_64'>hvm</type>
+    <boot dev='hd'/>
+  </os>
+  <clock offset='utc'/>
+  <on_poweroff>destroy</on_poweroff>
+  <on_reboot>restart</on_reboot>
+  <on_crash>destroy</on_crash>
+  <devices>
+    <disk type='file' device='disk'>
+      <driver name='file' type='raw'/>
+      <source file='/tmp/freebsd.img'/>
+      <target dev='hda' bus='sata'/>
+      <address type='drive' controller='0' bus='0' target='0' unit='0'/>
+    </disk>
+    <controller type='usb' index='0' model='nec-xhci'>
+      <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/>
+    </controller>
+    <controller type='pci' index='0' model='pci-root'/>
+    <controller type='sata' index='0'>
+      <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
+    </controller>
+    <input type='tablet' bus='usb'/>
+  </devices>
+</domain>
diff --git a/tests/bhyvexml2xmltest.c b/tests/bhyvexml2xmltest.c
index ba9af2996..3270fee3c 100644
--- a/tests/bhyvexml2xmltest.c
+++ b/tests/bhyvexml2xmltest.c
@@ -118,6 +118,9 @@ mymain(void)
     DO_TEST_DIFFERENT("addr-no32devs-multiple-sata-disks");
     DO_TEST_FAILURE("addr-no32devs-more-than-32-sata-disks");
 
+    /* USB xhci tablet */
+    DO_TEST_DIFFERENT("input-xhci-tablet");
+
     virObjectUnref(driver.caps);
     virObjectUnref(driver.xmlopt);
 
-- 
2.11.0




More information about the libvir-list mailing list