]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
bhyve: add xhci tablet support
authorRoman Bogorodskiy <bogorodskiy@gmail.com>
Mon, 20 Mar 2017 13:58:51 +0000 (17:58 +0400)
committerRoman Bogorodskiy <bogorodskiy@gmail.com>
Sun, 26 Mar 2017 15:22:30 +0000 (19:22 +0400)
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:

 - Introduces a new capability bit for XHCI support in bhyve
 - Adds an XHCI controller and tabled support with 1:1 mapping
   between them
 - Adds a couple of unit tests

13 files changed:
src/bhyve/bhyve_capabilities.c
src/bhyve/bhyve_capabilities.h
src/bhyve/bhyve_command.c
src/bhyve/bhyve_device.c
tests/bhyvexml2argvdata/bhyvexml2argv-input-xhci-tablet.args [new file with mode: 0644]
tests/bhyvexml2argvdata/bhyvexml2argv-input-xhci-tablet.ldargs [new file with mode: 0644]
tests/bhyvexml2argvdata/bhyvexml2argv-input-xhci-tablet.xml [new file with mode: 0644]
tests/bhyvexml2argvdata/bhyvexml2argv-xhci-multiple-controllers.xml [new file with mode: 0644]
tests/bhyvexml2argvdata/bhyvexml2argv-xhci-multiple-devs.xml [new file with mode: 0644]
tests/bhyvexml2argvdata/bhyvexml2argv-xhci-no-devs.xml [new file with mode: 0644]
tests/bhyvexml2argvtest.c
tests/bhyvexml2xmloutdata/bhyvexml2xmlout-input-xhci-tablet.xml [new file with mode: 0644]
tests/bhyvexml2xmltest.c

index 6769f1888ae269515de4cd67e02c99950aaf050f..f97834242d512c95012537effc1194ad67b4981d 100644 (file)
@@ -310,6 +310,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)
 {
@@ -337,6 +349,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;
index 194061fde6dc09db3f6c6ad52bcbfb807a674a38..0e310e6eda7663af78be3c798e7c64f460371aa4 100644 (file)
@@ -48,6 +48,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);
index ec7a71572eb1ee8661e144e70badcf29dad321ae..e0528ed77a2c0259de5282b8c56c62bf4ef2f0b5 100644 (file)
@@ -248,6 +248,45 @@ bhyveBuildAHCIControllerArgStr(const virDomainDef *def,
     return ret;
 }
 
+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,
@@ -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++) {
index a3a263b7e27954ec1bee8275f267a0026e18014d..fdfd512e1062ecfe70947b4d5b722e67a13bc9a5 100644 (file)
@@ -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 (file)
index 0000000..b1c0c94
--- /dev/null
@@ -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 (file)
index 0000000..32538b5
--- /dev/null
@@ -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 (file)
index 0000000..95492e6
--- /dev/null
@@ -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 (file)
index 0000000..b3f2592
--- /dev/null
@@ -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 (file)
index 0000000..b0828f6
--- /dev/null
@@ -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 (file)
index 0000000..3230633
--- /dev/null
@@ -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>
index 4cbc398b74c7027c4db5ac8fb3c79e46a3c39c6e..475e62666961aca75dd8d655c56fa1364bbba0b4 100644 (file)
@@ -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 (file)
index 0000000..797868e
--- /dev/null
@@ -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>
index ba9af29960e7298890080d5f24ce31cbf0e18cf2..3270fee3ce00d75916e033dd348e7a76bb948eec 100644 (file)
@@ -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);