Run query-pci on the pc and q35 aliases, the 12.0 and the 11.2 types.
With -usb the former two pairs get qemu-xhci at 1d.0, the 11.2 ones
PIIX3 UHCI and ICH9 EHCI plus companions; without -usb there is no
USB controller.

Signed-off-by: Junjie Cao <[email protected]>
---
 tests/qtest/meson.build           |   3 +
 tests/qtest/usb-pc-default-test.c | 135 ++++++++++++++++++++++++++++++
 2 files changed, 138 insertions(+)
 create mode 100644 tests/qtest/usb-pc-default-test.c

diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
index ff4bf9528a..615056876d 100644
--- a/tests/qtest/meson.build
+++ b/tests/qtest/meson.build
@@ -91,6 +91,9 @@ qtests_i386 = \
   (config_all_devices.has_key('CONFIG_USB_UHCI') and                           
             \
    config_all_devices.has_key('CONFIG_USB_EHCI') ? ['usb-hcd-ehci-test'] : []) 
+            \
   (config_all_devices.has_key('CONFIG_USB_XHCI_NEC') ? ['usb-hcd-xhci-test'] : 
[]) +        \
+  (config_all_devices.has_key('CONFIG_USB_UHCI') and                           
             \
+   config_all_devices.has_key('CONFIG_USB_EHCI_PCI') and                       
             \
+   config_all_devices.has_key('CONFIG_USB_XHCI_PCI') ? ['usb-pc-default-test'] 
: []) +      \
   (config_all_devices.has_key('CONFIG_TPM_CRB') ? ['tpm-crb-test'] : []) +     
             \
   (config_all_devices.has_key('CONFIG_TPM_CRB') ? ['tpm-crb-swtpm-test'] : []) 
+            \
   (config_all_devices.has_key('CONFIG_TPM_TIS_ISA') ? ['tpm-tis-test'] : []) + 
             \
diff --git a/tests/qtest/usb-pc-default-test.c 
b/tests/qtest/usb-pc-default-test.c
new file mode 100644
index 0000000000..060e9bc469
--- /dev/null
+++ b/tests/qtest/usb-pc-default-test.c
@@ -0,0 +1,135 @@
+/*
+ * Which USB host controller -usb creates on the pc and q35 machines
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "libqtest.h"
+#include "qobject/qdict.h"
+#include "qobject/qlist.h"
+#include "hw/pci/pci.h"
+#include "hw/pci/pci_ids.h"
+
+typedef struct {
+    int slot, func;
+    uint16_t vendor, device;
+} Controller;
+
+typedef struct {
+    const char *machine;
+    bool usb;
+    const char *const *devices;
+    const Controller *ctrl;
+    size_t n;
+} TestCase;
+
+static const Controller piix3_uhci[] = {
+    { 1, 2, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371SB_2 },
+};
+
+static const Controller xhci[] = {
+    { 0x1d, 0, PCI_VENDOR_ID_REDHAT, PCI_DEVICE_ID_REDHAT_XHCI },
+};
+
+static const Controller ich9_ehci[] = {
+    { 0x1d, 0, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801I_UHCI1 },
+    { 0x1d, 1, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801I_UHCI2 },
+    { 0x1d, 2, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801I_UHCI3 },
+    { 0x1d, 7, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801I_EHCI1 },
+};
+
+/* host controller types a case needs, in case the build left them out */
+static const char *const xhci_dev[] = { "qemu-xhci", NULL };
+static const char *const piix3_dev[] = { "piix3-usb-uhci", NULL };
+static const char *const ich9_dev[] = { "ich9-usb-ehci1", "ich9-usb-uhci1",
+                                        NULL };
+
+static const TestCase cases[] = {
+    { "pc", true, xhci_dev, xhci, ARRAY_SIZE(xhci) },
+    { "q35", true, xhci_dev, xhci, ARRAY_SIZE(xhci) },
+    { "pc-i440fx-12.0", true, xhci_dev, xhci, ARRAY_SIZE(xhci) },
+    { "pc-q35-12.0", true, xhci_dev, xhci, ARRAY_SIZE(xhci) },
+    { "pc-i440fx-11.2", true, piix3_dev, piix3_uhci, ARRAY_SIZE(piix3_uhci) },
+    { "pc-q35-11.2", true, ich9_dev, ich9_ehci, ARRAY_SIZE(ich9_ehci) },
+    { "pc", false, NULL, NULL, 0 },
+    { "q35", false, NULL, NULL, 0 },
+};
+
+static bool has_devices(const char *const *devices)
+{
+    for (; devices && *devices; devices++) {
+        if (!qtest_has_device(*devices)) {
+            return false;
+        }
+    }
+    return true;
+}
+
+static void test_usb_controllers(const void *data)
+{
+    const TestCase *tc = data;
+    QTestState *qts = qtest_initf(tc->usb ? "-M %s -usb" : "-M %s",
+                                  tc->machine);
+    QDict *resp = qtest_qmp(qts, "{ 'execute': 'query-pci' }");
+    QList *buses = qdict_get_qlist(resp, "return");
+    QListEntry *be, *de;
+    size_t found = 0;
+
+    QLIST_FOREACH_ENTRY(buses, be) {
+        QDict *bus = qobject_to(QDict, qlist_entry_obj(be));
+        QList *devices = qdict_get_qlist(bus, "devices");
+
+        QLIST_FOREACH_ENTRY(devices, de) {
+            QDict *dev = qobject_to(QDict, qlist_entry_obj(de));
+            QDict *id = qdict_get_qdict(dev, "id");
+            int slot = qdict_get_int(dev, "slot");
+            int func = qdict_get_int(dev, "function");
+            int vendor = qdict_get_int(id, "vendor");
+            int device = qdict_get_int(id, "device");
+            size_t i;
+
+            if (qdict_get_int(qdict_get_qdict(dev, "class_info"), "class") !=
+                PCI_CLASS_SERIAL_USB) {
+                continue;
+            }
+            for (i = 0; i < tc->n; i++) {
+                if (tc->ctrl[i].slot == slot && tc->ctrl[i].func == func) {
+                    break;
+                }
+            }
+            if (i == tc->n) {
+                g_test_message("unexpected USB controller %02x.%x %04x:%04x",
+                               slot, func, vendor, device);
+                g_assert_not_reached();
+            }
+            g_assert_cmpint(vendor, ==, tc->ctrl[i].vendor);
+            g_assert_cmpint(device, ==, tc->ctrl[i].device);
+            found++;
+        }
+    }
+    g_assert_cmpuint(found, ==, tc->n);
+
+    qobject_unref(resp);
+    qtest_quit(qts);
+}
+
+int main(int argc, char **argv)
+{
+    size_t i;
+
+    g_test_init(&argc, &argv, NULL);
+    for (i = 0; i < ARRAY_SIZE(cases); i++) {
+        static const char *const kind[] = { "no-usb", "usb" };
+        g_autofree char *path = NULL;
+
+        if (!qtest_has_machine(cases[i].machine) ||
+            !has_devices(cases[i].devices)) {
+            continue;
+        }
+        path = g_strdup_printf("/usb/pc-default/%s/%s", kind[cases[i].usb],
+                               cases[i].machine);
+        qtest_add_data_func(path, &cases[i], test_usb_controllers);
+    }
+    return g_test_run();
+}
-- 
2.43.0


Reply via email to