diff options
Diffstat (limited to 'tests')
103 files changed, 11908 insertions, 2248 deletions
diff --git a/tests/Makefile.include b/tests/Makefile.include index 45a4302103..a5719551dd 100644 --- a/tests/Makefile.include +++ b/tests/Makefile.include @@ -151,37 +151,10 @@ check-qtest-generic-y += tests/qmp-cmd-test$(EXESUF) check-qtest-generic-y += tests/device-introspect-test$(EXESUF) check-qtest-generic-y += tests/cdrom-test$(EXESUF) -check-qtest-ipack-y += tests/ipoctal232-test$(EXESUF) - -check-qtest-virtioserial-$(CONFIG_VIRTIO_SERIAL) += tests/virtio-console-test$(EXESUF) - -check-qtest-virtio-$(CONFIG_VIRTIO_NET) += tests/virtio-net-test$(EXESUF) -check-qtest-virtio-$(CONFIG_VIRTIO_BALLOON) += tests/virtio-balloon-test$(EXESUF) -check-qtest-virtio-$(CONFIG_VIRTIO_BLK) += tests/virtio-blk-test$(EXESUF) -check-qtest-virtio-$(CONFIG_VIRTIO_RNG) += tests/virtio-rng-test$(EXESUF) -check-qtest-virtio-$(CONFIG_VIRTIO_SCSI) += tests/virtio-scsi-test$(EXESUF) -ifeq ($(CONFIG_VIRTIO)$(CONFIG_VIRTFS)$(CONFIG_PCI),yyy) -check-qtest-virtio-$(CONFIG_VIRTIO_9P) += tests/virtio-9p-test$(EXESUF) -endif -check-qtest-virtio-$(CONFIG_VIRTIO_SERIAL) += tests/virtio-serial-test$(EXESUF) -check-qtest-virtio-y += $(check-qtest-virtioserial-y) - -check-qtest-pci-y += tests/e1000-test$(EXESUF) -check-qtest-pci-y += tests/e1000e-test$(EXESUF) check-qtest-pci-$(CONFIG_RTL8139_PCI) += tests/rtl8139-test$(EXESUF) -check-qtest-pci-$(CONFIG_PCNET_PCI) += tests/pcnet-test$(EXESUF) -check-qtest-pci-$(CONFIG_EEPRO100_PCI) += tests/eepro100-test$(EXESUF) -check-qtest-pci-$(CONFIG_NE2000_PCI) += tests/ne2000-test$(EXESUF) -check-qtest-pci-$(CONFIG_NVME_PCI) += tests/nvme-test$(EXESUF) -check-qtest-pci-$(CONFIG_AC97) += tests/ac97-test$(EXESUF) -check-qtest-pci-$(CONFIG_ES1370) += tests/es1370-test$(EXESUF) -check-qtest-pci-$(CONFIG_VIRTIO) += $(check-qtest-virtio-y) -check-qtest-pci-$(CONFIG_IPACK) += tests/tpci200-test$(EXESUF) -check-qtest-pci-$(CONFIG_IPACK) += $(check-qtest-ipack-y) check-qtest-pci-$(CONFIG_VGA) += tests/display-vga-test$(EXESUF) check-qtest-pci-$(CONFIG_HDA) += tests/intel-hda-test$(EXESUF) check-qtest-pci-$(CONFIG_IVSHMEM_DEVICE) += tests/ivshmem-test$(EXESUF) -check-qtest-pci-$(CONFIG_MEGASAS_SCSI_PCI) += tests/megasas-test$(EXESUF) check-qtest-i386-$(CONFIG_ISA_TESTDEV) = tests/endianness-test$(EXESUF) check-qtest-i386-y += tests/fdc-test$(EXESUF) @@ -203,11 +176,9 @@ check-qtest-i386-y += tests/drive_del-test$(EXESUF) check-qtest-i386-$(CONFIG_WDT_IB700) += tests/wdt_ib700-test$(EXESUF) check-qtest-i386-y += tests/tco-test$(EXESUF) check-qtest-i386-y += $(check-qtest-pci-y) -check-qtest-i386-$(CONFIG_VMXNET3_PCI) += tests/vmxnet3-test$(EXESUF) check-qtest-i386-$(CONFIG_PVPANIC) += tests/pvpanic-test$(EXESUF) check-qtest-i386-$(CONFIG_I82801B11) += tests/i82801b11-test$(EXESUF) check-qtest-i386-$(CONFIG_IOH3420) += tests/ioh3420-test$(EXESUF) -check-qtest-i386-$(CONFIG_USB_OHCI) += tests/usb-hcd-ohci-test$(EXESUF) check-qtest-i386-$(CONFIG_USB_UHCI) += tests/usb-hcd-uhci-test$(EXESUF) ifeq ($(CONFIG_USB_ECHI)$(CONFIG_USB_UHCI),yy) check-qtest-i386-y += tests/usb-hcd-ehci-test$(EXESUF) @@ -216,7 +187,6 @@ check-qtest-i386-$(CONFIG_USB_XHCI_NEC) += tests/usb-hcd-xhci-test$(EXESUF) check-qtest-i386-y += tests/cpu-plug-test$(EXESUF) check-qtest-i386-y += tests/q35-test$(EXESUF) check-qtest-i386-y += tests/vmgenid-test$(EXESUF) -check-qtest-i386-$(CONFIG_VHOST_NET_USER) += tests/vhost-user-test$(EXESUF) check-qtest-i386-$(CONFIG_TPM_CRB) += tests/tpm-crb-swtpm-test$(EXESUF) check-qtest-i386-$(CONFIG_TPM_CRB) += tests/tpm-crb-test$(EXESUF) check-qtest-i386-$(CONFIG_TPM_TIS) += tests/tpm-tis-swtpm-test$(EXESUF) @@ -229,7 +199,6 @@ check-qtest-i386-y += tests/test-announce-self$(EXESUF) check-qtest-i386-y += tests/test-x86-cpuid-compat$(EXESUF) check-qtest-i386-y += tests/numa-test$(EXESUF) check-qtest-x86_64-y += $(check-qtest-i386-y) -check-qtest-x86_64-$(CONFIG_SDHCI) += tests/sdhci-test$(EXESUF) check-qtest-alpha-y += tests/boot-serial-test$(EXESUF) check-qtest-alpha-$(CONFIG_VGA) += tests/display-vga-test$(EXESUF) @@ -260,17 +229,14 @@ check-qtest-ppc-y += tests/boot-serial-test$(EXESUF) check-qtest-ppc-$(CONFIG_M48T59) += tests/m48t59-test$(EXESUF) check-qtest-ppc64-y += $(check-qtest-ppc-y) -check-qtest-ppc64-$(CONFIG_PSERIES) += tests/spapr-phb-test$(EXESUF) check-qtest-ppc64-$(CONFIG_PSERIES) += tests/device-plug-test$(EXESUF) check-qtest-ppc64-$(CONFIG_POWERNV) += tests/pnv-xscom-test$(EXESUF) check-qtest-ppc64-y += tests/migration-test$(EXESUF) check-qtest-ppc64-y += tests/test-announce-self$(EXESUF) check-qtest-ppc64-$(CONFIG_PSERIES) += tests/rtas-test$(EXESUF) check-qtest-ppc64-$(CONFIG_SLIRP) += tests/pxe-test$(EXESUF) -check-qtest-ppc64-$(CONFIG_USB_OHCI) += tests/usb-hcd-ohci-test$(EXESUF) check-qtest-ppc64-$(CONFIG_USB_UHCI) += tests/usb-hcd-uhci-test$(EXESUF) check-qtest-ppc64-$(CONFIG_USB_XHCI_NEC) += tests/usb-hcd-xhci-test$(EXESUF) -check-qtest-ppc64-$(CONFIG_VIRTIO) += $(check-qtest-virtio-y) check-qtest-ppc64-$(CONFIG_SLIRP) += tests/test-netfilter$(EXESUF) check-qtest-ppc64-$(CONFIG_POSIX) += tests/test-filter-mirror$(EXESUF) check-qtest-ppc64-$(CONFIG_RTL8139_PCI) += tests/test-filter-redirector$(EXESUF) @@ -296,14 +262,11 @@ check-qtest-arm-y += tests/pca9552-test$(EXESUF) check-qtest-arm-y += tests/ds1338-test$(EXESUF) check-qtest-arm-y += tests/microbit-test$(EXESUF) check-qtest-arm-y += tests/m25p80-test$(EXESUF) -check-qtest-arm-$(CONFIG_VIRTIO_BLK) += tests/virtio-blk-test$(EXESUF) check-qtest-arm-y += tests/test-arm-mptimer$(EXESUF) check-qtest-arm-y += tests/boot-serial-test$(EXESUF) -check-qtest-arm-$(CONFIG_SDHCI) += tests/sdhci-test$(EXESUF) check-qtest-arm-y += tests/hexloader-test$(EXESUF) check-qtest-aarch64-y = tests/numa-test$(EXESUF) -check-qtest-aarch64-$(CONFIG_SDHCI) += tests/sdhci-test$(EXESUF) check-qtest-aarch64-y += tests/boot-serial-test$(EXESUF) check-qtest-aarch64-y += tests/migration-test$(EXESUF) @@ -732,7 +695,10 @@ tests/test-crypto-ivgen$(EXESUF): tests/test-crypto-ivgen.o $(test-crypto-obj-y) tests/test-crypto-afsplit$(EXESUF): tests/test-crypto-afsplit.o $(test-crypto-obj-y) tests/test-crypto-block$(EXESUF): tests/test-crypto-block.o $(test-crypto-obj-y) -libqos-obj-y = tests/libqos/pci.o tests/libqos/fw_cfg.o tests/libqos/malloc.o +libqgraph-obj-y = tests/libqos/qgraph.o + +libqos-obj-y = $(libqgraph-obj-y) tests/libqos/pci.o tests/libqos/fw_cfg.o +libqos-obj-y += tests/libqos/malloc.o libqos-obj-y += tests/libqos/i2c.o tests/libqos/libqos.o libqos-spapr-obj-y = $(libqos-obj-y) tests/libqos/malloc-spapr.o libqos-spapr-obj-y += tests/libqos/libqos-spapr.o @@ -744,7 +710,64 @@ libqos-pc-obj-y += tests/libqos/ahci.o libqos-omap-obj-y = $(libqos-obj-y) tests/libqos/i2c-omap.o libqos-imx-obj-y = $(libqos-obj-y) tests/libqos/i2c-imx.o libqos-usb-obj-y = $(libqos-spapr-obj-y) $(libqos-pc-obj-y) tests/libqos/usb.o -libqos-virtio-obj-y = $(libqos-spapr-obj-y) $(libqos-pc-obj-y) tests/libqos/virtio.o tests/libqos/virtio-pci.o tests/libqos/virtio-mmio.o tests/libqos/malloc-generic.o + +# Devices +qos-test-obj-y = tests/qos-test.o $(libqgraph-obj-y) +qos-test-obj-y += $(libqos-pc-obj-y) $(libqos-spapr-obj-y) +qos-test-obj-y += tests/libqos/e1000e.o +qos-test-obj-y += tests/libqos/sdhci.o +qos-test-obj-y += tests/libqos/tpci200.o +qos-test-obj-y += tests/libqos/virtio.o +qos-test-obj-$(CONFIG_VIRTFS) += tests/libqos/virtio-9p.o +qos-test-obj-y += tests/libqos/virtio-balloon.o +qos-test-obj-y += tests/libqos/virtio-blk.o +qos-test-obj-y += tests/libqos/virtio-mmio.o +qos-test-obj-y += tests/libqos/virtio-net.o +qos-test-obj-y += tests/libqos/virtio-pci.o +qos-test-obj-y += tests/libqos/virtio-rng.o +qos-test-obj-y += tests/libqos/virtio-scsi.o +qos-test-obj-y += tests/libqos/virtio-serial.o + +# Machines +qos-test-obj-y += tests/libqos/aarch64-xlnx-zcu102-machine.o +qos-test-obj-y += tests/libqos/arm-raspi2-machine.o +qos-test-obj-y += tests/libqos/arm-sabrelite-machine.o +qos-test-obj-y += tests/libqos/arm-smdkc210-machine.o +qos-test-obj-y += tests/libqos/arm-virt-machine.o +qos-test-obj-y += tests/libqos/arm-xilinx-zynq-a9-machine.o +qos-test-obj-y += tests/libqos/ppc64_pseries-machine.o +qos-test-obj-y += tests/libqos/x86_64_pc-machine.o + +# Tests +qos-test-obj-y += tests/ac97-test.o +qos-test-obj-y += tests/e1000-test.o +qos-test-obj-y += tests/e1000e-test.o +qos-test-obj-y += tests/eepro100-test.o +qos-test-obj-y += tests/es1370-test.o +qos-test-obj-y += tests/ipoctal232-test.o +qos-test-obj-y += tests/megasas-test.o +qos-test-obj-y += tests/ne2000-test.o +qos-test-obj-y += tests/nvme-test.o +qos-test-obj-y += tests/pci-test.o +qos-test-obj-y += tests/pcnet-test.o +qos-test-obj-y += tests/sdhci-test.o +qos-test-obj-y += tests/spapr-phb-test.o +qos-test-obj-y += tests/usb-hcd-ohci-test.o $(libqos-usb-obj-y) +qos-test-obj-$(CONFIG_VHOST_NET_USER) += tests/vhost-user-test.o $(chardev-obj-y) $(test-io-obj-y) +qos-test-obj-y += tests/virtio-test.o +qos-test-obj-$(CONFIG_VIRTFS) += tests/virtio-9p-test.o +qos-test-obj-y += tests/virtio-blk-test.o +qos-test-obj-y += tests/virtio-net-test.o +qos-test-obj-y += tests/virtio-rng-test.o +qos-test-obj-y += tests/virtio-scsi-test.o +qos-test-obj-y += tests/virtio-serial-test.o +qos-test-obj-y += tests/vmxnet3-test.o + +check-unit-y += tests/test-qgraph$(EXESUF) +tests/test-qgraph$(EXESUF): tests/test-qgraph.o $(libqgraph-obj-y) + +check-qtest-generic-y += tests/qos-test$(EXESUF) +tests/qos-test$(EXESUF): $(qos-test-obj-y) tests/qmp-test$(EXESUF): tests/qmp-test.o tests/qmp-cmd-test$(EXESUF): tests/qmp-cmd-test.o @@ -753,7 +776,6 @@ tests/rtc-test$(EXESUF): tests/rtc-test.o tests/m48t59-test$(EXESUF): tests/m48t59-test.o tests/hexloader-test$(EXESUF): tests/hexloader-test.o tests/endianness-test$(EXESUF): tests/endianness-test.o -tests/spapr-phb-test$(EXESUF): tests/spapr-phb-test.o $(libqos-obj-y) tests/prom-env-test$(EXESUF): tests/prom-env-test.o $(libqos-obj-y) tests/rtas-test$(EXESUF): tests/rtas-test.o $(libqos-spapr-obj-y) tests/fdc-test$(EXESUF): tests/fdc-test.o @@ -775,50 +797,27 @@ tests/m25p80-test$(EXESUF): tests/m25p80-test.o tests/i440fx-test$(EXESUF): tests/i440fx-test.o $(libqos-pc-obj-y) tests/q35-test$(EXESUF): tests/q35-test.o $(libqos-pc-obj-y) tests/fw_cfg-test$(EXESUF): tests/fw_cfg-test.o $(libqos-pc-obj-y) -tests/e1000-test$(EXESUF): tests/e1000-test.o -tests/e1000e-test$(EXESUF): tests/e1000e-test.o $(libqos-pc-obj-y) tests/rtl8139-test$(EXESUF): tests/rtl8139-test.o $(libqos-pc-obj-y) -tests/pcnet-test$(EXESUF): tests/pcnet-test.o tests/pnv-xscom-test$(EXESUF): tests/pnv-xscom-test.o -tests/eepro100-test$(EXESUF): tests/eepro100-test.o -tests/vmxnet3-test$(EXESUF): tests/vmxnet3-test.o -tests/ne2000-test$(EXESUF): tests/ne2000-test.o tests/wdt_ib700-test$(EXESUF): tests/wdt_ib700-test.o tests/tco-test$(EXESUF): tests/tco-test.o $(libqos-pc-obj-y) -tests/virtio-balloon-test$(EXESUF): tests/virtio-balloon-test.o $(libqos-virtio-obj-y) -tests/virtio-blk-test$(EXESUF): tests/virtio-blk-test.o $(libqos-virtio-obj-y) tests/virtio-ccw-test$(EXESUF): tests/virtio-ccw-test.o -tests/virtio-net-test$(EXESUF): tests/virtio-net-test.o $(libqos-pc-obj-y) $(libqos-virtio-obj-y) -tests/virtio-rng-test$(EXESUF): tests/virtio-rng-test.o $(libqos-pc-obj-y) -tests/virtio-scsi-test$(EXESUF): tests/virtio-scsi-test.o $(libqos-virtio-obj-y) -tests/virtio-9p-test$(EXESUF): tests/virtio-9p-test.o $(libqos-virtio-obj-y) -tests/virtio-serial-test$(EXESUF): tests/virtio-serial-test.o $(libqos-virtio-obj-y) -tests/virtio-console-test$(EXESUF): tests/virtio-console-test.o $(libqos-virtio-obj-y) -tests/tpci200-test$(EXESUF): tests/tpci200-test.o tests/display-vga-test$(EXESUF): tests/display-vga-test.o -tests/ipoctal232-test$(EXESUF): tests/ipoctal232-test.o tests/qom-test$(EXESUF): tests/qom-test.o tests/test-hmp$(EXESUF): tests/test-hmp.o tests/machine-none-test$(EXESUF): tests/machine-none-test.o tests/device-plug-test$(EXESUF): tests/device-plug-test.o -tests/drive_del-test$(EXESUF): tests/drive_del-test.o $(libqos-virtio-obj-y) -tests/nvme-test$(EXESUF): tests/nvme-test.o $(libqos-pc-obj-y) +tests/drive_del-test$(EXESUF): tests/drive_del-test.o tests/pvpanic-test$(EXESUF): tests/pvpanic-test.o tests/i82801b11-test$(EXESUF): tests/i82801b11-test.o -tests/ac97-test$(EXESUF): tests/ac97-test.o -tests/es1370-test$(EXESUF): tests/es1370-test.o tests/intel-hda-test$(EXESUF): tests/intel-hda-test.o tests/ioh3420-test$(EXESUF): tests/ioh3420-test.o -tests/usb-hcd-ohci-test$(EXESUF): tests/usb-hcd-ohci-test.o $(libqos-usb-obj-y) tests/usb-hcd-uhci-test$(EXESUF): tests/usb-hcd-uhci-test.o $(libqos-usb-obj-y) tests/usb-hcd-ehci-test$(EXESUF): tests/usb-hcd-ehci-test.o $(libqos-usb-obj-y) tests/usb-hcd-xhci-test$(EXESUF): tests/usb-hcd-xhci-test.o $(libqos-usb-obj-y) tests/cpu-plug-test$(EXESUF): tests/cpu-plug-test.o tests/migration-test$(EXESUF): tests/migration-test.o tests/test-announce-self$(EXESUF): tests/test-announce-self.o -tests/vhost-user-test$(EXESUF): tests/vhost-user-test.o $(test-util-obj-y) \ - $(qtest-obj-y) $(test-io-obj-y) $(libqos-virtio-obj-y) $(libqos-pc-obj-y) \ - $(chardev-obj-y) tests/qemu-iotests/socket_scm_helper$(EXESUF): tests/qemu-iotests/socket_scm_helper.o tests/test-qemu-opts$(EXESUF): tests/test-qemu-opts.o $(test-util-obj-y) tests/test-keyval$(EXESUF): tests/test-keyval.o $(test-util-obj-y) $(test-qapi-obj-y) @@ -828,14 +827,12 @@ tests/test-filter-mirror$(EXESUF): tests/test-filter-mirror.o $(qtest-obj-y) tests/test-filter-redirector$(EXESUF): tests/test-filter-redirector.o $(qtest-obj-y) tests/test-x86-cpuid-compat$(EXESUF): tests/test-x86-cpuid-compat.o $(qtest-obj-y) tests/ivshmem-test$(EXESUF): tests/ivshmem-test.o contrib/ivshmem-server/ivshmem-server.o $(libqos-pc-obj-y) $(libqos-spapr-obj-y) -tests/megasas-test$(EXESUF): tests/megasas-test.o $(libqos-spapr-obj-y) $(libqos-pc-obj-y) tests/vhost-user-bridge$(EXESUF): tests/vhost-user-bridge.o $(test-util-obj-y) libvhost-user.a tests/test-uuid$(EXESUF): tests/test-uuid.o $(test-util-obj-y) tests/test-arm-mptimer$(EXESUF): tests/test-arm-mptimer.o tests/test-qapi-util$(EXESUF): tests/test-qapi-util.o $(test-util-obj-y) tests/numa-test$(EXESUF): tests/numa-test.o tests/vmgenid-test$(EXESUF): tests/vmgenid-test.o tests/boot-sector.o tests/acpi-utils.o -tests/sdhci-test$(EXESUF): tests/sdhci-test.o $(libqos-pc-obj-y) tests/cdrom-test$(EXESUF): tests/cdrom-test.o tests/boot-sector.o $(libqos-obj-y) tests/migration/stress$(EXESUF): tests/migration/stress.o diff --git a/tests/ac97-test.c b/tests/ac97-test.c index e0d177bd9c..532fb1cc98 100644 --- a/tests/ac97-test.c +++ b/tests/ac97-test.c @@ -9,23 +9,48 @@ #include "qemu/osdep.h" #include "libqtest.h" +#include "libqos/qgraph.h" +#include "libqos/pci.h" -/* Tests only initialization so far. TODO: Replace with functional tests */ -static void nop(void) +typedef struct QAC97 QAC97; + +struct QAC97 { + QOSGraphObject obj; + QPCIDevice dev; +}; + +static void *ac97_get_driver(void *obj, const char *interface) { + QAC97 *ac97 = obj; + + if (!g_strcmp0(interface, "pci-device")) { + return &ac97->dev; + } + + fprintf(stderr, "%s not present in e1000e\n", interface); + g_assert_not_reached(); } -int main(int argc, char **argv) +static void *ac97_create(void *pci_bus, QGuestAllocator *alloc, void *addr) { - int ret; + QAC97 *ac97 = g_new0(QAC97, 1); + QPCIBus *bus = pci_bus; - g_test_init(&argc, &argv, NULL); - qtest_add_func("/ac97/nop", nop); - - qtest_start("-device AC97"); - ret = g_test_run(); + qpci_device_init(&ac97->dev, bus, addr); + ac97->obj.get_driver = ac97_get_driver; + return &ac97->obj; +} - qtest_end(); +static void ac97_register_nodes(void) +{ + QOSGraphEdgeOptions opts = { + .extra_device_opts = "addr=04.0", + }; + add_qpci_address(&opts, &(QPCIAddress) { .devfn = QPCI_DEVFN(4, 0) }); - return ret; + qos_node_create_driver("AC97", ac97_create); + qos_node_produces("AC97", "pci-device"); + qos_node_consumes("AC97", "pci-bus", &opts); } + +libqos_init(ac97_register_nodes); diff --git a/tests/ahci-test.c b/tests/ahci-test.c index 5dd380e5ea..9f07e6f2ce 100644 --- a/tests/ahci-test.c +++ b/tests/ahci-test.c @@ -162,7 +162,7 @@ static AHCIQState *ahci_vboot(const char *cli, va_list ap) s = g_new0(AHCIQState, 1); s->parent = qtest_pc_vboot(cli, ap); global_qtest = s->parent->qts; - alloc_set_flags(s->parent->alloc, ALLOC_LEAK_ASSERT); + alloc_set_flags(&s->parent->alloc, ALLOC_LEAK_ASSERT); /* Verify that we have an AHCI device present. */ s->dev = get_ahci_device(s->parent->qts, &s->fingerprint); @@ -1039,7 +1039,7 @@ static void test_dma_fragmented(void) generate_pattern(tx, bufsize, AHCI_SECTOR_SIZE); /* Create a DMA buffer in guest memory, and write our pattern to it. */ - ptr = guest_alloc(ahci->parent->alloc, bufsize); + ptr = guest_alloc(&ahci->parent->alloc, bufsize); g_assert(ptr); bufwrite(ptr, tx, bufsize); @@ -1059,7 +1059,7 @@ static void test_dma_fragmented(void) /* Read back the guest's receive buffer into local memory */ bufread(ptr, rx, bufsize); - guest_free(ahci->parent->alloc, ptr); + guest_free(&ahci->parent->alloc, ptr); g_assert_cmphex(memcmp(tx, rx, bufsize), ==, 0); diff --git a/tests/check-qdict.c b/tests/check-qdict.c index a1e8305066..b5efa859b0 100644 --- a/tests/check-qdict.c +++ b/tests/check-qdict.c @@ -291,7 +291,7 @@ static void qdict_stress_test(void) FILE *test_file; QDict *qdict; QString *value; - const char *test_file_path = "qdict-test-data.txt"; + const char *test_file_path = "tests/data/qobject/qdict.txt"; test_file = fopen(test_file_path, "r"); g_assert(test_file != NULL); diff --git a/tests/data/qobject/qdict.txt b/tests/data/qobject/qdict.txt new file mode 100644 index 0000000000..122fda4524 --- /dev/null +++ b/tests/data/qobject/qdict.txt @@ -0,0 +1,4999 @@ +00-INDEX: 333 +07: 4096 +1040.bin.ihex: 92633 +11d.c: 17874 +11d.h: 2386 +1200.bin.ihex: 14717 +12160.bin.ihex: 77829 +1232ea962bbaf0e909365f4964f6cceb2ba8ce: 298 +1280.bin.ihex: 88220 +15562512ca6cf14c1b8f08e09d5907118deaf0: 297 +17: 4096 +1d: 4096 +1.Intro: 14968 +21142.c: 8591 +21285.c: 11721 +2860_main_dev.c: 33854 +2860_rtmp_init.c: 26170 +2870_main_dev.c: 39352 +2870_rtmp_init.c: 51247 +2.Process: 22356 +300vtbl.h: 43771 +310vtbl.h: 59655 +3270.ChangeLog: 1889 +3270.txt: 10964 +3550.bin.ihex: 13916 +3780i.c: 21485 +3780i.h: 14180 +38C0800.bin.ihex: 14772 +38C1600.bin.ihex: 17504 +3C359.bin.ihex: 69044 +3c359.c: 60161 +3c359.h: 7264 +3c359.txt: 2463 +3c501.c: 23869 +3c501.h: 2623 +3c503.c: 22491 +3c503.h: 3880 +3c505.c: 48605 +3c505.h: 6535 +3c505.txt: 1831 +3c507.c: 28758 +3c509.c: 42879 +3c509.txt: 9006 +3c515.c: 49671 +3c523.c: 39251 +3c523.h: 11169 +3c527.c: 43065 +3c527.h: 1482 +3c574_cs.c: 35859 +3c589_cs.c: 30110 +3c59x.c: 103272 +3CCFEM556.cis.ihex: 469 +3com: 4096 +3CXEM556.cis.ihex: 463 +3.Early-stage: 9993 +3w-9xxx.c: 77318 +3w-9xxx.h: 26357 +3w-xxxx.c: 85227 +3w-xxxx.h: 16846 +40x: 4096 +40x_mmu.c: 4082 +42: 4096 +44x: 4096 +44x.c: 3615 +44x_emulate.c: 4512 +44x.h: 448 +44x_mmu.c: 2966 +44x_tlb.c: 13997 +44x_tlb.h: 2465 +4.Coding: 20212 +4level-fixup.h: 1028 +4xx: 4096 +4xx.c: 16297 +4xx.h: 1174 +512x: 4096 +5206: 4096 +5206e: 4096 +520x: 4096 +523x: 4096 +5249: 4096 +5272: 4096 +527x: 4096 +528x: 4096 +52xx: 4096 +5307: 4096 +532x: 4096 +53c700.c: 71188 +53c700_d.h_shipped: 28887 +53c700.h: 16652 +53c700.scr: 10894 +53c700.txt: 5042 +5407: 4096 +57xx_iscsi_constants.h: 7004 +57xx_iscsi_hsi.h: 36895 +5d: 4096 +5.Posting: 15211 +66b00c9dc3e1e071bde0ebfeadc40bbc1e8316: 298 +68328: 4096 +68328fb.c: 13570 +68328serial.c: 35841 +68328serial.h: 6237 +68360: 4096 +68360serial.c: 76262 +68EZ328: 4096 +68VZ328: 4096 +6c5e45fe4f1c83df9429b7c2668b41446baac2: 297 +6.Followthrough: 11745 +6pack.c: 24715 +6pack.txt: 7940 +6xx-suspend.S: 1086 +712_defconfig: 25531 +7206: 4096 +73: 4096 +7343: 4096 +770x: 4096 +7721: 4096 +7722: 4096 +7724: 4096 +7751: 4096 +7780: 4096 +7990.c: 22036 +7990.h: 10421 +7.AdvancedTopics: 9648 +7c: 4096 +7segled.c: 2698 +802: 4096 +80211core: 4096 +80211hdr.h: 12326 +80211mgr.c: 28179 +80211mgr.h: 23006 +8021q: 4096 +8139cp.c: 56138 +8139too.c: 71384 +8250_accent.c: 1071 +8250_acorn.c: 3194 +8250_boca.c: 1301 +8250.c: 83003 +8250_early.c: 6636 +8250_exar_st16c554.c: 1191 +8250_fourport.c: 1216 +8250_gsc.c: 3620 +8250.h: 2432 +8250_hp300.c: 7797 +8250_hub6.c: 1224 +8250_mca.c: 1375 +8250_pci.c: 93521 +8250_pci.h: 999 +8250-platform.c: 1091 +8250_pnp.c: 14783 +8253.h: 10999 +8253pit.h: 48 +8255.c: 10692 +8255.h: 1805 +82571.c: 48377 +82596.c: 41209 +82xx: 4096 +8390.c: 2094 +8390.h: 9629 +8390p.c: 2248 +83xx: 4096 +83xx-512x-pci.txt: 1323 +85xx: 4096 +86xx: 4096 +87: 4096 +8b: 4096 +8.Conclusion: 3137 +8xx: 4096 +8xx_immap.h: 14089 +8xxx_gpio.txt: 1343 +941a7798a5169ee0dd69a9e8d5c40ceb702023: 298 +9600.bin.ihex: 14715 +9p: 4096 +9p.h: 13443 +9p.txt: 5113 +a100u2w.c: 36919 +a100u2w.h: 16936 +a2065.c: 20730 +a2065.h: 5135 +a2091.c: 6445 +a2091.h: 1712 +a20.c: 3548 +a20r.c: 5261 +a3000.c: 6528 +a3000.h: 1807 +a3d.c: 11335 +a4000t.c: 3579 +a500_defconfig: 31440 +a800.c: 5950 +aachba.c: 84424 +aaci.c: 27297 +aaci.h: 7022 +aacraid: 4096 +aacraid.h: 53671 +aacraid.txt: 6849 +aaec2000.h: 8936 +aaed2000.c: 2298 +aaed2000.h: 1354 +aaed2000_kbd.c: 5059 +aarp.c: 25379 +ab3100-core.c: 22600 +ab3100.h: 3510 +abdac.c: 15469 +ABI: 4096 +abi.h: 782 +abituguru: 3731 +abituguru3: 2493 +abituguru3.c: 41974 +abituguru.c: 53440 +abituguru-datasheet: 12294 +abi.txt: 1413 +ABI.txt: 1413 +ablkcipher.c: 9484 +abort-ev4.S: 882 +abort-ev4t.S: 913 +abort-ev5tj.S: 987 +abort-ev5t.S: 912 +abort-ev6.S: 1320 +abort-ev7.S: 774 +abort-lv4t.S: 6546 +abort-macro.S: 1144 +abort-nommu.S: 462 +abs_addr.h: 1800 +abspath.c: 2808 +abs.S: 238 +abyss.c: 11197 +abyss.h: 1550 +ac3200.c: 11838 +ac97: 4096 +ac97_bus.c: 1681 +ac97.c: 4489 +ac97c.c: 26095 +ac97c.h: 2045 +ac97_codec.c: 36925 +ac97_codec.h: 15115 +ac97.h: 507 +ac97_id.h: 2422 +ac97_local.h: 1689 +ac97_patch.c: 128568 +ac97_patch.h: 4386 +ac97_pcm.c: 21244 +ac97_proc.c: 18243 +acadia_defconfig: 23272 +acadia.dts: 5188 +ac.c: 9202 +accel.c: 8625 +accel.h: 5627 +access.c: 10521 +accessibility: 4096 +access_ok.h: 1305 +accommon.h: 2825 +acconfig.h: 7688 +accounting: 4096 +acct.c: 17700 +acct.h: 5949 +acdebug.h: 6836 +acdispat.h: 10988 +acecad.c: 7982 +acenic: 4096 +acenic.c: 88166 +acenic.h: 16029 +acenv.h: 11821 +acerhdf.c: 14909 +acer-wmi.c: 30530 +acer-wmi.txt: 6480 +acevents.h: 6692 +acexcep.h: 12764 +acgcc.h: 2843 +acglobal.h: 14485 +achware.h: 4355 +acinterp.h: 16329 +ackvec.c: 12985 +ackvec.h: 3426 +acl7225b.c: 3794 +acl.c: 5321 +acl.h: 1548 +aclinux.h: 5049 +aclocal.h: 34614 +acmacros.h: 22966 +acm.txt: 4974 +acnames.h: 3482 +acnamesp.h: 10211 +acobject.h: 16573 +acopcode.h: 22365 +acorn.c: 12206 +acornfb.c: 35783 +acornfb.h: 4809 +acorn.h: 623 +acornscsi.c: 87770 +acornscsi.h: 9694 +acornscsi-io.S: 3320 +acoutput.h: 10925 +acparser.h: 7436 +acpi: 4096 +acpi_bus.h: 11195 +acpi.c: 6529 +acpica: 12288 +acpi-cpufreq.c: 21588 +acpi_drivers.h: 5322 +acpi-ext.c: 2774 +acpi-ext.h: 590 +acpi.h: 4768 +acpi_memhotplug.c: 14832 +acpi_numa.h: 471 +acpiosxf.h: 7880 +acpi_pcihp.c: 14898 +acpiphp_core.c: 10949 +acpiphp_glue.c: 44065 +acpiphp.h: 6325 +acpiphp_ibm.c: 14740 +acpi_pm.c: 6723 +acpi_pmtmr.h: 672 +acpi-processor.c: 1893 +acpixf.h: 12045 +acpredef.h: 18909 +acquirewdt.c: 8920 +acresrc.h: 11064 +acrestyp.h: 11267 +acs5k_defconfig: 28786 +acs5k_tiny_defconfig: 21413 +acstruct.h: 7738 +act2000: 4096 +act2000.h: 6271 +act2000_isa.c: 11978 +act2000_isa.h: 7615 +act200l-sir.c: 7142 +actables.h: 3945 +act_api.c: 23712 +act_api.h: 4195 +actbl1.h: 35761 +actbl.h: 15492 +act_gact.c: 5493 +action.c: 40 +action.h: 40 +act_ipt.c: 7564 +actisys-sir.c: 7692 +active_mm.txt: 3805 +act_mirred.c: 6285 +act_nat.c: 7265 +act_pedit.c: 6148 +act_police.c: 9833 +act_simple.c: 5238 +act_skbedit.c: 5510 +actypes.h: 34263 +acutils.h: 16898 +acx.c: 16590 +acx.h: 33552 +ad1816a: 4096 +ad1816a.c: 8825 +ad1816a.h: 5363 +ad1816a_lib.c: 30656 +ad1843.c: 16402 +ad1843.h: 1516 +ad1848: 4096 +ad1848.c: 75959 +ad1848.h: 982 +ad1848_mixer.h: 10957 +ad1889.c: 27048 +ad1889.h: 8073 +ad1980.c: 8427 +ad1980.h: 468 +ad73311.c: 2765 +ad73311.h: 2404 +ad7414.c: 7164 +ad7418.c: 8304 +ad7877.c: 20856 +ad7877.h: 796 +ad7879.c: 19019 +ad7879.h: 1004 +adaptec: 4096 +adapter.h: 400 +adb.c: 19706 +adb.h: 2770 +adbhid.c: 35627 +adb-iop.c: 6325 +adb_iop.h: 1081 +adc.c: 8573 +adc.h: 886 +ADC-LH7-Touchscreen: 2187 +adcxx.c: 8256 +adder875.c: 3142 +adder875_defconfig: 21956 +adder875-redboot.dts: 4102 +adder875-uboot.dts: 4072 +addi_amcc_S5920.c: 7563 +addi_amcc_S5920.h: 1016 +addi_amcc_s5933.h: 13296 +addi_apci_035.c: 128 +addi_apci_1032.c: 63 +addi_apci_1500.c: 63 +addi_apci_1516.c: 63 +addi_apci_1564.c: 63 +addi_apci_16xx.c: 63 +addi_apci_1710.c: 63 +addi_apci_2016.c: 63 +addi_apci_2032.c: 63 +addi_apci_2200.c: 63 +addi_apci_3001.c: 63 +addi_apci_3120.c: 63 +addi_apci_3200.c: 63 +addi_apci_3300.c: 63 +addi_apci_3501.c: 63 +addi_apci_3xxx.c: 63 +addi_apci_all.c: 468 +addi_common.c: 57084 +addi_common.h: 15536 +addi-data: 4096 +addi_eeprom.c: 35657 +addinitrd.c: 3837 +addnote.c: 5117 +addon_cpuid_features.c: 3269 +addRamDisk.c: 9120 +addr.c: 13176 +addrconf.c: 112491 +addrconf_core.c: 2484 +addrconf.h: 7261 +address.c: 10451 +addr.h: 615 +addrlabel.c: 14012 +addr-map.c: 3725 +addr-map.h: 1054 +addrs.h: 14810 +addrspace.h: 4233 +adfs: 4096 +adfs_fs.h: 1337 +adfs.h: 5064 +adfs.txt: 1816 +adi.c: 14310 +adlib.c: 3006 +adl_pci6208.c: 11803 +adl_pci7296.c: 4671 +adl_pci7432.c: 5617 +adl_pci8164.c: 9991 +adl_pci9111.c: 38266 +adl_pci9118.c: 69079 +adm1021: 4184 +adm1021.c: 14057 +adm1025: 2364 +adm1025.c: 19865 +adm1026: 4578 +adm1026.c: 60096 +adm1029.c: 13774 +adm1031: 1193 +adm1031.c: 31209 +adm8211.c: 56115 +adm8211.h: 18093 +adm9240: 6804 +adm9240.c: 24112 +adma.c: 5497 +adma.h: 13803 +adq12b.c: 12147 +ads7828: 1146 +ads7828.c: 8084 +ads7846.c: 31008 +ads7846.h: 1844 +ADSBitsy: 1396 +adssphere.c: 1810 +adt7462: 2515 +adt7462.c: 60645 +adt7470: 2759 +adt7470.c: 42397 +adt7473: 2757 +adt7473.c: 35779 +adt7475: 2578 +adt7475.c: 35318 +adummy.c: 3035 +adutux.c: 25427 +adv7170.c: 9645 +adv7175.c: 10457 +adv7343.c: 12608 +adv7343.h: 730 +adv7343_regs.h: 5764 +advansys: 4096 +advansys.c: 382572 +advansys.txt: 9492 +advantechwdt.c: 8222 +adv_pci1710.c: 46220 +adv_pci1723.c: 12975 +adv_pci_dio.c: 34130 +ae7400074d449189d41fceb6d6f871490d7842: 298 +aead.c: 12873 +aead.h: 2027 +aec62xx.c: 9392 +aedsp16.c: 36369 +ael1002.c: 41054 +aer: 4096 +aerdrv_acpi.c: 1347 +aerdrv.c: 8935 +aerdrv_core.c: 22958 +aerdrv_errprint.c: 5915 +aerdrv.h: 3468 +aer.h: 773 +aer_inject.c: 10715 +aes.c: 11973 +aes_ccm.c: 3589 +aes_ccm.h: 810 +aes_ccmp.c: 14024 +aes_ccmp.h: 1469 +aes_cmac.c: 2737 +aes_cmac.h: 587 +aes_generic.c: 63316 +aes_glue.c: 1691 +aes.h: 279 +aes-i586-asm_32.S: 10637 +aesni-intel_asm.S: 21991 +aesni-intel_glue.c: 19525 +aes_s390.c: 13814 +aes-x86_64-asm_64.S: 4820 +af802154.h: 1271 +af9005.c: 28215 +af9005-fe.c: 36514 +af9005.h: 120579 +af9005-remote.c: 4403 +af9005-script.h: 5193 +af9013.c: 38083 +af9013.h: 3095 +af9013_priv.h: 21508 +af9015.c: 43153 +af9015.h: 28439 +af_ax25.c: 45160 +af_bluetooth.c: 10089 +af_can.c: 23294 +af_can.h: 4053 +af_decnet.c: 54945 +afeb9260_defconfig: 29783 +af_econet.c: 25853 +affs: 4096 +affs.h: 10590 +affs_hardblocks.h: 1481 +affs.txt: 8188 +af_ieee802154.c: 8683 +af_ieee802154.h: 1620 +af_inet6.c: 29847 +af_inet.c: 40041 +af_ipx.c: 50967 +af_irda.c: 67827 +af_irda.h: 2964 +af_iucv.c: 41285 +af_iucv.h: 2495 +af_key.c: 102229 +af_llc.c: 29863 +af_netlink.c: 46590 +af_netrom.c: 33634 +af_packet.c: 55964 +af_phonet.c: 10845 +af_rds.c: 14309 +af_rose.c: 39337 +af_rxrpc.c: 20908 +af_rxrpc.h: 2017 +afs: 4096 +afs.c: 6434 +afs_cm.h: 1213 +afs_fs.h: 2342 +afs.h: 6110 +afs.txt: 7976 +afs_vl.h: 3680 +af_unix.c: 53673 +af_unix.h: 1891 +af_x25.c: 38538 +agent.c: 6214 +agent.h: 2106 +agg-rx.c: 10061 +agg-tx.c: 19983 +agnx: 4096 +agnx.h: 4414 +agp: 4096 +agp_backend.h: 909 +agpgart.h: 6567 +agp.h: 11594 +ah4.c: 7802 +ah6.c: 13438 +aha152x.c: 100462 +aha152x_core.c: 61 +aha152x.h: 10175 +aha152x_stub.c: 7843 +aha152x.txt: 6540 +aha1542.c: 50376 +aha1542.h: 4776 +aha1740.c: 19608 +aha1740.h: 4954 +ahash.c: 5607 +ahb.c: 4740 +ah.c: 3493 +ahci.c: 82058 +ah.h: 894 +aic7770.c: 9851 +aic7770_osm.c: 4437 +aic79xx_core.c: 299904 +aic79xx.h: 46803 +aic79xx_inline.h: 5997 +aic79xx_osm.c: 79947 +aic79xx_osm.h: 21300 +aic79xx_osm_pci.c: 10626 +aic79xx_pci.c: 27694 +aic79xx_pci.h: 3106 +aic79xx_proc.c: 10559 +aic79xx.reg: 73912 +aic79xx_reg.h_shipped: 71718 +aic79xx_reg_print.c_shipped: 19691 +aic79xx.seq: 72735 +aic79xx_seq.h_shipped: 29327 +aic79xx.txt: 24091 +aic7xxx: 4096 +aic7xxx_93cx6.c: 9761 +aic7xxx_93cx6.h: 3670 +aic7xxx_core.c: 216583 +aic7xxx.h: 42160 +aic7xxx_inline.h: 3774 +aic7xxx_old: 4096 +aic7xxx_old.c: 366880 +aic7xxx_old.txt: 24500 +aic7xxx_osm.c: 73118 +aic7xxx_osm.h: 21353 +aic7xxx_osm_pci.c: 12355 +aic7xxx_pci.c: 61842 +aic7xxx_pci.h: 5296 +aic7xxx_proc.c: 10950 +aic7xxx.reg: 38137 +aic7xxx_reg.h: 15305 +aic7xxx_reg.h_shipped: 23099 +aic7xxx_reg_print.c_shipped: 10818 +aic7xxx.seq: 70499 +aic7xxx_seq.c: 20747 +aic7xxx_seq.h_shipped: 32908 +aic7xxx.txt: 19701 +aic94xx: 4096 +aic94xx_dev.c: 11236 +aic94xx_dump.c: 36929 +aic94xx_dump.h: 1451 +aic94xx.h: 3007 +aic94xx_hwi.c: 38875 +aic94xx_hwi.h: 10646 +aic94xx_init.c: 28607 +aic94xx_reg.c: 10895 +aic94xx_reg_def.h: 74147 +aic94xx_reg.h: 10470 +aic94xx_sas.h: 22044 +aic94xx_scb.c: 27220 +aic94xx_sds.c: 37304 +aic94xx_sds.h: 4644 +aic94xx_seq.c: 47415 +aic94xx_seq.h: 2011 +aic94xx_task.c: 17414 +aic94xx_tmf.c: 20129 +aica.c: 18912 +aica.h: 2322 +aicasm: 4096 +aicasm.c: 20235 +aicasm_gram.y: 41937 +aicasm.h: 3213 +aicasm_insformat.h: 5394 +aicasm_macro_gram.y: 4072 +aicasm_macro_scan.l: 4166 +aicasm_scan.l: 15538 +aicasm_symbol.c: 16089 +aicasm_symbol.h: 4889 +aiclib.c: 1599 +aiclib.h: 6327 +aio_abi.h: 3060 +aio_aio12_8.c: 5597 +aio.c: 9345 +aio.h: 530 +aio_iiro_16.c: 4521 +aiptek.c: 63719 +aircable.c: 16905 +airo.c: 224549 +airo_cs.c: 16214 +airo.h: 272 +aironet.c: 38 +aironet.h: 31 +airport.c: 6741 +airq.c: 3567 +airq.h: 530 +ak4104.c: 8783 +ak4104.h: 143 +ak4114.c: 18943 +ak4114.h: 10191 +ak4117.c: 16871 +ak4117.h: 9193 +ak4396.h: 1065 +ak4531_codec.c: 17543 +ak4531_codec.h: 3161 +ak4535.c: 18361 +ak4535.h: 1042 +ak4xxx-adda.c: 25308 +ak4xxx-adda.h: 3333 +ak4xxx.c: 5039 +aki3068net: 4096 +alauda.c: 34485 +alaw_main.csp.ihex: 3714 +alchemy: 4096 +alchemy-flash.c: 4191 +algapi.c: 16668 +algapi.h: 8721 +algboss.c: 6296 +algos: 4096 +ali14xx.c: 6564 +ali5451: 4096 +ali5451.c: 59400 +ali-agp.c: 10369 +alias.c: 1447 +aliasing-test.c: 6103 +aliasing.txt: 8753 +alias.txt: 1181 +align.c: 24429 +alignment.c: 23757 +align.S: 11650 +ali-ircc.c: 57570 +ali-ircc.h: 7748 +alim1535_wdt.c: 10224 +alim15x3.c: 14978 +alim7101_wdt.c: 11048 +allocator.c: 10151 +alloc.c: 10261 +alloc.h: 9219 +allocpercpu.c: 4150 +alpaca.h: 1209 +alpha: 4096 +alpha-agp.c: 5476 +alpha_ksyms.c: 2696 +alphatrack.c: 23326 +alphatrack.h: 2005 +alps.c: 15813 +alps.h: 1047 +ALS: 3770 +als100.c: 9384 +als300.c: 23789 +als4000.c: 32136 +alsa: 4096 +alsa.c: 2430 +ALSA-Configuration.txt: 75006 +alsa-driver-api.tmpl: 3216 +alsa.h: 370 +alternative-asm.h: 289 +alternative.c: 14237 +alternative.h: 5895 +altpciechdma: 4096 +altpciechdma.c: 37598 +am200epd.c: 9652 +am200epdkit_defconfig: 26949 +am300epd.c: 6564 +am79c961a.c: 18502 +am79c961a.h: 3109 +am9513.h: 1940 +amba: 4096 +amba-clcd.c: 12494 +ambakmi.c: 4554 +amba-pl010.c: 19490 +amba-pl011.c: 21509 +amba-pl022.c: 53346 +ambassador.c: 68387 +ambassador.h: 16192 +amcc: 4096 +amcc_s5933_58.h: 14263 +amcc_s5933.h: 6603 +amd5536udc.c: 86854 +amd5536udc.h: 17276 +amd64-agp.c: 20128 +amd64_edac.c: 98492 +amd64_edac_dbg.c: 5401 +amd64_edac_err_types.c: 3628 +amd64_edac.h: 19221 +amd64_edac_inj.c: 4304 +amd74xx.c: 10198 +amd76x_edac.c: 9371 +amd76xrom.c: 9404 +amd7930.c: 31102 +amd7930_fn.c: 23626 +amd7930_fn.h: 1162 +amd8111e.c: 53690 +amd8111_edac.c: 16756 +amd8111_edac.h: 4244 +amd8111e.h: 21006 +amd8131_edac.c: 10985 +amd8131_edac.h: 3772 +amd_bus.c: 13843 +amd.c: 3180 +amd_iommu.c: 52618 +amd_iommu.h: 1421 +amd_iommu_init.c: 34814 +amd_iommu_types.h: 13377 +amd-k7-agp.c: 15673 +amd-powernow.txt: 1673 +amd-rng.c: 3458 +amifb.c: 103212 +amifd.h: 1995 +amifdreg.h: 2674 +amiflop.c: 46962 +amiga: 4096 +amiga.c: 3445 +amiga_defconfig: 28613 +amigaffs.c: 11549 +amigaffs.h: 2927 +amiga.h: 116 +amigahw.h: 11232 +amigaints.h: 3583 +amigaone: 4096 +amigaone_defconfig: 40433 +amigaone.dts: 4189 +amigayle.h: 3135 +amiints.c: 6489 +amijoy.c: 4591 +amijoy.txt: 7701 +amikbd.c: 6468 +amimouse.c: 3296 +amipcmcia.h: 2568 +amiserial.c: 54254 +amisound.c: 2828 +amix86.c: 23331 +amlcode.h: 18976 +aml_nfw.c: 5630 +amlresrc.h: 9975 +amon.h: 141 +amp.c: 2736 +amp.h: 1594 +amplc_dio200.c: 38731 +amplc_pc236.c: 16962 +amplc_pc263.c: 11680 +amplc_pci224.c: 44174 +amplc_pci230.c: 92910 +ams: 4096 +ams-core.c: 6046 +ams-delta.c: 5974 +ams_delta_defconfig: 28481 +amsdu.c: 5428 +ams.h: 1354 +ams-i2c.c: 6365 +ams-input.c: 3542 +amso1100: 4096 +ams-pmu.c: 4469 +analog.c: 20366 +anchor.h: 3882 +anchors.txt: 2625 +android: 4096 +ani.c: 23441 +ani.h: 4062 +anode.c: 14491 +anomaly.h: 11228 +anon_inodes.c: 5477 +anon_inodes.h: 312 +ansi_cprng.c: 10011 +ansidecl.h: 4393 +ans-lcd.c: 3847 +ans-lcd.h: 206 +anubis.c: 28484 +anubis-cpld.h: 652 +anubis-irq.h: 596 +anubis-map.h: 1219 +anycast.c: 11884 +anysee.c: 15434 +anysee.h: 14174 +aoa: 4096 +aoa-gpio.h: 2434 +aoa.h: 3816 +aoe: 4096 +aoeblk.c: 7321 +aoechr.c: 6092 +aoecmd.c: 23023 +aoedev.c: 5392 +aoe.h: 4748 +aoemain.c: 2032 +aoenet.c: 3237 +aoe.txt: 4600 +aops.c: 49318 +aops.h: 4017 +a.out-core.h: 2444 +a.out.h: 2438 +ap325rxa_defconfig: 31462 +apanel.c: 8043 +apb.h: 1043 +ap_bus.c: 45317 +ap_bus.h: 6091 +apc.c: 4412 +apc.h: 1682 +APCI1710_82x54.c: 55614 +APCI1710_82x54.h: 2408 +APCI1710_Chrono.c: 75530 +APCI1710_Chrono.h: 2397 +APCI1710_Dig_io.c: 35243 +APCI1710_Dig_io.h: 1437 +APCI1710_INCCPT.c: 206966 +APCI1710_INCCPT.h: 10615 +APCI1710_Inp_cpt.c: 32511 +APCI1710_Inp_cpt.h: 1414 +APCI1710_Pwm.c: 110859 +APCI1710_Pwm.h: 2722 +APCI1710_Ssi.c: 30348 +APCI1710_Ssi.h: 1343 +APCI1710_Tor.c: 70692 +APCI1710_Tor.h: 1684 +APCI1710_Ttl.c: 35072 +APCI1710_Ttl.h: 1338 +apdbg.c: 12729 +aperture_64.c: 13850 +ap.h: 26 +apic: 4096 +api.c: 4766 +apic.c: 56323 +apicdef.h: 10790 +apic_flat_64.c: 9680 +apic.h: 48 +apicnum.h: 229 +API.html: 738 +api-intro.txt: 6569 +apm_32.c: 71310 +apm-acpi.txt: 1541 +apm_bios.h: 5647 +apm.c: 1961 +apm_emu.c: 3225 +apm-emulation.c: 17959 +apm-emulation.h: 1575 +apm.h: 1722 +apm_power.c: 10334 +apm-power.c: 2659 +apne.c: 17115 +apollo: 4096 +apollo_defconfig: 25574 +apollodma.h: 9409 +apollohw.h: 2876 +appldata: 4096 +appldata_base.c: 16414 +appldata.h: 2269 +appldata_mem.c: 4196 +appldata_net_sum.c: 4240 +appldata_os.c: 6134 +appledisplay.c: 9793 +applesmc.c: 46139 +appletalk: 4096 +appletouch.c: 25051 +appletouch.txt: 3199 +applicom.c: 24465 +applicom.h: 2558 +applying-patches.txt: 19961 +applypatch-msg.sample: 452 +aq100x.c: 8974 +ar7: 4096 +ar7_defconfig: 29419 +ar7.h: 4432 +ar7part.c: 4186 +ar7_wdt.c: 8576 +ar9170: 4096 +ar9170.h: 7335 +ar-accept.c: 12406 +ar-ack.c: 33274 +arbiter.c: 11549 +arbiter.h: 607 +arc: 4096 +arc4.c: 2066 +ar-call.c: 21724 +arc_con.c: 973 +arcdevice.h: 12708 +arcfb.c: 16908 +arcfb.h: 150 +arch: 4096 +arch_checks.c: 3045 +arches_defconfig: 19397 +arches.dts: 7694 +arch.h: 1650 +arch-kev7a400.c: 2933 +arch-lpd7a40x.c: 10208 +archparam.h: 246 +archsetjmp.h: 363 +arch-v10: 4096 +arch-v32: 4096 +arcmsr: 4096 +arcmsr_attr.c: 12953 +arcmsr.h: 22540 +arcmsr_hba.c: 68471 +arcmsr_spec.txt: 22891 +arcnet: 4096 +arcnet.c: 30476 +arcnet-hardware.txt: 112635 +arcnet.txt: 23983 +arcofi.c: 3664 +arcofi.h: 721 +ar-connection.c: 23383 +ar-connevent.c: 9295 +arc-rawmode.c: 5274 +arc-rimi.c: 10949 +ar-error.c: 5949 +argv_split.c: 1893 +ariadne.c: 24224 +ariadne.h: 15566 +ar-input.c: 20380 +ar-internal.h: 28881 +ark3116.c: 12365 +ar-key.c: 8236 +arkfb.c: 31427 +arkfb.txt: 2024 +arlan.h: 16773 +arlan-main.c: 51969 +arlan-proc.c: 30009 +ar-local.c: 7670 +arm: 4096 +armadillo5x0.c: 7149 +ARM-gcc.h: 4503 +armksyms.c: 4758 +arm_timer.h: 576 +ar-output.c: 18343 +arp.c: 35296 +ar-peer.c: 7599 +arp.h: 1028 +ar-proc.c: 5159 +arptable_filter.c: 3496 +arp_tables.c: 47085 +arp_tables.h: 8551 +arpt_mangle.c: 2391 +arpt_mangle.h: 547 +array.c: 13244 +arrayRCU.txt: 4475 +ar-recvmsg.c: 11003 +ar-security.c: 5588 +ar-skbuff.c: 3506 +arthur.c: 2275 +artpec_3_defconfig: 13781 +ar-transport.c: 7196 +arv.c: 22235 +arxescsi.c: 9967 +asb100: 2093 +asb100.c: 29220 +asb2303_defconfig: 13559 +asciidoc.conf: 2238 +asequencer.h: 24733 +ashiftrt.S: 3468 +ashldi3.c: 1516 +__ashldi3.S: 1340 +ashldi3.S: 1594 +ashlsi3.S: 3814 +ashrdi3.c: 1578 +__ashrdi3.S: 1359 +ashrdi3.S: 1594 +ashrsi3.S: 3765 +ashxdi3.S: 5014 +asic3.c: 23429 +asic3.h: 11966 +asids-debugfs.c: 1875 +asi.h: 13855 +asiliantfb.c: 17057 +as-iosched.c: 39676 +as-iosched.txt: 8697 +asix.c: 39119 +as-layout.h: 1666 +asl.c: 9101 +asm: 4096 +asm-compat.h: 1951 +asm-generic: 4096 +asm.h: 9481 +asmmacro-32.h: 4815 +asmmacro-64.h: 3961 +asmmacro.h: 2767 +asm-offsets_32.c: 5194 +asm-offsets_64.c: 3637 +asm-offsets.c: 4611 +asmregs.h: 3115 +asn1.c: 15700 +asoundef.h: 14263 +asound_fm.h: 4313 +asound.h: 39901 +asp8347_defconfig: 35011 +asp834x.c: 2108 +asp834x-redboot.dts: 6941 +asp.c: 3631 +aspenite.c: 2671 +asp.h: 608 +aspm.c: 25790 +Assabet: 9201 +assabet.c: 11283 +assabet_defconfig: 17595 +assabet.h: 4477 +assembler.h: 2834 +assembly.h: 12972 +assoc.c: 36 +assoc.h: 408 +association.h: 4661 +associola.c: 43957 +ast.c: 3630 +ast.h: 878 +asus_acpi.c: 39676 +asus_atk0110.c: 24097 +asuscom.c: 11573 +asus-laptop.c: 36214 +asus_oled: 4096 +asus_oled.c: 18945 +async.c: 11128 +asyncdata.c: 15045 +async.h: 973 +async_memcpy.c: 3227 +async_memset.c: 2994 +async-thread.c: 13350 +async-thread.h: 3400 +async_tx: 4096 +async-tx-api.txt: 8950 +async_tx.c: 8062 +async_tx.h: 5062 +async_xor.c: 9790 +at1700.c: 25461 +at24.c: 17172 +at24.h: 1084 +at25.c: 10286 +at32ap700x.c: 54284 +at32ap700x.h: 9017 +at32ap700x_wdt.c: 10216 +at32psif.c: 8545 +at73c213.c: 28442 +at73c213.h: 3187 +at76c50x-usb.c: 69577 +at76c50x-usb.h: 11556 +at76_usb: 4096 +at76_usb.c: 159931 +at76_usb.h: 18785 +at91_adc.h: 2447 +at91_aic.h: 2578 +at91cap9adk_defconfig: 28118 +at91cap9.c: 9260 +at91cap9_ddrsdr.h: 4803 +at91cap9_devices.c: 32852 +at91cap9.h: 5120 +at91cap9_matrix.h: 8438 +at91_cf.c: 10319 +at91_dbgu.h: 2878 +at91_ether.c: 37656 +at91_ether.h: 3116 +at91_ide.c: 10538 +at91_mci.c: 31894 +at91_mci.h: 5220 +at91_pio.h: 2085 +at91_pit.h: 1189 +at91_pmc.h: 6822 +at91rm9200.c: 8544 +at91rm9200_devices.c: 32118 +at91rm9200dk_defconfig: 19334 +at91rm9200ek_defconfig: 19319 +at91rm9200_emac.h: 6334 +at91rm9200.h: 4634 +at91rm9200_mc.h: 7552 +at91rm9200_time.c: 6137 +at91rm9200_wdt.c: 6655 +at91_rstc.h: 1684 +at91_rtc.h: 3381 +at91_rtt.h: 1335 +at91sam9260.c: 9719 +at91sam9260_devices.c: 28830 +at91sam9260ek_defconfig: 23675 +at91sam9260.h: 5601 +at91sam9260_matrix.h: 4360 +at91sam9261.c: 7811 +at91sam9261_devices.c: 27547 +at91sam9261ek_defconfig: 27131 +at91sam9261.h: 3985 +at91sam9261_matrix.h: 3171 +at91sam9263.c: 8693 +at91sam9263_devices.c: 36564 +at91sam9263ek_defconfig: 27888 +at91sam9263.h: 5088 +at91sam9263_matrix.h: 7531 +at91sam926x_time.c: 4812 +at91sam9g20ek_defconfig: 26082 +at91sam9rl.c: 8144 +at91sam9rl_devices.c: 28643 +at91sam9rlek_defconfig: 21184 +at91sam9rl.h: 4332 +at91sam9rl_matrix.h: 5086 +at91sam9_sdramc.h: 3914 +at91sam9_smc.h: 3570 +at91sam9_wdt.c: 7764 +at91_shdwc.h: 1497 +at91_spi.h: 3738 +at91_ssc.h: 4846 +at91_st.h: 1983 +at91_tc.h: 6897 +at91_twi.h: 3075 +at91_udc.c: 48229 +at91_udc.h: 6283 +at91_wdt.h: 1464 +at91x40.c: 1914 +at91x40.h: 2025 +at91x40_time.c: 2547 +at93c.c: 2613 +at93c.h: 292 +ata: 12288 +ata.c: 4208 +ata_defs_asm.h: 8736 +ata_defs.h: 6434 +atafb.c: 91174 +atafb.h: 1708 +atafb_iplan2p2.c: 6818 +atafb_iplan2p4.c: 7301 +atafb_iplan2p8.c: 8377 +atafb_mfb.c: 2554 +atafb_utils.h: 11235 +atafd.h: 261 +atafdreg.h: 2704 +ataflop.c: 52286 +ata_generic.c: 6543 +atags.c: 1588 +atags.h: 132 +ata.h: 787 +ataints.c: 14727 +atakbd.c: 6402 +atakeyb.c: 15982 +atalk.h: 5240 +atalk_proc.c: 7290 +ata_piix.c: 45848 +ata_platform.h: 910 +atari: 4096 +atari.c: 3911 +atari_defconfig: 26788 +atari.h: 1077 +atarihw.h: 20620 +atariints.h: 5520 +atari_joystick.h: 418 +atarikbd.txt: 26109 +atarikb.h: 1514 +atarilance.c: 34168 +atarimouse.c: 3865 +atari_NCR5380.c: 92608 +atari_scsi.c: 35928 +atari_scsi.h: 5820 +atari_stdma.h: 458 +atari_stram.h: 429 +atasound.c: 2705 +ateb9200_defconfig: 26557 +aten2011.c: 65277 +aten.c: 3343 +ath: 4096 +ath5k: 4096 +ath5k.h: 45994 +ath9k: 4096 +ath9k.h: 20541 +ath9k_platform.h: 1116 +athr_common.h: 4056 +ati-agp.c: 14653 +ati_ids.h: 8172 +atiixp.c: 5592 +atiixp_modem.c: 36739 +ati_pcigart.c: 5516 +ati_remote2.c: 23391 +ati_remote.c: 27913 +atkbd.c: 40410 +atl1c: 4096 +atl1.c: 101403 +atl1c_ethtool.c: 9188 +atl1c.h: 20395 +atl1c_hw.c: 13975 +atl1c_hw.h: 31069 +atl1c_main.c: 77505 +atl1e: 4096 +atl1e_ethtool.c: 11679 +atl1e.h: 17562 +atl1e_hw.c: 16680 +atl1e_hw.h: 38581 +atl1e_main.c: 71172 +atl1e_param.c: 7245 +atl1.h: 24023 +atl2.c: 82456 +atl2.h: 16349 +atlas_btns.c: 4752 +atlx: 4096 +atlx.c: 7198 +atlx.h: 18176 +atm: 4096 +atmapi.h: 889 +atmarp.h: 1233 +atmbr2684.h: 3208 +atmclip.h: 513 +atmdev.h: 16681 +atmel: 4096 +atmel-abdac.h: 626 +atmel-ac97c.h: 1409 +atmel.c: 132756 +atmel_cs.c: 17914 +atmel.h: 1533 +atmel_lcdc.h: 7265 +atmel_lcdfb.c: 31305 +atmel-mci.c: 43139 +atmel-mci.h: 1269 +atmel-mci-regs.h: 6476 +atmel_nand.c: 15137 +atmel_nand_ecc.h: 1412 +atmel_pci.c: 2533 +atmel-pcm.c: 14083 +atmel-pcm.h: 2987 +atmel_pdc.h: 1410 +atmel-pwm-bl.c: 6152 +atmel-pwm-bl.h: 1550 +atmel_pwm.c: 9359 +atmel_pwm.h: 2724 +atmel_read_eeprom.c: 3671 +atmel_read_eeprom.h: 2413 +atmel_serial.c: 40894 +atmel_serial.h: 6087 +atmel_spi.c: 23923 +atmel_spi.h: 4446 +atmel-ssc.c: 3605 +atmel_ssc_dai.c: 20632 +atmel_ssc_dai.h: 3265 +atmel-ssc.h: 9369 +atmel_tc.h: 11075 +atmel_tclib.c: 3626 +atmel_tsadcc.c: 10816 +atmel_usba_udc.c: 50940 +atmel_usba_udc.h: 10031 +atmel-wm97xx.c: 11848 +atm_eni.h: 585 +atm.h: 7995 +atm_he.h: 343 +atm_idt77105.h: 892 +atmioc.h: 1583 +atmlec.h: 2561 +atm_misc.c: 2638 +atmmpc.h: 4163 +atm_nicstar.h: 1215 +atmppp.h: 576 +atmsap.h: 4907 +atmsar11.HEX: 19191 +atm_suni.h: 253 +atmsvc.h: 1790 +atm_sysfs.c: 3945 +atmtcp.c: 11650 +atm_tcp.h: 1768 +atm.txt: 426 +atm_zatm.h: 1606 +atngw100: 4096 +atngw100_defconfig: 28242 +atngw100_evklcd100_defconfig: 29353 +atngw100_evklcd101_defconfig: 29353 +atngw100_mrmt_defconfig: 33751 +atombios_crtc.c: 23254 +atombios.h: 221852 +atom-bits.h: 1882 +atom.c: 29689 +atom.h: 4494 +atomic32.c: 2859 +atomic_32.h: 11086 +atomic_32.S: 2663 +atomic64.c: 3863 +atomic_64.h: 10903 +atomic64.h: 1840 +atomic64-ops.S: 4827 +atomic_64.S: 2925 +atomic-grb.h: 4642 +atomic.h: 7333 +atomic-irq.h: 1375 +atomic-llsc.h: 2813 +atomic-long.h: 5244 +atomic_mm.h: 4061 +atomic_no.h: 3556 +atomic-ops.S: 5339 +atomic_ops.txt: 19503 +atomic-ops.txt: 4632 +atomic.S: 15917 +atom-names.h: 4758 +atom-types.h: 1430 +atp870u.c: 86512 +atp870u.h: 1487 +atp.c: 29816 +atp.h: 8737 +atstk1000: 4096 +atstk1000.h: 535 +atstk1002.c: 8012 +atstk1002_defconfig: 30107 +atstk1003.c: 3765 +atstk1003_defconfig: 25774 +atstk1004.c: 3756 +atstk1004_defconfig: 15379 +atstk1006_defconfig: 32583 +attach.c: 9647 +attr.c: 2666 +attrib.c: 91896 +attrib.h: 4321 +attribute_container.c: 12242 +attribute_container.h: 2530 +atxp1.c: 9417 +aty: 4096 +aty128fb.c: 67277 +aty128fb.txt: 2119 +aty128.h: 13554 +atyfb_base.c: 111634 +atyfb.h: 8973 +au0828: 4096 +au0828-cards.c: 9773 +au0828-cards.h: 1060 +au0828-core.c: 7629 +au0828-dvb.c: 11151 +au0828.h: 7385 +au0828-i2c.c: 9287 +au0828-reg.h: 2134 +au0828-video.c: 41940 +au1000_db1x00.c: 7294 +au1000_dma.h: 11212 +au1000_eth.c: 33708 +au1000_eth.h: 3012 +au1000_generic.c: 14674 +au1000_generic.h: 4280 +au1000.h: 53188 +au1000_ircc.h: 3758 +au1000_pb1x00.c: 9234 +au1000_xxs1500.c: 4378 +au1100fb.c: 20752 +au1100fb.h: 14620 +au1100_mmc.h: 5888 +au1200fb.c: 52491 +au1200fb.h: 18704 +au1550_ac97.c: 51655 +au1550nd.c: 14821 +au1550_spi.c: 26531 +au1550_spi.h: 433 +au1k_ir.c: 20249 +au1x: 4096 +au1x00.c: 19173 +au1xmmc.c: 28453 +au1xxx_dbdma.h: 13134 +au1xxx.h: 1723 +au1xxx-ide.c: 15369 +au1xxx_ide.h: 6491 +AU1xxx_IDE.README: 4039 +au1xxx_psc.h: 15895 +au6610.c: 6091 +au6610.h: 1286 +au8522_decoder.c: 27416 +au8522_dig.c: 21506 +au8522.h: 2387 +au8522_priv.h: 17128 +au8810.c: 379 +au8810.h: 7007 +au8820.c: 331 +au8820.h: 6479 +au8830.c: 404 +au8830.h: 8629 +au88x0: 4096 +au88x0_a3d.c: 25257 +au88x0_a3ddata.c: 2908 +au88x0_a3d.h: 4336 +au88x0.c: 10316 +au88x0_core.c: 78891 +au88x0_eq.c: 23045 +au88x0_eqdata.c: 3952 +au88x0_eq.h: 1287 +au88x0_game.c: 3655 +au88x0.h: 8929 +au88x0_mixer.c: 773 +au88x0_mpu401.c: 3619 +au88x0_pcm.c: 15858 +au88x0_synth.c: 11076 +au88x0_wt.h: 2347 +au88x0_xtalk.c: 23426 +au88x0_xtalk.h: 2304 +Audigy-mixer.txt: 13956 +audio.c: 7519 +AudioExcelDSP16: 3886 +audio.h: 525 +Audiophile-Usb.txt: 17915 +audit_64.c: 1870 +audit.c: 1888 +audit_change_attr.h: 320 +audit_dir_write.h: 238 +auditfilter.c: 34110 +audit.h: 394 +audit_read.h: 127 +auditsc.c: 67706 +audit_signal.h: 36 +audit_tree.c: 22256 +audit_watch.c: 14765 +audit_write.h: 255 +aureon.c: 64017 +aureon.h: 2419 +autcpu12.c: 5831 +autcpu12.h: 2590 +autcpu12-nvram.c: 3124 +auth.c: 35 +authenc.c: 13429 +authenc.h: 609 +auth_generic.c: 4800 +auth_gss: 4096 +auth_gss.c: 40950 +auth_gss.h: 2256 +auth.h: 540 +auth_null.c: 2607 +authorization.txt: 2640 +authors: 38 +AUTHORS: 38 +auth_rsp.c: 39 +auth_unix.c: 5607 +auto_dev-ioctl.h: 5186 +autofs: 4096 +autofs4: 4096 +auto_fs4.h: 4095 +autofs4-mount-control.txt: 17706 +auto_fs.h: 2467 +autofs_i.h: 7355 +autoload.c: 967 +autoload.sh: 339 +automount-support.txt: 4694 +autoprobe.c: 4772 +auxdisplay: 4096 +auxio_32.c: 3721 +auxio_32.h: 2622 +auxio_64.c: 3214 +auxio_64.h: 3266 +auxio.h: 176 +aux_reg.h: 646 +auxvec.h: 60 +av7110: 4096 +av7110_av.c: 40033 +av7110_av.h: 1214 +av7110.c: 82729 +av7110_ca.c: 9180 +av7110_ca.h: 441 +av7110.h: 7155 +av7110_hw.c: 31995 +av7110_hw.h: 12512 +av7110_ipack.c: 7991 +av7110_ipack.h: 402 +av7110_ir.c: 11196 +av7110_v4l.c: 27884 +avc.c: 24534 +avc.h: 3102 +avc_ss.h: 617 +avermedia.txt: 13922 +avila.h: 917 +avila-pci.c: 1817 +avila-setup.c: 4610 +av_inherit.h: 1693 +avm: 4096 +avm_a1.c: 8303 +avma1_cs.c: 9468 +avm_a1p.c: 7146 +avmcard.h: 13933 +avm_cs.c: 9107 +avm_pci.c: 23187 +av_permissions.h: 53693 +av_perm_to_string.h: 10893 +avr32: 4096 +__avr32_asr64.S: 560 +avr32_ksyms.c: 1843 +__avr32_lsl64.S: 559 +__avr32_lsr64.S: 559 +avtab.c: 12842 +avtab.h: 2874 +aw2: 4096 +aw2-alsa.c: 22536 +aw2-saa7146.c: 12816 +aw2-saa7146.h: 3650 +aw2-tsl.c: 4092 +awacs.c: 32895 +awacs.h: 8192 +ax25: 4096 +ax25_addr.c: 6217 +ax25_dev.c: 4867 +ax25_ds_in.c: 7261 +ax25_ds_subr.c: 5218 +ax25_ds_timer.c: 5960 +ax25.h: 2752 +ax25_iface.c: 5067 +ax25_in.c: 10789 +ax25_ip.c: 5405 +ax25_out.c: 8933 +ax25_route.c: 11432 +ax25_std_in.c: 11343 +ax25_std_subr.c: 2329 +ax25_std_timer.c: 4335 +ax25_subr.c: 7113 +ax25_timer.c: 5261 +ax25.txt: 610 +ax25_uid.c: 5032 +ax88796.c: 25354 +ax88796.h: 751 +axisflashmap.c: 11854 +axisflashmap.h: 1932 +axnet_cs.c: 55656 +axon_msi.c: 11768 +axonram.c: 9510 +azt2320.c: 9995 +azt3328.c: 74771 +azt3328.h: 16466 +b128ops.h: 2471 +b180_defconfig: 30806 +b1.c: 20917 +b1dma.c: 24682 +b1isa.c: 6013 +b1lli.h: 1654 +b1pci.c: 10903 +b1pcmcia.c: 5718 +b1pcmcia.h: 666 +b2: 4096 +b2c2: 4096 +b3dfg: 4096 +b3dfg.c: 29136 +b43: 4096 +b43.h: 34564 +b43legacy: 4096 +b43legacy.h: 26792 +b43_pci_bridge.c: 1563 +b44.c: 58926 +b44.h: 17577 +ba_action.c: 43 +baboon.c: 2869 +backchannel_rqst.c: 9002 +backend-api.txt: 23417 +backend.c: 8969 +background.c: 4246 +backing-dev.c: 7753 +backing-dev.h: 7625 +backing_ops.c: 11152 +backlight: 4096 +backlight.c: 8488 +backlight.h: 1076 +backoff.h: 514 +backtrace.c: 2048 +backtrace.S: 3769 +backtracetest.c: 2135 +badge4.c: 7278 +badge4_defconfig: 25237 +badge4.h: 2530 +bad_inode.c: 8103 +bad_memory.txt: 1113 +balance: 5103 +balloc.c: 28466 +balloon.c: 15823 +bamboo.c: 1219 +bamboo_defconfig: 23088 +bamboo.dts: 7833 +barrier.h: 751 +barrier.txt: 10841 +base: 4096 +baseband.c: 69836 +baseband.h: 5142 +base.c: 17017 +base.h: 5692 +base.S: 2976 +bas-gigaset.c: 70245 +basic: 4096 +basic-pm-debugging.txt: 10323 +basic_profiling.txt: 1707 +basler: 4096 +bast-cpld.h: 1556 +bast-ide.c: 2522 +bast-irq.c: 3575 +bast-irq.h: 842 +bast-map.h: 5001 +bast-pmu.h: 1140 +battery.c: 26147 +baycom_epp.c: 34930 +baycom.h: 820 +baycom_par.c: 16899 +baycom_ser_fdx.c: 21220 +baycom_ser_hdx.c: 21005 +baycom.txt: 7038 +bbc_envctrl.c: 15825 +bbc.h: 9957 +bbc_i2c.c: 9865 +bbc_i2c.h: 1987 +bbm.h: 4408 +bcache.h: 1450 +bcast.c: 21337 +bcast.h: 5594 +bcd.c: 257 +bcd.h: 195 +bcm1480: 4096 +bcm1480_int.h: 18356 +bcm1480_l2c.h: 8696 +bcm1480_mc.h: 51843 +bcm1480_regs.h: 42338 +bcm1480_scd.h: 15457 +bcm203x.c: 7066 +bcm3510.c: 21894 +bcm3510.h: 1667 +bcm3510_priv.h: 9194 +bcm47xx: 4096 +bcm47xx_defconfig: 44162 +bcm47xx.h: 914 +bcm47xx_wdt.c: 6278 +bcm5974.c: 22743 +bcm5974.txt: 2275 +bcm.c: 39855 +bcm.h: 2057 +bcom_ata_task.c: 1873 +bcom_fec_rx_task.c: 2688 +bcom_fec_tx_task.c: 3548 +bcom_gen_bd_rx_task.c: 1901 +bcom_gen_bd_tx_task.c: 2118 +bc_svc.c: 2387 +bcu.c: 5507 +bc_xprt.h: 1873 +bdx.bin.ihex: 117765 +beacon.c: 16577 +bearer.c: 17977 +bearer.h: 6277 +beat.c: 5680 +beat.h: 1477 +beat_htab.c: 12023 +beat_hvCall.S: 4654 +beat_interrupt.c: 7398 +beat_interrupt.h: 1147 +beat_iommu.c: 3142 +beat_smp.c: 2934 +beat_spu_priv1.c: 5295 +beat_syscall.h: 9338 +beat_udbg.c: 2419 +beat_wrapper.h: 7284 +be_byteshift.h: 1424 +be_cmds.c: 28134 +be_cmds.h: 21092 +beep.c: 7937 +be_ethtool.c: 10213 +befs: 4096 +befs_fs_types.h: 5040 +befs.h: 3265 +befs.txt: 3636 +be.h: 9794 +be_hw.h: 6736 +belkin_sa.c: 17581 +belkin_sa.h: 5114 +be_main.c: 53536 +be_memmove.h: 770 +Benchmark.h: 14912 +benet: 4096 +berry_charge.c: 5094 +bestcomm: 4096 +bestcomm.c: 13444 +bestcomm.h: 5696 +bestcomm_priv.h: 10178 +be_struct.h: 749 +BF518F-EZBRD_defconfig: 30487 +bf518.h: 3233 +BF526-EZBRD_defconfig: 37925 +BF527-EZKIT_defconfig: 39344 +bf527.h: 3368 +BF533-EZKIT_defconfig: 27699 +bf533.h: 3987 +BF533-STAMP_defconfig: 31991 +bf537.h: 3679 +BF537-STAMP_defconfig: 33322 +BF538-EZKIT_defconfig: 31824 +bf538.h: 3110 +BF548-EZKIT_defconfig: 41918 +bf548.h: 3408 +bf54x-keys.c: 10383 +bf54x_keys.h: 373 +bf54x-lq043fb.c: 19521 +bf54x-lq043.h: 486 +BF561-EZKIT_defconfig: 27483 +bf561.h: 5899 +bf5xx-ac97.c: 10719 +bf5xx-ac97.h: 1698 +bf5xx-ac97-pcm.c: 13449 +bf5xx-ac97-pcm.h: 595 +bf5xx-ad1980.c: 3043 +bf5xx-ad73311.c: 6491 +bf5xx-i2s.c: 8397 +bf5xx-i2s.h: 321 +bf5xx-i2s-pcm.c: 7810 +bf5xx-i2s-pcm.h: 591 +bf5xx_nand.c: 19911 +bf5xx-sport.c: 26015 +bf5xx-sport.h: 5191 +bf5xx-ssm2602.c: 4846 +bfin_5xx.c: 37574 +bfin5xx_spi.h: 3282 +bfin-async-flash.c: 5961 +bfin_cf_pcmcia.c: 8045 +bfind.c: 4484 +bfin_dma_5xx.c: 13838 +bfin-global.h: 3579 +bfin_gpio.c: 31670 +bfin-gpio-notes.txt: 2459 +bfin_jtag_comm.c: 9699 +bfin_ksyms.c: 3302 +bfin_mac.c: 29136 +bfin_mac.h: 1654 +bfin_oprofile.c: 303 +bfin-otp.c: 4874 +bfin_sdh.h: 273 +bfin_serial_5xx.h: 5124 +bfin_simple_timer.h: 446 +bfin_sir.c: 18943 +bfin_sir.h: 5300 +bfin_sport.h: 3839 +bfin_sport_uart.c: 16463 +bfin_sport_uart.h: 3726 +bfin-t350mcqb-fb.c: 16570 +bfin_wdt.c: 11813 +bfrom.h: 3443 +bfs: 4096 +bfs_fs.h: 1830 +bfs.h: 1424 +bfs.txt: 2118 +bfusb.c: 17036 +bif_core_defs_asm.h: 15240 +bif_core_defs.h: 9672 +bif_dma_defs_asm.h: 22539 +bif_dma_defs.h: 14998 +bif_slave_defs_asm.h: 11664 +bif_slave_defs.h: 8256 +big_endian.h: 3729 +big-endian.S: 304 +BIG.FAT.WARNING: 234 +bigsmp_32.c: 6414 +bigsur_defconfig: 32018 +bigsur.h: 1540 +bin2c.c: 702 +bin2hex.c: 755 +bin.c: 11164 +bind_addr.c: 13678 +bind.c: 7327 +bindec.S: 28113 +binder.c: 105864 +binder.h: 9073 +bind.h: 1305 +binding.txt: 3687 +binfmt_aout.c: 13156 +binfmt_elf32.c: 3565 +binfmt_elf.c: 55465 +binfmt_elf_fdpic.c: 48887 +binfmt_elfn32.c: 3368 +binfmt_elfo32.c: 4508 +binfmt_em86.c: 2848 +binfmt_flat.c: 27410 +binfmt_loader.c: 1116 +binfmt_misc.c: 15436 +binfmt_misc.txt: 6108 +binfmt_script.c: 2829 +binfmts.h: 4146 +binfmt_som.c: 7567 +binoffset.c: 4039 +binstr.S: 4302 +bio.c: 39950 +biodoc.txt: 55452 +bio.h: 20583 +bio-integrity.c: 21385 +bios32.c: 17673 +bios.c: 2953 +bioscall.S: 1566 +bioscalls.c: 13235 +bios_ebda.h: 794 +bios.h: 3282 +bios_uv.c: 4629 +bitblit.c: 10909 +bitext.c: 2979 +bitext.h: 613 +bitfield.h: 19835 +bitmap.c: 45202 +bitmap.h: 10515 +bit_operations.h: 5627 +bitops: 4096 +bitops_32.h: 2988 +bitops_64.h: 2428 +bitops.c: 1091 +bitops-grb.h: 6325 +bitops.h: 3153 +bitops-llsc.h: 2819 +bitops_mm.h: 11048 +bitops_no.h: 8097 +bitops-op32.h: 3832 +bitops.S: 2667 +bitrev.c: 2157 +bitrev.h: 270 +bits.h: 2634 +bitsperlong.h: 37 +bit_spinlock.h: 2210 +bitstream.bin.ihex: 33395 +bitstream.HEX: 192281 +bkm_a4t.c: 9149 +bkm_a8.c: 11765 +bkm_ax.h: 4575 +blackfin: 4096 +blackfin.c: 7552 +blackfin.h: 1089 +blackfin_sram.h: 1207 +blacklist.c: 8658 +blacklist.h: 108 +blackstamp.c: 9838 +BlackStamp_defconfig: 27434 +blinken.h: 617 +blizzard.c: 41338 +blizzard.h: 249 +blk-barrier.c: 9923 +blkcipher.c: 19013 +blk-core.c: 65533 +blkdev.h: 38233 +blk-exec.c: 2683 +blk.h: 4565 +blkif.h: 3398 +blk-integrity.c: 10137 +blk-ioc.c: 4083 +blk-map.c: 8314 +blk-merge.c: 9996 +blkpg.h: 1569 +blk-settings.c: 21842 +blk-softirq.c: 4192 +blk-sysfs.c: 12022 +blk-tag.c: 10090 +blk-timeout.c: 5850 +blktrace_api.h: 7347 +blktrace.c: 40749 +blktrans.h: 1935 +bloat-o-meter: 1711 +block: 4096 +block2mtd.c: 10757 +block.c: 15974 +blockcheck.c: 16817 +blockcheck.h: 3928 +blockdev: 4096 +block_dev.c: 37737 +blockgroup_lock.h: 1164 +block.h: 12870 +blockops.S: 2573 +block_validity.c: 6187 +blowfish.c: 17890 +bluecard_cs.c: 21854 +bluetooth: 4096 +bluetooth.h: 4823 +bmac.c: 42545 +bmac.h: 8220 +bmap.c: 17082 +bmap.h: 8896 +bmap_union.h: 1274 +bnep: 4096 +bnep.h: 4313 +bnode.c: 15448 +bnx2: 4096 +bnx2.c: 204472 +bnx2_fw.h: 2909 +bnx2.h: 328128 +bnx2i: 4096 +bnx2i.h: 23900 +bnx2i_hwi.c: 73780 +bnx2i_init.c: 11868 +bnx2i_iscsi.c: 56395 +bnx2i_sysfs.c: 3632 +bnx2-mips-06-4.6.16.fw.ihex: 255140 +bnx2-mips-09-4.6.17.fw.ihex: 255536 +bnx2-rv2p-06-4.6.16.fw.ihex: 19256 +bnx2-rv2p-09-4.6.15.fw.ihex: 21444 +bnx2x_dump.h: 28960 +bnx2x-e1-4.8.53.0.fw.ihex: 455912 +bnx2x-e1h-4.8.53.0.fw.ihex: 529144 +bnx2x_fw_defs.h: 15968 +bnx2x_fw_file_hdr.h: 1226 +bnx2x.h: 36495 +bnx2x_hsi.h: 87970 +bnx2x_init.h: 12172 +bnx2x_init_ops.h: 12435 +bnx2x_link.c: 162411 +bnx2x_link.h: 6119 +bnx2x_main.c: 321334 +bnx2x_reg.h: 308654 +board-1arm.c: 2699 +board-2430sdp.c: 5365 +board-3430sdp.c: 12788 +board-4430sdp.c: 2343 +board-a9m9750dev.c: 3624 +board-a9m9750dev.h: 478 +board-acs5k.c: 5495 +board-afeb-9260v1.c: 5234 +board-ams-delta.c: 6109 +board-ams-delta.h: 3023 +board-ap325rxa.c: 13583 +board-apollon.c: 8566 +board-armadillo5x0.h: 564 +board.c: 3934 +board-cam60.c: 4681 +board-cap9adk.c: 9718 +board-carmeva.c: 4435 +board-csb337.c: 6265 +board-csb637.c: 3642 +board-dk.c: 5862 +board-dm355-evm.c: 7541 +board-dm355-leopard.c: 7584 +board-dm644x-evm.c: 17303 +board-dm646x-evm.c: 5912 +board-dsm320.c: 2919 +board-eb01.c: 1385 +board-eb9200.c: 3461 +board-eb.h: 3843 +board-ecbat91.c: 4404 +board-edosk7760.c: 4611 +board-ek.c: 5054 +boardergo.c: 16200 +boardergo.h: 4069 +board-espt.c: 2426 +board-fsample.c: 8474 +board-generic.c: 1918 +board.h: 3611 +board-h2.c: 10497 +board-h2.h: 1585 +board-h2-mmc.c: 1862 +board-h3.c: 9698 +board-h3.h: 1550 +board-h3-mmc.c: 1668 +board-h4.c: 9524 +board-halibut.c: 2112 +board-innovator.c: 10872 +board-jscc9p9360.c: 457 +board-jscc9p9360.h: 390 +board-kafa.c: 2778 +board-kb9202.c: 3738 +board-ldp.c: 9161 +board-magicpanelr2.c: 11382 +board-micrel.c: 1450 +board-mx21ads.h: 1998 +board-mx27ads.h: 10858 +board-mx27lite.h: 544 +board-mx27pdk.h: 541 +board-mx31ads.h: 3850 +board-mx31lilly.h: 1430 +board-mx31lite.h: 508 +board-mx31moboard.h: 1408 +board-mx31pdk.h: 2120 +board-mx35pdk.h: 1062 +board-neocore926.c: 9196 +board-nokia770.c: 9780 +board-omap3beagle.c: 10647 +board-omap3evm.c: 7649 +board-omap3pandora.c: 10350 +board-osk.c: 15556 +board-overo.c: 11768 +board-palmte.c: 9495 +board-palmtt.c: 7148 +board-palmz71.c: 8139 +board-pb1176.h: 3534 +board-pb11mp.h: 3933 +board-pba8.h: 3279 +board-pbx.h: 4735 +board-pcm037.h: 1039 +board-pcm038.h: 1428 +board-pcm043.h: 1039 +board-perseus2.c: 7106 +board-picotux200.c: 4544 +board-polaris.c: 3273 +board-qil-a9260.c: 6417 +board-qong.h: 590 +board-rut1xx.c: 2111 +board-rx51.c: 2237 +board-rx51-peripherals.c: 9630 +boards: 4096 +board-sam9260ek.c: 8166 +board-sam9261ek.c: 14425 +board-sam9263ek.c: 10154 +board-sam9g20ek.c: 7036 +board-sam9-l9260.c: 5065 +board-sam9rlek.c: 5294 +boards.c: 9634 +board-se7619.c: 368 +board_setup.c: 991 +board-sffsdr.c: 5298 +boards.h: 874 +board-sh7785lcr.c: 8051 +board-shmin.c: 715 +board-sx1.c: 10319 +board-sx1.h: 1472 +board-sx1-mmc.c: 1614 +board.txt: 1400 +board-urquell.c: 4834 +board-usb-a9260.c: 5382 +board-usb-a9263.c: 5692 +board-voiceblue.c: 6718 +board-voiceblue.h: 552 +board-yl-9200.c: 19259 +board-zoom2.c: 2568 +board-zoom-debugboard.c: 3833 +bond_3ad.c: 81880 +bond_3ad.h: 9440 +bond_alb.c: 45790 +bond_alb.h: 4802 +bonding: 4096 +bonding.h: 10602 +bonding.txt: 98243 +bond_ipv6.c: 5432 +bond_main.c: 137243 +bond_sysfs.c: 42050 +bonito64.h: 16247 +bonito-irq.c: 2465 +booke.c: 16034 +booke_emulate.c: 6991 +booke.h: 2429 +booke_interrupts.S: 11644 +booke_wdt.c: 4745 +boot: 4096 +boot2.H16: 14566 +boot.c: 8143 +bootcode.bin.ihex: 604 +boot-elf: 4096 +bootflag.c: 1698 +bootgraph.pl: 5753 +boot.h: 1195 +boot.H16: 14980 +boot_head.S: 4023 +bootinfo.h: 3250 +Booting: 4704 +booting.txt: 5755 +booting-without-of.txt: 61721 +boot.ld: 812 +boot.lds.S: 927 +bootloader.c: 3823 +bootloader.lds: 501 +bootlogo.h: 236895 +bootlogo.pl: 165 +bootmem.c: 19242 +bootmem.h: 4841 +boot-options.txt: 12803 +bootp: 4096 +bootparam.h: 1530 +bootp.c: 5689 +bootp.lds: 695 +bootpz.c: 13415 +boot-redboot: 4096 +Boot.S: 2820 +bootstd.h: 4709 +bootstr_32.c: 1207 +bootstr_64.c: 1055 +bootstrap.asm: 2924 +bootstrap.bin.ihex: 1080 +bootstrap.S: 4829 +boot.txt: 35058 +bootwrapper.txt: 7768 +bootx.h: 5211 +bootx_init.c: 16762 +bottom_half.h: 224 +bounce.c: 6616 +bounds.c: 526 +bpa10x.c: 10967 +bpck6.c: 6457 +bpck.c: 9505 +bpqether.c: 14923 +bpqether.h: 952 +bq24022.c: 4006 +bq24022.h: 728 +bq27x00_battery.c: 8343 +br2684.c: 20774 +braille: 4096 +braille_console.c: 8194 +braille-console.txt: 1458 +branch.c: 5609 +branches: 4096 +branch.h: 794 +br.c: 2297 +brcmphy.h: 277 +brd.c: 13994 +br_device.c: 4305 +break.h: 1512 +break.S: 20777 +brec.c: 13153 +br_fdb.c: 10129 +br_forward.c: 3296 +brg.txt: 450 +bridge: 4096 +bridge.h: 29862 +bridge-regs.h: 1121 +bridge.txt: 382 +br_if.c: 9454 +br_input.c: 4146 +br_ioctl.c: 9353 +briq_panel.c: 5383 +brl_emu.c: 5592 +br_netfilter.c: 28764 +br_netlink.c: 4931 +br_notify.c: 2202 +broadcom.c: 17870 +broadsheetfb.c: 13698 +broadsheetfb.h: 1727 +br_private.h: 7906 +br_private_stp.h: 1654 +br_stp_bpdu.c: 5251 +br_stp.c: 11134 +br_stp_if.c: 7340 +br_stp_timer.c: 4651 +br_sysfs_br.c: 12447 +br_sysfs_if.c: 6540 +Brutus: 1927 +bsbe1.h: 3346 +bsd_comp.c: 29587 +bsg.c: 23964 +bsg.h: 3096 +bsr.c: 8971 +bsru6.h: 3855 +bssdb.c: 59681 +bssdb.h: 9978 +bt3c_cs.c: 16786 +bt431.h: 5854 +bt455.h: 2096 +bt819.c: 14549 +bt819.h: 1082 +bt848.h: 11788 +bt856.c: 7085 +bt866.c: 6222 +bt878.c: 16114 +bt878.h: 4113 +bt87x.c: 30530 +Bt87x.txt: 2597 +bt8xx: 4096 +bt8xxgpio.c: 8476 +bt8xxgpio.txt: 4402 +bt8xx.txt: 3940 +btaudio: 3104 +btcx-risc.c: 6470 +btcx-risc.h: 863 +bte.c: 12913 +bte_error.c: 7665 +bte.h: 7765 +btext.c: 38463 +btext.h: 858 +btfixup.c: 10268 +btfixup.h: 7304 +btfixupprep.c: 11589 +btnode.c: 8474 +btnode.h: 2067 +btree.c: 8032 +btree.h: 5488 +btrfs: 4096 +btrfs_inode.h: 4339 +btrfs.txt: 2918 +btsdio.c: 8446 +bttv: 4096 +bttv-audio-hook.c: 9617 +bttv-audio-hook.h: 1126 +bttv-cards.c: 151213 +bttv-driver.c: 121604 +bttv-gpio.c: 4858 +bttv.h: 14877 +bttv-i2c.c: 10677 +bttv-if.c: 2894 +bttv-input.c: 10597 +bttvp.h: 14108 +bttv-risc.c: 25965 +bttv-vbi.c: 12835 +btuart_cs.c: 15857 +btusb.c: 24625 +buddha.c: 5673 +budget-av.c: 45832 +budget.c: 23026 +budget-ci.c: 46442 +budget-core.c: 17319 +budget.h: 3030 +budget-patch.c: 20598 +buffer.c: 3308 +buffer-format.txt: 4606 +buffer_head.h: 11463 +buffer_head_io.c: 10961 +buffer_head_io.h: 2416 +buffer_icap.c: 10726 +buffer_icap.h: 2297 +buffer_sync.c: 13744 +buffer_sync.h: 432 +bug.c: 423 +bugfix.S: 14062 +bug.h: 400 +BUG-HUNTING: 8326 +BUGS: 235 +bugs_64.c: 778 +bugs.c: 1893 +bugs.h: 451 +BUGS-parport: 319 +build.c: 39439 +builddeb: 5872 +buildtar: 2659 +builtin-annotate.c: 29512 +builtin.h: 1035 +builtin-help.c: 11520 +builtin-list.c: 408 +builtin-record.c: 14786 +builtin-report.c: 35243 +builtin-stat.c: 13788 +builtin-top.c: 17061 +bunzip2.h: 258 +burgundy.c: 25045 +burgundy.h: 4105 +bus.c: 8958 +busctl-regs.h: 2071 +bus.h: 950 +BusLogic.c: 151498 +BusLogic.h: 40976 +BusLogic.txt: 26440 +bus-osm.c: 4125 +busses: 4096 +bust_spinlocks.c: 636 +bus.txt: 4536 +bus_watcher.c: 7864 +butterfly: 2990 +button.c: 12060 +buttons.c: 1516 +bvme6000: 4096 +bvme6000_defconfig: 24611 +bvme6000hw.h: 3490 +bvme6000_scsi.c: 3343 +bw2.c: 9440 +bw-qcam.c: 25715 +bw-qcam.h: 2049 +byteorder: 4096 +byteorder.h: 277 +bzero.S: 3581 +c101.c: 11218 +c16e9e8bb74f14f4504305957e4346e7fc46ea: 296 +c2_ae.c: 9166 +c2_ae.h: 3338 +c2_alloc.c: 4106 +c2.c: 33727 +c2_cm.c: 9984 +c2_cq.c: 10526 +c2.h: 13957 +c2_intr.c: 5630 +c2k.c: 3705 +c2k_defconfig: 48649 +c2k.dts: 8777 +c2_mm.c: 8862 +c2_mq.c: 4622 +c2_mq.h: 3238 +c2p_core.h: 2688 +c2_pd.c: 3012 +c2p.h: 631 +c2p_iplan2.c: 3576 +c2port: 4096 +c2port-duramar2150.c: 3241 +c2port.h: 1788 +c2port.txt: 2848 +c2p_planar.c: 3697 +c2_provider.c: 21747 +c2_provider.h: 4101 +c2_qp.c: 25022 +c2_rnic.c: 16782 +c2_status.h: 5103 +c2_user.h: 2415 +c2_vq.c: 7741 +c2_vq.h: 2530 +c2_wr.h: 35475 +c3000_defconfig: 37418 +c4.c: 33871 +c67x00: 4096 +c67x00-drv.c: 6069 +c67x00.h: 9392 +c67x00-hcd.c: 10012 +c67x00-hcd.h: 4298 +c67x00-ll-hpi.c: 12221 +c67x00-sched.c: 30459 +c6xdigio.c: 13668 +ca0106: 4096 +ca0106.h: 37992 +ca0106_main.c: 59396 +ca0106_mixer.c: 27767 +ca0106_proc.c: 14457 +cacheasm.h: 3274 +cache.c: 10301 +cache-c.c: 733 +cachectl.h: 752 +cache-debugfs.c: 3861 +cache-fa.S: 5726 +cachefeatures.txt: 1538 +cache-feroceon-l2.c: 8394 +cache-feroceon-l2.h: 358 +cachefiles: 4096 +cachefiles.txt: 17132 +cacheflush_32.h: 3544 +cacheflush_64.h: 2543 +cacheflush.h: 7154 +cacheflush_mm.h: 4194 +cache-flush-mn10300.S: 5528 +cacheflush_no.h: 2672 +cacheflush.S: 1897 +cache.h: 4660 +cacheinfo.c: 20221 +cacheinfo.h: 240 +cacheinit.c: 1960 +cache-l2x0.c: 3064 +cache-l2x0.h: 1931 +cache-lock.txt: 1222 +cache-mn10300.S: 6477 +cacheops.h: 2183 +cache-page.c: 1964 +cache.S: 2858 +cache-sh2a.c: 3241 +cache-sh2.c: 2044 +cache-sh3.c: 2486 +cache-sh4.c: 20825 +cache-sh5.c: 27270 +cache-sh7705.c: 5050 +cachetlb.txt: 16265 +cachetype.h: 1643 +cache-v3.S: 3174 +cache-v4.S: 3364 +cache-v4wb.S: 5731 +cache-v4wt.S: 4411 +cache-v6.S: 6450 +cache-v7.S: 7015 +cache-xsc3l2.c: 5806 +caching: 4096 +cafe_ccic: 2424 +cafe_ccic.c: 53700 +cafe_ccic-regs.h: 6845 +cafe_nand.c: 25500 +cagg.c: 110445 +cagg.h: 15067 +ca.h: 3022 +caiaq: 4096 +caleb.c: 3138 +caleb.h: 636 +calgary.h: 2452 +calib.c: 28905 +calib.h: 3835 +calibrate.c: 5121 +callback.c: 9965 +callback.h: 2994 +callback_proc.c: 6012 +callbacks.c: 7878 +callbacks.h: 1495 +callback_srm.S: 2840 +callbacks.txt: 4860 +callback_xdr.c: 18050 +callc.c: 48919 +callchain.c: 3746 +callchain.h: 711 +call_hpt.h: 3078 +calling.h: 5596 +call_o32.S: 2534 +call_pci.h: 7934 +call_sm.h: 1270 +calls.S: 10619 +cam60_defconfig: 28038 +camellia.c: 35950 +camera.h: 1504 +cam.h: 4590 +ca_midi.c: 8689 +ca_midi.h: 2024 +can: 4096 +can.h: 3326 +can.txt: 35254 +canyonlands_defconfig: 25711 +canyonlands.dts: 14369 +capability.c: 8203 +capability.h: 17864 +capability.txt: 618 +capcella_defconfig: 18424 +capcella.h: 1486 +capi: 4096 +capi20.h: 29357 +capi.c: 33038 +capicmd.h: 4663 +capidrv.c: 64650 +capidrv.h: 4862 +capidtmf.c: 26932 +capidtmf.h: 3726 +capifs.c: 5266 +capifs.h: 360 +capifunc.c: 31377 +capifunc.h: 903 +capi.h: 10360 +capilib.c: 4606 +capilli.h: 3567 +capimain.c: 3336 +capiutil.c: 30023 +capiutil.h: 14649 +capmode.c: 8041 +caps.c: 5160 +capture.c: 9562 +capture.h: 702 +card: 4096 +cardbus.c: 6323 +card.c: 10228 +card.h: 4366 +CARDLIST.au0828: 527 +CARDLIST.bttv: 9061 +CARDLIST.cx23885: 1693 +CARDLIST.cx88: 5876 +CARDLIST.em28xx: 4880 +CARDLIST.ivtv: 1163 +CARDLIST.saa7134: 9829 +CARDLIST.tuner: 2995 +CARDLIST.usbvision: 4940 +Cards: 26708 +cards.txt: 4752 +cardtype.h: 39894 +carmel.h: 1969 +carmeva_defconfig: 13180 +carminefb.c: 22690 +carminefb.h: 2251 +carminefb_regs.h: 6940 +carta_random.S: 1032 +casio-e55: 4096 +cassini.bin.ihex: 6246 +cassini.c: 145494 +cassini.h: 125724 +cast5.c: 34939 +cast6.c: 22021 +catalog.c: 10749 +catas.c: 4281 +catc.c: 24085 +cats-hw.c: 2052 +cats-pci.c: 1313 +cavium-octeon: 4096 +cavium-octeon_defconfig: 22786 +cayman_defconfig: 31979 +cb710: 4096 +cb710.h: 6584 +cb710-mmc.c: 22406 +cb710-mmc.h: 3337 +cbaf.c: 20405 +cbc.c: 7621 +cb_das16_cs.c: 25977 +cbe_cpufreq.c: 4980 +cbe_cpufreq.h: 578 +cbe_cpufreq_pervasive.c: 2924 +cbe_cpufreq_pmi.c: 3695 +cbe_powerbutton.c: 3019 +cbe_regs.c: 6692 +cbe_thermal.c: 10724 +cb_pcidas64.c: 122559 +cb_pcidas.c: 54058 +cb_pcidda.c: 24298 +cb_pcidio.c: 9309 +cb_pcimdas.c: 14161 +cb_pcimdda.c: 15282 +cchips: 4096 +ccid2.c: 21699 +ccid2.h: 2480 +ccid3.c: 29348 +ccid3.h: 6401 +ccid.c: 5450 +ccid.h: 7568 +ccids: 4096 +ccio-dma.c: 48900 +ccio-rm-dma.c: 5203 +cciss.c: 121676 +cciss_cmd.h: 8834 +cciss.h: 7343 +cciss_ioctl.h: 6805 +cciss_scsi.c: 49769 +cciss_scsi.h: 3184 +cciss.txt: 6396 +ccm.c: 22059 +ccmd.c: 47173 +ccwdev.h: 6880 +ccwgroup.c: 16375 +ccwgroup.h: 2479 +cd1400.h: 7059 +cd1865.h: 13309 +cd32.txt: 535 +cda2df87ba4ecc7988be7a45d01645e11c9f4c: 307 +cdb89712.c: 5870 +cdc2.c: 6912 +cdc-acm.c: 43081 +cdc-acm.h: 3737 +cdc_eem.c: 9394 +cdc_ether.c: 17432 +cdc.h: 7100 +cdc_subset.c: 10970 +cdc-wdm.c: 19634 +cdefBF512.h: 1386 +cdefBF514.h: 5819 +cdefBF516.h: 16666 +cdefBF518.h: 16668 +cdefBF51x_base.h: 71524 +cdefBF522.h: 1386 +cdefBF525.h: 26762 +cdefBF527.h: 37609 +cdefBF52x_base.h: 71524 +cdefBF532.h: 48301 +cdefBF534.h: 124785 +cdefBF537.h: 13187 +cdefBF538.h: 148152 +cdefBF539.h: 16826 +cdefBF542.h: 35078 +cdefBF544.h: 59758 +cdefBF547.h: 48769 +cdefBF548.h: 98262 +cdefBF549.h: 115636 +cdefBF54x_base.h: 169306 +cdefBF561.h: 117485 +cdef_LPBlackfin.h: 20055 +cdev.c: 25135 +cdev.h: 677 +cdk.h: 12770 +cdrom: 4096 +cdrom.c: 99243 +cdrom.h: 36224 +cdrom-standard.tex: 51371 +cdrom.txt: 19223 +cds.txt: 21022 +ce6230.c: 8126 +ce6230.h: 2306 +ceiva.c: 7563 +cell: 4096 +cell.c: 9326 +cell_defconfig: 37867 +celleb_defconfig: 32091 +celleb_pci.c: 12369 +celleb_pci.h: 1402 +celleb_scc_epci.c: 10052 +celleb_scc.h: 7871 +celleb_scc_pciex.c: 15023 +celleb_scc_sio.c: 2600 +celleb_scc_uhc.c: 2518 +celleb_setup.c: 6097 +cell_edac.c: 7394 +cell-pmu.h: 4133 +cell-regs.h: 9211 +centaur.c: 5432 +central.c: 6181 +CERF: 1215 +cerf.c: 3449 +cerfcube_defconfig: 17978 +cerf.h: 810 +cerr-sb1.c: 16742 +cevt-bcm1480.c: 4444 +cevt-ds1287.c: 2833 +cevt-gt641xx.c: 3662 +cevt-r4k.c: 5115 +cevt-r4k.h: 1421 +cevt-sb1250.c: 4380 +cevt-smtc.c: 8920 +cevt-txx9.c: 5694 +cex-gen.S: 1009 +cex-oct.S: 1574 +cex-sb1.S: 4707 +cfag12864b: 3173 +cfag12864b.c: 8350 +cfag12864b-example.c: 5897 +cfag12864bfb.c: 4656 +cfag12864b.h: 2147 +cfbcopyarea.c: 11312 +cfbfillrect.c: 8940 +cfbimgblt.c: 8396 +cfe: 4096 +cfe_api.c: 11219 +cfe_api.h: 3833 +cfe_api_int.h: 4031 +cfe.c: 8423 +cfe_console.c: 1737 +cfe_error.h: 2197 +cfg80211.c: 10563 +cfg80211.h: 1079 +cfg.c: 35379 +cfg.h: 155 +cfi_cmdset_0001.c: 73671 +cfi_cmdset_0002.c: 53117 +cfi_cmdset_0020.c: 38615 +cfi_endian.h: 1238 +cfi_flagadm.c: 3947 +cfi.h: 13714 +cfi_probe.c: 11670 +cfi_util.c: 5934 +cfm.c: 16482 +cfq-iosched.c: 65456 +cfunc.c: 33674 +cfunc.h: 23021 +cg14.c: 15044 +cg3.c: 11707 +cg6.c: 22284 +cgroup.c: 95997 +cgroup_debug.c: 2057 +cgroup_freezer.c: 9146 +cgroup.h: 15604 +cgroups: 4096 +cgroupstats.h: 2155 +cgroupstats.txt: 1307 +cgroups.txt: 21831 +cgroup_subsys.h: 697 +ch341.c: 15479 +ch9.h: 24667 +chafsr.h: 9671 +chainiv.c: 8763 +changebit.S: 617 +ChangeLog: 18049 +CHANGELOG: 18049 +ChangeLog.1992-1997: 59954 +ChangeLog.arcmsr: 6754 +ChangeLog.history: 25741 +ChangeLog.ide-cd.1994-2004: 15586 +ChangeLog.ide-floppy.1996-2002: 4068 +ChangeLog.ide-tape.1995-2002: 16249 +ChangeLog.ips: 5304 +ChangeLog.lpfc: 89671 +ChangeLog.megaraid: 23975 +ChangeLog.megaraid_sas: 12624 +ChangeLog.ncr53c8xx: 22786 +ChangeLog.sym53c8xx: 29464 +ChangeLog.sym53c8xx_2: 6011 +Changes: 4725 +CHANGES: 4725 +chan_kern.c: 13142 +chan_kern.h: 1587 +chan_user.c: 7101 +chan_user.h: 1710 +char: 4096 +char_dev.c: 13712 +chb.c: 5975 +ch.c: 24601 +check-all.sh: 434 +check.c: 3835 +check-gas: 277 +check-gas-asm.S: 37 +check.h: 551 +checkincludes.pl: 529 +checkkconfigsymbols.sh: 1851 +checklist.c: 8211 +checklist.txt: 14315 +check-lxdialog.sh: 1653 +check-model.c: 47 +checkpatch.pl: 70566 +checkpoint.c: 21921 +checks.c: 15663 +check-segrel.lds: 203 +check-segrel.S: 45 +check-serialize.S: 41 +check.sh: 214 +check_signature.c: 599 +checkstack.pl: 5332 +checksum_32.h: 4895 +checksum_32.S: 4739 +checksum_64.h: 5349 +checksum_64.S: 6192 +checksum.c: 4610 +checksumcopy.S: 2455 +checksum.h: 6169 +checksum_mm.h: 3391 +checksum_no.h: 3074 +checksum.S: 9073 +checksyscalls.sh: 5661 +check-text-align.S: 69 +checkversion.pl: 1867 +chelsio: 4096 +cherrs.S: 15233 +chio.h: 5287 +chip.c: 15518 +chip.h: 5099 +chipram.c: 3350 +chipreg.c: 2405 +chips: 4096 +chipsfb.c: 12752 +chlist.h: 30 +chmc.c: 20666 +chmctrl.h: 8057 +chp.c: 17406 +chp.h: 1489 +chpid.h: 1040 +chrp: 4096 +chrp32_defconfig: 40160 +chrp.h: 308 +chsc.c: 22534 +chsc.h: 2470 +chsc_sch.c: 19838 +chsc_sch.h: 179 +chunk.c: 8172 +ci13xxx_udc.c: 69484 +ci13xxx_udc.h: 6227 +cia.c: 4343 +cicada.c: 3994 +cic.c: 14355 +cifs: 4096 +cif.S: 1000 +cifsacl.c: 21375 +cifsacl.h: 2405 +cifs_debug.c: 21856 +cifs_debug.h: 2329 +cifs_dfs_ref.c: 9982 +cifsencrypt.c: 12795 +cifsencrypt.h: 1256 +cifsfs.c: 31585 +cifsfs.h: 4854 +cifs_fs_sb.h: 2432 +cifsglob.h: 23265 +cifspdu.h: 81322 +cifsproto.h: 16968 +cifssmb.c: 173618 +cifs_spnego.c: 4357 +cifs_spnego.h: 1628 +cifs.txt: 2406 +cifs_unicode.c: 7190 +cifs_unicode.h: 8878 +cifs_uniupr.h: 12874 +cimax2.c: 11227 +cimax2.h: 1921 +cinergyT2-core.c: 6717 +cinergyT2-fe.c: 8456 +cinergyT2.h: 3001 +cinit.c: 59044 +cio: 4096 +cio.c: 27748 +cio_debug.h: 849 +cio.h: 4879 +cipher.c: 7783 +cipso_ipv4.c: 64343 +cipso_ipv4.h: 7616 +cipso_ipv4.txt: 2252 +circ_buf.h: 1000 +cirrusfb.c: 77607 +cirrusfb.txt: 1934 +cirrus.h: 8939 +cis: 4096 +ciscode.h: 3364 +cisreg.h: 2804 +cistpl.c: 38770 +cistpl.h: 14596 +ci.txt: 6753 +ck804xrom.c: 10948 +class: 4096 +class.c: 12662 +class_to_string.h: 1508 +class.txt: 4758 +claw.c: 115821 +claw.h: 14619 +clcd.c: 5668 +clcd.h: 6601 +cleanfile: 3492 +cleanpatch: 5132 +cleanup.c: 28008 +clearbit.S: 613 +clear_page_64.S: 969 +clear_page.S: 401 +clear_user.S: 2687 +clep7312.c: 1478 +client.c: 45575 +client.h: 7071 +clinkage.h: 27 +clip.c: 24997 +clk.c: 774 +clkdev.c: 3488 +clkdev.h: 122 +clkgen_defs_asm.h: 7393 +clkgen_defs.h: 5421 +clk.h: 4465 +clk_interface.h: 683 +clksupport.h: 844 +clk.txt: 1173 +clnt.c: 42336 +clnt.h: 5095 +clntlock.c: 6865 +clntproc.c: 21263 +clock24xx.c: 22943 +clock24xx.h: 82888 +clock34xx.c: 31225 +clock34xx.h: 84973 +clock-7x01a.c: 4770 +clock.c: 6387 +clockchips.h: 4535 +clock-cpg.c: 5839 +clock-dclk.c: 4423 +clockdomain.c: 16366 +clockdomain.h: 3231 +clockdomains.h: 9108 +clockevents.c: 6244 +clock_getres.S: 1020 +clock_gettime.S: 2948 +clock.h: 1320 +clock_imx21.c: 23302 +clock_imx27.c: 22042 +clock-imx35.c: 13016 +clocking.txt: 1582 +clocks.c: 2153 +clocks.h: 2092 +clock-sh3.c: 2204 +clock-sh4-202.c: 3818 +clock-sh4.c: 1967 +clock-sh5.c: 1848 +clock-sh7201.c: 1982 +clock-sh7203.c: 1936 +clock-sh7206.c: 1931 +clock-sh7343.c: 6574 +clock-sh7366.c: 6500 +clock-sh7619.c: 1741 +clock-sh7705.c: 2140 +clock-sh7706.c: 2055 +clock-sh7709.c: 2302 +clock-sh7710.c: 1874 +clock-sh7712.c: 1592 +clock-sh7722.c: 5683 +clock-sh7723.c: 7223 +clock-sh7724.c: 7654 +clock-sh7763.c: 2503 +clock-sh7770.c: 1749 +clock-sh7780.c: 2630 +clock-sh7785.c: 3792 +clock-sh7786.c: 3252 +clock-shx3.c: 2959 +clocks-init.c: 2524 +clocksource: 4096 +clocksource.c: 16881 +clocksource.h: 11531 +clock.txt: 2443 +clone.c: 1295 +clps7111.h: 5605 +clps711x.c: 13340 +clps711xfb.c: 10751 +cls_api.c: 14078 +cls_basic.c: 6522 +cls_cgroup.c: 6506 +cls_flow.c: 15621 +cls_fw.c: 8499 +cls_route.c: 12482 +cls_rsvp6.c: 768 +cls_rsvp.c: 761 +cls_rsvp.h: 14927 +cls_tcindex.c: 11961 +cls_u32.c: 16562 +cluster: 4096 +cluster.c: 14916 +cluster.h: 3649 +clut_vga16.ppm: 230 +cm109.c: 24186 +cm4000_cs.c: 50839 +cm4000_cs.h: 1822 +cm4040_cs.c: 17240 +cm4040_cs.h: 1435 +cm5200_defconfig: 30374 +cm5200.dts: 5770 +cm9780.h: 1648 +cma.c: 76031 +cmap_xfbdev.txt: 1927 +cm_bf527.c: 24357 +CM-BF527_defconfig: 33449 +cm_bf533.c: 10441 +CM-BF533_defconfig: 17784 +cm_bf537.c: 15825 +CM-BF537E_defconfig: 22519 +CM-BF537U_defconfig: 18739 +cm_bf548.c: 20079 +CM-BF548_defconfig: 31514 +cm_bf561.c: 11463 +CM-BF561_defconfig: 19376 +cmb.h: 2128 +cm.c: 108467 +cmd640.c: 22942 +cmd64x.c: 13588 +cmdblk.h: 1843 +cmd.c: 12040 +cmd.h: 3292 +cmdline.c: 774 +cmdlinepart.c: 9405 +cmdpkt.h: 4387 +cmdresp.c: 16004 +cmf.c: 34004 +cm.h: 3735 +CMI8330: 3229 +cmi8330.c: 22466 +cmipci.c: 104710 +CMIPCI.txt: 9357 +cmmap.c: 75502 +cmm.c: 74564 +cmm_data_2860.c: 34802 +cmm_data_2870.c: 28944 +cmm_data.c: 42 +cmm_info.c: 42 +cmm_sanity.c: 44 +cm_msgs.h: 21469 +cmmsta.c: 182636 +cmm_sync.c: 42 +cmm_wpa.c: 41 +cmode.S: 4744 +cmpdi2.c: 435 +cmp.h: 486 +cmpxchg_32.h: 9438 +cmpxchg_64.h: 4582 +cmpxchg.c: 1500 +cmpxchg-grb.h: 2053 +cmpxchg.h: 3173 +cmpxchg-irq.h: 796 +cmpxchg-llsc.h: 1420 +cmpxchg-local.h: 1369 +cm-regbits-24xx.h: 14321 +cm-regbits-34xx.h: 26454 +cm_sbs.c: 3007 +cmservice.c: 13501 +cmtdef.h: 23113 +cmt.h: 1786 +cmtp: 4096 +cmtp.h: 3099 +cmu.c: 5791 +cm-x255.c: 5295 +cm-x270.c: 7295 +cmx270_nand.c: 6063 +cm-x2xx.c: 11698 +cm_x2xx_defconfig: 48725 +cm-x2xx-pci.c: 5404 +cm-x2xx-pci.h: 460 +cm-x300.c: 11712 +cm_x300_defconfig: 39363 +cn_cifs.h: 1323 +cnic.c: 66079 +cnic_defs.h: 16086 +cnic.h: 7097 +cnic_if.h: 7270 +cnode.c: 4219 +cn_proc.c: 7019 +cn_proc.h: 3206 +cn_queue.c: 6122 +cnt32_to_63.h: 3193 +cn_test.c: 4483 +cnv_float.h: 13001 +coalesced_mmio.c: 3435 +coalesced_mmio.h: 652 +cobalt: 4096 +cobalt_btns.c: 4645 +cobalt_defconfig: 29161 +cobalt.h: 614 +cobalt_lcdfb.c: 7871 +cobra.c: 6747 +c-octeon.c: 7206 +coda: 4096 +coda_cache.h: 673 +coda_fs_i.h: 1700 +coda.h: 17708 +coda_int.h: 434 +coda_linux.c: 5125 +coda_linux.h: 2883 +coda_psdev.h: 3200 +coda.txt: 49725 +code16gcc.h: 388 +codecs: 12288 +codec.txt: 5826 +code-patching.c: 12715 +code-patching.h: 1744 +CodingStyle: 29820 +coff.h: 12413 +coh901327_wdt.c: 14160 +coid.c: 75657 +coldfire: 4096 +coldfire.h: 1492 +colibri.h: 1059 +colibri-pxa270.c: 3375 +colibri_pxa270_defconfig: 42182 +colibri-pxa300.c: 4795 +colibri_pxa300_defconfig: 27217 +colibri-pxa320.c: 4735 +colibri-pxa3xx.c: 3817 +collate.c: 3675 +collate.h: 1705 +collie.c: 7329 +collie_defconfig: 18902 +collie.h: 3779 +color.c: 4817 +color.h: 1187 +com20020.c: 10296 +com20020_cs.c: 10301 +com20020.h: 3624 +com20020-isa.c: 5185 +com20020-pci.c: 5701 +com90io.c: 11118 +com90xx.c: 18469 +comedi: 4096 +comedi_bond.c: 17048 +comedi_compat32.c: 17423 +comedi_compat32.h: 1861 +comedidev.h: 16882 +comedi_fc.c: 3317 +comedi_fc.h: 2462 +comedi_fops.c: 60764 +comedi_fops.h: 191 +comedi.h: 29999 +comedi_ksyms.c: 2407 +comedilib.h: 7998 +comedi_parport.c: 9181 +comedi_pci.h: 1605 +comedi_test.c: 14760 +command.c: 8449 +command.h: 8829 +command-list.txt: 288 +commands.c: 25775 +commands.h: 11936 +comm.c: 4950 +commctrl.c: 23882 +comminit.c: 13072 +commit.c: 32855 +commit-msg.sample: 894 +common: 4096 +common.c: 25712 +commoncap.c: 27617 +common_defconfig: 11971 +common.h: 12299 +CommonIO: 4651 +common.lds.S: 2212 +common-offsets.h: 1451 +common-pci.c: 12979 +common_perm_to_string.h: 1100 +common-smdk.c: 4474 +common-smdk.h: 451 +commproc.c: 8070 +commproc.h: 25607 +commsup.c: 51665 +CompactFlash: 1735 +compal-laptop.c: 8886 +comparator.h: 5271 +compartmentalisation.txt: 1944 +compat_audit.c: 664 +compat_binfmt_elf.c: 3496 +compat.c: 2196 +compat_exec_domain.c: 741 +compat.h: 369 +compatibility-list.txt: 1345 +compat_ioctl.c: 7581 +compat_ioctl.h: 4449 +compat_linux.c: 21127 +compat_linux.h: 7320 +compatmac.h: 332 +compat_mq.c: 4132 +compat_ptrace.h: 2572 +compat_rt_sigframe.h: 1846 +compat_signal.c: 17351 +compat_signal.h: 57 +compat-signal.h: 2664 +compat_ucontext.h: 552 +compat_wrapper.S: 48644 +compiler-gcc3.h: 823 +compiler-gcc4.h: 1407 +compiler-gcc.h: 3118 +compiler.h: 4524 +compiler-intel.h: 746 +completion.h: 3226 +composite.c: 30121 +composite.h: 14982 +compr.c: 10363 +compress.c: 1839 +compressed: 4096 +compress.h: 974 +compression.c: 18461 +compression.h: 1742 +compr.h: 3025 +compr_lzo.c: 2312 +compr_rtime.c: 2867 +compr_rubin.c: 8932 +compr_zlib.c: 5850 +computone.txt: 17570 +comstats.h: 3120 +con3215.c: 30319 +con3270.c: 15947 +concap.h: 3778 +concat.h: 454 +conditional.c: 11225 +conditional.h: 617 +conex.c: 32880 +conf.c: 11969 +confdata.c: 19322 +config: 2695 +config3270.sh: 2009 +config.c: 24033 +config.c.in: 496 +config_defs_asm.h: 5405 +config_defs.h: 4370 +configfs: 4096 +configfs_example_explicit.c: 12619 +configfs_example_macros.c: 11555 +configfs.h: 8837 +configfs_internal.h: 5080 +configfs.txt: 21464 +config.h: 1142 +config.mk: 7917 +config-osm.c: 2170 +config_roms.c: 4579 +config_roms.h: 588 +configs: 4096 +configs.c: 2818 +configuring.txt: 4139 +cong.c: 12223 +conmakehash.c: 6121 +connect.c: 38 +connection.c: 13263 +connector: 4096 +connector.c: 11327 +connector.h: 4405 +connector.txt: 6503 +conntrack.h: 810 +consistent.c: 3927 +console: 4096 +console_32.c: 2071 +console_64.c: 1575 +console.c: 7199 +console.h: 2080 +consolemap.c: 22885 +consolemap.h: 1029 +console_struct.h: 5109 +console.txt: 5814 +constants.c: 49479 +constants.h: 2939 +const.h: 596 +constraint.h: 2093 +consumer.h: 8894 +consumer.txt: 6869 +container.c: 7095 +container.h: 198 +contec_pci_dio.c: 5763 +context.c: 1678 +context.h: 3703 +context.S: 6412 +contig.c: 7791 +contregs.h: 3351 +CONTRIBUTORS: 495 +contributors.txt: 3035 +control.c: 43620 +control_compat.c: 11584 +controlfb.c: 27775 +controlfb.h: 4696 +control.h: 9928 +ControlNames.txt: 2085 +control_w.h: 1820 +cookie.c: 13149 +coprocessor.h: 5194 +coprocessor.S: 7277 +coproc.h: 362 +cops.c: 29453 +cops_ffdrv.h: 21384 +cops.h: 1400 +cops_ltdrv.h: 9491 +cops.txt: 2768 +copy_32.S: 9822 +copy.c: 2883 +copy_from_user.S: 1986 +COPYING: 18693 +COPYING.LIB: 25265 +copy_in_user.S: 1659 +copy_page_64.S: 2337 +copypage_64.S: 2011 +copypage-fa.c: 2349 +copypage-feroceon.c: 3145 +copy_page_mck.S: 5871 +copy_page.S: 532 +copypage-v3.c: 2110 +copypage-v4mc.c: 3649 +copypage-v4wb.c: 2820 +copypage-v4wt.c: 2403 +copypage-v6.c: 3822 +copypage-xsc3.c: 2840 +copypage-xscale.c: 3881 +copy.S: 1321 +copy_template.S: 5586 +copy_to_user.S: 2016 +copy_user_64.S: 5420 +copyuser_64.S: 9936 +copy_user_memcpy.S: 5245 +copy_user_nocache_64.S: 2468 +copy_user.S: 2573 +core: 4096 +core_apecs.c: 10176 +core_apecs.h: 17281 +coreb.c: 1844 +core.c: 24656 +core-card.c: 15330 +core-cdev.c: 37224 +core_cia.c: 33365 +core_cia.h: 15760 +core-device.c: 32375 +coredump.c: 5613 +core.h: 5921 +core_irongate.c: 10486 +core_irongate.h: 6754 +core-iso.c: 8971 +core_lca.c: 14096 +core_lca.h: 11596 +core_locking.txt: 4081 +core_marvel.c: 25082 +core_marvel.h: 9350 +core_mcpcia.c: 16238 +core_mcpcia.h: 11691 +core_polaris.c: 4523 +core_polaris.h: 2948 +core_priv.h: 1817 +core_t2.c: 16416 +core_t2.h: 20353 +coretemp: 1672 +coretemp.c: 11947 +core_titan.c: 20020 +core_titan.h: 11455 +core-topology.c: 15332 +core-transaction.c: 27218 +core_tsunami.c: 13148 +core_tsunami.h: 8469 +core.txt: 804 +core_wildfire.c: 17607 +core_wildfire.h: 8616 +corgi.c: 9471 +corgi_defconfig: 47365 +corgi.h: 4831 +corgikbd.c: 12406 +corgi_lcd.c: 16845 +corgi_lcd.h: 421 +corgi_pm.c: 7155 +corgi_ssp.c: 7384 +corgi_ts.c: 9648 +cosa.c: 59334 +cosa.h: 4349 +country.h: 4726 +cow.h: 1883 +cow_sys.h: 692 +cow_user.c: 12166 +coyote.h: 949 +coyote-pci.c: 1459 +coyote-setup.c: 3158 +cp1emu.c: 28793 +cp210x.c: 24866 +cp437.uni: 4426 +cp6.c: 1398 +cpc925_edac.c: 30540 +cpc.h: 16904 +cpci_hotplug_core.c: 17267 +cpci_hotplug.h: 3193 +cpci_hotplug_pci.c: 7823 +cpcihp_generic.c: 6519 +cpcihp_zt5550.c: 8619 +cpcihp_zt5550.h: 2730 +cpc_int.h: 2284 +cpcmd.c: 3087 +cpcmd.h: 1259 +cpc-usb: 4096 +cpc-usb_drv.c: 28935 +cpcusb.h: 2856 +cpfile.c: 24964 +cpfile.h: 1680 +cphy.h: 6427 +cpia2: 4096 +cpia2_core.c: 77737 +cpia2dev.h: 1919 +cpia2.h: 13192 +cpia2_overview.txt: 2357 +cpia2_registers.h: 17890 +cpia2_usb.c: 25426 +cpia2_v4l.c: 50779 +cpia.c: 114212 +cpia.h: 11791 +cpia_pp.c: 22139 +cpia_usb.c: 16084 +cp_intc.c: 3984 +cp_intc.h: 2302 +cpl5_cmd.h: 12577 +cplb.h: 4597 +cplbinfo.c: 3920 +cplbinit.c: 3353 +cplbinit.h: 2491 +cplbmgr.c: 9975 +cplb-mpu: 4096 +cplb-nompu: 4096 +cpm: 4096 +cpm1.c: 19027 +cpm1.h: 23000 +cpm2.c: 8657 +cpm2.h: 51335 +cpm2_pic.c: 7028 +cpm2_pic.h: 177 +cpmac.c: 35475 +cpm_common.c: 8715 +cpm.h: 3601 +cpm_qe: 4096 +cpm-serial.c: 5276 +cpm.txt: 2279 +cpm_uart: 4096 +cpm_uart_core.c: 34184 +cpm_uart_cpm1.c: 4062 +cpm_uart_cpm1.h: 630 +cpm_uart_cpm2.c: 4728 +cpm_uart_cpm2.h: 692 +cpm_uart.h: 3846 +cppi_dma.c: 44672 +cppi_dma.h: 3257 +cpqarray.c: 48267 +cpqarray.h: 3023 +cpqarray.txt: 2224 +cpqphp_core.c: 37277 +cpqphp_ctrl.c: 77860 +cpqphp.h: 22122 +cpqphp_nvram.c: 13820 +cpqphp_nvram.h: 1534 +cpqphp_pci.c: 39788 +cpqphp_sysfs.c: 5682 +cprecomp.h: 1072 +cpsmgr.c: 18525 +cpu: 4096 +cpu5wdt.c: 6940 +cpuacct.txt: 1941 +cpu_buffer.c: 11402 +cpu_buffer.h: 2876 +cpu-bugs64.c: 7627 +cpu.c: 5945 +cpucheck.c: 6054 +cpu-common: 4096 +cpudata_32.h: 574 +cpudata_64.h: 1041 +cpudata.h: 184 +cpu_debug.c: 17937 +cpu_debug.h: 3759 +cpu-drivers.txt: 7387 +cpufeature.h: 13827 +cpu-feature-overrides.h: 1176 +cpu-features.h: 7307 +cpu_features.txt: 2681 +cpufreq: 4096 +cpu-freq: 4096 +cpufreq_32.c: 18804 +cpufreq_64.c: 20116 +cpufreq.c: 49742 +cpufreq_conservative.c: 18026 +cpu-freq.h: 2392 +cpufreq.h: 12164 +cpufreq-nforce2.c: 9537 +cpufreq-nforce2.txt: 597 +cpufreq_ondemand.c: 19342 +cpufreq_performance.c: 1553 +cpufreq_powersave.c: 1625 +cpufreq-pxa2xx.c: 14833 +cpufreq-pxa3xx.c: 6493 +cpufreq_spudemand.c: 4449 +cpufreq_stats.c: 9729 +cpufreq-stats.txt: 5021 +cpufreq_userspace.c: 6109 +cpu.h: 1297 +cpu-h7201.c: 1510 +cpu-h7202.c: 5243 +cpu_hotplug.c: 2052 +cpu-hotplug-spec: 1155 +cpu-hotplug.txt: 14935 +cpuid.c: 5549 +cpuid.h: 617 +cpuidle: 4096 +cpuidle.c: 8664 +cpuidle.h: 1058 +cpu_imx27.c: 1739 +cpuinfo.c: 2141 +cpu-info.h: 2924 +cpuinfo.h: 2135 +cpuinfo-pvr-full.c: 2822 +cpuinfo-static.c: 4940 +cpu-irqs.h: 2654 +cpu-load.txt: 3110 +cpumap.c: 10894 +cpumap.h: 320 +cpumask.c: 4643 +cpumask.h: 381 +cpu-multi32.h: 1743 +cpu-omap.c: 4053 +cpu-probe.c: 23180 +cpu-regs.h: 14601 +cpu-sa1100.c: 7866 +cpu-sa1110.c: 9518 +cpuset.c: 72697 +cpuset.h: 4740 +cpusets.txt: 36191 +cpu_setup_44x.S: 1639 +cpu_setup_6xx.S: 11167 +cpu_setup_fsl_booke.S: 1766 +cpu_setup_pa6t.S: 1218 +cpu_setup_ppc970.S: 3704 +cpu-sh2: 4096 +cpu-sh2a: 4096 +cpu-sh3: 4096 +cpu-sh4: 4096 +cpu-sh5: 4096 +cpu-single.h: 1429 +cputable.c: 57765 +cputable.h: 19753 +cputhreads.h: 1572 +cputime.h: 118 +cputopology.txt: 3013 +cputype.h: 840 +cpu_vect.h: 1321 +cp_vers.h: 933 +cpwd.c: 16512 +cq.c: 20469 +c-qcam.c: 19812 +CQcam.txt: 7069 +cq_desc.h: 2507 +cq_enet_desc.h: 6342 +cq_exch_desc.h: 5837 +cq.h: 4130 +c-r3k.c: 8056 +c-r4k.c: 37720 +cramfs: 4096 +cramfs_fs.h: 2930 +cramfs_fs_sb.h: 343 +cramfs.txt: 2599 +crash.c: 9898 +crash_dump_32.c: 2149 +crash_dump_64.c: 1417 +crash_dump.c: 3851 +crash_dump.h: 2002 +cr_bllcd.c: 7402 +crc16.c: 2838 +crc16.h: 622 +crc32.c: 15299 +crc32c.c: 8200 +crc32c.h: 254 +crc32c-intel.c: 4975 +crc32defs.h: 1072 +crc32.h: 880 +crc32hash.c: 654 +crc7.c: 2329 +crc7.h: 272 +crc-ccitt.c: 3052 +crc-ccitt.h: 330 +crc.h: 880 +crc-itu-t.c: 2892 +crc-itu-t.h: 615 +crc-t10dif.c: 2965 +crc-t10dif.h: 140 +cred.c: 14888 +credentials.txt: 20932 +cred.h: 10905 +cred-internals.h: 559 +CREDITS: 603 +crime.c: 2833 +crime.h: 5271 +cris: 4096 +cris_defs_asm.h: 3805 +crisksyms.c: 472 +cris_supp_reg.h: 198 +crisv10.c: 129158 +crisv10.h: 4289 +crm_regs.h: 1700 +cr_pll.c: 4842 +crt0_ram.S: 2152 +crt0_rom.S: 3157 +crt0.S: 1979 +crtsavres.S: 6123 +crunch-bits.S: 8521 +crunch.c: 2001 +crw.c: 4007 +crw.h: 2025 +cryptd.c: 16974 +cryptd.h: 650 +crypto: 4096 +crypto4xx_alg.c: 8383 +crypto4xx_core.c: 34847 +crypto4xx_core.h: 5634 +crypto4xx_reg_def.h: 7646 +crypto4xx_sa.c: 2984 +crypto4xx_sa.h: 5742 +crypto.c: 16089 +crypto_compat.h: 2294 +cryptocop.c: 111134 +cryptocop.h: 7614 +crypto_des.h: 516 +crypto.h: 35141 +cryptohash.h: 264 +cryptoloop.c: 5005 +crypto_null.c: 5051 +crypto_wq.c: 896 +crypto_wq.h: 122 +crypt_s390.h: 10190 +cs4231.c: 6021 +cs4231-regs.h: 8547 +cs4236.c: 22848 +cs4236_lib.c: 35470 +cs423x: 4096 +cs4270.c: 26832 +cs4270.h: 804 +cs4281.c: 66411 +cs4362a.h: 2039 +cs4398.h: 1968 +cs461x.txt: 2184 +cs46xx: 4096 +cs46xx.c: 5301 +cs46xx_dsp_scb_types.h: 28137 +cs46xx_dsp_spos.h: 6198 +cs46xx_dsp_task_types.h: 7293 +cs46xx.h: 73681 +cs46xx_image.h: 155782 +cs46xx_lib.c: 107227 +cs46xx_lib.h: 8586 +cs5345.c: 5839 +cs5345.h: 1210 +cs53l32a.c: 5932 +cs53l32a.h: 1196 +cs5520.c: 4777 +cs5530.c: 8332 +cs5535audio: 4096 +cs5535audio.c: 10538 +cs5535audio.h: 4162 +cs5535audio_olpc.c: 4595 +cs5535audio_pcm.c: 13419 +cs5535audio_pm.c: 4043 +cs5535.c: 6298 +cs5535_gpio.c: 6000 +cs5536.c: 7861 +cs553x_nand.c: 10268 +cs8403.h: 8833 +cs8420.h: 1681 +cs8427.c: 18610 +cs8427.h: 10572 +cs89712.h: 1848 +cs89x0.c: 59868 +cs89x0.h: 16242 +cs89x0.txt: 25508 +csb337_defconfig: 28177 +csb637_defconfig: 29026 +csb701.c: 1321 +csb726.c: 7527 +csb726.h: 658 +cs.c: 21706 +cscanmgr.c: 14014 +cs.h: 6099 +cs_internal.h: 7245 +csr1212.c: 38810 +csr1212.h: 14571 +csr.c: 26430 +csrc-bcm1480.c: 1705 +csrc-ioasic.c: 1796 +csrc-octeon.c: 1473 +csrc-r4k.c: 885 +csrc-sb1250.c: 2176 +csr.h: 2690 +css.c: 26134 +css.h: 4460 +cstate.c: 4904 +cs_types.h: 934 +csum-copy_64.S: 4160 +csum_copy_from_user.S: 439 +csum_copy.S: 7018 +csum_copy_to_user.S: 431 +csumcpfruser.S: 1663 +csum_ipv6_magic.S: 2885 +csumipv6.S: 696 +csum-partial_64.c: 3530 +csum_partial_copy.c: 8909 +csum_partial_copy_generic.S: 1729 +csumpartialcopygeneric.S: 6850 +csumpartialcopy.S: 1151 +csumpartialcopyuser.S: 2378 +csum_partial.S: 16737 +csumpartial.S: 3126 +csum-wrappers_64.c: 3926 +ct20k1reg.h: 20603 +ct20k2reg.h: 3088 +ct82c710.c: 6778 +ctamixer.c: 10033 +ctamixer.h: 2795 +ctatc.c: 42227 +ctatc.h: 5058 +ctcm_dbug.c: 1932 +ctcm_dbug.h: 3316 +ctcm_fsms.c: 75291 +ctcm_fsms.h: 8271 +ctcm_main.c: 45768 +ctcm_main.h: 6938 +ctcm_mpc.c: 59919 +ctcm_mpc.h: 5324 +ctcm_sysfs.c: 5171 +ctdaio.c: 17904 +ctdaio.h: 3291 +cthardware.c: 1688 +cthardware.h: 7286 +cthw20k1.c: 49680 +cthw20k1.h: 598 +cthw20k2.c: 49114 +cthw20k2.h: 598 +ctimap.c: 2516 +ctimap.h: 1167 +ctkip.c: 17399 +ctl_unnumbered.txt: 962 +ctmixer.c: 28786 +ctmixer.h: 1691 +ctpcm.c: 11244 +ctpcm.h: 612 +ctr.c: 11026 +ctree.c: 111552 +ctree.h: 75158 +ctresource.c: 5825 +ctresource.h: 2267 +ctr.h: 524 +ctrlchar.c: 1752 +ctrlchar.h: 484 +cts.c: 10045 +ctsrc.c: 19870 +ctsrc.h: 4527 +cttimer.c: 11342 +cttimer.h: 686 +ctvmem.c: 5666 +ctvmem.h: 1787 +c-tx39.c: 10852 +ctxfi: 4096 +ctxrx.c: 147975 +ctype.c: 1041 +ctype.h: 1399 +cu3088.c: 3577 +cu3088.h: 848 +cuboot-52xx.c: 1660 +cuboot-824x.c: 1224 +cuboot-83xx.c: 1525 +cuboot-85xx.c: 1673 +cuboot-85xx-cpm2.c: 1764 +cuboot-8xx.c: 1149 +cuboot-acadia.c: 4964 +cuboot-amigaone.c: 868 +cuboot-bamboo.c: 689 +cuboot.c: 944 +cuboot-c2k.c: 4884 +cuboot-ebony.c: 782 +cuboot.h: 365 +cuboot-katmai.c: 1294 +cuboot-mpc7448hpc2.c: 1279 +cuboot-pq2.c: 7138 +cuboot-rainier.c: 1453 +cuboot-sam440ep.c: 1254 +cuboot-sequoia.c: 1453 +cuboot-taishan.c: 1361 +cuboot-warp.c: 916 +cuboot-yosemite.c: 1095 +cuda.h: 978 +cumana_1.c: 7960 +cumana_2.c: 14690 +current.h: 677 +cuse.c: 14893 +cvisionppc.h: 1577 +cvmx-address.h: 8499 +cvmx-asm.h: 4526 +cvmx-asxx-defs.h: 14223 +cvmx-bootinfo.h: 9081 +cvmx-bootmem.c: 20524 +cvmx-bootmem.h: 12982 +cvmx-ciu-defs.h: 39090 +cvmx-cmd-queue.c: 9400 +cvmx-cmd-queue.h: 18993 +cvmx-config.h: 6486 +cvmx-dbg-defs.h: 2123 +cvmx-fau.h: 19011 +cvmx-fpa.c: 4975 +cvmx-fpa-defs.h: 11938 +cvmx-fpa.h: 8284 +cvmx-gmxx-defs.h: 79305 +cvmx-gpio-defs.h: 6346 +cvmx.h: 14240 +cvmx-helper-board.c: 21950 +cvmx-helper-board.h: 6656 +cvmx-helper.c: 32770 +cvmx-helper-errata.c: 2592 +cvmx-helper-errata.h: 1277 +cvmx-helper-fpa.c: 7545 +cvmx-helper-fpa.h: 2360 +cvmx-helper.h: 7482 +cvmx-helper-jtag.c: 4203 +cvmx-helper-jtag.h: 1530 +cvmx-helper-loop.c: 2679 +cvmx-helper-loop.h: 1901 +cvmx-helper-npi.c: 3413 +cvmx-helper-npi.h: 1897 +cvmx-helper-rgmii.c: 17448 +cvmx-helper-rgmii.h: 3560 +cvmx-helper-sgmii.c: 17037 +cvmx-helper-sgmii.h: 3417 +cvmx-helper-spi.c: 6088 +cvmx-helper-spi.h: 2785 +cvmx-helper-util.c: 12555 +cvmx-helper-util.h: 6164 +cvmx-helper-xaui.c: 11997 +cvmx-helper-xaui.h: 3409 +cvmx-interrupt-decodes.c: 13959 +cvmx-interrupt-rsl.c: 3787 +cvmx-iob-defs.h: 16589 +cvmx-ipd-defs.h: 27302 +cvmx-ipd.h: 10763 +cvmx-l2c.c: 19669 +cvmx-l2c-defs.h: 23395 +cvmx-l2c.h: 10068 +cvmx-l2d-defs.h: 9721 +cvmx-l2t-defs.h: 3720 +cvmx-led-defs.h: 6731 +cvmx-mdio.h: 13085 +cvmx-mio-defs.h: 54538 +cvmx-npei-defs.h: 61528 +cvmx-npi-defs.h: 46348 +cvmx-packet.h: 1964 +cvmx-pci-defs.h: 40401 +cvmx-pcieep-defs.h: 32743 +cvmx-pciercx-defs.h: 36139 +cvmx-pcsx-defs.h: 11497 +cvmx-pcsxx-defs.h: 9562 +cvmx-pescx-defs.h: 11439 +cvmx-pexp-defs.h: 9365 +cvmx-pip-defs.h: 34993 +cvmx-pip.h: 16579 +cvmx-pko.c: 14987 +cvmx-pko-defs.h: 31966 +cvmx-pko.h: 18946 +cvmx-pow-defs.h: 19069 +cvmx-pow.h: 59817 +cvmx-scratch.h: 3875 +cvmx-smix-defs.h: 5173 +cvmx-spi.c: 22343 +cvmx-spi.h: 9516 +cvmx-spinlock.h: 6516 +cvmx-spxx-defs.h: 9687 +cvmx-srxx-defs.h: 3849 +cvmx-stxx-defs.h: 8491 +cvmx-sysinfo.c: 3570 +cvmx-sysinfo.h: 4893 +cvmx-wqe.h: 11943 +cwc4630.h: 15478 +cwcasync.h: 7969 +cwcbinhack.h: 1566 +cwcdma.asp: 4526 +cwcdma.h: 2174 +cwcsnoop.h: 1513 +cwep.c: 9662 +cwm.c: 3787 +cwm.h: 2421 +cx18: 4096 +cx18-audio.c: 2589 +cx18-audio.h: 905 +cx18-av-audio.c: 14932 +cx18-av-core.c: 41048 +cx18-av-core.h: 13381 +cx18-av-firmware.c: 7225 +cx18-av-vbi.c: 9043 +cx18-cards.c: 16165 +cx18-cards.h: 4838 +cx18-controls.c: 9435 +cx18-controls.h: 1257 +cx18-driver.c: 35409 +cx18-driver.h: 23311 +cx18-dvb.c: 9950 +cx18-dvb.h: 946 +cx18-fileops.c: 21082 +cx18-fileops.h: 1421 +cx18-firmware.c: 14987 +cx18-firmware.h: 1001 +cx18-gpio.c: 9268 +cx18-gpio.h: 1226 +cx18-i2c.c: 8776 +cx18-i2c.h: 1083 +cx18-io.c: 2807 +cx18-ioctl.c: 27533 +cx18-ioctl.h: 1423 +cx18-io.h: 4951 +cx18-irq.c: 2319 +cx18-irq.h: 1417 +cx18-mailbox.c: 21623 +cx18-mailbox.h: 3643 +cx18-queue.c: 6955 +cx18-queue.h: 2294 +cx18-scb.c: 5787 +cx18-scb.h: 7441 +cx18-streams.c: 21499 +cx18-streams.h: 1889 +cx18.txt: 811 +cx18-vbi.c: 7419 +cx18-vbi.h: 1031 +cx18-version.h: 1319 +cx18-video.c: 1080 +cx18-video.h: 875 +cx22700.c: 11029 +cx22700.h: 1488 +cx22702.c: 14516 +cx22702.h: 1673 +cx231xx: 4096 +cx231xx-audio.c: 14952 +cx231xx-avcore.c: 77231 +cx231xx-cards.c: 23257 +cx231xx-conf-reg.h: 25445 +cx231xx-core.c: 30779 +cx231xx-dvb.c: 13339 +cx231xx.h: 22018 +cx231xx-i2c.c: 12912 +cx231xx-input.c: 6423 +cx231xx-pcb-cfg.c: 20991 +cx231xx-pcb-cfg.h: 6456 +cx231xx-reg.h: 67462 +cx231xx-vbi.c: 17757 +cx231xx-vbi.h: 2261 +cx231xx-video.c: 58825 +cx23418.h: 17951 +cx2341x: 4096 +cx2341x.c: 38287 +cx2341x.h: 7383 +cx23885: 4096 +cx23885-417.c: 48981 +cx23885-cards.c: 25645 +cx23885-core.c: 54422 +cx23885-dvb.c: 26635 +cx23885.h: 16143 +cx23885-i2c.c: 9910 +cx23885-reg.h: 12999 +cx23885-vbi.c: 6762 +cx23885-video.c: 40258 +cx24110.c: 20853 +cx24110.h: 1810 +cx24113.c: 14661 +cx24113.h: 1673 +cx24116.c: 40768 +cx24116.h: 1706 +cx24123.c: 30243 +cx24123.h: 1979 +cx25840: 4096 +cx25840-audio.c: 11073 +cx25840-core.c: 45706 +cx25840-core.h: 3605 +cx25840-firmware.c: 3889 +cx25840.h: 3250 +cx25840-vbi.c: 7108 +cx88: 4096 +cx88-alsa.c: 23036 +cx88-blackbird.c: 39031 +cx88-cards.c: 89130 +cx88-core.c: 31343 +cx88-dsp.c: 8787 +cx88-dvb.c: 39095 +cx88.h: 22857 +cx88-i2c.c: 5568 +cx88-input.c: 14002 +cx88-mpeg.c: 24270 +cx88-reg.h: 34334 +cx88-tvaudio.c: 28674 +cx88-vbi.c: 6438 +cx88-video.c: 56637 +cx88-vp3054-i2c.c: 4322 +cx88-vp3054-i2c.h: 1559 +cxacru.c: 37008 +cxacru.txt: 2325 +cxgb2.c: 38481 +cxgb3: 4096 +cxgb3_ctl_defs.h: 5067 +cxgb3_defs.h: 3489 +cxgb3i: 4096 +cxgb3i_ddp.c: 20593 +cxgb3i_ddp.h: 8254 +cxgb3i.h: 4401 +cxgb3i_init.c: 3040 +cxgb3i_iscsi.c: 27545 +cxgb3_ioctl.h: 3847 +cxgb3i_offload.c: 50331 +cxgb3i_offload.h: 7277 +cxgb3i_pdu.c: 12368 +cxgb3i_pdu.h: 1710 +cxgb3i.txt: 3295 +cxgb3_main.c: 84313 +cxgb3_offload.c: 37599 +cxgb3_offload.h: 6272 +cxgb.txt: 13829 +cxio_dbg.c: 5114 +cxio_hal.c: 38094 +cxio_hal.h: 7482 +cxio_resource.c: 9188 +cxio_resource.h: 3116 +cxio_wr.h: 20826 +cxusb.c: 48202 +cxusb.h: 724 +cy82c693.c: 10524 +cyber2000fb.c: 43356 +cyber2000fb.h: 16008 +cyberjack.c: 14547 +cyclades.c: 158213 +cyclades.h: 24974 +cyclomx.h: 2544 +cyclone.c: 3125 +cyclone.h: 403 +cycx_cfm.h: 2926 +cycx_drv.c: 15649 +cycx_drv.h: 2183 +cycx_main.c: 9413 +cycx_x25.c: 45814 +cycx_x25.h: 3727 +cylinder.c: 5848 +cypress_atacb.c: 8391 +cypress_cy7c63.c: 7689 +cypress.h: 2856 +cypress_m8.c: 47071 +cypress_m8.h: 2367 +cyrix.c: 5962 +cytherm.c: 11260 +d101m_ucode.bin.ihex: 1675 +d101s_ucode.bin.ihex: 1675 +d102e_ucode.bin.ihex: 1675 +da9030_battery.c: 16256 +da9034-ts.c: 9057 +da903x_bl.c: 4988 +da903x.c: 13455 +da903x.h: 7048 +dabusb: 4096 +dabusb.c: 22084 +dabusb.h: 1873 +DAC960.c: 265715 +DAC960.h: 151800 +daca.c: 7036 +dac.h: 752 +dadapter.c: 14853 +dadapter.h: 1070 +daemon.c: 16879 +daemon.h: 8435 +daemon_kern.c: 2419 +daemon_user.c: 4368 +daisy.c: 12538 +DAI.txt: 2270 +dapm.txt: 10267 +daqboard2000.c: 25750 +darla20.c: 2889 +darla20_dsp.c: 3479 +darla24.c: 3153 +darla24_dsp.c: 3845 +dart.h: 2235 +dart_iommu.c: 10816 +das08.c: 26325 +das08_cs.c: 14893 +das08.h: 2561 +das16.c: 44853 +das16m1.c: 21006 +das1800.c: 48894 +das6402.c: 8510 +das800.c: 24454 +DASD: 3388 +dasd_3990_erp.c: 68376 +dasd_alias.c: 26580 +dasd.c: 72767 +dasd_devmap.c: 29631 +dasd_diag.c: 17829 +dasd_diag.h: 2628 +dasd_eckd.c: 95322 +dasd_eckd.h: 11295 +dasd_eer.c: 20468 +dasd_erp.c: 4866 +dasd_fba.c: 17801 +dasd_fba.h: 1816 +dasd_genhd.c: 4783 +dasd.h: 11124 +dasd_int.h: 21917 +dasd_ioctl.c: 11160 +dasd_proc.c: 9802 +data.c: 2497 +datafab.c: 20690 +datagram.c: 4449 +data-integrity.txt: 13815 +datalink.h: 482 +datapage.S: 2018 +datarate.c: 12551 +datarate.h: 2494 +datastream.c: 15931 +datastream.h: 514 +dat.c: 11476 +dat.h: 2048 +davicom.c: 4985 +davinci: 4096 +davinci_all_defconfig: 43899 +davinci.c: 13768 +davinci_emac.c: 84968 +davinci-evm.c: 6719 +davinci.h: 3430 +davinci-i2s.c: 17146 +davinci-i2s.h: 495 +davinci_nand.c: 23119 +davinci-pcm.c: 10560 +davinci-pcm.h: 783 +davinci-sffsdr.c: 4374 +davinci_wdt.c: 6690 +db1000_defconfig: 23355 +db1100_defconfig: 23611 +db1200_defconfig: 25180 +db1200.h: 6115 +db1500_defconfig: 30453 +db1550_defconfig: 26655 +db1x00: 4096 +db1x00.h: 5353 +db78x00-bp-setup.c: 2591 +db88f5281-setup.c: 9805 +db88f6281-bp-setup.c: 2227 +db9.c: 21255 +dbdma2.c: 10987 +dbdma.c: 29134 +dbdma.h: 3834 +dbell.c: 1075 +dbell.h: 1308 +dbg.c: 7231 +dbg_current.S: 402 +dbg.h: 144 +dbg_io.c: 5088 +dbg_stackcheck.S: 427 +dbg_stackkill.S: 575 +dbl_float.h: 36770 +dbox2-flash.c: 2719 +dbri.c: 80387 +dbus_contexts: 195 +dc21285.c: 5936 +dc21285-timer.c: 1332 +dc232b: 4096 +dc395x.c: 145696 +dc395x.h: 25842 +dc395x.txt: 3337 +dca: 4096 +dcache.c: 60424 +dcache.h: 2009 +dca-core.c: 6864 +dca.h: 2530 +dca-sysfs.c: 2700 +dcb: 4096 +dcbnl.c: 29597 +dcbnl.h: 11558 +dccp: 4096 +dccp.h: 15873 +dccp.txt: 7484 +dcdbas.c: 16163 +dcdbas.h: 2821 +dcdbas.txt: 3709 +dcookies.c: 6936 +dcookies.h: 1289 +dcore.c: 21748 +dcr.c: 6132 +dcr-generic.h: 1621 +dcr.h: 6308 +dcr-low.S: 983 +dcr-mmio.h: 1838 +dcr-native.h: 4500 +dcr-regs.h: 5140 +dcssblk.c: 27372 +dcu.h: 1481 +dd.c: 9413 +ddp.c: 49018 +ddr2_defs_asm.h: 11790 +ddr2_defs.h: 9835 +ddr.h: 4564 +de2104x.c: 54503 +de4x5.c: 169230 +de4x5.h: 49229 +de4x5.txt: 8677 +de600.c: 13275 +de600.h: 5588 +de620.c: 26654 +de620.h: 4970 +deadline-iosched.c: 11700 +deadline-iosched.txt: 2841 +debug-8250.S: 719 +debug.c: 7221 +debug-cmd.h: 1653 +debug-devices.c: 1975 +debugfs: 4096 +debug_fs.c: 16621 +debugfs.c: 6192 +debugfs.h: 2563 +debugfs_key.c: 9097 +debugfs_key.h: 1348 +debugfs-kmemtrace: 2769 +debugfs_netdev.c: 14895 +debugfs_netdev.h: 739 +debugfs-pktcdvd: 448 +debugfs_sta.c: 7063 +debugfs_sta.h: 427 +debugfs.txt: 7128 +debugging: 1594 +Debugging390.txt: 97243 +debugging-modules.txt: 954 +debugging-via-ohci1394.txt: 7635 +debug.h: 1195 +Debug.h: 1195 +debug_if.h: 3572 +debug-leds.c: 7120 +debug-levels.h: 1482 +debuglib.c: 4523 +debuglib.h: 11740 +debug_locks.c: 1127 +debug_locks.h: 1663 +debug-macro.S: 619 +debugobjects.c: 24352 +debugobjects.h: 2960 +debugobjects.tmpl: 14144 +debug-pagealloc.c: 2607 +debug-pl01x.S: 693 +debugport.c: 12453 +debugreg.h: 2904 +debug.S: 2650 +debug-stub.c: 6089 +debugtraps.S: 1210 +debug.txt: 5755 +dec: 4096 +dec21285.h: 5572 +dec_and_lock.c: 809 +decbin.S: 15728 +declance.c: 35842 +decl.h: 2409 +decnet: 4096 +decnet.txt: 10805 +decodecode: 1702 +decode_exc.c: 11585 +decode_rs.c: 6959 +decompress: 4096 +decompress_bunzip2.c: 23556 +decompress.c: 1126 +decompress_inflate.c: 3544 +decompress_unlzma.c: 15528 +decompress_v10.lds: 342 +decompress_v32.lds: 337 +decstation_defconfig: 17956 +dectypes.h: 427 +default_defconfig: 39014 +defBF512.h: 1271 +defBF514.h: 13406 +defBF516.h: 46402 +defBF518.h: 48358 +defBF51x_base.h: 113540 +defBF522.h: 1271 +defBF525.h: 44639 +defBF527.h: 77635 +defBF52x_base.h: 116393 +defBF532.h: 74150 +defBF534.h: 189790 +defBF537.h: 35002 +defBF539.h: 212777 +defBF542.h: 58060 +defBF544.h: 57371 +defBF547.h: 78333 +defBF548.h: 117603 +defBF549.h: 180941 +defBF54x_base.h: 251535 +defBF561.h: 109277 +defconfig: 20414 +deferred_io.txt: 3031 +defines.h: 5063 +define_trace.h: 1988 +defkeymap.c: 6243 +defkeymap.c_shipped: 11007 +defkeymap.map: 12183 +deflate.c: 5615 +deflate_syms.c: 377 +def_LPBlackfin.h: 29239 +defpalo.conf: 789 +defs.h: 12522 +deftree.c: 40510 +defutil.h: 11891 +defxx.c: 116343 +defxx.h: 54496 +delay_32.h: 882 +delay_64.h: 378 +delay-accounting.txt: 3837 +delayacct.c: 5038 +delayacct.h: 4108 +delay.c: 581 +delayed-ref.c: 24860 +delayed-ref.h: 6619 +delay.h: 1166 +delay_mm.h: 1362 +delay_no.h: 2314 +delay.S: 1279 +delay.txt: 694 +delegation.c: 14100 +delegation.h: 2261 +delkin_cb.c: 4687 +dell-laptop.c: 9519 +dell_rbu.c: 19420 +dell_rbu.txt: 4973 +dell-wmi.c: 6724 +delta.c: 23513 +delta.h: 5823 +demo_main.c: 29367 +demux.h: 8791 +denormal.c: 3335 +dentry.c: 2934 +dentry-locking.txt: 8359 +depca.c: 61475 +depca.h: 6823 +depca.txt: 1245 +desc.c: 19546 +desc_defs.h: 2385 +desc.h: 20526 +des_check_key.c: 4011 +descore-readme.txt: 17200 +description: 73 +des_generic.c: 36210 +des.h: 403 +design_notes.txt: 4626 +design.txt: 17558 +des_s390.c: 17966 +dev-audio.c: 1656 +devboards: 4096 +dev.c: 16990 +devconnect.c: 33409 +devdma.c: 2008 +devdma.h: 271 +development-process: 4096 +dev-fb.c: 1681 +devfs: 459 +dev.h: 9111 +dev-hsmmc1.c: 1647 +dev-hsmmc.c: 1640 +dev-i2c0.c: 1622 +dev-i2c1.c: 1587 +device.c: 3904 +device_cfg.h: 2924 +device_cgroup.c: 12005 +device_cgroup.h: 380 +device-drivers.tmpl: 13872 +device_fsm.c: 34071 +device.h: 31245 +device_handler: 4096 +device_id.c: 8750 +device_id.h: 9158 +device-init.c: 23541 +deviceiobook.tmpl: 11288 +device_main.c: 128828 +device-mapper: 4096 +device-mapper.h: 10956 +device_ops.c: 22502 +device_pgid.c: 16031 +devices: 4096 +devices.c: 19482 +devices.h: 918 +devices-rsk7203.c: 2587 +device_status.c: 12596 +devices.txt: 118144 +devicetable.txt: 1298 +device.txt: 6393 +devinet.c: 40642 +dev-interface: 8905 +devio.c: 45517 +dev-ioctl.c: 18582 +devmap.c: 1464 +dev_mcast.c: 5650 +devops_32.c: 1879 +devops_64.c: 1006 +devpts: 4096 +devpts_fs.h: 1454 +devpts.txt: 5085 +devres.c: 16191 +devres.txt: 7761 +devs.c: 9766 +devs.h: 1960 +dev-sysfs.c: 3852 +dev_table.c: 5563 +dev_table.h: 10908 +devtree.c: 8324 +dev-uart.c: 3521 +dev-usb.c: 1134 +dev-usb-hsotg.c: 992 +dfadd.c: 15801 +dfcmp.c: 5306 +dfdiv.c: 12636 +dfifo.h: 2160 +dfmpy.c: 11736 +dfrem.c: 8997 +dfs.c: 37 +dfs.h: 27 +dfsqrt.c: 5530 +dfsub.c: 15897 +dfu: 4096 +dfu.c: 6025 +dgram.c: 8393 +diag.c: 1739 +diag.h: 1050 +dialog.h: 6696 +dib0070.c: 13441 +dib0070.h: 1691 +dib0700_core.c: 11979 +dib0700_devices.c: 54526 +dib0700.h: 2680 +dib07x0.h: 266 +dib3000.h: 1813 +dib3000mb.c: 23970 +dib3000mb_priv.h: 16232 +dib3000mc.c: 26706 +dib3000mc.h: 2337 +dib7000m.c: 40754 +dib7000m.h: 2102 +dib7000p.c: 40757 +dib7000p.h: 2849 +dibusb-common.c: 12123 +dibusb.h: 3337 +dibusb-mb.c: 14485 +dibusb-mc.c: 5124 +dibx000_common.c: 4156 +dibx000_common.h: 2896 +di.c: 31214 +di_dbg.h: 1102 +diddfunc.c: 2703 +di_defs.h: 8217 +did_vers.h: 933 +diffconfig: 3642 +dig: 4096 +digest.c: 2574 +digi1.h: 3665 +digi_acceleport.c: 58641 +digiepca.txt: 3789 +digiFep1.h: 1928 +digiPCI.h: 1382 +digitv.c: 9329 +digitv.h: 1457 +digsy_mtc.dts: 5933 +di.h: 4386 +dilnetpc.c: 13589 +dino.c: 31503 +dio: 4096 +dio.c: 8573 +dio-driver.c: 3552 +dio.h: 11200 +dio-sysfs.c: 2250 +dir.c: 25683 +direct.c: 6527 +direct.h: 1640 +direct-io.c: 35225 +directory.c: 7736 +directory-locking: 5153 +dirent.h: 177 +dir_f.c: 10085 +dir_f.h: 1267 +dir_fplus.c: 4598 +dir_fplus.h: 1014 +dir.h: 1246 +dirhash.c: 6496 +dir-item.c: 11583 +disable-tsc-ctxt-sw-stress-test.c: 1724 +disable-tsc-on-off-stress-test.c: 1717 +disable-tsc-test.c: 2121 +dis-asm.h: 895 +disassemble.c: 19044 +disassemble.h: 1766 +dis.c: 41703 +discontig.c: 1271 +discover.c: 9895 +discover.h: 2378 +discovery.c: 12785 +discovery.h: 3572 +disk-io.c: 67604 +disk-io.h: 4751 +diskonchip.c: 50636 +disk-shock-protection.txt: 6881 +dispc.c: 37465 +dispc.h: 1183 +display: 4096 +display7seg.c: 6503 +display7seg.h: 1882 +display.c: 1573 +display_gx1.c: 6318 +display_gx1.h: 4598 +display_gx.c: 4945 +display.h: 2117 +display-sysfs.c: 6099 +diu.txt: 470 +div64.c: 3889 +div64-generic.c: 283 +div64.h: 371 +div64.S: 3866 +diva.c: 34488 +divacapi.h: 50994 +diva_didd.c: 3571 +diva_dma.c: 2843 +diva_dma.h: 1993 +diva.h: 1010 +divamnt.c: 5616 +diva_pci.h: 631 +divasfunc.c: 5512 +divasi.c: 12379 +divasmain.c: 21787 +divasproc.c: 10764 +divasync.h: 20126 +divdi3.S: 6280 +divert: 4096 +divert_init.c: 2399 +divert_procfs.c: 8581 +divide.S: 4293 +divsi3.S: 6392 +div_small.S: 1546 +div_Xsig.S: 10096 +dl2k.c: 48901 +dl2k.h: 14949 +dl2k.txt: 9387 +dlci.c: 11723 +DLINK.txt: 7386 +dlm: 4096 +dlmapi.h: 9492 +dlmast.c: 13019 +dlmcommon.h: 29686 +dlmconstants.h: 5013 +dlmconvert.c: 15590 +dlmconvert.h: 1218 +dlmdebug.c: 28761 +dlmdebug.h: 2109 +dlm_device.h: 2536 +dlmdomain.c: 49292 +dlmdomain.h: 1165 +dlmfs.c: 15242 +dlmfs.txt: 4319 +dlmfsver.c: 1211 +dlmfsver.h: 997 +dlmglue.c: 110475 +dlmglue.h: 5587 +dlm.h: 5602 +dlm_internal.h: 16633 +dlmlock.c: 19997 +dlmmaster.c: 96511 +dlm_netlink.h: 1064 +dlm_plock.h: 1135 +dlmrecovery.c: 85132 +dlmthread.c: 21013 +dlmunlock.c: 19250 +dlmver.c: 1203 +dlmver.h: 991 +dm1105: 4096 +dm1105.c: 22399 +dm355.c: 17263 +dm355evm_keys.c: 8928 +dm355evm_msp.c: 10717 +dm355evm_msp.h: 2879 +dm355.h: 586 +dm644x.c: 14946 +dm644x.h: 1316 +dm646x.c: 15438 +dm646x.h: 757 +dm9000.c: 34291 +dm9000.h: 4167 +dm9000.txt: 5137 +dm9601.c: 15941 +dma: 4096 +dma-alloc.c: 4571 +dma-api.c: 9315 +DMA-API.txt: 28886 +DMA-attributes.txt: 1376 +dma-attrs.h: 1758 +dmabounce.c: 14340 +dmabrg.c: 5279 +dmabrg.h: 497 +dmabuf.c: 35686 +dma.c: 6328 +dmac.c: 4805 +dmac.h: 11517 +dma-coherence.h: 1492 +dma-coherent.c: 3667 +dma-coherent.h: 891 +dmacopy.c: 909 +dma-core.h: 639 +dmactl-regs.h: 4663 +dma-debug.c: 31988 +dma-debug.h: 4915 +dma-default.c: 8575 +dma_defs_asm.h: 14594 +dma_defs.h: 14110 +dmaengine.c: 28040 +dmaengine.h: 15831 +dmaengine.txt: 42 +dma-g2.c: 4776 +dma.h: 2547 +dma-iommu.c: 3128 +dma-isa.c: 5163 +DMA-ISA-LPC.txt: 5333 +dma_lib.c: 16254 +dma-m2p.c: 9922 +dma-mapping-broken.h: 2488 +dma-mapping.c: 5434 +dma-mapping-common.h: 5646 +dma-mapping.h: 4368 +DMA-mapping.txt: 27929 +dma_mm.h: 455 +dma-mx1-mx2.c: 23615 +dma-mx1-mx2.h: 2711 +dma_no.h: 16955 +dma-noncoherent.c: 10156 +dma-octeon.c: 10532 +dma-plat.h: 2025 +dmapool.c: 13226 +dmapool.h: 923 +dma-pvr2.c: 2423 +dmar.c: 31385 +dma_remapping.h: 988 +dmar.h: 6143 +dmascc.c: 37724 +dma-sh4a.h: 2469 +dma-sh7760.c: 10216 +dma-sh.c: 7913 +dma-sh.h: 2862 +dmasound: 4096 +dmasound_atari.c: 42606 +dmasound_core.c: 44456 +dmasound.h: 8131 +dmasound_paula.c: 19160 +dmasound_q40.c: 14354 +dma-swiotlb.c: 4748 +dma-sysfs.c: 4348 +dmatest.c: 15129 +dma_timer.c: 2282 +dma.txt: 6352 +DMA.txt: 6352 +dma_v.h: 1177 +dm-bio-record.h: 1629 +dm.c: 60780 +dm-crypt.c: 32243 +dm-crypt.txt: 1485 +dm-delay.c: 8567 +dm-dirty-log.h: 3944 +dme1737: 11748 +dme1737.c: 74868 +dmesg.c: 1657 +dm-exception-store.c: 6745 +dm-exception-store.h: 4659 +dmfe.c: 60351 +dmfe.txt: 2168 +dm.h: 3933 +dmi.h: 411 +dmi-id.c: 6586 +dm-io.c: 11366 +dm-ioctl.c: 33212 +dm-ioctl.h: 9109 +dm-io.h: 2051 +dm-io.txt: 3298 +dmi_scan.c: 15130 +dm-kcopyd.c: 14244 +dm-kcopyd.h: 1335 +dm-linear.c: 3614 +dm-log.c: 19367 +dm-log.txt: 2397 +dm-log-userspace-base.c: 16497 +dm-log-userspace.h: 12944 +dm-log-userspace-transfer.c: 6936 +dm-log-userspace-transfer.h: 452 +dmm32at.c: 30666 +dm-mpath.c: 37626 +dm-mpath.h: 415 +dm-path-selector.c: 2473 +dm-path-selector.h: 2533 +dm-queue-length.c: 5495 +dm-queue-length.txt: 1218 +dm-raid1.c: 32159 +dm-region-hash.c: 18043 +dm-region-hash.h: 3217 +dm-round-robin.c: 4673 +dm-service-time.c: 8360 +dm-service-time.txt: 3243 +dm-snap.c: 33940 +dm-snap-persistent.c: 17550 +dm-snap-transient.c: 3687 +dm-stripe.c: 8013 +dm-sysfs.c: 2204 +dm-table.c: 27836 +dm-target.c: 2600 +dmtimer.c: 22824 +dmtimer.h: 3450 +dm-uevent.c: 5482 +dm-uevent.h: 1678 +dm-uevent.txt: 2650 +dmv182.c: 3833 +dmx3191d.c: 4547 +dmxdev.c: 28366 +dmxdev.h: 2409 +dmx.h: 3848 +dm-zero.c: 1495 +dn_dev.c: 33824 +dn_dev.h: 5493 +dnet.c: 25715 +dnet.h: 7221 +dnfb.c: 8139 +dn_fib.c: 18396 +dn_fib.h: 4894 +dn.h: 4527 +dn_ints.c: 1049 +dn_neigh.c: 15875 +dn_neigh.h: 824 +dn_nsp.h: 6229 +dn_nsp_in.c: 21566 +dn_nsp_out.c: 17942 +dnode.c: 30235 +dnotify: 4096 +dnotify.c: 12385 +dnotify.h: 978 +dnotify.txt: 3565 +dn_route.c: 44768 +dn_route.h: 4165 +dn_rtmsg.c: 3778 +dn_rules.c: 5755 +dns323-setup.c: 10831 +dns_resolve.c: 3678 +dns_resolve.h: 1294 +dn_table.c: 20482 +dn_timer.c: 3167 +do_balan.c: 58466 +doc2000.c: 32664 +doc2000.h: 5486 +doc2001.c: 25107 +doc2001plus.c: 31825 +DocBook: 4096 +docecc.c: 15968 +dock.c: 31358 +docprobe.c: 10340 +docproc.c: 11716 +do_csum.S: 2991 +Documentation: 4096 +do_func.S: 13813 +domain.c: 29471 +domain.h: 2107 +do_mounts.c: 9465 +do_mounts.h: 1396 +do_mounts_initrd.c: 3256 +do_mounts_md.c: 8071 +do_mounts_rd.c: 8166 +donauboe.c: 48207 +donauboe.h: 14213 +dontdiff: 1964 +doorbell.c: 2900 +doorbell.h: 2894 +dot11d.c: 5434 +dot11d.h: 2916 +dot_command.c: 4062 +dot_command.h: 2259 +dot.gdbinit: 5372 +dot.gdbinit_200MHz_16MB: 5763 +dot.gdbinit_300MHz_32MB: 5763 +dot.gdbinit_400MHz_32MB: 5764 +dot.gdbinit.nommu: 3891 +dot.gdbinit.smp: 8938 +dot.gdbinit.vdec2: 5442 +do_timer.h: 349 +double_cpdo.c: 4122 +doublefault_32.c: 1732 +double.h: 6303 +down2.H16: 33610 +down3.bin.ihex: 35892 +down.H16: 36678 +dp_add.c: 4700 +dpc.c: 58689 +dpc.h: 1771 +dp_cmp.c: 1842 +dpcsup.c: 9553 +dp_div.c: 4369 +dp_fint.c: 1932 +dp_flong.c: 1912 +dp_frexp.c: 1450 +dp_fsp.c: 1879 +dp_logb.c: 1446 +dpmc.c: 3024 +dpmc.h: 1247 +dpmc_modes.S: 14539 +dp_modf.c: 2064 +dp_mul.c: 4812 +dp_scalb.c: 1508 +dp_simple.c: 2057 +dp_sqrt.c: 4372 +dp_sub.c: 4977 +dpt: 4096 +dpt_i2o.c: 96500 +dpti.h: 11787 +dpti_i2o.h: 13449 +dpti_ioctl.h: 5365 +dp_tint.c: 3021 +dpti.txt: 3614 +dp_tlong.c: 3061 +dptsig.h: 14986 +dqblk_qtree.h: 2108 +dqblk_v1.h: 342 +dqblk_v2.h: 367 +dqblk_xfs.h: 6607 +dqueue.c: 2180 +dqueue.h: 1007 +dquot.c: 72530 +draft-ietf-cipso-ipsecurity-01.txt: 28638 +dram_init.S: 3913 +draw_functrace.py: 3560 +dreamcast_defconfig: 25856 +driver: 11995 +driver.c: 54722 +driver-changes.txt: 4022 +driver_chipcommon.c: 13262 +driver_chipcommon_pmu.c: 17510 +driver_extif.c: 3829 +driver_gige.c: 7415 +driver.h: 4405 +driver_mipscore.c: 6999 +driver-model: 4096 +driver-model.txt: 10127 +driver-ops.h: 5035 +driver_pcicore.c: 16619 +drivers: 4096 +drivers.c: 22567 +drivers-testing.txt: 2173 +driver.txt: 8049 +drm: 4096 +drm_agpsupport.c: 13149 +drm_auth.c: 5698 +drm_bufs.c: 44350 +drm_cache.c: 2119 +drm_context.c: 11821 +drm_core.h: 1468 +drm_crtc.c: 63999 +drm_crtc.h: 25347 +drm_crtc_helper.c: 29207 +drm_crtc_helper.h: 4951 +drm_debugfs.c: 6275 +drm_dma.c: 4147 +drm_drawable.c: 5166 +drm_drv.c: 16709 +drm_edid.c: 24730 +drm_edid.h: 5722 +drm_fops.c: 14460 +drm_gem.c: 14905 +drm.h: 23018 +drm_hashtab.c: 5440 +drm_hashtab.h: 2589 +drm_info.c: 9606 +drm_ioc32.c: 33632 +drm_ioctl.c: 9402 +drm_irq.c: 17068 +drm_lock.c: 11107 +drm_memory.c: 5012 +drm_memory.h: 1936 +drm_mm.c: 9213 +drm_mm.h: 3301 +drm_mode.h: 6855 +drm_modes.c: 14802 +drm_os_linux.h: 4047 +drm_pci.c: 3839 +drm_pciids.h: 40171 +drmP.h: 49714 +drm_proc.c: 6339 +drm_sarea.h: 2655 +drm_scatter.c: 5431 +drm_sman.c: 8782 +drm_sman.h: 5975 +drm_stub.c: 13017 +drm_sysfs.c: 13561 +drm_vm.c: 18670 +drop_caches.c: 1684 +drop_monitor.c: 8677 +drp-avail.c: 8822 +drp.c: 24684 +drp-ie.c: 9743 +drv.c: 22503 +drvfbi.c: 12647 +drx397xD.c: 30335 +drx397xD_fw.h: 1525 +drx397xD.h: 3015 +ds1286.h: 1223 +ds1287.h: 1019 +ds1302.c: 7604 +ds1305.h: 1068 +ds1603.c: 3162 +ds1603.h: 566 +ds1620.c: 8486 +ds1621: 2670 +ds1621.c: 9932 +ds1682.c: 7160 +ds17287rtc.h: 2676 +ds1_ctrl.fw.ihex: 33804 +ds1_dsp.fw.ihex: 364 +ds1e_ctrl.fw.ihex: 33804 +ds1wm.c: 11691 +ds1wm.h: 114 +ds2482: 743 +ds2482.c: 14041 +ds2490: 3576 +ds2490.c: 24260 +ds2760_battery.c: 13485 +dsa: 4096 +dsa.c: 9418 +dsa.h: 1617 +dsa_priv.h: 4060 +dsbr100.c: 17605 +ds.c: 38706 +dsc.c: 1195 +dscc4.c: 55052 +dsdt-override.txt: 247 +dsemul.c: 4501 +dsfield.c: 19154 +dsfield.h: 1127 +ds.h: 8003 +dsinit.c: 6745 +dsmethod.c: 19169 +dsmg600.h: 1216 +dsmg600-pci.c: 1898 +dsmg600-setup.c: 7030 +dsmthdat.c: 21585 +dsobject.c: 23900 +dsopcode.c: 39305 +dsp56k: 4096 +dsp56k.c: 12404 +dsp56k.h: 1269 +dsp_audio.c: 11056 +dsp_biquad.h: 1622 +dsp_blowfish.c: 23738 +dspbootcode.bin.ihex: 36048 +dsp_cmx.c: 52826 +dsp_common.h: 1309 +dsp_core.c: 33551 +dsp_defs.h: 12149 +dspdids.h: 2695 +dsp_dtmf.c: 7570 +dsp_ecdis.h: 3527 +dsp.h: 7893 +dsp_hwec.c: 3049 +dsp_hwec.h: 242 +dsp_pipeline.c: 8348 +dsp_spos.c: 55617 +dsp_spos.h: 7631 +dsp_spos_scb_lib.c: 49424 +dsp_tones.c: 17264 +dsp_tst.h: 1486 +dsrv4bri.h: 1644 +dsrv_bri.h: 1178 +dsrv_pri.h: 1247 +ds_selftest.c: 9393 +ds_selftest.h: 363 +dst: 4096 +dst.c: 49967 +dst_ca.c: 21634 +dst_ca.h: 1591 +dst_common.h: 4277 +dst.h: 14556 +dst_priv.h: 598 +dstr.c: 5143 +dsutils.c: 25450 +dswexec.c: 19731 +dswload.c: 31066 +dswscope.c: 6750 +dswstate.c: 21428 +dt019x.c: 9062 +dt2801.c: 15251 +dt2811.c: 14680 +dt2814.c: 8589 +dt2815.c: 7337 +dt2817.c: 4517 +dt282x.c: 35248 +dt3000.c: 23494 +dt9812.c: 28480 +dtc: 4096 +dt.c: 16907 +dtc2278.c: 3867 +dtc3x80.txt: 1952 +dtc.c: 13348 +dtc.h: 2644 +dtc-lexer.l: 6979 +dtc-lexer.lex.c_shipped: 57920 +dtc-parser.tab.c_shipped: 55472 +dtc-parser.tab.h_shipped: 3233 +dtc-parser.y: 6540 +dtc-src: 4096 +dtl1_cs.c: 14325 +dtlb_miss.S: 747 +dtlb_prot.S: 1267 +dtl.c: 6493 +dtlk.c: 16644 +dtlk.h: 3768 +dts: 4096 +dts-bindings: 4096 +dtt200u.c: 9848 +dtt200u-fe.c: 5300 +dtt200u.h: 1606 +dtv5100.c: 5845 +dtv5100.h: 1534 +dum.h: 7581 +dummy.c: 3850 +dummycon.c: 1805 +dummy_hcd.c: 50629 +dump_pagetables.c: 8879 +dumprequest.c: 3343 +dumprequest.h: 2117 +dumpstack_32.c: 3323 +dumpstack_64.c: 7276 +dump_stack.c: 290 +dumpstack.c: 8067 +dumpstack.h: 1003 +dump_tlb.c: 2643 +dv1394: 390 +dv1394.c: 74226 +dv1394.h: 10409 +dv1394-private.h: 17471 +dvb: 4096 +dvb-bt8xx.c: 28096 +dvb-bt8xx.h: 1816 +dvb_ca_en50221.c: 45737 +dvb_ca_en50221.h: 4082 +dvb-core: 4096 +dvb_demux.c: 30507 +dvb_demux.h: 3579 +dvbdev.c: 11761 +dvbdev.h: 4065 +dvb_dummy_fe.c: 7049 +dvb_dummy_fe.h: 1698 +dvb_filter.c: 12922 +dvb_filter.h: 6064 +dvb_frontend.c: 54720 +dvb_frontend.h: 11618 +dvb_math.c: 5423 +dvb_math.h: 1974 +dvb_net.c: 42892 +dvb_net.h: 1379 +dvb-pll.c: 17175 +dvb-pll.h: 1617 +dvb_ringbuffer.c: 7188 +dvb_ringbuffer.h: 6340 +dvb-ttusb-budget.c: 44105 +dvb-usb: 12288 +dvb-usb-common.h: 2150 +dvb-usb-dvb.c: 5850 +dvb-usb-firmware.c: 3956 +dvb-usb.h: 12194 +dvb-usb-i2c.c: 1061 +dvb-usb-ids.h: 11042 +dvb-usb-init.c: 8477 +dvb-usb-remote.c: 5519 +dvb-usb-urb.c: 2585 +dvi.c: 18260 +dvi.h: 2461 +dvma.c: 1265 +dvma.h: 9864 +dvo_ch7017.c: 14698 +dvo_ch7xxx.c: 9179 +dvo.h: 4860 +dvo_ivch.c: 10628 +dvo_sil164.c: 7534 +dvo_tfp410.c: 8848 +dw2102.c: 27129 +dw2102.h: 240 +dwarf2.h: 2393 +dw_dmac.c: 37849 +dw_dmac.h: 3078 +dw_dmac_regs.h: 6137 +dynamic_debug.c: 18386 +dynamic_debug.h: 2666 +dynamic-debug-howto.txt: 8633 +dyn.lds.S: 5092 +dz.c: 23133 +dz.h: 5439 +e00154b8e949bf4b89ac198aef9a247532ac2d: 297 +e100: 4096 +e1000: 4096 +e1000_82575.c: 42179 +e1000_82575.h: 8176 +e1000_defines.h: 28796 +e1000e: 4096 +e1000_ethtool.c: 56605 diff --git a/tests/drive_del-test.c b/tests/drive_del-test.c index 4a1a0889c8..2f9474e03c 100644 --- a/tests/drive_del-test.c +++ b/tests/drive_del-test.c @@ -63,6 +63,24 @@ static void test_drive_without_dev(void) qtest_end(); } +/* + * qvirtio_get_dev_type: + * Returns: the preferred virtio bus/device type for the current architecture. + * TODO: delete this + */ +static const char *qvirtio_get_dev_type(void) +{ + const char *arch = qtest_get_arch(); + + if (g_str_equal(arch, "arm") || g_str_equal(arch, "aarch64")) { + return "device"; /* for virtio-mmio */ + } else if (g_str_equal(arch, "s390x")) { + return "ccw"; + } else { + return "pci"; + } +} + static void test_after_failed_device_add(void) { char driver[32]; @@ -119,16 +137,11 @@ static void test_drive_del_device_del(void) int main(int argc, char **argv) { - const char *arch = qtest_get_arch(); - g_test_init(&argc, &argv, NULL); qtest_add_func("/drive_del/without-dev", test_drive_without_dev); - /* TODO I guess any arch with a hot-pluggable virtio bus would do */ - if (!strcmp(arch, "i386") || !strcmp(arch, "x86_64") || - !strcmp(arch, "ppc") || !strcmp(arch, "ppc64") || - !strcmp(arch, "s390x")) { + if (qvirtio_get_dev_type() != NULL) { qtest_add_func("/drive_del/after_failed_device_add", test_after_failed_device_add); qtest_add_func("/blockdev/drive_del_device_del", diff --git a/tests/e1000-test.c b/tests/e1000-test.c index 0c5fcdcc44..9e67916169 100644 --- a/tests/e1000-test.c +++ b/tests/e1000-test.c @@ -9,22 +9,15 @@ #include "qemu/osdep.h" #include "libqtest.h" +#include "libqos/qgraph.h" +#include "libqos/pci.h" -/* Tests only initialization so far. TODO: Replace with functional tests */ -static void test_device(gconstpointer data) -{ - const char *model = data; - QTestState *s; - char *args; - - args = g_strdup_printf("-device %s", model); - s = qtest_start(args); +typedef struct QE1000 QE1000; - if (s) { - qtest_quit(s); - } - g_free(args); -} +struct QE1000 { + QOSGraphObject obj; + QPCIDevice dev; +}; static const char *models[] = { "e1000", @@ -33,19 +26,42 @@ static const char *models[] = { "e1000-82545em", }; -int main(int argc, char **argv) +static void *e1000_get_driver(void *obj, const char *interface) { - int i; + QE1000 *e1000 = obj; - g_test_init(&argc, &argv, NULL); + if (!g_strcmp0(interface, "pci-device")) { + return &e1000->dev; + } - for (i = 0; i < ARRAY_SIZE(models); i++) { - char *path; + fprintf(stderr, "%s not present in e1000e\n", interface); + g_assert_not_reached(); +} - path = g_strdup_printf("e1000/%s", models[i]); - qtest_add_data_func(path, models[i], test_device); - g_free(path); - } +static void *e1000_create(void *pci_bus, QGuestAllocator *alloc, void *addr) +{ + QE1000 *e1000 = g_new0(QE1000, 1); + QPCIBus *bus = pci_bus; + + qpci_device_init(&e1000->dev, bus, addr); + e1000->obj.get_driver = e1000_get_driver; + + return &e1000->obj; +} + +static void e1000_register_nodes(void) +{ + int i; + QOSGraphEdgeOptions opts = { + .extra_device_opts = "addr=04.0", + }; + add_qpci_address(&opts, &(QPCIAddress) { .devfn = QPCI_DEVFN(4, 0) }); - return g_test_run(); + for (i = 0; i < ARRAY_SIZE(models); i++) { + qos_node_create_driver(models[i], e1000_create); + qos_node_consumes(models[i], "pci-bus", &opts); + qos_node_produces(models[i], "pci-device"); + } } + +libqos_init(e1000_register_nodes); diff --git a/tests/e1000e-test.c b/tests/e1000e-test.c index c9408a5d1f..77ba8095bb 100644 --- a/tests/e1000e-test.c +++ b/tests/e1000e-test.c @@ -32,210 +32,9 @@ #include "qemu/iov.h" #include "qemu/bitops.h" #include "libqos/malloc.h" -#include "libqos/malloc-pc.h" -#include "libqos/malloc-generic.h" +#include "libqos/e1000e.h" -#define E1000E_IMS (0x00d0) - -#define E1000E_STATUS (0x0008) -#define E1000E_STATUS_LU BIT(1) -#define E1000E_STATUS_ASDV1000 BIT(9) - -#define E1000E_CTRL (0x0000) -#define E1000E_CTRL_RESET BIT(26) - -#define E1000E_RCTL (0x0100) -#define E1000E_RCTL_EN BIT(1) -#define E1000E_RCTL_UPE BIT(3) -#define E1000E_RCTL_MPE BIT(4) - -#define E1000E_RFCTL (0x5008) -#define E1000E_RFCTL_EXTEN BIT(15) - -#define E1000E_TCTL (0x0400) -#define E1000E_TCTL_EN BIT(1) - -#define E1000E_CTRL_EXT (0x0018) -#define E1000E_CTRL_EXT_DRV_LOAD BIT(28) -#define E1000E_CTRL_EXT_TXLSFLOW BIT(22) - -#define E1000E_RX0_MSG_ID (0) -#define E1000E_TX0_MSG_ID (1) -#define E1000E_OTHER_MSG_ID (2) - -#define E1000E_IVAR (0x00E4) -#define E1000E_IVAR_TEST_CFG ((E1000E_RX0_MSG_ID << 0) | BIT(3) | \ - (E1000E_TX0_MSG_ID << 8) | BIT(11) | \ - (E1000E_OTHER_MSG_ID << 16) | BIT(19) | \ - BIT(31)) - -#define E1000E_RING_LEN (0x1000) -#define E1000E_TXD_LEN (16) -#define E1000E_RXD_LEN (16) - -#define E1000E_TDBAL (0x3800) -#define E1000E_TDBAH (0x3804) -#define E1000E_TDLEN (0x3808) -#define E1000E_TDH (0x3810) -#define E1000E_TDT (0x3818) - -#define E1000E_RDBAL (0x2800) -#define E1000E_RDBAH (0x2804) -#define E1000E_RDLEN (0x2808) -#define E1000E_RDH (0x2810) -#define E1000E_RDT (0x2818) - -typedef struct e1000e_device { - QPCIDevice *pci_dev; - QPCIBar mac_regs; - - uint64_t tx_ring; - uint64_t rx_ring; -} e1000e_device; - -static int test_sockets[2]; -static QGuestAllocator *test_alloc; -static QPCIBus *test_bus; - -static void e1000e_pci_foreach_callback(QPCIDevice *dev, int devfn, void *data) -{ - QPCIDevice **res = data; - - g_assert_null(*res); - *res = dev; -} - -static QPCIDevice *e1000e_device_find(QPCIBus *bus) -{ - static const int e1000e_vendor_id = 0x8086; - static const int e1000e_dev_id = 0x10D3; - - QPCIDevice *e1000e_dev = NULL; - - qpci_device_foreach(bus, e1000e_vendor_id, e1000e_dev_id, - e1000e_pci_foreach_callback, &e1000e_dev); - - g_assert_nonnull(e1000e_dev); - - return e1000e_dev; -} - -static void e1000e_macreg_write(e1000e_device *d, uint32_t reg, uint32_t val) -{ - qpci_io_writel(d->pci_dev, d->mac_regs, reg, val); -} - -static uint32_t e1000e_macreg_read(e1000e_device *d, uint32_t reg) -{ - return qpci_io_readl(d->pci_dev, d->mac_regs, reg); -} - -static void e1000e_device_init(QPCIBus *bus, e1000e_device *d) -{ - uint32_t val; - - d->pci_dev = e1000e_device_find(bus); - - /* Enable the device */ - qpci_device_enable(d->pci_dev); - - /* Map BAR0 (mac registers) */ - d->mac_regs = qpci_iomap(d->pci_dev, 0, NULL); - - /* Reset the device */ - val = e1000e_macreg_read(d, E1000E_CTRL); - e1000e_macreg_write(d, E1000E_CTRL, val | E1000E_CTRL_RESET); - - /* Enable and configure MSI-X */ - qpci_msix_enable(d->pci_dev); - e1000e_macreg_write(d, E1000E_IVAR, E1000E_IVAR_TEST_CFG); - - /* Check the device status - link and speed */ - val = e1000e_macreg_read(d, E1000E_STATUS); - g_assert_cmphex(val & (E1000E_STATUS_LU | E1000E_STATUS_ASDV1000), - ==, E1000E_STATUS_LU | E1000E_STATUS_ASDV1000); - - /* Initialize TX/RX logic */ - e1000e_macreg_write(d, E1000E_RCTL, 0); - e1000e_macreg_write(d, E1000E_TCTL, 0); - - /* Notify the device that the driver is ready */ - val = e1000e_macreg_read(d, E1000E_CTRL_EXT); - e1000e_macreg_write(d, E1000E_CTRL_EXT, - val | E1000E_CTRL_EXT_DRV_LOAD | E1000E_CTRL_EXT_TXLSFLOW); - - /* Allocate and setup TX ring */ - d->tx_ring = guest_alloc(test_alloc, E1000E_RING_LEN); - g_assert(d->tx_ring != 0); - - e1000e_macreg_write(d, E1000E_TDBAL, (uint32_t) d->tx_ring); - e1000e_macreg_write(d, E1000E_TDBAH, (uint32_t) (d->tx_ring >> 32)); - e1000e_macreg_write(d, E1000E_TDLEN, E1000E_RING_LEN); - e1000e_macreg_write(d, E1000E_TDT, 0); - e1000e_macreg_write(d, E1000E_TDH, 0); - - /* Enable transmit */ - e1000e_macreg_write(d, E1000E_TCTL, E1000E_TCTL_EN); - - /* Allocate and setup RX ring */ - d->rx_ring = guest_alloc(test_alloc, E1000E_RING_LEN); - g_assert(d->rx_ring != 0); - - e1000e_macreg_write(d, E1000E_RDBAL, (uint32_t)d->rx_ring); - e1000e_macreg_write(d, E1000E_RDBAH, (uint32_t)(d->rx_ring >> 32)); - e1000e_macreg_write(d, E1000E_RDLEN, E1000E_RING_LEN); - e1000e_macreg_write(d, E1000E_RDT, 0); - e1000e_macreg_write(d, E1000E_RDH, 0); - - /* Enable receive */ - e1000e_macreg_write(d, E1000E_RFCTL, E1000E_RFCTL_EXTEN); - e1000e_macreg_write(d, E1000E_RCTL, E1000E_RCTL_EN | - E1000E_RCTL_UPE | - E1000E_RCTL_MPE); - - /* Enable all interrupts */ - e1000e_macreg_write(d, E1000E_IMS, 0xFFFFFFFF); -} - -static void e1000e_tx_ring_push(e1000e_device *d, void *descr) -{ - uint32_t tail = e1000e_macreg_read(d, E1000E_TDT); - uint32_t len = e1000e_macreg_read(d, E1000E_TDLEN) / E1000E_TXD_LEN; - - memwrite(d->tx_ring + tail * E1000E_TXD_LEN, descr, E1000E_TXD_LEN); - e1000e_macreg_write(d, E1000E_TDT, (tail + 1) % len); - - /* Read WB data for the packet transmitted */ - memread(d->tx_ring + tail * E1000E_TXD_LEN, descr, E1000E_TXD_LEN); -} - -static void e1000e_rx_ring_push(e1000e_device *d, void *descr) -{ - uint32_t tail = e1000e_macreg_read(d, E1000E_RDT); - uint32_t len = e1000e_macreg_read(d, E1000E_RDLEN) / E1000E_RXD_LEN; - - memwrite(d->rx_ring + tail * E1000E_RXD_LEN, descr, E1000E_RXD_LEN); - e1000e_macreg_write(d, E1000E_RDT, (tail + 1) % len); - - /* Read WB data for the packet received */ - memread(d->rx_ring + tail * E1000E_RXD_LEN, descr, E1000E_RXD_LEN); -} - -static void e1000e_wait_isr(e1000e_device *d, uint16_t msg_id) -{ - guint64 end_time = g_get_monotonic_time() + 5 * G_TIME_SPAN_SECOND; - - do { - if (qpci_msix_pending(d->pci_dev, msg_id)) { - return; - } - clock_step(10000); - } while (g_get_monotonic_time() < end_time); - - g_error("Timeout expired"); -} - -static void e1000e_send_verify(e1000e_device *d) +static void e1000e_send_verify(QE1000E *d, int *test_sockets, QGuestAllocator *alloc) { struct { uint64_t buffer_addr; @@ -268,7 +67,7 @@ static void e1000e_send_verify(e1000e_device *d) uint32_t recv_len; /* Prepare test data buffer */ - uint64_t data = guest_alloc(test_alloc, data_len); + uint64_t data = guest_alloc(alloc, data_len); memwrite(data, "TEST", 5); /* Prepare TX descriptor */ @@ -296,10 +95,10 @@ static void e1000e_send_verify(e1000e_device *d) g_assert_cmpstr(buffer, == , "TEST"); /* Free test data buffer */ - guest_free(test_alloc, data); + guest_free(alloc, data); } -static void e1000e_receive_verify(e1000e_device *d) +static void e1000e_receive_verify(QE1000E *d, int *test_sockets, QGuestAllocator *alloc) { union { struct { @@ -348,7 +147,7 @@ static void e1000e_receive_verify(e1000e_device *d) g_assert_cmpint(ret, == , sizeof(test) + sizeof(len)); /* Prepare test data buffer */ - uint64_t data = guest_alloc(test_alloc, data_len); + uint64_t data = guest_alloc(alloc, data_len); /* Prepare RX descriptor */ memset(&descr, 0, sizeof(descr)); @@ -369,111 +168,108 @@ static void e1000e_receive_verify(e1000e_device *d) g_assert_cmpstr(buffer, == , "TEST"); /* Free test data buffer */ - guest_free(test_alloc, data); -} - -static void e1000e_device_clear(QPCIBus *bus, e1000e_device *d) -{ - qpci_iounmap(d->pci_dev, d->mac_regs); - qpci_msix_disable(d->pci_dev); -} - -static void data_test_init(e1000e_device *d) -{ - char *cmdline; - - int ret = socketpair(PF_UNIX, SOCK_STREAM, 0, test_sockets); - g_assert_cmpint(ret, != , -1); - - cmdline = g_strdup_printf("-netdev socket,fd=%d,id=hs0 " - "-device e1000e,netdev=hs0", test_sockets[1]); - g_assert_nonnull(cmdline); - - qtest_start(cmdline); - g_free(cmdline); - - test_alloc = pc_alloc_init(global_qtest); - g_assert_nonnull(test_alloc); - - test_bus = qpci_init_pc(global_qtest, test_alloc); - g_assert_nonnull(test_bus); - - e1000e_device_init(test_bus, d); + guest_free(alloc, data); } -static void data_test_clear(e1000e_device *d) +static void test_e1000e_init(void *obj, void *data, QGuestAllocator * alloc) { - e1000e_device_clear(test_bus, d); - close(test_sockets[0]); - pc_alloc_uninit(test_alloc); - g_free(d->pci_dev); - qpci_free_pc(test_bus); - qtest_end(); + /* init does nothing */ } -static void test_e1000e_init(gconstpointer data) +static void test_e1000e_tx(void *obj, void *data, QGuestAllocator * alloc) { - e1000e_device d; - - data_test_init(&d); - data_test_clear(&d); -} - -static void test_e1000e_tx(gconstpointer data) -{ - e1000e_device d; + QE1000E_PCI *e1000e = obj; + QE1000E *d = &e1000e->e1000e; + QOSGraphObject *e_object = obj; + QPCIDevice *dev = e_object->get_driver(e_object, "pci-device"); + + /* FIXME: add spapr support */ + if (qpci_check_buggy_msi(dev)) { + return; + } - data_test_init(&d); - e1000e_send_verify(&d); - data_test_clear(&d); + e1000e_send_verify(d, data, alloc); } -static void test_e1000e_rx(gconstpointer data) +static void test_e1000e_rx(void *obj, void *data, QGuestAllocator * alloc) { - e1000e_device d; + QE1000E_PCI *e1000e = obj; + QE1000E *d = &e1000e->e1000e; + QOSGraphObject *e_object = obj; + QPCIDevice *dev = e_object->get_driver(e_object, "pci-device"); + + /* FIXME: add spapr support */ + if (qpci_check_buggy_msi(dev)) { + return; + } - data_test_init(&d); - e1000e_receive_verify(&d); - data_test_clear(&d); + e1000e_receive_verify(d, data, alloc); } -static void test_e1000e_multiple_transfers(gconstpointer data) +static void test_e1000e_multiple_transfers(void *obj, void *data, + QGuestAllocator *alloc) { static const long iterations = 4 * 1024; long i; - e1000e_device d; + QE1000E_PCI *e1000e = obj; + QE1000E *d = &e1000e->e1000e; + QOSGraphObject *e_object = obj; + QPCIDevice *dev = e_object->get_driver(e_object, "pci-device"); - data_test_init(&d); + /* FIXME: add spapr support */ + if (qpci_check_buggy_msi(dev)) { + return; + } for (i = 0; i < iterations; i++) { - e1000e_send_verify(&d); - e1000e_receive_verify(&d); + e1000e_send_verify(d, data, alloc); + e1000e_receive_verify(d, data, alloc); } - data_test_clear(&d); } -static void test_e1000e_hotplug(gconstpointer data) +static void test_e1000e_hotplug(void *obj, void *data, QGuestAllocator * alloc) { - qtest_start("-device e1000e"); - qtest_qmp_device_add("e1000e", "e1000e_net", "{'addr': '0x06'}"); qpci_unplug_acpi_device_test("e1000e_net", 0x06); +} + +static void data_test_clear(void *sockets) +{ + int *test_sockets = sockets; - qtest_end(); + close(test_sockets[0]); + qos_invalidate_command_line(); + close(test_sockets[1]); + g_free(test_sockets); } -int main(int argc, char **argv) +static void *data_test_init(GString *cmd_line, void *arg) { - g_test_init(&argc, &argv, NULL); + int *test_sockets = g_new(int, 2); + int ret = socketpair(PF_UNIX, SOCK_STREAM, 0, test_sockets); + g_assert_cmpint(ret, != , -1); - qtest_add_data_func("e1000e/init", NULL, test_e1000e_init); - qtest_add_data_func("e1000e/tx", NULL, test_e1000e_tx); - qtest_add_data_func("e1000e/rx", NULL, test_e1000e_rx); - qtest_add_data_func("e1000e/multiple_transfers", NULL, - test_e1000e_multiple_transfers); - qtest_add_data_func("e1000e/hotplug", NULL, test_e1000e_hotplug); + g_string_append_printf(cmd_line, " -netdev socket,fd=%d,id=hs0 ", + test_sockets[1]); - return g_test_run(); + g_test_queue_destroy(data_test_clear, test_sockets); + return test_sockets; } + +static void register_e1000e_test(void) +{ + QOSGraphTestOptions opts = { + .before = data_test_init, + }; + + qos_add_test("init", "e1000e", test_e1000e_init, &opts); + qos_add_test("tx", "e1000e", test_e1000e_tx, &opts); + qos_add_test("rx", "e1000e", test_e1000e_rx, &opts); + qos_add_test("multiple_transfers", "e1000e", + test_e1000e_multiple_transfers, &opts); + qos_add_test("hotplug", "e1000e", test_e1000e_hotplug, &opts); +} + +libqos_init(register_e1000e_test); diff --git a/tests/eepro100-test.c b/tests/eepro100-test.c index bdc8a67d57..90b5c1afd9 100644 --- a/tests/eepro100-test.c +++ b/tests/eepro100-test.c @@ -9,23 +9,15 @@ #include "qemu/osdep.h" #include "libqtest.h" +#include "libqos/qgraph.h" +#include "libqos/pci.h" -static void test_device(gconstpointer data) -{ - const char *model = data; - QTestState *s; - char *args; - - args = g_strdup_printf("-device %s", model); - s = qtest_start(args); - - /* Tests only initialization so far. TODO: Implement functional tests */ +typedef struct QEEPRO100 QEEPRO100; - if (s) { - qtest_quit(s); - } - g_free(args); -} +struct QEEPRO100 { + QOSGraphObject obj; + QPCIDevice dev; +}; static const char *models[] = { "i82550", @@ -43,19 +35,42 @@ static const char *models[] = { "i82801", }; -int main(int argc, char **argv) +static void *eepro100_get_driver(void *obj, const char *interface) { - int i; + QEEPRO100 *eepro100 = obj; - g_test_init(&argc, &argv, NULL); + if (!g_strcmp0(interface, "pci-device")) { + return &eepro100->dev; + } - for (i = 0; i < ARRAY_SIZE(models); i++) { - char *path; + fprintf(stderr, "%s not present in eepro100\n", interface); + g_assert_not_reached(); +} - path = g_strdup_printf("eepro100/%s", models[i]); - qtest_add_data_func(path, models[i], test_device); - g_free(path); - } +static void *eepro100_create(void *pci_bus, QGuestAllocator *alloc, void *addr) +{ + QEEPRO100 *eepro100 = g_new0(QEEPRO100, 1); + QPCIBus *bus = pci_bus; + + qpci_device_init(&eepro100->dev, bus, addr); + eepro100->obj.get_driver = eepro100_get_driver; + + return &eepro100->obj; +} + +static void eepro100_register_nodes(void) +{ + int i; + QOSGraphEdgeOptions opts = { + .extra_device_opts = "addr=04.0", + }; - return g_test_run(); + add_qpci_address(&opts, &(QPCIAddress) { .devfn = QPCI_DEVFN(4, 0) }); + for (i = 0; i < ARRAY_SIZE(models); i++) { + qos_node_create_driver(models[i], eepro100_create); + qos_node_consumes(models[i], "pci-bus", &opts); + qos_node_produces(models[i], "pci-device"); + } } + +libqos_init(eepro100_register_nodes); diff --git a/tests/es1370-test.c b/tests/es1370-test.c index 199fe193ce..d845cd06f8 100644 --- a/tests/es1370-test.c +++ b/tests/es1370-test.c @@ -9,23 +9,49 @@ #include "qemu/osdep.h" #include "libqtest.h" +#include "libqos/qgraph.h" +#include "libqos/pci.h" -/* Tests only initialization so far. TODO: Replace with functional tests */ -static void nop(void) +typedef struct QES1370 QES1370; + +struct QES1370 { + QOSGraphObject obj; + QPCIDevice dev; +}; + +static void *es1370_get_driver(void *obj, const char *interface) { + QES1370 *es1370 = obj; + + if (!g_strcmp0(interface, "pci-device")) { + return &es1370->dev; + } + + fprintf(stderr, "%s not present in e1000e\n", interface); + g_assert_not_reached(); } -int main(int argc, char **argv) +static void *es1370_create(void *pci_bus, QGuestAllocator *alloc, void *addr) { - int ret; + QES1370 *es1370 = g_new0(QES1370, 1); + QPCIBus *bus = pci_bus; - g_test_init(&argc, &argv, NULL); - qtest_add_func("/es1370/nop", nop); + qpci_device_init(&es1370->dev, bus, addr); + es1370->obj.get_driver = es1370_get_driver; - qtest_start("-device ES1370"); - ret = g_test_run(); + return &es1370->obj; +} - qtest_end(); +static void es1370_register_nodes(void) +{ + QOSGraphEdgeOptions opts = { + .extra_device_opts = "addr=04.0", + }; + add_qpci_address(&opts, &(QPCIAddress) { .devfn = QPCI_DEVFN(4, 0) }); - return ret; + qos_node_create_driver("ES1370", es1370_create); + qos_node_consumes("ES1370", "pci-bus", &opts); + qos_node_produces("ES1370", "pci-device"); } + +libqos_init(es1370_register_nodes); diff --git a/tests/i440fx-test.c b/tests/i440fx-test.c index 4390e5591e..69205b58a8 100644 --- a/tests/i440fx-test.c +++ b/tests/i440fx-test.c @@ -38,7 +38,7 @@ static QPCIBus *test_start_get_bus(const TestData *s) cmdline = g_strdup_printf("-smp %d", s->num_cpus); qtest_start(cmdline); g_free(cmdline); - return qpci_init_pc(global_qtest, NULL); + return qpci_new_pc(global_qtest, NULL); } static void test_i440fx_defaults(gconstpointer opaque) diff --git a/tests/ide-test.c b/tests/ide-test.c index 300d64e77d..d863a99f7f 100644 --- a/tests/ide-test.c +++ b/tests/ide-test.c @@ -120,7 +120,7 @@ enum { #define assert_bit_clear(data, mask) g_assert_cmphex((data) & (mask), ==, 0) static QPCIBus *pcibus = NULL; -static QGuestAllocator *guest_malloc; +static QGuestAllocator guest_malloc; static char tmp_path[] = "/tmp/qtest.XXXXXX"; static char debug_path[] = "/tmp/qtest-blkdebug.XXXXXX"; @@ -135,7 +135,7 @@ static void ide_test_start(const char *cmdline_fmt, ...) va_end(ap); qtest_start(cmdline); - guest_malloc = pc_alloc_init(global_qtest); + pc_alloc_init(&guest_malloc, global_qtest, 0); g_free(cmdline); } @@ -146,8 +146,7 @@ static void ide_test_quit(void) qpci_free_pc(pcibus); pcibus = NULL; } - pc_alloc_uninit(guest_malloc); - guest_malloc = NULL; + alloc_destroy(&guest_malloc); qtest_end(); } @@ -157,7 +156,7 @@ static QPCIDevice *get_pci_device(QPCIBar *bmdma_bar, QPCIBar *ide_bar) uint16_t vendor_id, device_id; if (!pcibus) { - pcibus = qpci_init_pc(global_qtest, NULL); + pcibus = qpci_new_pc(global_qtest, NULL); } /* Find PCI device and verify it's the right one */ @@ -246,7 +245,7 @@ static int send_dma_request(int cmd, uint64_t sector, int nb_sectors, /* Setup PRDT */ len = sizeof(*prdt) * prdt_entries; - guest_prdt = guest_alloc(guest_malloc, len); + guest_prdt = guest_alloc(&guest_malloc, len); memwrite(guest_prdt, prdt, len); qpci_io_writel(dev, bmdma_bar, bmreg_prdt, guest_prdt); @@ -311,7 +310,7 @@ static void test_bmdma_simple_rw(void) uint8_t *buf; uint8_t *cmpbuf; size_t len = 512; - uintptr_t guest_buf = guest_alloc(guest_malloc, len); + uintptr_t guest_buf = guest_alloc(&guest_malloc, len); PrdtEntry prdt[] = { { @@ -381,7 +380,7 @@ static void test_bmdma_trim(void) const uint64_t bad_range = trim_range_le(TEST_IMAGE_SIZE / 512 - 1, 2); size_t len = 512; uint8_t *buf; - uintptr_t guest_buf = guest_alloc(guest_malloc, len); + uintptr_t guest_buf = guest_alloc(&guest_malloc, len); PrdtEntry prdt[] = { { @@ -625,7 +624,7 @@ static void make_dirty(uint8_t device) dev = get_pci_device(&bmdma_bar, &ide_bar); - guest_buf = guest_alloc(guest_malloc, len); + guest_buf = guest_alloc(&guest_malloc, len); buf = g_malloc(len); memset(buf, rand() % 255 + 1, len); g_assert(guest_buf); @@ -986,7 +985,7 @@ static void test_cdrom_dma(void) "-device ide-cd,drive=sr0,bus=ide.0", tmp_path); qtest_irq_intercept_in(global_qtest, "ioapic"); - guest_buf = guest_alloc(guest_malloc, len); + guest_buf = guest_alloc(&guest_malloc, len); prdt[0].addr = cpu_to_le32(guest_buf); prdt[0].size = cpu_to_le32(len | PRDT_EOT); diff --git a/tests/ipoctal232-test.c b/tests/ipoctal232-test.c index 684914164d..42d53718b8 100644 --- a/tests/ipoctal232-test.c +++ b/tests/ipoctal232-test.c @@ -9,23 +9,40 @@ #include "qemu/osdep.h" #include "libqtest.h" +#include "libqos/qgraph.h" + +typedef struct QIpoctal232 QIpoctal232; + +struct QIpoctal232 { + QOSGraphObject obj; +}; /* Tests only initialization so far. TODO: Replace with functional tests */ -static void nop(void) +static void nop(void *obj, void *data, QGuestAllocator *alloc) { } -int main(int argc, char **argv) +static void *ipoctal232_create(void *pci_bus, QGuestAllocator *alloc, + void *addr) { - int ret; + QIpoctal232 *ipoctal232 = g_new0(QIpoctal232, 1); - g_test_init(&argc, &argv, NULL); - qtest_add_func("/ipoctal232/tpci200/nop", nop); + return &ipoctal232->obj; +} - qtest_start("-device tpci200,id=ipack0 -device ipoctal232,bus=ipack0.0"); - ret = g_test_run(); +static void ipoctal232_register_nodes(void) +{ + qos_node_create_driver("ipoctal232", ipoctal232_create); + qos_node_consumes("ipoctal232", "ipack", &(QOSGraphEdgeOptions) { + .extra_device_opts = "bus=ipack0.0", + }); +} - qtest_end(); +libqos_init(ipoctal232_register_nodes); - return ret; +static void register_ipoctal232_test(void) +{ + qos_add_test("nop", "ipoctal232", nop, NULL); } + +libqos_init(register_ipoctal232_test); diff --git a/tests/ivshmem-test.c b/tests/ivshmem-test.c index 942ddc9192..227561fbca 100644 --- a/tests/ivshmem-test.c +++ b/tests/ivshmem-test.c @@ -74,7 +74,7 @@ static inline unsigned in_reg(IVState *s, enum Reg reg) unsigned res; res = qpci_io_readl(s->dev, s->reg_bar, reg); - g_test_message("*%s -> %x\n", name, res); + g_test_message("*%s -> %x", name, res); return res; } @@ -83,7 +83,7 @@ static inline void out_reg(IVState *s, enum Reg reg, unsigned v) { const char *name = reg2str(reg); - g_test_message("%x -> *%s\n", v, name); + g_test_message("%x -> *%s", v, name); qpci_io_writel(s->dev, s->reg_bar, reg, v); } diff --git a/tests/libqos/aarch64-xlnx-zcu102-machine.c b/tests/libqos/aarch64-xlnx-zcu102-machine.c new file mode 100644 index 0000000000..6fff040b37 --- /dev/null +++ b/tests/libqos/aarch64-xlnx-zcu102-machine.c @@ -0,0 +1,94 @@ +/* + * libqos driver framework + * + * Copyright (c) 2018 Emanuele Giuseppe Esposito <e.emanuelegiuseppe@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/> + */ + +#include "qemu/osdep.h" +#include "libqtest.h" +#include "libqos/malloc.h" +#include "libqos/qgraph.h" +#include "sdhci.h" + +typedef struct QXlnxZCU102Machine QXlnxZCU102Machine; + +struct QXlnxZCU102Machine { + QOSGraphObject obj; + QGuestAllocator alloc; + QSDHCI_MemoryMapped sdhci; +}; + +#define ARM_PAGE_SIZE 4096 +#define XLNX_ZCU102_RAM_ADDR 0 +#define XLNX_ZCU102_RAM_SIZE 0x20000000 + +static void *xlnx_zcu102_get_driver(void *object, const char *interface) +{ + QXlnxZCU102Machine *machine = object; + if (!g_strcmp0(interface, "memory")) { + return &machine->alloc; + } + + fprintf(stderr, "%s not present in aarch64/xlnx-zcu102\n", interface); + g_assert_not_reached(); +} + +static QOSGraphObject *xlnx_zcu102_get_device(void *obj, const char *device) +{ + QXlnxZCU102Machine *machine = obj; + if (!g_strcmp0(device, "generic-sdhci")) { + return &machine->sdhci.obj; + } + + fprintf(stderr, "%s not present in aarch64/xlnx-zcu102\n", device); + g_assert_not_reached(); +} + +static void xlnx_zcu102_destructor(QOSGraphObject *obj) +{ + QXlnxZCU102Machine *machine = (QXlnxZCU102Machine *) obj; + alloc_destroy(&machine->alloc); +} + +static void *qos_create_machine_aarch64_xlnx_zcu102(QTestState *qts) +{ + QXlnxZCU102Machine *machine = g_new0(QXlnxZCU102Machine, 1); + + alloc_init(&machine->alloc, 0, + XLNX_ZCU102_RAM_ADDR + (1 << 20), + XLNX_ZCU102_RAM_ADDR + XLNX_ZCU102_RAM_SIZE, + ARM_PAGE_SIZE); + + machine->obj.get_device = xlnx_zcu102_get_device; + machine->obj.get_driver = xlnx_zcu102_get_driver; + machine->obj.destructor = xlnx_zcu102_destructor; + /* Datasheet: UG1085 (v1.7) */ + qos_init_sdhci_mm(&machine->sdhci, qts, 0xff160000, &(QSDHCIProperties) { + .version = 3, + .baseclock = 0, + .capab.sdma = true, + .capab.reg = 0x280737ec6481 + }); + return &machine->obj; +} + +static void xlnx_zcu102_register_nodes(void) +{ + qos_node_create_machine("aarch64/xlnx-zcu102", + qos_create_machine_aarch64_xlnx_zcu102); + qos_node_contains("aarch64/xlnx-zcu102", "generic-sdhci", NULL); +} + +libqos_init(xlnx_zcu102_register_nodes); diff --git a/tests/libqos/ahci.c b/tests/libqos/ahci.c index 63fbc9e3c9..cc1b08eabe 100644 --- a/tests/libqos/ahci.c +++ b/tests/libqos/ahci.c @@ -130,7 +130,7 @@ QPCIDevice *get_ahci_device(QTestState *qts, uint32_t *fingerprint) uint32_t ahci_fingerprint; QPCIBus *pcibus; - pcibus = qpci_init_pc(qts, NULL); + pcibus = qpci_new_pc(qts, NULL); /* Find the AHCI PCI device and verify it's the right one. */ ahci = qpci_device_find(pcibus, QPCI_DEVFN(0x1F, 0x02)); diff --git a/tests/libqos/arm-raspi2-machine.c b/tests/libqos/arm-raspi2-machine.c new file mode 100644 index 0000000000..3aff670f76 --- /dev/null +++ b/tests/libqos/arm-raspi2-machine.c @@ -0,0 +1,91 @@ +/* + * libqos driver framework + * + * Copyright (c) 2018 Emanuele Giuseppe Esposito <e.emanuelegiuseppe@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/> + */ + +#include "qemu/osdep.h" +#include "libqtest.h" +#include "libqos/malloc.h" +#include "libqos/qgraph.h" +#include "sdhci.h" + +#define ARM_PAGE_SIZE 4096 +#define RASPI2_RAM_ADDR 0 +#define RASPI2_RAM_SIZE 0x20000000 + +typedef struct QRaspi2Machine QRaspi2Machine; + +struct QRaspi2Machine { + QOSGraphObject obj; + QGuestAllocator alloc; + QSDHCI_MemoryMapped sdhci; +}; + +static void *raspi2_get_driver(void *object, const char *interface) +{ + QRaspi2Machine *machine = object; + if (!g_strcmp0(interface, "memory")) { + return &machine->alloc; + } + + fprintf(stderr, "%s not present in arm/raspi2\n", interface); + g_assert_not_reached(); +} + +static QOSGraphObject *raspi2_get_device(void *obj, const char *device) +{ + QRaspi2Machine *machine = obj; + if (!g_strcmp0(device, "generic-sdhci")) { + return &machine->sdhci.obj; + } + + fprintf(stderr, "%s not present in arm/raspi2\n", device); + g_assert_not_reached(); +} + +static void raspi2_destructor(QOSGraphObject *obj) +{ + QRaspi2Machine *machine = (QRaspi2Machine *) obj; + alloc_destroy(&machine->alloc); +} + +static void *qos_create_machine_arm_raspi2(QTestState *qts) +{ + QRaspi2Machine *machine = g_new0(QRaspi2Machine, 1); + + alloc_init(&machine->alloc, 0, + RASPI2_RAM_ADDR + (1 << 20), + RASPI2_RAM_ADDR + RASPI2_RAM_SIZE, + ARM_PAGE_SIZE); + machine->obj.get_device = raspi2_get_device; + machine->obj.get_driver = raspi2_get_driver; + machine->obj.destructor = raspi2_destructor; + qos_init_sdhci_mm(&machine->sdhci, qts, 0x3f300000, &(QSDHCIProperties) { + .version = 3, + .baseclock = 52, + .capab.sdma = false, + .capab.reg = 0x052134b4 + }); + return &machine->obj; +} + +static void raspi2_register_nodes(void) +{ + qos_node_create_machine("arm/raspi2", qos_create_machine_arm_raspi2); + qos_node_contains("arm/raspi2", "generic-sdhci", NULL); +} + +libqos_init(raspi2_register_nodes); diff --git a/tests/libqos/arm-sabrelite-machine.c b/tests/libqos/arm-sabrelite-machine.c new file mode 100644 index 0000000000..c4128d8686 --- /dev/null +++ b/tests/libqos/arm-sabrelite-machine.c @@ -0,0 +1,91 @@ +/* + * libqos driver framework + * + * Copyright (c) 2018 Emanuele Giuseppe Esposito <e.emanuelegiuseppe@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/> + */ + +#include "qemu/osdep.h" +#include "libqtest.h" +#include "libqos/malloc.h" +#include "libqos/qgraph.h" +#include "sdhci.h" + +#define ARM_PAGE_SIZE 4096 +#define SABRELITE_RAM_START 0x10000000 +#define SABRELITE_RAM_END 0x30000000 + +typedef struct QSabreliteMachine QSabreliteMachine; + +struct QSabreliteMachine { + QOSGraphObject obj; + QGuestAllocator alloc; + QSDHCI_MemoryMapped sdhci; +}; + +static void *sabrelite_get_driver(void *object, const char *interface) +{ + QSabreliteMachine *machine = object; + if (!g_strcmp0(interface, "memory")) { + return &machine->alloc; + } + + fprintf(stderr, "%s not present in arm/sabrelite\n", interface); + g_assert_not_reached(); +} + +static QOSGraphObject *sabrelite_get_device(void *obj, const char *device) +{ + QSabreliteMachine *machine = obj; + if (!g_strcmp0(device, "generic-sdhci")) { + return &machine->sdhci.obj; + } + + fprintf(stderr, "%s not present in arm/sabrelite\n", device); + g_assert_not_reached(); +} + +static void sabrelite_destructor(QOSGraphObject *obj) +{ + QSabreliteMachine *machine = (QSabreliteMachine *) obj; + alloc_destroy(&machine->alloc); +} + +static void *qos_create_machine_arm_sabrelite(QTestState *qts) +{ + QSabreliteMachine *machine = g_new0(QSabreliteMachine, 1); + + alloc_init(&machine->alloc, 0, + SABRELITE_RAM_START, + SABRELITE_RAM_END, + ARM_PAGE_SIZE); + machine->obj.get_device = sabrelite_get_device; + machine->obj.get_driver = sabrelite_get_driver; + machine->obj.destructor = sabrelite_destructor; + qos_init_sdhci_mm(&machine->sdhci, qts, 0x02190000, &(QSDHCIProperties) { + .version = 3, + .baseclock = 0, + .capab.sdma = true, + .capab.reg = 0x057834b4, + }); + return &machine->obj; +} + +static void sabrelite_register_nodes(void) +{ + qos_node_create_machine("arm/sabrelite", qos_create_machine_arm_sabrelite); + qos_node_contains("arm/sabrelite", "generic-sdhci", NULL); +} + +libqos_init(sabrelite_register_nodes); diff --git a/tests/libqos/arm-smdkc210-machine.c b/tests/libqos/arm-smdkc210-machine.c new file mode 100644 index 0000000000..1fb9dfc0cb --- /dev/null +++ b/tests/libqos/arm-smdkc210-machine.c @@ -0,0 +1,91 @@ +/* + * libqos driver framework + * + * Copyright (c) 2018 Emanuele Giuseppe Esposito <e.emanuelegiuseppe@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/> + */ + +#include "qemu/osdep.h" +#include "libqtest.h" +#include "libqos/malloc.h" +#include "libqos/qgraph.h" +#include "sdhci.h" + +#define ARM_PAGE_SIZE 4096 +#define SMDKC210_RAM_ADDR 0x40000000ull +#define SMDKC210_RAM_SIZE 0x40000000ull + +typedef struct QSmdkc210Machine QSmdkc210Machine; + +struct QSmdkc210Machine { + QOSGraphObject obj; + QGuestAllocator alloc; + QSDHCI_MemoryMapped sdhci; +}; + +static void *smdkc210_get_driver(void *object, const char *interface) +{ + QSmdkc210Machine *machine = object; + if (!g_strcmp0(interface, "memory")) { + return &machine->alloc; + } + + fprintf(stderr, "%s not present in arm/smdkc210\n", interface); + g_assert_not_reached(); +} + +static QOSGraphObject *smdkc210_get_device(void *obj, const char *device) +{ + QSmdkc210Machine *machine = obj; + if (!g_strcmp0(device, "generic-sdhci")) { + return &machine->sdhci.obj; + } + + fprintf(stderr, "%s not present in arm/smdkc210\n", device); + g_assert_not_reached(); +} + +static void smdkc210_destructor(QOSGraphObject *obj) +{ + QSmdkc210Machine *machine = (QSmdkc210Machine *) obj; + alloc_destroy(&machine->alloc); +} + +static void *qos_create_machine_arm_smdkc210(QTestState *qts) +{ + QSmdkc210Machine *machine = g_new0(QSmdkc210Machine, 1); + + alloc_init(&machine->alloc, 0, + SMDKC210_RAM_ADDR, + SMDKC210_RAM_ADDR + SMDKC210_RAM_SIZE, + ARM_PAGE_SIZE); + machine->obj.get_device = smdkc210_get_device; + machine->obj.get_driver = smdkc210_get_driver; + machine->obj.destructor = smdkc210_destructor; + qos_init_sdhci_mm(&machine->sdhci, qts, 0x12510000, &(QSDHCIProperties) { + .version = 2, + .baseclock = 0, + .capab.sdma = true, + .capab.reg = 0x5e80080, + }); + return &machine->obj; +} + +static void smdkc210_register_nodes(void) +{ + qos_node_create_machine("arm/smdkc210", qos_create_machine_arm_smdkc210); + qos_node_contains("arm/smdkc210", "generic-sdhci", NULL); +} + +libqos_init(smdkc210_register_nodes); diff --git a/tests/libqos/arm-virt-machine.c b/tests/libqos/arm-virt-machine.c new file mode 100644 index 0000000000..2abc431ecf --- /dev/null +++ b/tests/libqos/arm-virt-machine.c @@ -0,0 +1,90 @@ +/* + * libqos driver framework + * + * Copyright (c) 2018 Emanuele Giuseppe Esposito <e.emanuelegiuseppe@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/> + */ + +#include "qemu/osdep.h" +#include "libqtest.h" +#include "libqos/malloc.h" +#include "libqos/qgraph.h" +#include "libqos/virtio-mmio.h" + +#define ARM_PAGE_SIZE 4096 +#define VIRTIO_MMIO_BASE_ADDR 0x0A003E00 +#define ARM_VIRT_RAM_ADDR 0x40000000 +#define ARM_VIRT_RAM_SIZE 0x20000000 +#define VIRTIO_MMIO_SIZE 0x00000200 + +typedef struct QVirtMachine QVirtMachine; + +struct QVirtMachine { + QOSGraphObject obj; + QGuestAllocator alloc; + QVirtioMMIODevice virtio_mmio; +}; + +static void virt_destructor(QOSGraphObject *obj) +{ + QVirtMachine *machine = (QVirtMachine *) obj; + alloc_destroy(&machine->alloc); +} + +static void *virt_get_driver(void *object, const char *interface) +{ + QVirtMachine *machine = object; + if (!g_strcmp0(interface, "memory")) { + return &machine->alloc; + } + + fprintf(stderr, "%s not present in arm/virtio\n", interface); + g_assert_not_reached(); +} + +static QOSGraphObject *virt_get_device(void *obj, const char *device) +{ + QVirtMachine *machine = obj; + if (!g_strcmp0(device, "virtio-mmio")) { + return &machine->virtio_mmio.obj; + } + + fprintf(stderr, "%s not present in arm/virtio\n", device); + g_assert_not_reached(); +} + +static void *qos_create_machine_arm_virt(QTestState *qts) +{ + QVirtMachine *machine = g_new0(QVirtMachine, 1); + + alloc_init(&machine->alloc, 0, + ARM_VIRT_RAM_ADDR, + ARM_VIRT_RAM_ADDR + ARM_VIRT_RAM_SIZE, + ARM_PAGE_SIZE); + qvirtio_mmio_init_device(&machine->virtio_mmio, qts, VIRTIO_MMIO_BASE_ADDR, + VIRTIO_MMIO_SIZE); + + machine->obj.get_device = virt_get_device; + machine->obj.get_driver = virt_get_driver; + machine->obj.destructor = virt_destructor; + return machine; +} + +static void virtio_mmio_register_nodes(void) +{ + qos_node_create_machine("arm/virt", qos_create_machine_arm_virt); + qos_node_contains("arm/virt", "virtio-mmio", NULL); +} + +libqos_init(virtio_mmio_register_nodes); diff --git a/tests/libqos/arm-xilinx-zynq-a9-machine.c b/tests/libqos/arm-xilinx-zynq-a9-machine.c new file mode 100644 index 0000000000..4e199fcd48 --- /dev/null +++ b/tests/libqos/arm-xilinx-zynq-a9-machine.c @@ -0,0 +1,94 @@ +/* + * libqos driver framework + * + * Copyright (c) 2018 Emanuele Giuseppe Esposito <e.emanuelegiuseppe@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/> + */ + +#include "qemu/osdep.h" +#include "libqtest.h" +#include "libqos/malloc.h" +#include "libqos/qgraph.h" +#include "sdhci.h" + +typedef struct QXilinxZynqA9Machine QXilinxZynqA9Machine; + +struct QXilinxZynqA9Machine { + QOSGraphObject obj; + QGuestAllocator alloc; + QSDHCI_MemoryMapped sdhci; +}; + +#define ARM_PAGE_SIZE 4096 +#define XILINX_ZYNQ_A9_RAM_ADDR 0 +#define XILINX_ZYNQ_A9_RAM_SIZE 0x20000000 + +static void *xilinx_zynq_a9_get_driver(void *object, const char *interface) +{ + QXilinxZynqA9Machine *machine = object; + if (!g_strcmp0(interface, "memory")) { + return &machine->alloc; + } + + fprintf(stderr, "%s not present in arm/xilinx-zynq-a9\n", interface); + g_assert_not_reached(); +} + +static QOSGraphObject *xilinx_zynq_a9_get_device(void *obj, const char *device) +{ + QXilinxZynqA9Machine *machine = obj; + if (!g_strcmp0(device, "generic-sdhci")) { + return &machine->sdhci.obj; + } + + fprintf(stderr, "%s not present in arm/xilinx-zynq-a9\n", device); + g_assert_not_reached(); +} + +static void xilinx_zynq_a9_destructor(QOSGraphObject *obj) +{ + QXilinxZynqA9Machine *machine = (QXilinxZynqA9Machine *) obj; + alloc_destroy(&machine->alloc); +} + +static void *qos_create_machine_arm_xilinx_zynq_a9(QTestState *qts) +{ + QXilinxZynqA9Machine *machine = g_new0(QXilinxZynqA9Machine, 1); + + alloc_init(&machine->alloc, 0, + XILINX_ZYNQ_A9_RAM_ADDR + (1 << 20), + XILINX_ZYNQ_A9_RAM_ADDR + XILINX_ZYNQ_A9_RAM_SIZE, + ARM_PAGE_SIZE); + + machine->obj.get_device = xilinx_zynq_a9_get_device; + machine->obj.get_driver = xilinx_zynq_a9_get_driver; + machine->obj.destructor = xilinx_zynq_a9_destructor; + /* Datasheet: UG585 (v1.12.1) */ + qos_init_sdhci_mm(&machine->sdhci, qts, 0xe0100000, &(QSDHCIProperties) { + .version = 2, + .baseclock = 0, + .capab.sdma = true, + .capab.reg = 0x69ec0080, + }); + return &machine->obj; +} + +static void xilinx_zynq_a9_register_nodes(void) +{ + qos_node_create_machine("arm/xilinx-zynq-a9", + qos_create_machine_arm_xilinx_zynq_a9); + qos_node_contains("arm/xilinx-zynq-a9", "generic-sdhci", NULL); +} + +libqos_init(xilinx_zynq_a9_register_nodes); diff --git a/tests/libqos/e1000e.c b/tests/libqos/e1000e.c new file mode 100644 index 0000000000..54d3898899 --- /dev/null +++ b/tests/libqos/e1000e.c @@ -0,0 +1,260 @@ +/* + * libqos driver framework + * + * Copyright (c) 2018 Emanuele Giuseppe Esposito <e.emanuelegiuseppe@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/> + */ + +#include "qemu/osdep.h" +#include "libqtest.h" +#include "qemu-common.h" +#include "libqos/pci-pc.h" +#include "qemu/sockets.h" +#include "qemu/iov.h" +#include "qemu/bitops.h" +#include "libqos/malloc.h" +#include "libqos/qgraph.h" +#include "e1000e.h" + +#define E1000E_IMS (0x00d0) + +#define E1000E_STATUS (0x0008) +#define E1000E_STATUS_LU BIT(1) +#define E1000E_STATUS_ASDV1000 BIT(9) + +#define E1000E_CTRL (0x0000) +#define E1000E_CTRL_RESET BIT(26) + +#define E1000E_RCTL (0x0100) +#define E1000E_RCTL_EN BIT(1) +#define E1000E_RCTL_UPE BIT(3) +#define E1000E_RCTL_MPE BIT(4) + +#define E1000E_RFCTL (0x5008) +#define E1000E_RFCTL_EXTEN BIT(15) + +#define E1000E_TCTL (0x0400) +#define E1000E_TCTL_EN BIT(1) + +#define E1000E_CTRL_EXT (0x0018) +#define E1000E_CTRL_EXT_DRV_LOAD BIT(28) +#define E1000E_CTRL_EXT_TXLSFLOW BIT(22) + +#define E1000E_IVAR (0x00E4) +#define E1000E_IVAR_TEST_CFG ((E1000E_RX0_MSG_ID << 0) | BIT(3) | \ + (E1000E_TX0_MSG_ID << 8) | BIT(11) | \ + (E1000E_OTHER_MSG_ID << 16) | BIT(19) | \ + BIT(31)) + +#define E1000E_RING_LEN (0x1000) + +#define E1000E_TDBAL (0x3800) + +#define E1000E_TDBAH (0x3804) +#define E1000E_TDH (0x3810) + +#define E1000E_RDBAL (0x2800) +#define E1000E_RDBAH (0x2804) +#define E1000E_RDH (0x2810) + +#define E1000E_TXD_LEN (16) +#define E1000E_RXD_LEN (16) + +static void e1000e_macreg_write(QE1000E *d, uint32_t reg, uint32_t val) +{ + QE1000E_PCI *d_pci = container_of(d, QE1000E_PCI, e1000e); + qpci_io_writel(&d_pci->pci_dev, d_pci->mac_regs, reg, val); +} + +static uint32_t e1000e_macreg_read(QE1000E *d, uint32_t reg) +{ + QE1000E_PCI *d_pci = container_of(d, QE1000E_PCI, e1000e); + return qpci_io_readl(&d_pci->pci_dev, d_pci->mac_regs, reg); +} + +void e1000e_tx_ring_push(QE1000E *d, void *descr) +{ + uint32_t tail = e1000e_macreg_read(d, E1000E_TDT); + uint32_t len = e1000e_macreg_read(d, E1000E_TDLEN) / E1000E_TXD_LEN; + + memwrite(d->tx_ring + tail * E1000E_TXD_LEN, descr, E1000E_TXD_LEN); + e1000e_macreg_write(d, E1000E_TDT, (tail + 1) % len); + + /* Read WB data for the packet transmitted */ + memread(d->tx_ring + tail * E1000E_TXD_LEN, descr, E1000E_TXD_LEN); +} + +void e1000e_rx_ring_push(QE1000E *d, void *descr) +{ + uint32_t tail = e1000e_macreg_read(d, E1000E_RDT); + uint32_t len = e1000e_macreg_read(d, E1000E_RDLEN) / E1000E_RXD_LEN; + + memwrite(d->rx_ring + tail * E1000E_RXD_LEN, descr, E1000E_RXD_LEN); + e1000e_macreg_write(d, E1000E_RDT, (tail + 1) % len); + + /* Read WB data for the packet received */ + memread(d->rx_ring + tail * E1000E_RXD_LEN, descr, E1000E_RXD_LEN); +} + +static void e1000e_foreach_callback(QPCIDevice *dev, int devfn, void *data) +{ + QPCIDevice *res = data; + memcpy(res, dev, sizeof(QPCIDevice)); + g_free(dev); +} + +void e1000e_wait_isr(QE1000E *d, uint16_t msg_id) +{ + QE1000E_PCI *d_pci = container_of(d, QE1000E_PCI, e1000e); + guint64 end_time = g_get_monotonic_time() + 5 * G_TIME_SPAN_SECOND; + + do { + if (qpci_msix_pending(&d_pci->pci_dev, msg_id)) { + return; + } + clock_step(10000); + } while (g_get_monotonic_time() < end_time); + + g_error("Timeout expired"); +} + +static void e1000e_pci_destructor(QOSGraphObject *obj) +{ + QE1000E_PCI *epci = (QE1000E_PCI *) obj; + qpci_iounmap(&epci->pci_dev, epci->mac_regs); + qpci_msix_disable(&epci->pci_dev); +} + +static void e1000e_pci_start_hw(QOSGraphObject *obj) +{ + QE1000E_PCI *d = (QE1000E_PCI *) obj; + uint32_t val; + + /* Enable the device */ + qpci_device_enable(&d->pci_dev); + + /* Reset the device */ + val = e1000e_macreg_read(&d->e1000e, E1000E_CTRL); + e1000e_macreg_write(&d->e1000e, E1000E_CTRL, val | E1000E_CTRL_RESET); + + /* Enable and configure MSI-X */ + qpci_msix_enable(&d->pci_dev); + e1000e_macreg_write(&d->e1000e, E1000E_IVAR, E1000E_IVAR_TEST_CFG); + + /* Check the device status - link and speed */ + val = e1000e_macreg_read(&d->e1000e, E1000E_STATUS); + g_assert_cmphex(val & (E1000E_STATUS_LU | E1000E_STATUS_ASDV1000), + ==, E1000E_STATUS_LU | E1000E_STATUS_ASDV1000); + + /* Initialize TX/RX logic */ + e1000e_macreg_write(&d->e1000e, E1000E_RCTL, 0); + e1000e_macreg_write(&d->e1000e, E1000E_TCTL, 0); + + /* Notify the device that the driver is ready */ + val = e1000e_macreg_read(&d->e1000e, E1000E_CTRL_EXT); + e1000e_macreg_write(&d->e1000e, E1000E_CTRL_EXT, + val | E1000E_CTRL_EXT_DRV_LOAD | E1000E_CTRL_EXT_TXLSFLOW); + + e1000e_macreg_write(&d->e1000e, E1000E_TDBAL, + (uint32_t) d->e1000e.tx_ring); + e1000e_macreg_write(&d->e1000e, E1000E_TDBAH, + (uint32_t) (d->e1000e.tx_ring >> 32)); + e1000e_macreg_write(&d->e1000e, E1000E_TDLEN, E1000E_RING_LEN); + e1000e_macreg_write(&d->e1000e, E1000E_TDT, 0); + e1000e_macreg_write(&d->e1000e, E1000E_TDH, 0); + + /* Enable transmit */ + e1000e_macreg_write(&d->e1000e, E1000E_TCTL, E1000E_TCTL_EN); + e1000e_macreg_write(&d->e1000e, E1000E_RDBAL, + (uint32_t)d->e1000e.rx_ring); + e1000e_macreg_write(&d->e1000e, E1000E_RDBAH, + (uint32_t)(d->e1000e.rx_ring >> 32)); + e1000e_macreg_write(&d->e1000e, E1000E_RDLEN, E1000E_RING_LEN); + e1000e_macreg_write(&d->e1000e, E1000E_RDT, 0); + e1000e_macreg_write(&d->e1000e, E1000E_RDH, 0); + + /* Enable receive */ + e1000e_macreg_write(&d->e1000e, E1000E_RFCTL, E1000E_RFCTL_EXTEN); + e1000e_macreg_write(&d->e1000e, E1000E_RCTL, E1000E_RCTL_EN | + E1000E_RCTL_UPE | + E1000E_RCTL_MPE); + + /* Enable all interrupts */ + e1000e_macreg_write(&d->e1000e, E1000E_IMS, 0xFFFFFFFF); + +} + +static void *e1000e_pci_get_driver(void *obj, const char *interface) +{ + QE1000E_PCI *epci = obj; + if (!g_strcmp0(interface, "e1000e-if")) { + return &epci->e1000e; + } + + /* implicit contains */ + if (!g_strcmp0(interface, "pci-device")) { + return &epci->pci_dev; + } + + fprintf(stderr, "%s not present in e1000e\n", interface); + g_assert_not_reached(); +} + +static void *e1000e_pci_create(void *pci_bus, QGuestAllocator *alloc, + void *addr) +{ + QE1000E_PCI *d = g_new0(QE1000E_PCI, 1); + QPCIBus *bus = pci_bus; + QPCIAddress *address = addr; + + qpci_device_foreach(bus, address->vendor_id, address->device_id, + e1000e_foreach_callback, &d->pci_dev); + + /* Map BAR0 (mac registers) */ + d->mac_regs = qpci_iomap(&d->pci_dev, 0, NULL); + + /* Allocate and setup TX ring */ + d->e1000e.tx_ring = guest_alloc(alloc, E1000E_RING_LEN); + g_assert(d->e1000e.tx_ring != 0); + + /* Allocate and setup RX ring */ + d->e1000e.rx_ring = guest_alloc(alloc, E1000E_RING_LEN); + g_assert(d->e1000e.rx_ring != 0); + + d->obj.get_driver = e1000e_pci_get_driver; + d->obj.start_hw = e1000e_pci_start_hw; + d->obj.destructor = e1000e_pci_destructor; + + return &d->obj; +} + +static void e1000e_register_nodes(void) +{ + QPCIAddress addr = { + .vendor_id = 0x8086, + .device_id = 0x10D3, + }; + + /* FIXME: every test using this node needs to setup a -netdev socket,id=hs0 + * otherwise QEMU is not going to start */ + QOSGraphEdgeOptions opts = { + .extra_device_opts = "netdev=hs0", + }; + add_qpci_address(&opts, &addr); + + qos_node_create_driver("e1000e", e1000e_pci_create); + qos_node_consumes("e1000e", "pci-bus", &opts); +} + +libqos_init(e1000e_register_nodes); diff --git a/tests/libqos/e1000e.h b/tests/libqos/e1000e.h new file mode 100644 index 0000000000..9d37094f43 --- /dev/null +++ b/tests/libqos/e1000e.h @@ -0,0 +1,53 @@ +/* + * libqos driver framework + * + * Copyright (c) 2018 Emanuele Giuseppe Esposito <e.emanuelegiuseppe@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/> + */ + +#ifndef QGRAPH_E1000E +#define QGRAPH_E1000E + +#include "libqos/qgraph.h" +#include "pci.h" + +#define E1000E_RX0_MSG_ID (0) +#define E1000E_TX0_MSG_ID (1) +#define E1000E_OTHER_MSG_ID (2) + +#define E1000E_TDLEN (0x3808) +#define E1000E_TDT (0x3818) +#define E1000E_RDLEN (0x2808) +#define E1000E_RDT (0x2818) + +typedef struct QE1000E QE1000E; +typedef struct QE1000E_PCI QE1000E_PCI; + +struct QE1000E { + uint64_t tx_ring; + uint64_t rx_ring; +}; + +struct QE1000E_PCI { + QOSGraphObject obj; + QPCIDevice pci_dev; + QPCIBar mac_regs; + QE1000E e1000e; +}; + +void e1000e_wait_isr(QE1000E *d, uint16_t msg_id); +void e1000e_tx_ring_push(QE1000E *d, void *descr); +void e1000e_rx_ring_push(QE1000E *d, void *descr); + +#endif diff --git a/tests/libqos/libqos-pc.c b/tests/libqos/libqos-pc.c index a9c1aceaa7..d04abc548b 100644 --- a/tests/libqos/libqos-pc.c +++ b/tests/libqos/libqos-pc.c @@ -4,9 +4,8 @@ #include "libqos/pci-pc.h" static QOSOps qos_ops = { - .init_allocator = pc_alloc_init_flags, - .uninit_allocator = pc_alloc_uninit, - .qpci_init = qpci_init_pc, + .alloc_init = pc_alloc_init, + .qpci_new = qpci_new_pc, .qpci_free = qpci_free_pc, .shutdown = qtest_pc_shutdown, }; diff --git a/tests/libqos/libqos-spapr.c b/tests/libqos/libqos-spapr.c index a37791e5d0..8766d543ce 100644 --- a/tests/libqos/libqos-spapr.c +++ b/tests/libqos/libqos-spapr.c @@ -4,9 +4,8 @@ #include "libqos/pci-spapr.h" static QOSOps qos_ops = { - .init_allocator = spapr_alloc_init_flags, - .uninit_allocator = spapr_alloc_uninit, - .qpci_init = qpci_init_spapr, + .alloc_init = spapr_alloc_init, + .qpci_new = qpci_new_spapr, .qpci_free = qpci_free_spapr, .shutdown = qtest_spapr_shutdown, }; diff --git a/tests/libqos/libqos.c b/tests/libqos/libqos.c index c514187344..636a111a6f 100644 --- a/tests/libqos/libqos.c +++ b/tests/libqos/libqos.c @@ -24,8 +24,8 @@ QOSState *qtest_vboot(QOSOps *ops, const char *cmdline_fmt, va_list ap) qs->qts = qtest_init(cmdline); qs->ops = ops; if (ops) { - qs->alloc = ops->init_allocator(qs->qts, ALLOC_NO_FLAGS); - qs->pcibus = ops->qpci_init(qs->qts, qs->alloc); + ops->alloc_init(&qs->alloc, qs->qts, ALLOC_NO_FLAGS); + qs->pcibus = ops->qpci_new(qs->qts, &qs->alloc); } g_free(cmdline); @@ -58,11 +58,8 @@ void qtest_common_shutdown(QOSState *qs) qs->ops->qpci_free(qs->pcibus); qs->pcibus = NULL; } - if (qs->alloc && qs->ops->uninit_allocator) { - qs->ops->uninit_allocator(qs->alloc); - qs->alloc = NULL; - } } + alloc_destroy(&qs->alloc); qtest_quit(qs->qts); g_free(qs); } @@ -116,7 +113,7 @@ void migrate(QOSState *from, QOSState *to, const char *uri) /* If we were running, we can wait for an event. */ if (running) { - migrate_allocator(from->alloc, to->alloc); + migrate_allocator(&from->alloc, &to->alloc); set_context(to); qtest_qmp_eventwait(to->qts, "RESUME"); return; @@ -146,7 +143,7 @@ void migrate(QOSState *from, QOSState *to, const char *uri) g_assert_not_reached(); } - migrate_allocator(from->alloc, to->alloc); + migrate_allocator(&from->alloc, &to->alloc); set_context(to); } diff --git a/tests/libqos/libqos.h b/tests/libqos/libqos.h index 07d4b93d1d..149b0be8bc 100644 --- a/tests/libqos/libqos.h +++ b/tests/libqos/libqos.h @@ -3,21 +3,20 @@ #include "libqtest.h" #include "libqos/pci.h" -#include "libqos/malloc-pc.h" +#include "libqos/malloc.h" typedef struct QOSState QOSState; typedef struct QOSOps { - QGuestAllocator *(*init_allocator)(QTestState *qts, QAllocOpts); - void (*uninit_allocator)(QGuestAllocator *); - QPCIBus *(*qpci_init)(QTestState *qts, QGuestAllocator *alloc); + void (*alloc_init)(QGuestAllocator *, QTestState *, QAllocOpts); + QPCIBus *(*qpci_new)(QTestState *qts, QGuestAllocator *alloc); void (*qpci_free)(QPCIBus *bus); void (*shutdown)(QOSState *); } QOSOps; struct QOSState { QTestState *qts; - QGuestAllocator *alloc; + QGuestAllocator alloc; QPCIBus *pcibus; QOSOps *ops; }; @@ -36,12 +35,12 @@ void generate_pattern(void *buffer, size_t len, size_t cycle_len); static inline uint64_t qmalloc(QOSState *q, size_t bytes) { - return guest_alloc(q->alloc, bytes); + return guest_alloc(&q->alloc, bytes); } static inline void qfree(QOSState *q, uint64_t addr) { - guest_free(q->alloc, addr); + guest_free(&q->alloc, addr); } #endif diff --git a/tests/libqos/malloc-generic.c b/tests/libqos/malloc-generic.c deleted file mode 100644 index 33ce90b925..0000000000 --- a/tests/libqos/malloc-generic.c +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Basic libqos generic malloc support - * - * Copyright (c) 2014 Marc Marà - * - * This work is licensed under the terms of the GNU GPL, version 2 or later. - * See the COPYING file in the top-level directory. - */ - -#include "qemu/osdep.h" -#include "libqos/malloc-generic.h" -#include "libqos/malloc.h" - -/* - * Mostly for valgrind happiness, but it does offer - * a chokepoint for debugging guest memory leaks, too. - */ -void generic_alloc_uninit(QGuestAllocator *allocator) -{ - alloc_uninit(allocator); -} - -QGuestAllocator *generic_alloc_init_flags(uint64_t base_addr, uint64_t size, - uint32_t page_size, QAllocOpts flags) -{ - QGuestAllocator *s; - uint64_t start = base_addr + (1 << 20); /* Start at 1MB */ - - s = alloc_init_flags(flags, start, start + size); - alloc_set_page_size(s, page_size); - - return s; -} - -inline QGuestAllocator *generic_alloc_init(uint64_t base_addr, uint64_t size, - uint32_t page_size) -{ - return generic_alloc_init_flags(base_addr, size, page_size, ALLOC_NO_FLAGS); -} diff --git a/tests/libqos/malloc-generic.h b/tests/libqos/malloc-generic.h deleted file mode 100644 index 90104ecec9..0000000000 --- a/tests/libqos/malloc-generic.h +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Basic libqos generic malloc support - * - * Copyright (c) 2014 Marc Marà - * - * This work is licensed under the terms of the GNU GPL, version 2 or later. - * See the COPYING file in the top-level directory. - */ - -#ifndef LIBQOS_MALLOC_GENERIC_H -#define LIBQOS_MALLOC_GENERIC_H - -#include "libqos/malloc.h" - -QGuestAllocator *generic_alloc_init(uint64_t base_addr, uint64_t size, - uint32_t page_size); -QGuestAllocator *generic_alloc_init_flags(uint64_t base_addr, uint64_t size, - uint32_t page_size, QAllocOpts flags); -void generic_alloc_uninit(QGuestAllocator *allocator); - -#endif diff --git a/tests/libqos/malloc-pc.c b/tests/libqos/malloc-pc.c index b83cb8f0af..949a99361d 100644 --- a/tests/libqos/malloc-pc.c +++ b/tests/libqos/malloc-pc.c @@ -20,32 +20,14 @@ #define PAGE_SIZE (4096) -/* - * Mostly for valgrind happiness, but it does offer - * a chokepoint for debugging guest memory leaks, too. - */ -void pc_alloc_uninit(QGuestAllocator *allocator) -{ - alloc_uninit(allocator); -} - -QGuestAllocator *pc_alloc_init_flags(QTestState *qts, QAllocOpts flags) +void pc_alloc_init(QGuestAllocator *s, QTestState *qts, QAllocOpts flags) { - QGuestAllocator *s; uint64_t ram_size; QFWCFG *fw_cfg = pc_fw_cfg_init(qts); ram_size = qfw_cfg_get_u64(fw_cfg, FW_CFG_RAM_SIZE); - s = alloc_init_flags(flags, 1 << 20, MIN(ram_size, 0xE0000000)); - alloc_set_page_size(s, PAGE_SIZE); + alloc_init(s, flags, 1 << 20, MIN(ram_size, 0xE0000000), PAGE_SIZE); /* clean-up */ g_free(fw_cfg); - - return s; -} - -inline QGuestAllocator *pc_alloc_init(QTestState *qts) -{ - return pc_alloc_init_flags(qts, ALLOC_NO_FLAGS); } diff --git a/tests/libqos/malloc-pc.h b/tests/libqos/malloc-pc.h index 10f3da6cf2..21e75ae004 100644 --- a/tests/libqos/malloc-pc.h +++ b/tests/libqos/malloc-pc.h @@ -15,8 +15,6 @@ #include "libqos/malloc.h" -QGuestAllocator *pc_alloc_init(QTestState *qts); -QGuestAllocator *pc_alloc_init_flags(QTestState *qts, QAllocOpts flags); -void pc_alloc_uninit(QGuestAllocator *allocator); +void pc_alloc_init(QGuestAllocator *s, QTestState *qts, QAllocOpts flags); #endif diff --git a/tests/libqos/malloc-spapr.c b/tests/libqos/malloc-spapr.c index 1c359cea6c..2a6b7e3776 100644 --- a/tests/libqos/malloc-spapr.c +++ b/tests/libqos/malloc-spapr.c @@ -17,22 +17,7 @@ */ #define SPAPR_MIN_SIZE 0x10000000 -void spapr_alloc_uninit(QGuestAllocator *allocator) +void spapr_alloc_init(QGuestAllocator *s, QTestState *qts, QAllocOpts flags) { - alloc_uninit(allocator); -} - -QGuestAllocator *spapr_alloc_init_flags(QTestState *qts, QAllocOpts flags) -{ - QGuestAllocator *s; - - s = alloc_init_flags(flags, 1 << 20, SPAPR_MIN_SIZE); - alloc_set_page_size(s, PAGE_SIZE); - - return s; -} - -QGuestAllocator *spapr_alloc_init(void) -{ - return spapr_alloc_init_flags(NULL, ALLOC_NO_FLAGS); + alloc_init(s, flags, 1 << 20, SPAPR_MIN_SIZE, PAGE_SIZE); } diff --git a/tests/libqos/malloc-spapr.h b/tests/libqos/malloc-spapr.h index 52a9346a26..e5fe9bfc4b 100644 --- a/tests/libqos/malloc-spapr.h +++ b/tests/libqos/malloc-spapr.h @@ -10,8 +10,6 @@ #include "libqos/malloc.h" -QGuestAllocator *spapr_alloc_init(void); -QGuestAllocator *spapr_alloc_init_flags(QTestState *qts, QAllocOpts flags); -void spapr_alloc_uninit(QGuestAllocator *allocator); +void spapr_alloc_init(QGuestAllocator *s, QTestState *qts, QAllocOpts flags); #endif diff --git a/tests/libqos/malloc.c b/tests/libqos/malloc.c index f7bae47a08..615422a5c4 100644 --- a/tests/libqos/malloc.c +++ b/tests/libqos/malloc.c @@ -15,24 +15,12 @@ #include "qemu-common.h" #include "qemu/host-utils.h" -typedef QTAILQ_HEAD(MemList, MemBlock) MemList; - typedef struct MemBlock { QTAILQ_ENTRY(MemBlock) MLIST_ENTNAME; uint64_t size; uint64_t addr; } MemBlock; -struct QGuestAllocator { - QAllocOpts opts; - uint64_t start; - uint64_t end; - uint32_t page_size; - - MemList *used; - MemList *free; -}; - #define DEFAULT_PAGE_SIZE 4096 static void mlist_delete(MemList *list, MemBlock *node) @@ -225,7 +213,7 @@ static void mlist_free(QGuestAllocator *s, uint64_t addr) * Mostly for valgrind happiness, but it does offer * a chokepoint for debugging guest memory leaks, too. */ -void alloc_uninit(QGuestAllocator *allocator) +void alloc_destroy(QGuestAllocator *allocator) { MemBlock *node; MemBlock *tmp; @@ -261,7 +249,6 @@ void alloc_uninit(QGuestAllocator *allocator) g_free(allocator->used); g_free(allocator->free); - g_free(allocator); } uint64_t guest_alloc(QGuestAllocator *allocator, size_t size) @@ -297,11 +284,13 @@ void guest_free(QGuestAllocator *allocator, uint64_t addr) } } -QGuestAllocator *alloc_init(uint64_t start, uint64_t end) +void alloc_init(QGuestAllocator *s, QAllocOpts opts, + uint64_t start, uint64_t end, + size_t page_size) { - QGuestAllocator *s = g_malloc0(sizeof(*s)); MemBlock *node; + s->opts = opts; s->start = start; s->end = end; @@ -313,26 +302,7 @@ QGuestAllocator *alloc_init(uint64_t start, uint64_t end) node = mlist_new(s->start, s->end - s->start); QTAILQ_INSERT_HEAD(s->free, node, MLIST_ENTNAME); - s->page_size = DEFAULT_PAGE_SIZE; - - return s; -} - -QGuestAllocator *alloc_init_flags(QAllocOpts opts, - uint64_t start, uint64_t end) -{ - QGuestAllocator *s = alloc_init(start, end); - s->opts = opts; - return s; -} - -void alloc_set_page_size(QGuestAllocator *allocator, size_t page_size) -{ - /* Can't alter the page_size for an allocator in-use */ - g_assert(QTAILQ_EMPTY(allocator->used)); - - g_assert(is_power_of_2(page_size)); - allocator->page_size = page_size; + s->page_size = page_size; } void alloc_set_flags(QGuestAllocator *allocator, QAllocOpts opts) diff --git a/tests/libqos/malloc.h b/tests/libqos/malloc.h index 828fddabdb..4d1a2e2bef 100644 --- a/tests/libqos/malloc.h +++ b/tests/libqos/malloc.h @@ -23,19 +23,28 @@ typedef enum { ALLOC_PARANOID = 0x04 } QAllocOpts; -typedef struct QGuestAllocator QGuestAllocator; +typedef QTAILQ_HEAD(MemList, MemBlock) MemList; -void alloc_uninit(QGuestAllocator *allocator); +typedef struct QGuestAllocator { + QAllocOpts opts; + uint64_t start; + uint64_t end; + uint32_t page_size; + + MemList *used; + MemList *free; +} QGuestAllocator; /* Always returns page aligned values */ uint64_t guest_alloc(QGuestAllocator *allocator, size_t size); void guest_free(QGuestAllocator *allocator, uint64_t addr); void migrate_allocator(QGuestAllocator *src, QGuestAllocator *dst); -QGuestAllocator *alloc_init(uint64_t start, uint64_t end); -QGuestAllocator *alloc_init_flags(QAllocOpts flags, - uint64_t start, uint64_t end); -void alloc_set_page_size(QGuestAllocator *allocator, size_t page_size); void alloc_set_flags(QGuestAllocator *allocator, QAllocOpts opts); +void alloc_init(QGuestAllocator *alloc, QAllocOpts flags, + uint64_t start, uint64_t end, + size_t page_size); +void alloc_destroy(QGuestAllocator *allocator); + #endif diff --git a/tests/libqos/pci-pc.c b/tests/libqos/pci-pc.c index a4fc02b5d8..4ab16facf2 100644 --- a/tests/libqos/pci-pc.c +++ b/tests/libqos/pci-pc.c @@ -18,15 +18,9 @@ #include "qemu-common.h" - #define ACPI_PCIHP_ADDR 0xae00 #define PCI_EJ_BASE 0x0008 -typedef struct QPCIBusPC -{ - QPCIBus bus; -} QPCIBusPC; - static uint8_t qpci_pc_pio_readb(QPCIBus *bus, uint32_t addr) { return qtest_inb(bus->qts, addr); @@ -116,44 +110,68 @@ static void qpci_pc_config_writel(QPCIBus *bus, int devfn, uint8_t offset, uint3 qtest_outl(bus->qts, 0xcfc, value); } -QPCIBus *qpci_init_pc(QTestState *qts, QGuestAllocator *alloc) +static void *qpci_pc_get_driver(void *obj, const char *interface) { - QPCIBusPC *ret = g_new0(QPCIBusPC, 1); + QPCIBusPC *qpci = obj; + if (!g_strcmp0(interface, "pci-bus")) { + return &qpci->bus; + } + fprintf(stderr, "%s not present in pci-bus-pc\n", interface); + g_assert_not_reached(); +} +void qpci_init_pc(QPCIBusPC *qpci, QTestState *qts, QGuestAllocator *alloc) +{ assert(qts); - ret->bus.pio_readb = qpci_pc_pio_readb; - ret->bus.pio_readw = qpci_pc_pio_readw; - ret->bus.pio_readl = qpci_pc_pio_readl; - ret->bus.pio_readq = qpci_pc_pio_readq; + /* tests can use pci-bus */ + qpci->bus.has_buggy_msi = FALSE; + + qpci->bus.pio_readb = qpci_pc_pio_readb; + qpci->bus.pio_readw = qpci_pc_pio_readw; + qpci->bus.pio_readl = qpci_pc_pio_readl; + qpci->bus.pio_readq = qpci_pc_pio_readq; - ret->bus.pio_writeb = qpci_pc_pio_writeb; - ret->bus.pio_writew = qpci_pc_pio_writew; - ret->bus.pio_writel = qpci_pc_pio_writel; - ret->bus.pio_writeq = qpci_pc_pio_writeq; + qpci->bus.pio_writeb = qpci_pc_pio_writeb; + qpci->bus.pio_writew = qpci_pc_pio_writew; + qpci->bus.pio_writel = qpci_pc_pio_writel; + qpci->bus.pio_writeq = qpci_pc_pio_writeq; - ret->bus.memread = qpci_pc_memread; - ret->bus.memwrite = qpci_pc_memwrite; + qpci->bus.memread = qpci_pc_memread; + qpci->bus.memwrite = qpci_pc_memwrite; - ret->bus.config_readb = qpci_pc_config_readb; - ret->bus.config_readw = qpci_pc_config_readw; - ret->bus.config_readl = qpci_pc_config_readl; + qpci->bus.config_readb = qpci_pc_config_readb; + qpci->bus.config_readw = qpci_pc_config_readw; + qpci->bus.config_readl = qpci_pc_config_readl; - ret->bus.config_writeb = qpci_pc_config_writeb; - ret->bus.config_writew = qpci_pc_config_writew; - ret->bus.config_writel = qpci_pc_config_writel; + qpci->bus.config_writeb = qpci_pc_config_writeb; + qpci->bus.config_writew = qpci_pc_config_writew; + qpci->bus.config_writel = qpci_pc_config_writel; - ret->bus.qts = qts; - ret->bus.pio_alloc_ptr = 0xc000; - ret->bus.mmio_alloc_ptr = 0xE0000000; - ret->bus.mmio_limit = 0x100000000ULL; + qpci->bus.qts = qts; + qpci->bus.pio_alloc_ptr = 0xc000; + qpci->bus.mmio_alloc_ptr = 0xE0000000; + qpci->bus.mmio_limit = 0x100000000ULL; - return &ret->bus; + qpci->obj.get_driver = qpci_pc_get_driver; +} + +QPCIBus *qpci_new_pc(QTestState *qts, QGuestAllocator *alloc) +{ + QPCIBusPC *qpci = g_new0(QPCIBusPC, 1); + qpci_init_pc(qpci, qts, alloc); + + return &qpci->bus; } void qpci_free_pc(QPCIBus *bus) { - QPCIBusPC *s = container_of(bus, QPCIBusPC, bus); + QPCIBusPC *s; + + if (!bus) { + return; + } + s = container_of(bus, QPCIBusPC, bus); g_free(s); } @@ -172,3 +190,11 @@ void qpci_unplug_acpi_device_test(const char *id, uint8_t slot) qmp_eventwait("DEVICE_DELETED"); } + +static void qpci_pc_register_nodes(void) +{ + qos_node_create_driver("pci-bus-pc", NULL); + qos_node_produces("pci-bus-pc", "pci-bus"); +} + +libqos_init(qpci_pc_register_nodes); diff --git a/tests/libqos/pci-pc.h b/tests/libqos/pci-pc.h index 491eeac756..4690005232 100644 --- a/tests/libqos/pci-pc.h +++ b/tests/libqos/pci-pc.h @@ -15,8 +15,35 @@ #include "libqos/pci.h" #include "libqos/malloc.h" +#include "libqos/qgraph.h" + +typedef struct QPCIBusPC { + QOSGraphObject obj; + QPCIBus bus; +} QPCIBusPC; + +/* qpci_init_pc(): + * @ret: A valid QPCIBusPC * pointer + * @qts: The %QTestState for this PC machine + * @alloc: A previously initialized @alloc providing memory for @qts + * + * This function initializes an already allocated + * QPCIBusPC object. + */ +void qpci_init_pc(QPCIBusPC *ret, QTestState *qts, QGuestAllocator *alloc); + +/* qpci_pc_new(): + * @qts: The %QTestState for this PC machine + * @alloc: A previously initialized @alloc providing memory for @qts + * + * This function creates a new QPCIBusPC object, + * and properly initialize its fields. + * + * Returns the QPCIBus *bus field of a newly + * allocated QPCIBusPC. + */ +QPCIBus *qpci_new_pc(QTestState *qts, QGuestAllocator *alloc); -QPCIBus *qpci_init_pc(QTestState *qts, QGuestAllocator *alloc); void qpci_free_pc(QPCIBus *bus); #endif diff --git a/tests/libqos/pci-spapr.c b/tests/libqos/pci-spapr.c index 4c29889b0b..6925925997 100644 --- a/tests/libqos/pci-spapr.c +++ b/tests/libqos/pci-spapr.c @@ -9,33 +9,13 @@ #include "libqtest.h" #include "libqos/pci-spapr.h" #include "libqos/rtas.h" +#include "libqos/qgraph.h" #include "hw/pci/pci_regs.h" #include "qemu-common.h" #include "qemu/host-utils.h" - -/* From include/hw/pci-host/spapr.h */ - -typedef struct QPCIWindow { - uint64_t pci_base; /* window address in PCI space */ - uint64_t size; /* window size */ -} QPCIWindow; - -typedef struct QPCIBusSPAPR { - QPCIBus bus; - QGuestAllocator *alloc; - - uint64_t buid; - - uint64_t pio_cpu_base; - QPCIWindow pio; - - uint64_t mmio32_cpu_base; - QPCIWindow mmio32; -} QPCIBusSPAPR; - /* * PCI devices are always little-endian * SPAPR by default is big-endian @@ -160,60 +140,93 @@ static void qpci_spapr_config_writel(QPCIBus *bus, int devfn, uint8_t offset, #define SPAPR_PCI_MMIO32_WIN_SIZE 0x80000000 /* 2 GiB */ #define SPAPR_PCI_IO_WIN_SIZE 0x10000 -QPCIBus *qpci_init_spapr(QTestState *qts, QGuestAllocator *alloc) +static void *qpci_spapr_get_driver(void *obj, const char *interface) { - QPCIBusSPAPR *ret = g_new0(QPCIBusSPAPR, 1); + QPCIBusSPAPR *qpci = obj; + if (!g_strcmp0(interface, "pci-bus")) { + return &qpci->bus; + } + fprintf(stderr, "%s not present in pci-bus-spapr", interface); + g_assert_not_reached(); +} +void qpci_init_spapr(QPCIBusSPAPR *qpci, QTestState *qts, + QGuestAllocator *alloc) +{ assert(qts); - ret->alloc = alloc; + /* tests cannot use spapr, needs to be fixed first */ + qpci->bus.has_buggy_msi = TRUE; + + qpci->alloc = alloc; - ret->bus.pio_readb = qpci_spapr_pio_readb; - ret->bus.pio_readw = qpci_spapr_pio_readw; - ret->bus.pio_readl = qpci_spapr_pio_readl; - ret->bus.pio_readq = qpci_spapr_pio_readq; + qpci->bus.pio_readb = qpci_spapr_pio_readb; + qpci->bus.pio_readw = qpci_spapr_pio_readw; + qpci->bus.pio_readl = qpci_spapr_pio_readl; + qpci->bus.pio_readq = qpci_spapr_pio_readq; - ret->bus.pio_writeb = qpci_spapr_pio_writeb; - ret->bus.pio_writew = qpci_spapr_pio_writew; - ret->bus.pio_writel = qpci_spapr_pio_writel; - ret->bus.pio_writeq = qpci_spapr_pio_writeq; + qpci->bus.pio_writeb = qpci_spapr_pio_writeb; + qpci->bus.pio_writew = qpci_spapr_pio_writew; + qpci->bus.pio_writel = qpci_spapr_pio_writel; + qpci->bus.pio_writeq = qpci_spapr_pio_writeq; - ret->bus.memread = qpci_spapr_memread; - ret->bus.memwrite = qpci_spapr_memwrite; + qpci->bus.memread = qpci_spapr_memread; + qpci->bus.memwrite = qpci_spapr_memwrite; - ret->bus.config_readb = qpci_spapr_config_readb; - ret->bus.config_readw = qpci_spapr_config_readw; - ret->bus.config_readl = qpci_spapr_config_readl; + qpci->bus.config_readb = qpci_spapr_config_readb; + qpci->bus.config_readw = qpci_spapr_config_readw; + qpci->bus.config_readl = qpci_spapr_config_readl; - ret->bus.config_writeb = qpci_spapr_config_writeb; - ret->bus.config_writew = qpci_spapr_config_writew; - ret->bus.config_writel = qpci_spapr_config_writel; + qpci->bus.config_writeb = qpci_spapr_config_writeb; + qpci->bus.config_writew = qpci_spapr_config_writew; + qpci->bus.config_writel = qpci_spapr_config_writel; /* FIXME: We assume the default location of the PHB for now. * Ideally we'd parse the device tree deposited in the guest to * get the window locations */ - ret->buid = 0x800000020000000ULL; + qpci->buid = 0x800000020000000ULL; - ret->pio_cpu_base = SPAPR_PCI_BASE; - ret->pio.pci_base = 0; - ret->pio.size = SPAPR_PCI_IO_WIN_SIZE; + qpci->pio_cpu_base = SPAPR_PCI_BASE; + qpci->pio.pci_base = 0; + qpci->pio.size = SPAPR_PCI_IO_WIN_SIZE; /* 32-bit portion of the MMIO window is at PCI address 2..4 GiB */ - ret->mmio32_cpu_base = SPAPR_PCI_BASE; - ret->mmio32.pci_base = SPAPR_PCI_MMIO32_WIN_SIZE; - ret->mmio32.size = SPAPR_PCI_MMIO32_WIN_SIZE; + qpci->mmio32_cpu_base = SPAPR_PCI_BASE; + qpci->mmio32.pci_base = SPAPR_PCI_MMIO32_WIN_SIZE; + qpci->mmio32.size = SPAPR_PCI_MMIO32_WIN_SIZE; - ret->bus.qts = qts; - ret->bus.pio_alloc_ptr = 0xc000; - ret->bus.mmio_alloc_ptr = ret->mmio32.pci_base; - ret->bus.mmio_limit = ret->mmio32.pci_base + ret->mmio32.size; + qpci->bus.qts = qts; + qpci->bus.pio_alloc_ptr = 0xc000; + qpci->bus.mmio_alloc_ptr = qpci->mmio32.pci_base; + qpci->bus.mmio_limit = qpci->mmio32.pci_base + qpci->mmio32.size; - return &ret->bus; + qpci->obj.get_driver = qpci_spapr_get_driver; +} + +QPCIBus *qpci_new_spapr(QTestState *qts, QGuestAllocator *alloc) +{ + QPCIBusSPAPR *qpci = g_new0(QPCIBusSPAPR, 1); + qpci_init_spapr(qpci, qts, alloc); + + return &qpci->bus; } void qpci_free_spapr(QPCIBus *bus) { - QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus); + QPCIBusSPAPR *s; + + if (!bus) { + return; + } + s = container_of(bus, QPCIBusSPAPR, bus); g_free(s); } + +static void qpci_spapr_register_nodes(void) +{ + qos_node_create_driver("pci-bus-spapr", NULL); + qos_node_produces("pci-bus-spapr", "pci-bus"); +} + +libqos_init(qpci_spapr_register_nodes); diff --git a/tests/libqos/pci-spapr.h b/tests/libqos/pci-spapr.h index 387686dfc8..d9e25631c6 100644 --- a/tests/libqos/pci-spapr.h +++ b/tests/libqos/pci-spapr.h @@ -10,8 +10,32 @@ #include "libqos/malloc.h" #include "libqos/pci.h" +#include "libqos/qgraph.h" -QPCIBus *qpci_init_spapr(QTestState *qts, QGuestAllocator *alloc); +/* From include/hw/pci-host/spapr.h */ + +typedef struct QPCIWindow { + uint64_t pci_base; /* window address in PCI space */ + uint64_t size; /* window size */ +} QPCIWindow; + +typedef struct QPCIBusSPAPR { + QOSGraphObject obj; + QPCIBus bus; + QGuestAllocator *alloc; + + uint64_t buid; + + uint64_t pio_cpu_base; + QPCIWindow pio; + + uint64_t mmio32_cpu_base; + QPCIWindow mmio32; +} QPCIBusSPAPR; + +void qpci_init_spapr(QPCIBusSPAPR *ret, QTestState *qts, + QGuestAllocator *alloc); +QPCIBus *qpci_new_spapr(QTestState *qts, QGuestAllocator *alloc); void qpci_free_spapr(QPCIBus *bus); #endif diff --git a/tests/libqos/pci.c b/tests/libqos/pci.c index e8c342c257..662ee7a517 100644 --- a/tests/libqos/pci.c +++ b/tests/libqos/pci.c @@ -15,6 +15,7 @@ #include "hw/pci/pci_regs.h" #include "qemu/host-utils.h" +#include "libqos/qgraph.h" void qpci_device_foreach(QPCIBus *bus, int vendor_id, int device_id, void (*func)(QPCIDevice *dev, int devfn, void *data), @@ -50,13 +51,34 @@ void qpci_device_foreach(QPCIBus *bus, int vendor_id, int device_id, } } +bool qpci_has_buggy_msi(QPCIDevice *dev) +{ + return dev->bus->has_buggy_msi; +} + +bool qpci_check_buggy_msi(QPCIDevice *dev) +{ + if (qpci_has_buggy_msi(dev)) { + g_test_skip("Skipping due to incomplete support for MSI"); + return true; + } + return false; +} + +static void qpci_device_set(QPCIDevice *dev, QPCIBus *bus, int devfn) +{ + g_assert(dev); + + dev->bus = bus; + dev->devfn = devfn; +} + QPCIDevice *qpci_device_find(QPCIBus *bus, int devfn) { QPCIDevice *dev; dev = g_malloc0(sizeof(*dev)); - dev->bus = bus; - dev->devfn = devfn; + qpci_device_set(dev, bus, devfn); if (qpci_config_readw(dev, PCI_VENDOR_ID) == 0xFFFF) { g_free(dev); @@ -66,6 +88,17 @@ QPCIDevice *qpci_device_find(QPCIBus *bus, int devfn) return dev; } +void qpci_device_init(QPCIDevice *dev, QPCIBus *bus, QPCIAddress *addr) +{ + uint16_t vendor_id, device_id; + + qpci_device_set(dev, bus, addr->devfn); + vendor_id = qpci_config_readw(dev, PCI_VENDOR_ID); + device_id = qpci_config_readw(dev, PCI_DEVICE_ID); + g_assert(!addr->vendor_id || vendor_id == addr->vendor_id); + g_assert(!addr->device_id || device_id == addr->device_id); +} + void qpci_device_enable(QPCIDevice *dev) { uint16_t cmd; @@ -395,3 +428,12 @@ QPCIBar qpci_legacy_iomap(QPCIDevice *dev, uint16_t addr) QPCIBar bar = { .addr = addr }; return bar; } + +void add_qpci_address(QOSGraphEdgeOptions *opts, QPCIAddress *addr) +{ + g_assert(addr); + g_assert(opts); + + opts->arg = addr; + opts->size_arg = sizeof(QPCIAddress); +} diff --git a/tests/libqos/pci.h b/tests/libqos/pci.h index 0b7e936174..8e1d292a7d 100644 --- a/tests/libqos/pci.h +++ b/tests/libqos/pci.h @@ -14,6 +14,7 @@ #define LIBQOS_PCI_H #include "libqtest.h" +#include "libqos/qgraph.h" #define QPCI_PIO_LIMIT 0x10000 @@ -22,6 +23,7 @@ typedef struct QPCIDevice QPCIDevice; typedef struct QPCIBus QPCIBus; typedef struct QPCIBar QPCIBar; +typedef struct QPCIAddress QPCIAddress; struct QPCIBus { uint8_t (*pio_readb)(QPCIBus *bus, uint32_t addr); @@ -51,6 +53,8 @@ struct QPCIBus { QTestState *qts; uint16_t pio_alloc_ptr; uint64_t mmio_alloc_ptr, mmio_limit; + bool has_buggy_msi; /* TRUE for spapr, FALSE for pci */ + }; struct QPCIBar { @@ -66,10 +70,20 @@ struct QPCIDevice uint64_t msix_table_off, msix_pba_off; }; +struct QPCIAddress { + uint32_t devfn; + uint16_t vendor_id; + uint16_t device_id; +}; + void qpci_device_foreach(QPCIBus *bus, int vendor_id, int device_id, void (*func)(QPCIDevice *dev, int devfn, void *data), void *data); QPCIDevice *qpci_device_find(QPCIBus *bus, int devfn); +void qpci_device_init(QPCIDevice *dev, QPCIBus *bus, QPCIAddress *addr); + +bool qpci_has_buggy_msi(QPCIDevice *dev); +bool qpci_check_buggy_msi(QPCIDevice *dev); void qpci_device_enable(QPCIDevice *dev); uint8_t qpci_find_capability(QPCIDevice *dev, uint8_t id); @@ -110,4 +124,6 @@ void qpci_iounmap(QPCIDevice *dev, QPCIBar addr); QPCIBar qpci_legacy_iomap(QPCIDevice *dev, uint16_t addr); void qpci_unplug_acpi_device_test(const char *id, uint8_t slot); + +void add_qpci_address(QOSGraphEdgeOptions *opts, QPCIAddress *addr); #endif diff --git a/tests/libqos/ppc64_pseries-machine.c b/tests/libqos/ppc64_pseries-machine.c new file mode 100644 index 0000000000..2f3640010d --- /dev/null +++ b/tests/libqos/ppc64_pseries-machine.c @@ -0,0 +1,111 @@ +/* + * libqos driver framework + * + * Copyright (c) 2018 Emanuele Giuseppe Esposito <e.emanuelegiuseppe@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/> + */ + + #include "qemu/osdep.h" +#include "libqtest.h" +#include "libqos/qgraph.h" +#include "pci-spapr.h" +#include "libqos/malloc-spapr.h" + +typedef struct QSPAPR_pci_host QSPAPR_pci_host; +typedef struct Qppc64_pseriesMachine Qppc64_pseriesMachine; + +struct QSPAPR_pci_host { + QOSGraphObject obj; + QPCIBusSPAPR pci; +}; + +struct Qppc64_pseriesMachine { + QOSGraphObject obj; + QGuestAllocator alloc; + QSPAPR_pci_host bridge; +}; + +/* QSPAPR_pci_host */ + +static QOSGraphObject *QSPAPR_host_get_device(void *obj, const char *device) +{ + QSPAPR_pci_host *host = obj; + if (!g_strcmp0(device, "pci-bus-spapr")) { + return &host->pci.obj; + } + fprintf(stderr, "%s not present in QSPAPR_pci_host\n", device); + g_assert_not_reached(); +} + +static void qos_create_QSPAPR_host(QSPAPR_pci_host *host, + QTestState *qts, + QGuestAllocator *alloc) +{ + host->obj.get_device = QSPAPR_host_get_device; + qpci_init_spapr(&host->pci, qts, alloc); +} + +/* ppc64/pseries machine */ + +static void spapr_destructor(QOSGraphObject *obj) +{ + Qppc64_pseriesMachine *machine = (Qppc64_pseriesMachine *) obj; + alloc_destroy(&machine->alloc); +} + +static void *spapr_get_driver(void *object, const char *interface) +{ + Qppc64_pseriesMachine *machine = object; + if (!g_strcmp0(interface, "memory")) { + return &machine->alloc; + } + + fprintf(stderr, "%s not present in ppc64/pseries\n", interface); + g_assert_not_reached(); +} + +static QOSGraphObject *spapr_get_device(void *obj, const char *device) +{ + Qppc64_pseriesMachine *machine = obj; + if (!g_strcmp0(device, "spapr-pci-host-bridge")) { + return &machine->bridge.obj; + } + + fprintf(stderr, "%s not present in ppc64/pseries\n", device); + g_assert_not_reached(); +} + +static void *qos_create_machine_spapr(QTestState *qts) +{ + Qppc64_pseriesMachine *machine = g_new0(Qppc64_pseriesMachine, 1); + machine->obj.get_device = spapr_get_device; + machine->obj.get_driver = spapr_get_driver; + machine->obj.destructor = spapr_destructor; + spapr_alloc_init(&machine->alloc, qts, ALLOC_NO_FLAGS); + + qos_create_QSPAPR_host(&machine->bridge, qts, &machine->alloc); + + return &machine->obj; +} + +static void spapr_machine_register_nodes(void) +{ + qos_node_create_machine("ppc64/pseries", qos_create_machine_spapr); + qos_node_create_driver("spapr-pci-host-bridge", NULL); + qos_node_contains("ppc64/pseries", "spapr-pci-host-bridge", NULL); + qos_node_contains("spapr-pci-host-bridge", "pci-bus-spapr", NULL); +} + +libqos_init(spapr_machine_register_nodes); + diff --git a/tests/libqos/qgraph.c b/tests/libqos/qgraph.c new file mode 100644 index 0000000000..122efc1b7b --- /dev/null +++ b/tests/libqos/qgraph.c @@ -0,0 +1,753 @@ +/* + * libqos driver framework + * + * Copyright (c) 2018 Emanuele Giuseppe Esposito <e.emanuelegiuseppe@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/> + */ + +#include "qemu/osdep.h" +#include "libqtest.h" +#include "qemu/queue.h" +#include "libqos/qgraph_internal.h" +#include "libqos/qgraph.h" + +#define QGRAPH_PRINT_DEBUG 0 +#define QOS_ROOT "" +typedef struct QOSStackElement QOSStackElement; + +/* Graph Edge.*/ +struct QOSGraphEdge { + QOSEdgeType type; + char *dest; + void *arg; /* just for QEDGE_CONTAINS + * and QEDGE_CONSUMED_BY */ + char *extra_device_opts; /* added to -device option, "," is + * automatically added + */ + char *before_cmd_line; /* added before node cmd_line */ + char *after_cmd_line; /* added after -device options */ + char *edge_name; /* used by QEDGE_CONTAINS */ + QSLIST_ENTRY(QOSGraphEdge) edge_list; +}; + +typedef QSLIST_HEAD(, QOSGraphEdge) QOSGraphEdgeList; + +/** + * Stack used to keep track of the discovered path when using + * the DFS algorithm + */ +struct QOSStackElement { + QOSGraphNode *node; + QOSStackElement *parent; + QOSGraphEdge *parent_edge; + int length; +}; + +/* Each enty in these hash table will consist of <string, node/edge> pair. */ +static GHashTable *edge_table; +static GHashTable *node_table; + +/* stack used by the DFS algorithm to store the path from machine to test */ +static QOSStackElement qos_node_stack[QOS_PATH_MAX_ELEMENT_SIZE]; +static int qos_node_tos; + +/** + * add_edge(): creates an edge of type @type + * from @source to @dest node, and inserts it in the + * edges hash table + * + * Nodes @source and @dest do not necessarily need to exist. + * Possibility to add also options (see #QOSGraphEdgeOptions) + * edge->edge_name is used as identifier for get_device relationships, + * so by default is equal to @dest. + */ +static void add_edge(const char *source, const char *dest, + QOSEdgeType type, QOSGraphEdgeOptions *opts) +{ + char *key; + QOSGraphEdgeList *list = g_hash_table_lookup(edge_table, source); + + if (!list) { + list = g_new0(QOSGraphEdgeList, 1); + key = g_strdup(source); + g_hash_table_insert(edge_table, key, list); + } + + if (!opts) { + opts = &(QOSGraphEdgeOptions) { }; + } + + QOSGraphEdge *edge = g_new0(QOSGraphEdge, 1); + edge->type = type; + edge->dest = g_strdup(dest); + edge->edge_name = g_strdup(opts->edge_name ?: dest); + edge->arg = g_memdup(opts->arg, opts->size_arg); + + edge->before_cmd_line = + opts->before_cmd_line ? g_strconcat(" ", opts->before_cmd_line, NULL) : NULL; + edge->extra_device_opts = + opts->extra_device_opts ? g_strconcat(",", opts->extra_device_opts, NULL) : NULL; + edge->after_cmd_line = + opts->after_cmd_line ? g_strconcat(" ", opts->after_cmd_line, NULL) : NULL; + + QSLIST_INSERT_HEAD(list, edge, edge_list); +} + +/* destroy_edges(): frees all edges inside a given @list */ +static void destroy_edges(void *list) +{ + QOSGraphEdge *temp; + QOSGraphEdgeList *elist = list; + + while (!QSLIST_EMPTY(elist)) { + temp = QSLIST_FIRST(elist); + QSLIST_REMOVE_HEAD(elist, edge_list); + g_free(temp->dest); + g_free(temp->before_cmd_line); + g_free(temp->after_cmd_line); + g_free(temp->extra_device_opts); + g_free(temp->edge_name); + g_free(temp->arg); + g_free(temp); + } + g_free(elist); +} + +/** + * create_node(): creates a node @name of type @type + * and inserts it to the nodes hash table. + * By default, node is not available. + */ +static QOSGraphNode *create_node(const char *name, QOSNodeType type) +{ + if (g_hash_table_lookup(node_table, name)) { + g_printerr("Node %s already created\n", name); + abort(); + } + + QOSGraphNode *node = g_new0(QOSGraphNode, 1); + node->type = type; + node->available = false; + node->name = g_strdup(name); + g_hash_table_insert(node_table, node->name, node); + return node; +} + +/** + * destroy_node(): frees a node @val from the nodes hash table. + * Note that node->name is not free'd since it will represent the + * hash table key + */ +static void destroy_node(void *val) +{ + QOSGraphNode *node = val; + g_free(node->command_line); + g_free(node); +} + +/** + * destroy_string(): frees @key from the nodes hash table. + * Actually frees the node->name + */ +static void destroy_string(void *key) +{ + g_free(key); +} + +/** + * search_node(): search for a node @key in the nodes hash table + * Returns the QOSGraphNode if found, #NULL otherwise + */ +static QOSGraphNode *search_node(const char *key) +{ + return g_hash_table_lookup(node_table, key); +} + +/** + * get_edgelist(): returns the edge list (value) assigned to + * the @key in the edge hash table. + * This list will contain all edges with source equal to @key + * + * Returns: on success: the %QOSGraphEdgeList + * otherwise: abort() + */ +static QOSGraphEdgeList *get_edgelist(const char *key) +{ + return g_hash_table_lookup(edge_table, key); +} + +/** + * search_list_edges(): search for an edge with destination @dest + * in the given @edgelist. + * + * Returns: on success: the %QOSGraphEdge + * otherwise: #NULL + */ +static QOSGraphEdge *search_list_edges(QOSGraphEdgeList *edgelist, + const char *dest) +{ + QOSGraphEdge *tmp, *next; + if (!edgelist) { + return NULL; + } + QSLIST_FOREACH_SAFE(tmp, edgelist, edge_list, next) { + if (g_strcmp0(tmp->dest, dest) == 0) { + break; + } + } + return tmp; +} + +/** + * search_machine(): search for a machine @name in the node hash + * table. A machine is the child of the root node. + * This function forces the research in the childs of the root, + * to check the node is a proper machine + * + * Returns: on success: the %QOSGraphNode + * otherwise: #NULL + */ +static QOSGraphNode *search_machine(const char *name) +{ + QOSGraphNode *n; + QOSGraphEdgeList *root_list = get_edgelist(QOS_ROOT); + QOSGraphEdge *e = search_list_edges(root_list, name); + if (!e) { + return NULL; + } + n = search_node(e->dest); + if (n->type == QNODE_MACHINE) { + return n; + } + return NULL; +} + +/** + * create_interface(): checks if there is already + * a node @node in the node hash table, if not + * creates a node @node of type #QNODE_INTERFACE + * and inserts it. If there is one, check it's + * a #QNODE_INTERFACE and abort() if it's not. + */ +static void create_interface(const char *node) +{ + QOSGraphNode *interface; + interface = search_node(node); + if (!interface) { + create_node(node, QNODE_INTERFACE); + } else if (interface->type != QNODE_INTERFACE) { + fprintf(stderr, "Error: Node %s is not an interface\n", node); + abort(); + } +} + +/** + * build_machine_cmd_line(): builds the command line for the machine + * @node. The node name must be a valid qemu identifier, since it + * will be used to build the command line. + * + * It is also possible to pass an optional @args that will be + * concatenated to the command line. + * + * For machines, prepend -M to the machine name. ", @rgs" is added + * after the -M <machine> command. + */ +static void build_machine_cmd_line(QOSGraphNode *node, const char *args) +{ + char *machine = qos_get_machine_type(node->name); + if (args) { + node->command_line = g_strconcat("-M ", machine, ",", args, NULL); + } else { + node->command_line = g_strconcat("-M ", machine, " ", NULL); + } +} + +/** + * build_driver_cmd_line(): builds the command line for the driver + * @node. The node name must be a valid qemu identifier, since it + * will be used to build the command line. + * + * Driver do not need additional command line, since it will be + * provided by the edge options. + * + * For drivers, prepend -device to the node name. + */ +static void build_driver_cmd_line(QOSGraphNode *node) +{ + node->command_line = g_strconcat(" -device ", node->name, NULL); +} + +/* qos_print_cb(): callback prints all path found by the DFS algorithm. */ +static void qos_print_cb(QOSGraphNode *path, int length) +{ + #if QGRAPH_PRINT_DEBUG + printf("%d elements\n", length); + + if (!path) { + return; + } + + while (path->path_edge) { + printf("%s ", path->name); + switch (path->path_edge->type) { + case QEDGE_PRODUCES: + printf("--PRODUCES--> "); + break; + case QEDGE_CONSUMED_BY: + printf("--CONSUMED_BY--> "); + break; + case QEDGE_CONTAINS: + printf("--CONTAINS--> "); + break; + } + path = search_node(path->path_edge->dest); + } + + printf("%s\n\n", path->name); + #endif +} + +/* qos_push(): push a node @el and edge @e in the qos_node_stack */ +static void qos_push(QOSGraphNode *el, QOSStackElement *parent, + QOSGraphEdge *e) +{ + int len = 0; /* root is not counted */ + if (qos_node_tos == QOS_PATH_MAX_ELEMENT_SIZE) { + g_printerr("QOSStack: full stack, cannot push"); + abort(); + } + + if (parent) { + len = parent->length + 1; + } + qos_node_stack[qos_node_tos++] = (QOSStackElement) { + .node = el, + .parent = parent, + .parent_edge = e, + .length = len, + }; +} + +/* qos_tos(): returns the top of stack, without popping */ +static QOSStackElement *qos_tos(void) +{ + return &qos_node_stack[qos_node_tos - 1]; +} + +/* qos_pop(): pops an element from the tos, setting it unvisited*/ +static QOSStackElement *qos_pop(void) +{ + if (qos_node_tos == 0) { + g_printerr("QOSStack: empty stack, cannot pop"); + abort(); + } + QOSStackElement *e = qos_tos(); + e->node->visited = false; + qos_node_tos--; + return e; +} + +/** + * qos_reverse_path(): reverses the found path, going from + * test-to-machine to machine-to-test + */ +static QOSGraphNode *qos_reverse_path(QOSStackElement *el) +{ + if (!el) { + return NULL; + } + + el->node->path_edge = NULL; + + while (el->parent) { + el->parent->node->path_edge = el->parent_edge; + el = el->parent; + } + + return el->node; +} + +/** + * qos_traverse_graph(): graph-walking algorithm, using Depth First Search it + * starts from the root @machine and walks all possible path until it + * reaches a test node. + * At that point, it reverses the path found and invokes the @callback. + * + * Being Depth First Search, time complexity is O(|V| + |E|), while + * space is O(|V|). In this case, the maximum stack size is set by + * QOS_PATH_MAX_ELEMENT_SIZE. + */ +static void qos_traverse_graph(QOSGraphNode *root, QOSTestCallback callback) +{ + QOSGraphNode *v, *dest_node, *path; + QOSStackElement *s_el; + QOSGraphEdge *e, *next; + QOSGraphEdgeList *list; + + qos_push(root, NULL, NULL); + + while (qos_node_tos > 0) { + s_el = qos_tos(); + v = s_el->node; + if (v->visited) { + qos_pop(); + continue; + } + v->visited = true; + list = get_edgelist(v->name); + if (!list) { + qos_pop(); + if (v->type == QNODE_TEST) { + v->visited = false; + path = qos_reverse_path(s_el); + callback(path, s_el->length); + } + } else { + QSLIST_FOREACH_SAFE(e, list, edge_list, next) { + dest_node = search_node(e->dest); + + if (!dest_node) { + fprintf(stderr, "node %s in %s -> %s does not exist\n", + e->dest, v->name, e->dest); + abort(); + } + + if (!dest_node->visited && dest_node->available) { + qos_push(dest_node, s_el, e); + } + } + } + } +} + +/* QGRAPH API*/ + +QOSGraphNode *qos_graph_get_node(const char *key) +{ + return search_node(key); +} + +bool qos_graph_has_node(const char *node) +{ + QOSGraphNode *n = search_node(node); + return n != NULL; +} + +QOSNodeType qos_graph_get_node_type(const char *node) +{ + QOSGraphNode *n = search_node(node); + if (n) { + return n->type; + } + return -1; +} + +bool qos_graph_get_node_availability(const char *node) +{ + QOSGraphNode *n = search_node(node); + if (n) { + return n->available; + } + return false; +} + +QOSGraphEdge *qos_graph_get_edge(const char *node, const char *dest) +{ + QOSGraphEdgeList *list = get_edgelist(node); + return search_list_edges(list, dest); +} + +QOSEdgeType qos_graph_edge_get_type(QOSGraphEdge *edge) +{ + if (!edge) { + return -1; + } + return edge->type;; +} + +char *qos_graph_edge_get_dest(QOSGraphEdge *edge) +{ + if (!edge) { + return NULL; + } + return edge->dest; +} + +void *qos_graph_edge_get_arg(QOSGraphEdge *edge) +{ + if (!edge) { + return NULL; + } + return edge->arg; +} + +char *qos_graph_edge_get_after_cmd_line(QOSGraphEdge *edge) +{ + if (!edge) { + return NULL; + } + return edge->after_cmd_line; +} + +char *qos_graph_edge_get_before_cmd_line(QOSGraphEdge *edge) +{ + if (!edge) { + return NULL; + } + return edge->before_cmd_line; +} + +char *qos_graph_edge_get_extra_device_opts(QOSGraphEdge *edge) +{ + if (!edge) { + return NULL; + } + return edge->extra_device_opts; +} + +char *qos_graph_edge_get_name(QOSGraphEdge *edge) +{ + if (!edge) { + return NULL; + } + return edge->edge_name; +} + +bool qos_graph_has_edge(const char *start, const char *dest) +{ + QOSGraphEdgeList *list = get_edgelist(start); + QOSGraphEdge *e = search_list_edges(list, dest); + return e != NULL; +} + +QOSGraphNode *qos_graph_get_machine(const char *node) +{ + return search_machine(node); +} + +bool qos_graph_has_machine(const char *node) +{ + QOSGraphNode *m = search_machine(node); + return m != NULL; +} + +void qos_print_graph(void) +{ + qos_graph_foreach_test_path(qos_print_cb); +} + +void qos_graph_init(void) +{ + if (!node_table) { + node_table = g_hash_table_new_full(g_str_hash, g_str_equal, + destroy_string, destroy_node); + create_node(QOS_ROOT, QNODE_DRIVER); + } + + if (!edge_table) { + edge_table = g_hash_table_new_full(g_str_hash, g_str_equal, + destroy_string, destroy_edges); + } +} + +void qos_graph_destroy(void) +{ + if (node_table) { + g_hash_table_destroy(node_table); + } + + if (edge_table) { + g_hash_table_destroy(edge_table); + } + + node_table = NULL; + edge_table = NULL; +} + +void qos_node_destroy(void *key) +{ + g_hash_table_remove(node_table, key); +} + +void qos_edge_destroy(void *key) +{ + g_hash_table_remove(edge_table, key); +} + +void qos_add_test(const char *name, const char *interface, + QOSTestFunc test_func, QOSGraphTestOptions *opts) +{ + QOSGraphNode *node; + char *test_name = g_strdup_printf("%s-tests/%s", interface, name);; + + if (!opts) { + opts = &(QOSGraphTestOptions) { }; + } + node = create_node(test_name, QNODE_TEST); + node->u.test.function = test_func; + node->u.test.arg = opts->arg; + assert(!opts->edge.arg); + assert(!opts->edge.size_arg); + + node->u.test.before = opts->before; + node->u.test.subprocess = opts->subprocess; + node->available = true; + add_edge(interface, test_name, QEDGE_CONSUMED_BY, &opts->edge); + g_free(test_name); +} + +void qos_node_create_machine(const char *name, QOSCreateMachineFunc function) +{ + qos_node_create_machine_args(name, function, NULL); +} + +void qos_node_create_machine_args(const char *name, + QOSCreateMachineFunc function, + const char *opts) +{ + QOSGraphNode *node = create_node(name, QNODE_MACHINE); + build_machine_cmd_line(node, opts); + node->u.machine.constructor = function; + add_edge(QOS_ROOT, name, QEDGE_CONTAINS, NULL); +} + +void qos_node_create_driver(const char *name, QOSCreateDriverFunc function) +{ + QOSGraphNode *node = create_node(name, QNODE_DRIVER); + build_driver_cmd_line(node); + node->u.driver.constructor = function; +} + +void qos_node_contains(const char *container, const char *contained, + ...) +{ + va_list va; + va_start(va, contained); + QOSGraphEdgeOptions *opts; + + do { + opts = va_arg(va, QOSGraphEdgeOptions *); + add_edge(container, contained, QEDGE_CONTAINS, opts); + } while (opts != NULL); + + va_end(va); +} + +void qos_node_produces(const char *producer, const char *interface) +{ + create_interface(interface); + add_edge(producer, interface, QEDGE_PRODUCES, NULL); +} + +void qos_node_consumes(const char *consumer, const char *interface, + QOSGraphEdgeOptions *opts) +{ + create_interface(interface); + add_edge(interface, consumer, QEDGE_CONSUMED_BY, opts); +} + +void qos_graph_node_set_availability(const char *node, bool av) +{ + QOSGraphEdgeList *elist; + QOSGraphNode *n = search_node(node); + QOSGraphEdge *e, *next; + if (!n) { + return; + } + n->available = av; + elist = get_edgelist(node); + if (!elist) { + return; + } + QSLIST_FOREACH_SAFE(e, elist, edge_list, next) { + if (e->type == QEDGE_CONTAINS || e->type == QEDGE_PRODUCES) { + qos_graph_node_set_availability(e->dest, av); + } + } +} + +void qos_graph_foreach_test_path(QOSTestCallback fn) +{ + QOSGraphNode *root = qos_graph_get_node(QOS_ROOT); + qos_traverse_graph(root, fn); +} + +QOSGraphObject *qos_machine_new(QOSGraphNode *node, QTestState *qts) +{ + QOSGraphObject *obj; + + g_assert(node->type == QNODE_MACHINE); + obj = node->u.machine.constructor(qts); + obj->free = g_free; + return obj; +} + +QOSGraphObject *qos_driver_new(QOSGraphNode *node, QOSGraphObject *parent, + QGuestAllocator *alloc, void *arg) +{ + QOSGraphObject *obj; + + g_assert(node->type == QNODE_DRIVER); + obj = node->u.driver.constructor(parent, alloc, arg); + obj->free = g_free; + return obj; +} + +void qos_object_destroy(QOSGraphObject *obj) +{ + if (!obj) { + return; + } + if (obj->destructor) { + obj->destructor(obj); + } + if (obj->free) { + obj->free(obj); + } +} + +void qos_object_queue_destroy(QOSGraphObject *obj) +{ + g_test_queue_destroy((GDestroyNotify) qos_object_destroy, obj); +} + +void qos_object_start_hw(QOSGraphObject *obj) +{ + if (obj->start_hw) { + obj->start_hw(obj); + } +} + +char *qos_get_machine_type(char *name) +{ + while (*name != '\0' && *name != '/') { + name++; + } + + if (!*name || !name[1]) { + fprintf(stderr, "Machine name has to be of the form <arch>/<machine>\n"); + abort(); + } + + return name + 1; +} + +void qos_delete_cmd_line(const char *name) +{ + QOSGraphNode *node = search_node(name); + if (node) { + g_free(node->command_line); + node->command_line = NULL; + } +} diff --git a/tests/libqos/qgraph.h b/tests/libqos/qgraph.h new file mode 100644 index 0000000000..ef0c73837a --- /dev/null +++ b/tests/libqos/qgraph.h @@ -0,0 +1,575 @@ +/* + * libqos driver framework + * + * Copyright (c) 2018 Emanuele Giuseppe Esposito <e.emanuelegiuseppe@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/> + */ + +#ifndef QGRAPH_H +#define QGRAPH_H + +#include <stdio.h> +#include <stdlib.h> +#include <stdbool.h> +#include <gmodule.h> +#include <glib.h> +#include "qemu/module.h" +#include "malloc.h" + +/* maximum path length */ +#define QOS_PATH_MAX_ELEMENT_SIZE 50 + +typedef struct QOSGraphObject QOSGraphObject; +typedef struct QOSGraphNode QOSGraphNode; +typedef struct QOSGraphEdge QOSGraphEdge; +typedef struct QOSGraphNodeOptions QOSGraphNodeOptions; +typedef struct QOSGraphEdgeOptions QOSGraphEdgeOptions; +typedef struct QOSGraphTestOptions QOSGraphTestOptions; + +/* Constructor for drivers, machines and test */ +typedef void *(*QOSCreateDriverFunc) (void *parent, QGuestAllocator *alloc, + void *addr); +typedef void *(*QOSCreateMachineFunc) (QTestState *qts); +typedef void (*QOSTestFunc) (void *parent, void *arg, QGuestAllocator *alloc); + +/* QOSGraphObject functions */ +typedef void *(*QOSGetDriver) (void *object, const char *interface); +typedef QOSGraphObject *(*QOSGetDevice) (void *object, const char *name); +typedef void (*QOSDestructorFunc) (QOSGraphObject *object); +typedef void (*QOSStartFunct) (QOSGraphObject *object); + +/* Test options functions */ +typedef void *(*QOSBeforeTest) (GString *cmd_line, void *arg); + +/** + * SECTION: qgraph.h + * @title: Qtest Driver Framework + * @short_description: interfaces to organize drivers and tests + * as nodes in a graph + * + * This Qgraph API provides all basic functions to create a graph + * and instantiate nodes representing machines, drivers and tests + * representing their relations with CONSUMES, PRODUCES, and CONTAINS + * edges. + * + * The idea is to have a framework where each test asks for a specific + * driver, and the framework takes care of allocating the proper devices + * required and passing the correct command line arguments to QEMU. + * + * A node can be of four types: + * - QNODE_MACHINE: for example "arm/raspi2" + * - QNODE_DRIVER: for example "generic-sdhci" + * - QNODE_INTERFACE: for example "sdhci" (interface for all "-sdhci" drivers) + * an interface is not explicitly created, it will be auto- + * matically instantiated when a node consumes or produces + * it. + * - QNODE_TEST: for example "sdhci-test", consumes an interface and tests + * the functions provided + * + * Notes for the nodes: + * - QNODE_MACHINE: each machine struct must have a QGuestAllocator and + * implement get_driver to return the allocator passing + * "memory". The function can also return NULL if the + * allocator is not set. + * - QNODE_DRIVER: driver names must be unique, and machines and nodes + * planned to be "consumed" by other nodes must match QEMU + * drivers name, otherwise they won't be discovered + * + * An edge relation between two nodes (drivers or machines) X and Y can be: + * - X CONSUMES Y: Y can be plugged into X + * - X PRODUCES Y: X provides the interface Y + * - X CONTAINS Y: Y is part of X component + * + * Basic framework steps are the following: + * - All nodes and edges are created in their respective + * machine/driver/test files + * - The framework starts QEMU and asks for a list of available devices + * and machines (note that only machines and "consumed" nodes are mapped + * 1:1 with QEMU devices) + * - The framework walks the graph starting from the available machines and + * performs a Depth First Search for tests + * - Once a test is found, the path is walked again and all drivers are + * allocated accordingly and the final interface is passed to the test + * - The test is executed + * - Unused objects are cleaned and the path discovery is continued + * + * Depending on the QEMU binary used, only some drivers/machines will be + * available and only test that are reached by them will be executed. + * + * <example> + * <title>Creating new driver an its interface</title> + * <programlisting> + #include "libqos/qgraph.h" + + struct My_driver { + QOSGraphObject obj; + Node_produced prod; + Node_contained cont; + } + + static void my_destructor(QOSGraphObject *obj) + { + g_free(obj); + } + + static void my_get_driver(void *object, const char *interface) { + My_driver *dev = object; + if (!g_strcmp0(interface, "my_interface")) { + return &dev->prod; + } + abort(); + } + + static void my_get_device(void *object, const char *device) { + My_driver *dev = object; + if (!g_strcmp0(device, "my_driver_contained")) { + return &dev->cont; + } + abort(); + } + + static void *my_driver_constructor(void *node_consumed, + QOSGraphObject *alloc) + { + My_driver dev = g_new(My_driver, 1); + // get the node pointed by the produce edge + dev->obj.get_driver = my_get_driver; + // get the node pointed by the contains + dev->obj.get_device = my_get_device; + // free the object + dev->obj.destructor = my_destructor; + do_something_with_node_consumed(node_consumed); + // set all fields of contained device + init_contained_device(&dev->cont); + return &dev->obj; + } + + static void register_my_driver(void) + { + qos_node_create_driver("my_driver", my_driver_constructor); + // contained drivers don't need a constructor, + // they will be init by the parent. + qos_node_create_driver("my_driver_contained", NULL); + + // For the sake of this example, assume machine x86_64/pc contains + // "other_node". + // This relation, along with the machine and "other_node" creation, + // should be defined in the x86_64_pc-machine.c file. + // "my_driver" will then consume "other_node" + qos_node_contains("my_driver", "my_driver_contained"); + qos_node_produces("my_driver", "my_interface"); + qos_node_consumes("my_driver", "other_node"); + } + * </programlisting> + * </example> + * + * In the above example, all possible types of relations are created: + * node "my_driver" consumes, contains and produces other nodes. + * more specifically: + * x86_64/pc -->contains--> other_node <--consumes-- my_driver + * | + * my_driver_contained <--contains--+ + * | + * my_interface <--produces--+ + * + * or inverting the consumes edge in consumed_by: + * + * x86_64/pc -->contains--> other_node --consumed_by--> my_driver + * | + * my_driver_contained <--contains--+ + * | + * my_interface <--produces--+ + * + * <example> + * <title>Creating new test</title> + * <programlisting> + * #include "libqos/qgraph.h" + * + * static void my_test_function(void *obj, void *data) + * { + * Node_produced *interface_to_test = obj; + * // test interface_to_test + * } + * + * static void register_my_test(void) + * { + * qos_add_test("my_interface", "my_test", my_test_function); + * } + * + * libqos_init(register_my_test); + * + * </programlisting> + * </example> + * + * Here a new test is created, consuming "my_interface" node + * and creating a valid path from a machine to a test. + * Final graph will be like this: + * x86_64/pc -->contains--> other_node <--consumes-- my_driver + * | + * my_driver_contained <--contains--+ + * | + * my_test --consumes--> my_interface <--produces--+ + * + * or inverting the consumes edge in consumed_by: + * + * x86_64/pc -->contains--> other_node --consumed_by--> my_driver + * | + * my_driver_contained <--contains--+ + * | + * my_test <--consumed_by-- my_interface <--produces--+ + * + * Assuming there the binary is + * QTEST_QEMU_BINARY=x86_64-softmmu/qemu-system-x86_64 + * a valid test path will be: + * "/x86_64/pc/other_node/my_driver/my_interface/my_test". + * + * Additional examples are also in libqos/test-qgraph.c + * + * Command line: + * Command line is built by using node names and optional arguments + * passed by the user when building the edges. + * + * There are three types of command line arguments: + * - in node : created from the node name. For example, machines will + * have "-M <machine>" to its command line, while devices + * "-device <device>". It is automatically done by the + * framework. + * - after node : added as additional argument to the node name. + * This argument is added optionally when creating edges, + * by setting the parameter @after_cmd_line and + * @extra_edge_opts in #QOSGraphEdgeOptions. + * The framework automatically adds + * a comma before @extra_edge_opts, + * because it is going to add attributes + * after the destination node pointed by + * the edge containing these options, and automatically + * adds a space before @after_cmd_line, because it + * adds an additional device, not an attribute. + * - before node : added as additional argument to the node name. + * This argument is added optionally when creating edges, + * by setting the parameter @before_cmd_line in + * #QOSGraphEdgeOptions. This attribute + * is going to add attributes before the destination node + * pointed by the edge containing these options. It is + * helpful to commands that are not node-representable, + * such as "-fdsev" or "-netdev". + * + * While adding command line in edges is always used, not all nodes names are + * used in every path walk: this is because the contained or produced ones + * are already added by QEMU, so only nodes that "consumes" will be used to + * build the command line. Also, nodes that will have { "abstract" : true } + * as QMP attribute will loose their command line, since they are not proper + * devices to be added in QEMU. + * + * Example: + * + QOSGraphEdgeOptions opts = { + .arg = NULL, + .size_arg = 0, + .after_cmd_line = "-device other", + .before_cmd_line = "-netdev something", + .extra_edge_opts = "addr=04.0", + }; + QOSGraphNode * node = qos_node_create_driver("my_node", constructor); + qos_node_consumes_args("my_node", "interface", &opts); + * + * Will produce the following command line: + * "-netdev something -device my_node,addr=04.0 -device other" + */ + +/** + * Edge options to be passed to the contains/consumes *_args function. + */ +struct QOSGraphEdgeOptions { + void *arg; /* + * optional arg that will be used by + * dest edge + */ + uint32_t size_arg; /* + * optional arg size that will be used by + * dest edge + */ + const char *extra_device_opts;/* + *optional additional command line for dest + * edge, used to add additional attributes + * *after* the node command line, the + * framework automatically prepends "," + * to this argument. + */ + const char *before_cmd_line; /* + * optional additional command line for dest + * edge, used to add additional attributes + * *before* the node command line, usually + * other non-node represented commands, + * like "-fdsev synt" + */ + const char *after_cmd_line; /* + * optional extra command line to be added + * after the device command. This option + * is used to add other devices + * command line that depend on current node. + * Automatically prepends " " to this + * argument + */ + const char *edge_name; /* + * optional edge to differentiate multiple + * devices with same node name + */ +}; + +/** + * Test options to be passed to the test functions. + */ +struct QOSGraphTestOptions { + QOSGraphEdgeOptions edge; /* edge arguments that will be used by test. + * Note that test *does not* use edge_name, + * and uses instead arg and size_arg as + * data arg for its test function. + */ + void *arg; /* passed to the .before function, or to the + * test function if there is no .before + * function + */ + QOSBeforeTest before; /* executed before the test. Can add + * additional parameters to the command line + * and modify the argument to the test function. + */ + bool subprocess; /* run the test in a subprocess */ +}; + +/** + * Each driver, test or machine of this framework will have a + * QOSGraphObject as first field. + * + * This set of functions offered by QOSGraphObject are executed + * in different stages of the framework: + * - get_driver / get_device : Once a machine-to-test path has been + * found, the framework traverses it again and allocates all the + * nodes, using the provided constructor. To satisfy their relations, + * i.e. for produces or contains, where a struct constructor needs + * an external parameter represented by the previous node, + * the framework will call get_device (for contains) or + * get_driver (for produces), depending on the edge type, passing + * them the name of the next node to be taken and getting from them + * the corresponding pointer to the actual structure of the next node to + * be used in the path. + * + * - start_hw: This function is executed after all the path objects + * have been allocated, but before the test is run. It starts the hw, setting + * the initial configurations (*_device_enable) and making it ready for the + * test. + * + * - destructor: Opposite to the node constructor, destroys the object. + * This function is called after the test has been executed, and performs + * a complete cleanup of each node allocated field. In case no constructor + * is provided, no destructor will be called. + * + */ +struct QOSGraphObject { + /* for produces edges, returns void * */ + QOSGetDriver get_driver; + /* for contains edges, returns a QOSGraphObject * */ + QOSGetDevice get_device; + /* start the hw, get ready for the test */ + QOSStartFunct start_hw; + /* destroy this QOSGraphObject */ + QOSDestructorFunc destructor; + /* free the memory associated to the QOSGraphObject and its contained + * children */ + GDestroyNotify free; +}; + +/** + * qos_graph_init(): initialize the framework, creates two hash + * tables: one for the nodes and another for the edges. + */ +void qos_graph_init(void); + +/** + * qos_graph_destroy(): deallocates all the hash tables, + * freeing all nodes and edges. + */ +void qos_graph_destroy(void); + +/** + * qos_node_destroy(): removes and frees a node from the, + * nodes hash table. + */ +void qos_node_destroy(void *key); + +/** + * qos_edge_destroy(): removes and frees an edge from the, + * edges hash table. + */ +void qos_edge_destroy(void *key); + +/** + * qos_add_test(): adds a test node @name to the nodes hash table. + * + * The test will consume a @interface node, and once the + * graph walking algorithm has found it, the @test_func will be + * executed. It also has the possibility to + * add an optional @opts (see %QOSGraphNodeOptions). + * + * For tests, opts->edge.arg and size_arg represent the arg to pass + * to @test_func + */ +void qos_add_test(const char *name, const char *interface, + QOSTestFunc test_func, + QOSGraphTestOptions *opts); + +/** + * qos_node_create_machine(): creates the machine @name and + * adds it to the node hash table. + * + * This node will be of type QNODE_MACHINE and have @function + * as constructor + */ +void qos_node_create_machine(const char *name, QOSCreateMachineFunc function); + +/** + * qos_node_create_machine_args(): same as qos_node_create_machine, + * but with the possibility to add an optional ", @opts" after -M machine + * command line. + */ +void qos_node_create_machine_args(const char *name, + QOSCreateMachineFunc function, + const char *opts); + +/** + * qos_node_create_driver(): creates the driver @name and + * adds it to the node hash table. + * + * This node will be of type QNODE_DRIVER and have @function + * as constructor + */ +void qos_node_create_driver(const char *name, QOSCreateDriverFunc function); + +/** + * qos_node_contains(): creates an edge of type QEDGE_CONTAINS and + * adds it to the edge list mapped to @container in the + * edge hash table. + * + * This edge will have @container as source and @contained as destination. + * + * It also has the possibility to add optional NULL-terminated + * @opts parameters (see %QOSGraphEdgeOptions) + * + * This function can be useful when there are multiple devices + * with the same node name contained in a machine/other node + * + * For example, if "arm/raspi2" contains 2 "generic-sdhci" + * devices, the right commands will be: + * qos_node_create_machine("arm/raspi2"); + * qos_node_create_driver("generic-sdhci", constructor); + * //assume rest of the fields are set NULL + * QOSGraphEdgeOptions op1 = { .edge_name = "emmc" }; + * QOSGraphEdgeOptions op2 = { .edge_name = "sdcard" }; + * qos_node_contains("arm/raspi2", "generic-sdhci", &op1, &op2, NULL); + * + * Of course this also requires that the @container's get_device function + * should implement a case for "emmc" and "sdcard". + * + * For contains, op1.arg and op1.size_arg represent the arg to pass + * to @contained constructor to properly initialize it. + */ +void qos_node_contains(const char *container, const char *contained, ...); + +/** + * qos_node_produces(): creates an edge of type QEDGE_PRODUCES and + * adds it to the edge list mapped to @producer in the + * edge hash table. + * + * This edge will have @producer as source and @interface as destination. + */ +void qos_node_produces(const char *producer, const char *interface); + +/** + * qos_node_consumes(): creates an edge of type QEDGE_CONSUMED_BY and + * adds it to the edge list mapped to @interface in the + * edge hash table. + * + * This edge will have @interface as source and @consumer as destination. + * It also has the possibility to add an optional @opts + * (see %QOSGraphEdgeOptions) + */ +void qos_node_consumes(const char *consumer, const char *interface, + QOSGraphEdgeOptions *opts); + +/** + * qos_invalidate_command_line(): invalidates current command line, so that + * qgraph framework cannot try to cache the current command line and + * forces QEMU to restart. + */ +void qos_invalidate_command_line(void); + +/** + * qos_get_current_command_line(): return the command line required by the + * machine and driver objects. This is the same string that was passed to + * the test's "before" callback, if any. + */ +const char *qos_get_current_command_line(void); + +/** + * qos_allocate_objects(): + * @qts: The #QTestState that will be referred to by the machine object. + * @alloc: Where to store the allocator for the machine object, or %NULL. + * + * Allocate driver objects for the current test + * path, but relative to the QTestState @qts. + * + * Returns a test object just like the one that was passed to + * the test function, but relative to @qts. + */ +void *qos_allocate_objects(QTestState *qts, QGuestAllocator **p_alloc); + +/** + * qos_object_destroy(): calls the destructor for @obj + */ +void qos_object_destroy(QOSGraphObject *obj); + +/** + * qos_object_queue_destroy(): queue the destructor for @obj so that it is + * called at the end of the test + */ +void qos_object_queue_destroy(QOSGraphObject *obj); + +/** + * qos_object_start_hw(): calls the start_hw function for @obj + */ +void qos_object_start_hw(QOSGraphObject *obj); + +/** + * qos_machine_new(): instantiate a new machine node + * @node: A machine node to be instantiated + * @qts: The #QTestState that will be referred to by the machine object. + * + * Returns a machine object. + */ +QOSGraphObject *qos_machine_new(QOSGraphNode *node, QTestState *qts); + +/** + * qos_machine_new(): instantiate a new driver node + * @node: A driver node to be instantiated + * @parent: A #QOSGraphObject to be consumed by the new driver node + * @alloc: An allocator to be used by the new driver node. + * @arg: The argument for the consumed-by edge to @node. + * + * Calls the constructor for the driver object. + */ +QOSGraphObject *qos_driver_new(QOSGraphNode *node, QOSGraphObject *parent, + QGuestAllocator *alloc, void *arg); + + +#endif diff --git a/tests/libqos/qgraph_internal.h b/tests/libqos/qgraph_internal.h new file mode 100644 index 0000000000..2ef748baf6 --- /dev/null +++ b/tests/libqos/qgraph_internal.h @@ -0,0 +1,257 @@ +/* + * libqos driver framework + * + * Copyright (c) 2018 Emanuele Giuseppe Esposito <e.emanuelegiuseppe@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/> + */ + +#ifndef QGRAPH_EXTRA_H +#define QGRAPH_EXTRA_H + +/* This header is declaring additional helper functions defined in + * libqos/qgraph.c + * It should not be included in tests + */ + +#include "libqos/qgraph.h" + +typedef struct QOSGraphMachine QOSGraphMachine; +typedef enum QOSEdgeType QOSEdgeType; +typedef enum QOSNodeType QOSNodeType; + +/* callback called when the walk path algorithm found a + * valid path + */ +typedef void (*QOSTestCallback) (QOSGraphNode *path, int len); + +/* edge types*/ +enum QOSEdgeType { + QEDGE_CONTAINS, + QEDGE_PRODUCES, + QEDGE_CONSUMED_BY +}; + +/* node types*/ +enum QOSNodeType { + QNODE_MACHINE, + QNODE_DRIVER, + QNODE_INTERFACE, + QNODE_TEST +}; + +/* Graph Node */ +struct QOSGraphNode { + QOSNodeType type; + bool available; /* set by QEMU via QMP, used during graph walk */ + bool visited; /* used during graph walk */ + char *name; /* used to identify the node */ + char *command_line; /* used to start QEMU at test execution */ + union { + struct { + QOSCreateDriverFunc constructor; + } driver; + struct { + QOSCreateMachineFunc constructor; + } machine; + struct { + QOSTestFunc function; + void *arg; + QOSBeforeTest before; + bool subprocess; + } test; + } u; + + /** + * only used when traversing the path, never rely on that except in the + * qos_traverse_graph callback function + */ + QOSGraphEdge *path_edge; +}; + +/** + * qos_graph_get_node(): returns the node mapped to that @key. + * It performs an hash map search O(1) + * + * Returns: on success: the %QOSGraphNode + * otherwise: #NULL + */ +QOSGraphNode *qos_graph_get_node(const char *key); + +/** + * qos_graph_has_node(): returns #TRUE if the node + * has map has a node mapped to that @key. + */ +bool qos_graph_has_node(const char *node); + +/** + * qos_graph_get_node_type(): returns the %QOSNodeType + * of the node @node. + * It performs an hash map search O(1) + * Returns: on success: the %QOSNodeType + * otherwise: #-1 + */ +QOSNodeType qos_graph_get_node_type(const char *node); + +/** + * qos_graph_get_node_availability(): returns the availability (boolean) + * of the node @node. + */ +bool qos_graph_get_node_availability(const char *node); + +/** + * qos_graph_get_edge(): returns the edge + * linking of the node @node with @dest. + * + * Returns: on success: the %QOSGraphEdge + * otherwise: #NULL + */ +QOSGraphEdge *qos_graph_get_edge(const char *node, const char *dest); + +/** + * qos_graph_edge_get_type(): returns the edge type + * of the edge @edge. + * + * Returns: on success: the %QOSEdgeType + * otherwise: #-1 + */ +QOSEdgeType qos_graph_edge_get_type(QOSGraphEdge *edge); + +/** + * qos_graph_edge_get_dest(): returns the name of the node + * pointed as destination of edge @edge. + * + * Returns: on success: the destination + * otherwise: #NULL + */ +char *qos_graph_edge_get_dest(QOSGraphEdge *edge); + +/** + * qos_graph_has_edge(): returns #TRUE if there + * exists an edge from @start to @dest. + */ +bool qos_graph_has_edge(const char *start, const char *dest); + +/** + * qos_graph_edge_get_arg(): returns the args assigned + * to that @edge. + * + * Returns: on success: the arg + * otherwise: #NULL + */ +void *qos_graph_edge_get_arg(QOSGraphEdge *edge); + +/** + * qos_graph_edge_get_after_cmd_line(): returns the edge + * command line that will be added after all the node arguments + * and all the before_cmd_line arguments. + * + * Returns: on success: the char* arg + * otherwise: #NULL + */ +char *qos_graph_edge_get_after_cmd_line(QOSGraphEdge *edge); + +/** + * qos_graph_edge_get_before_cmd_line(): returns the edge + * command line that will be added before the node command + * line argument. + * + * Returns: on success: the char* arg + * otherwise: #NULL + */ +char *qos_graph_edge_get_before_cmd_line(QOSGraphEdge *edge); + +/** + * qos_graph_edge_get_extra_device_opts(): returns the arg + * command line that will be added to the node command + * line argument. + * + * Returns: on success: the char* arg + * otherwise: #NULL + */ +char *qos_graph_edge_get_extra_device_opts(QOSGraphEdge *edge); + +/** + * qos_graph_edge_get_name(): returns the name + * assigned to the destination node (different only) + * if there are multiple devices with the same node name + * e.g. a node has two "generic-sdhci", "emmc" and "sdcard" + * there will be two edges with edge_name ="emmc" and "sdcard" + * + * Returns always the char* edge_name + */ +char *qos_graph_edge_get_name(QOSGraphEdge *edge); + +/** + * qos_graph_get_machine(): returns the machine assigned + * to that @node name. + * + * It performs a search only trough the list of machines + * (i.e. the QOS_ROOT child). + * + * Returns: on success: the %QOSGraphNode + * otherwise: #NULL + */ +QOSGraphNode *qos_graph_get_machine(const char *node); + +/** + * qos_graph_has_machine(): returns #TRUE if the node + * has map has a node mapped to that @node. + */ +bool qos_graph_has_machine(const char *node); + + +/** + * qos_print_graph(): walks the graph and prints + * all machine-to-test paths. + */ +void qos_print_graph(void); + +/** + * qos_graph_foreach_test_path(): executes the Depth First search + * algorithm and applies @fn to all discovered paths. + * + * See qos_traverse_graph() in qgraph.c for more info on + * how it works. + */ +void qos_graph_foreach_test_path(QOSTestCallback fn); + +/** + * qos_get_machine_type(): return QEMU machine type for a machine node. + * This function requires every machine @name to be in the form + * <arch>/<machine_name>, like "arm/raspi2" or "x86_64/pc". + * + * The function will validate the format and return a pointer to + * @machine to <machine_name>. For example, when passed "x86_64/pc" + * it will return "pc". + * + * Note that this function *does not* allocate any new string. + */ +char *qos_get_machine_type(char *name); + +/** + * qos_delete_cmd_line(): delete the + * command line present in node mapped with key @name. + * + * This function is called when the QMP query returns a node with + * { "abstract" : true } attribute. + */ +void qos_delete_cmd_line(const char *name); + +/** + * qos_graph_node_set_availability(): sets the node identified + * by @node with availability @av. + */ +void qos_graph_node_set_availability(const char *node, bool av); + +#endif diff --git a/tests/libqos/sdhci.c b/tests/libqos/sdhci.c new file mode 100644 index 0000000000..22c33de453 --- /dev/null +++ b/tests/libqos/sdhci.c @@ -0,0 +1,163 @@ +/* + * libqos driver framework + * + * Copyright (c) 2018 Emanuele Giuseppe Esposito <e.emanuelegiuseppe@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/> + */ + +#include "qemu/osdep.h" +#include "libqtest.h" +#include "libqos/qgraph.h" +#include "pci.h" +#include "sdhci.h" +#include "hw/pci/pci.h" + +static void set_qsdhci_fields(QSDHCI *s, uint8_t version, uint8_t baseclock, + bool sdma, uint64_t reg) +{ + s->props.version = version; + s->props.baseclock = baseclock; + s->props.capab.sdma = sdma; + s->props.capab.reg = reg; +} + +/* Memory mapped implementation of QSDHCI */ + +static uint16_t sdhci_mm_readw(QSDHCI *s, uint32_t reg) +{ + QSDHCI_MemoryMapped *smm = container_of(s, QSDHCI_MemoryMapped, sdhci); + return qtest_readw(smm->qts, smm->addr + reg); +} + +static uint64_t sdhci_mm_readq(QSDHCI *s, uint32_t reg) +{ + QSDHCI_MemoryMapped *smm = container_of(s, QSDHCI_MemoryMapped, sdhci); + return qtest_readq(smm->qts, smm->addr + reg); +} + +static void sdhci_mm_writeq(QSDHCI *s, uint32_t reg, uint64_t val) +{ + QSDHCI_MemoryMapped *smm = container_of(s, QSDHCI_MemoryMapped, sdhci); + qtest_writeq(smm->qts, smm->addr + reg, val); +} + +static void *sdhci_mm_get_driver(void *obj, const char *interface) +{ + QSDHCI_MemoryMapped *smm = obj; + if (!g_strcmp0(interface, "sdhci")) { + return &smm->sdhci; + } + fprintf(stderr, "%s not present in generic-sdhci\n", interface); + g_assert_not_reached(); +} + +void qos_init_sdhci_mm(QSDHCI_MemoryMapped *sdhci, QTestState *qts, + uint32_t addr, QSDHCIProperties *common) +{ + sdhci->obj.get_driver = sdhci_mm_get_driver; + sdhci->sdhci.readw = sdhci_mm_readw; + sdhci->sdhci.readq = sdhci_mm_readq; + sdhci->sdhci.writeq = sdhci_mm_writeq; + memcpy(&sdhci->sdhci.props, common, sizeof(QSDHCIProperties)); + sdhci->addr = addr; + sdhci->qts = qts; +} + +/* PCI implementation of QSDHCI */ + +static uint16_t sdhci_pci_readw(QSDHCI *s, uint32_t reg) +{ + QSDHCI_PCI *spci = container_of(s, QSDHCI_PCI, sdhci); + return qpci_io_readw(&spci->dev, spci->mem_bar, reg); +} + +static uint64_t sdhci_pci_readq(QSDHCI *s, uint32_t reg) +{ + QSDHCI_PCI *spci = container_of(s, QSDHCI_PCI, sdhci); + return qpci_io_readq(&spci->dev, spci->mem_bar, reg); +} + +static void sdhci_pci_writeq(QSDHCI *s, uint32_t reg, uint64_t val) +{ + QSDHCI_PCI *spci = container_of(s, QSDHCI_PCI, sdhci); + return qpci_io_writeq(&spci->dev, spci->mem_bar, reg, val); +} + +static void *sdhci_pci_get_driver(void *object, const char *interface) +{ + QSDHCI_PCI *spci = object; + if (!g_strcmp0(interface, "sdhci")) { + return &spci->sdhci; + } + + fprintf(stderr, "%s not present in sdhci-pci\n", interface); + g_assert_not_reached(); +} + +static void sdhci_pci_start_hw(QOSGraphObject *obj) +{ + QSDHCI_PCI *spci = (QSDHCI_PCI *)obj; + qpci_device_enable(&spci->dev); +} + +static void sdhci_destructor(QOSGraphObject *obj) +{ + QSDHCI_PCI *spci = (QSDHCI_PCI *)obj; + qpci_iounmap(&spci->dev, spci->mem_bar); +} + +static void *sdhci_pci_create(void *pci_bus, QGuestAllocator *alloc, void *addr) +{ + QSDHCI_PCI *spci = g_new0(QSDHCI_PCI, 1); + QPCIBus *bus = pci_bus; + uint64_t barsize; + + qpci_device_init(&spci->dev, bus, addr); + spci->mem_bar = qpci_iomap(&spci->dev, 0, &barsize); + spci->sdhci.readw = sdhci_pci_readw; + spci->sdhci.readq = sdhci_pci_readq; + spci->sdhci.writeq = sdhci_pci_writeq; + set_qsdhci_fields(&spci->sdhci, 2, 0, 1, 0x057834b4); + + spci->obj.get_driver = sdhci_pci_get_driver; + spci->obj.start_hw = sdhci_pci_start_hw; + spci->obj.destructor = sdhci_destructor; + return &spci->obj; +} + +static void qsdhci_register_nodes(void) +{ + QPCIAddress addr = { + .devfn = QPCI_DEVFN(4, 0), + .vendor_id = PCI_VENDOR_ID_REDHAT, + .device_id = PCI_DEVICE_ID_REDHAT_SDHCI, + }; + + QOSGraphEdgeOptions opts = { + .extra_device_opts = "addr=04.0", + }; + + /* generic-sdhci */ + qos_node_create_driver("generic-sdhci", NULL); + qos_node_produces("generic-sdhci", "sdhci"); + + /* sdhci-pci */ + add_qpci_address(&opts, &addr); + qos_node_create_driver("sdhci-pci", sdhci_pci_create); + qos_node_produces("sdhci-pci", "sdhci"); + qos_node_consumes("sdhci-pci", "pci-bus", &opts); + +} + +libqos_init(qsdhci_register_nodes); diff --git a/tests/libqos/sdhci.h b/tests/libqos/sdhci.h new file mode 100644 index 0000000000..032d815c38 --- /dev/null +++ b/tests/libqos/sdhci.h @@ -0,0 +1,70 @@ +/* + * libqos driver framework + * + * Copyright (c) 2018 Emanuele Giuseppe Esposito <e.emanuelegiuseppe@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/> + */ + +#ifndef QGRAPH_QSDHCI +#define QGRAPH_QSDHCI + +#include "libqos/qgraph.h" +#include "pci.h" + +typedef struct QSDHCI QSDHCI; +typedef struct QSDHCI_MemoryMapped QSDHCI_MemoryMapped; +typedef struct QSDHCI_PCI QSDHCI_PCI; +typedef struct QSDHCIProperties QSDHCIProperties; + +/* Properties common to all QSDHCI devices */ +struct QSDHCIProperties { + uint8_t version; + uint8_t baseclock; + struct { + bool sdma; + uint64_t reg; + } capab; +}; + +struct QSDHCI { + uint16_t (*readw)(QSDHCI *s, uint32_t reg); + uint64_t (*readq)(QSDHCI *s, uint32_t reg); + void (*writeq)(QSDHCI *s, uint32_t reg, uint64_t val); + QSDHCIProperties props; +}; + +/* Memory Mapped implementation of QSDHCI */ +struct QSDHCI_MemoryMapped { + QOSGraphObject obj; + QTestState *qts; + QSDHCI sdhci; + uint64_t addr; +}; + +/* PCI implementation of QSDHCI */ +struct QSDHCI_PCI { + QOSGraphObject obj; + QPCIDevice dev; + QSDHCI sdhci; + QPCIBar mem_bar; +}; + +/** + * qos_init_sdhci_mm(): external constructor used by all drivers/machines + * that "contain" a #QSDHCI_MemoryMapped driver + */ +void qos_init_sdhci_mm(QSDHCI_MemoryMapped *sdhci, QTestState *qts, + uint32_t addr, QSDHCIProperties *common); + +#endif diff --git a/tests/libqos/tpci200.c b/tests/libqos/tpci200.c new file mode 100644 index 0000000000..98dc532933 --- /dev/null +++ b/tests/libqos/tpci200.c @@ -0,0 +1,65 @@ +/* + * QTest testcase for tpci200 PCI-IndustryPack bridge + * + * Copyright (c) 2014 SUSE LINUX Products GmbH + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#include "qemu/osdep.h" +#include "libqtest.h" +#include "libqos/qgraph.h" +#include "libqos/pci.h" + +typedef struct QTpci200 QTpci200; +typedef struct QIpack QIpack; + +struct QIpack { + +}; +struct QTpci200 { + QOSGraphObject obj; + QPCIDevice dev; + QIpack ipack; +}; + +/* tpci200 */ +static void *tpci200_get_driver(void *obj, const char *interface) +{ + QTpci200 *tpci200 = obj; + if (!g_strcmp0(interface, "ipack")) { + return &tpci200->ipack; + } + if (!g_strcmp0(interface, "pci-device")) { + return &tpci200->dev; + } + + fprintf(stderr, "%s not present in tpci200\n", interface); + g_assert_not_reached(); +} + +static void *tpci200_create(void *pci_bus, QGuestAllocator *alloc, void *addr) +{ + QTpci200 *tpci200 = g_new0(QTpci200, 1); + QPCIBus *bus = pci_bus; + + qpci_device_init(&tpci200->dev, bus, addr); + tpci200->obj.get_driver = tpci200_get_driver; + return &tpci200->obj; +} + +static void tpci200_register_nodes(void) +{ + QOSGraphEdgeOptions opts = { + .extra_device_opts = "addr=04.0,id=ipack0", + }; + add_qpci_address(&opts, &(QPCIAddress) { .devfn = QPCI_DEVFN(4, 0) }); + + qos_node_create_driver("tpci200", tpci200_create); + qos_node_consumes("tpci200", "pci-bus", &opts); + qos_node_produces("tpci200", "ipack"); + qos_node_produces("tpci200", "pci-device"); +} + +libqos_init(tpci200_register_nodes); diff --git a/tests/libqos/virtio-9p.c b/tests/libqos/virtio-9p.c new file mode 100644 index 0000000000..a378b56fa9 --- /dev/null +++ b/tests/libqos/virtio-9p.c @@ -0,0 +1,173 @@ +/* + * libqos driver framework + * + * Copyright (c) 2018 Emanuele Giuseppe Esposito <e.emanuelegiuseppe@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/> + */ + +#include "qemu/osdep.h" +#include "libqtest.h" +#include "standard-headers/linux/virtio_ids.h" +#include "libqos/virtio-9p.h" +#include "libqos/qgraph.h" + +static QGuestAllocator *alloc; + +static void virtio_9p_cleanup(QVirtio9P *interface) +{ + qvirtqueue_cleanup(interface->vdev->bus, interface->vq, alloc); +} + +static void virtio_9p_setup(QVirtio9P *interface) +{ + interface->vq = qvirtqueue_setup(interface->vdev, alloc, 0); + qvirtio_set_driver_ok(interface->vdev); +} + +/* virtio-9p-device */ +static void virtio_9p_device_destructor(QOSGraphObject *obj) +{ + QVirtio9PDevice *v_9p = (QVirtio9PDevice *) obj; + QVirtio9P *v9p = &v_9p->v9p; + + virtio_9p_cleanup(v9p); +} + +static void virtio_9p_device_start_hw(QOSGraphObject *obj) +{ + QVirtio9PDevice *v_9p = (QVirtio9PDevice *) obj; + QVirtio9P *v9p = &v_9p->v9p; + + virtio_9p_setup(v9p); +} + +static void *virtio_9p_get_driver(QVirtio9P *v_9p, + const char *interface) +{ + if (!g_strcmp0(interface, "virtio-9p")) { + return v_9p; + } + if (!g_strcmp0(interface, "virtio")) { + return v_9p->vdev; + } + + fprintf(stderr, "%s not present in virtio-9p-device\n", interface); + g_assert_not_reached(); +} + +static void *virtio_9p_device_get_driver(void *object, const char *interface) +{ + QVirtio9PDevice *v_9p = object; + return virtio_9p_get_driver(&v_9p->v9p, interface); +} + +static void *virtio_9p_device_create(void *virtio_dev, + QGuestAllocator *t_alloc, + void *addr) +{ + QVirtio9PDevice *virtio_device = g_new0(QVirtio9PDevice, 1); + QVirtio9P *interface = &virtio_device->v9p; + + interface->vdev = virtio_dev; + alloc = t_alloc; + + virtio_device->obj.destructor = virtio_9p_device_destructor; + virtio_device->obj.get_driver = virtio_9p_device_get_driver; + virtio_device->obj.start_hw = virtio_9p_device_start_hw; + + return &virtio_device->obj; +} + +/* virtio-9p-pci */ +static void virtio_9p_pci_destructor(QOSGraphObject *obj) +{ + QVirtio9PPCI *v9_pci = (QVirtio9PPCI *) obj; + QVirtio9P *interface = &v9_pci->v9p; + QOSGraphObject *pci_vobj = &v9_pci->pci_vdev.obj; + + virtio_9p_cleanup(interface); + qvirtio_pci_destructor(pci_vobj); +} + +static void virtio_9p_pci_start_hw(QOSGraphObject *obj) +{ + QVirtio9PPCI *v9_pci = (QVirtio9PPCI *) obj; + QVirtio9P *interface = &v9_pci->v9p; + QOSGraphObject *pci_vobj = &v9_pci->pci_vdev.obj; + + qvirtio_pci_start_hw(pci_vobj); + virtio_9p_setup(interface); +} + +static void *virtio_9p_pci_get_driver(void *object, const char *interface) +{ + QVirtio9PPCI *v_9p = object; + if (!g_strcmp0(interface, "pci-device")) { + return v_9p->pci_vdev.pdev; + } + return virtio_9p_get_driver(&v_9p->v9p, interface); +} + +static void *virtio_9p_pci_create(void *pci_bus, QGuestAllocator *t_alloc, + void *addr) +{ + QVirtio9PPCI *v9_pci = g_new0(QVirtio9PPCI, 1); + QVirtio9P *interface = &v9_pci->v9p; + QOSGraphObject *obj = &v9_pci->pci_vdev.obj; + + virtio_pci_init(&v9_pci->pci_vdev, pci_bus, addr); + interface->vdev = &v9_pci->pci_vdev.vdev; + alloc = t_alloc; + + g_assert_cmphex(interface->vdev->device_type, ==, VIRTIO_ID_9P); + + obj->destructor = virtio_9p_pci_destructor; + obj->start_hw = virtio_9p_pci_start_hw; + obj->get_driver = virtio_9p_pci_get_driver; + + return obj; +} + +static void virtio_9p_register_nodes(void) +{ + const char *str_simple = "fsdev=fsdev0,mount_tag=" MOUNT_TAG; + const char *str_addr = "fsdev=fsdev0,addr=04.0,mount_tag=" MOUNT_TAG; + + QPCIAddress addr = { + .devfn = QPCI_DEVFN(4, 0), + }; + + QOSGraphEdgeOptions opts = { + .before_cmd_line = "-fsdev synth,id=fsdev0", + }; + + /* virtio-9p-device */ + opts.extra_device_opts = str_simple, + qos_node_create_driver("virtio-9p-device", virtio_9p_device_create); + qos_node_consumes("virtio-9p-device", "virtio-bus", &opts); + qos_node_produces("virtio-9p-device", "virtio"); + qos_node_produces("virtio-9p-device", "virtio-9p"); + + /* virtio-9p-pci */ + opts.extra_device_opts = str_addr; + add_qpci_address(&opts, &addr); + qos_node_create_driver("virtio-9p-pci", virtio_9p_pci_create); + qos_node_consumes("virtio-9p-pci", "pci-bus", &opts); + qos_node_produces("virtio-9p-pci", "pci-device"); + qos_node_produces("virtio-9p-pci", "virtio"); + qos_node_produces("virtio-9p-pci", "virtio-9p"); + +} + +libqos_init(virtio_9p_register_nodes); diff --git a/tests/libqos/virtio-9p.h b/tests/libqos/virtio-9p.h new file mode 100644 index 0000000000..dba22772b5 --- /dev/null +++ b/tests/libqos/virtio-9p.h @@ -0,0 +1,42 @@ +/* + * libqos driver framework + * + * Copyright (c) 2018 Emanuele Giuseppe Esposito <e.emanuelegiuseppe@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/> + */ + +#include "libqos/qgraph.h" +#include "libqos/virtio.h" +#include "libqos/virtio-pci.h" + +typedef struct QVirtio9P QVirtio9P; +typedef struct QVirtio9PPCI QVirtio9PPCI; +typedef struct QVirtio9PDevice QVirtio9PDevice; + +#define MOUNT_TAG "qtest" + +struct QVirtio9P { + QVirtioDevice *vdev; + QVirtQueue *vq; +}; + +struct QVirtio9PPCI { + QVirtioPCIDevice pci_vdev; + QVirtio9P v9p; +}; + +struct QVirtio9PDevice { + QOSGraphObject obj; + QVirtio9P v9p; +}; diff --git a/tests/libqos/virtio-balloon.c b/tests/libqos/virtio-balloon.c new file mode 100644 index 0000000000..7e6e9e9de5 --- /dev/null +++ b/tests/libqos/virtio-balloon.c @@ -0,0 +1,113 @@ +/* + * libqos driver framework + * + * Copyright (c) 2018 Emanuele Giuseppe Esposito <e.emanuelegiuseppe@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/> + */ + +#include "qemu/osdep.h" +#include "libqtest.h" +#include "libqos/qgraph.h" +#include "libqos/virtio-balloon.h" + +/* virtio-balloon-device */ +static void *qvirtio_balloon_get_driver(QVirtioBalloon *v_balloon, + const char *interface) +{ + if (!g_strcmp0(interface, "virtio-balloon")) { + return v_balloon; + } + if (!g_strcmp0(interface, "virtio")) { + return v_balloon->vdev; + } + + fprintf(stderr, "%s not present in virtio-balloon-device\n", interface); + g_assert_not_reached(); +} + +static void *qvirtio_balloon_device_get_driver(void *object, + const char *interface) +{ + QVirtioBalloonDevice *v_balloon = object; + return qvirtio_balloon_get_driver(&v_balloon->balloon, interface); +} + +static void *virtio_balloon_device_create(void *virtio_dev, + QGuestAllocator *t_alloc, + void *addr) +{ + QVirtioBalloonDevice *virtio_bdevice = g_new0(QVirtioBalloonDevice, 1); + QVirtioBalloon *interface = &virtio_bdevice->balloon; + + interface->vdev = virtio_dev; + + virtio_bdevice->obj.get_driver = qvirtio_balloon_device_get_driver; + + return &virtio_bdevice->obj; +} + +/* virtio-balloon-pci */ +static void *qvirtio_balloon_pci_get_driver(void *object, + const char *interface) +{ + QVirtioBalloonPCI *v_balloon = object; + if (!g_strcmp0(interface, "pci-device")) { + return v_balloon->pci_vdev.pdev; + } + return qvirtio_balloon_get_driver(&v_balloon->balloon, interface); +} + +static void *virtio_balloon_pci_create(void *pci_bus, QGuestAllocator *t_alloc, + void *addr) +{ + QVirtioBalloonPCI *virtio_bpci = g_new0(QVirtioBalloonPCI, 1); + QVirtioBalloon *interface = &virtio_bpci->balloon; + QOSGraphObject *obj = &virtio_bpci->pci_vdev.obj; + + + virtio_pci_init(&virtio_bpci->pci_vdev, pci_bus, addr); + interface->vdev = &virtio_bpci->pci_vdev.vdev; + + obj->get_driver = qvirtio_balloon_pci_get_driver; + + return obj; +} + +static void virtio_balloon_register_nodes(void) +{ + QPCIAddress addr = { + .devfn = QPCI_DEVFN(4, 0), + }; + + QOSGraphEdgeOptions opts = { + .extra_device_opts = "addr=04.0", + }; + + /* virtio-balloon-device */ + qos_node_create_driver("virtio-balloon-device", + virtio_balloon_device_create); + qos_node_consumes("virtio-balloon-device", "virtio-bus", NULL); + qos_node_produces("virtio-balloon-device", "virtio"); + qos_node_produces("virtio-balloon-device", "virtio-balloon"); + + /* virtio-balloon-pci */ + add_qpci_address(&opts, &addr); + qos_node_create_driver("virtio-balloon-pci", virtio_balloon_pci_create); + qos_node_consumes("virtio-balloon-pci", "pci-bus", &opts); + qos_node_produces("virtio-balloon-pci", "pci-device"); + qos_node_produces("virtio-balloon-pci", "virtio"); + qos_node_produces("virtio-balloon-pci", "virtio-balloon"); +} + +libqos_init(virtio_balloon_register_nodes); diff --git a/tests/libqos/virtio-balloon.h b/tests/libqos/virtio-balloon.h new file mode 100644 index 0000000000..e8066c42bb --- /dev/null +++ b/tests/libqos/virtio-balloon.h @@ -0,0 +1,39 @@ +/* + * libqos driver framework + * + * Copyright (c) 2018 Emanuele Giuseppe Esposito <e.emanuelegiuseppe@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/> + */ + +#include "libqos/qgraph.h" +#include "libqos/virtio.h" +#include "libqos/virtio-pci.h" + +typedef struct QVirtioBalloon QVirtioBalloon; +typedef struct QVirtioBalloonPCI QVirtioBalloonPCI; +typedef struct QVirtioBalloonDevice QVirtioBalloonDevice; + +struct QVirtioBalloon { + QVirtioDevice *vdev; +}; + +struct QVirtioBalloonPCI { + QVirtioPCIDevice pci_vdev; + QVirtioBalloon balloon; +}; + +struct QVirtioBalloonDevice { + QOSGraphObject obj; + QVirtioBalloon balloon; +}; diff --git a/tests/libqos/virtio-blk.c b/tests/libqos/virtio-blk.c new file mode 100644 index 0000000000..c17bdf4217 --- /dev/null +++ b/tests/libqos/virtio-blk.c @@ -0,0 +1,124 @@ +/* + * libqos driver framework + * + * Copyright (c) 2018 Emanuele Giuseppe Esposito <e.emanuelegiuseppe@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/> + */ + +#include "qemu/osdep.h" +#include "libqtest.h" +#include "standard-headers/linux/virtio_blk.h" +#include "libqos/qgraph.h" +#include "libqos/virtio-blk.h" + +#define PCI_SLOT 0x04 +#define PCI_FN 0x00 + +/* virtio-blk-device */ +static void *qvirtio_blk_get_driver(QVirtioBlk *v_blk, + const char *interface) +{ + if (!g_strcmp0(interface, "virtio-blk")) { + return v_blk; + } + if (!g_strcmp0(interface, "virtio")) { + return v_blk->vdev; + } + + fprintf(stderr, "%s not present in virtio-blk-device\n", interface); + g_assert_not_reached(); +} + +static void *qvirtio_blk_device_get_driver(void *object, + const char *interface) +{ + QVirtioBlkDevice *v_blk = object; + return qvirtio_blk_get_driver(&v_blk->blk, interface); +} + +static void *virtio_blk_device_create(void *virtio_dev, + QGuestAllocator *t_alloc, + void *addr) +{ + QVirtioBlkDevice *virtio_blk = g_new0(QVirtioBlkDevice, 1); + QVirtioBlk *interface = &virtio_blk->blk; + + interface->vdev = virtio_dev; + + virtio_blk->obj.get_driver = qvirtio_blk_device_get_driver; + + return &virtio_blk->obj; +} + +/* virtio-blk-pci */ +static void *qvirtio_blk_pci_get_driver(void *object, const char *interface) +{ + QVirtioBlkPCI *v_blk = object; + if (!g_strcmp0(interface, "pci-device")) { + return v_blk->pci_vdev.pdev; + } + return qvirtio_blk_get_driver(&v_blk->blk, interface); +} + +static void *virtio_blk_pci_create(void *pci_bus, QGuestAllocator *t_alloc, + void *addr) +{ + QVirtioBlkPCI *virtio_blk = g_new0(QVirtioBlkPCI, 1); + QVirtioBlk *interface = &virtio_blk->blk; + QOSGraphObject *obj = &virtio_blk->pci_vdev.obj; + + virtio_pci_init(&virtio_blk->pci_vdev, pci_bus, addr); + interface->vdev = &virtio_blk->pci_vdev.vdev; + + g_assert_cmphex(interface->vdev->device_type, ==, VIRTIO_ID_BLOCK); + + obj->get_driver = qvirtio_blk_pci_get_driver; + + return obj; +} + +static void virtio_blk_register_nodes(void) +{ + /* FIXME: every test using these two nodes needs to setup a + * -drive,id=drive0 otherwise QEMU is not going to start. + * Therefore, we do not include "produces" edge for virtio + * and pci-device yet. + */ + + char *arg = g_strdup_printf("id=drv0,drive=drive0,addr=%x.%x", + PCI_SLOT, PCI_FN); + + QPCIAddress addr = { + .devfn = QPCI_DEVFN(PCI_SLOT, PCI_FN), + }; + + QOSGraphEdgeOptions opts = { }; + + /* virtio-blk-device */ + opts.extra_device_opts = "drive=drive0"; + qos_node_create_driver("virtio-blk-device", virtio_blk_device_create); + qos_node_consumes("virtio-blk-device", "virtio-bus", &opts); + qos_node_produces("virtio-blk-device", "virtio-blk"); + + /* virtio-blk-pci */ + opts.extra_device_opts = arg; + add_qpci_address(&opts, &addr); + qos_node_create_driver("virtio-blk-pci", virtio_blk_pci_create); + qos_node_consumes("virtio-blk-pci", "pci-bus", &opts); + qos_node_produces("virtio-blk-pci", "virtio-blk"); + + g_free(arg); +} + +libqos_init(virtio_blk_register_nodes); diff --git a/tests/libqos/virtio-blk.h b/tests/libqos/virtio-blk.h new file mode 100644 index 0000000000..dc258496ba --- /dev/null +++ b/tests/libqos/virtio-blk.h @@ -0,0 +1,40 @@ +/* + * libqos driver framework + * + * Copyright (c) 2018 Emanuele Giuseppe Esposito <e.emanuelegiuseppe@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/> + */ + +#include "libqos/qgraph.h" +#include "libqos/virtio.h" +#include "libqos/virtio-pci.h" + +typedef struct QVirtioBlk QVirtioBlk; +typedef struct QVirtioBlkPCI QVirtioBlkPCI; +typedef struct QVirtioBlkDevice QVirtioBlkDevice; + +/* virtqueue is created in each test */ +struct QVirtioBlk { + QVirtioDevice *vdev; +}; + +struct QVirtioBlkPCI { + QVirtioPCIDevice pci_vdev; + QVirtioBlk blk; +}; + +struct QVirtioBlkDevice { + QOSGraphObject obj; + QVirtioBlk blk; +}; diff --git a/tests/libqos/virtio-mmio.c b/tests/libqos/virtio-mmio.c index 7aa8383338..3678c07ef0 100644 --- a/tests/libqos/virtio-mmio.c +++ b/tests/libqos/virtio-mmio.c @@ -12,74 +12,74 @@ #include "libqos/virtio.h" #include "libqos/virtio-mmio.h" #include "libqos/malloc.h" -#include "libqos/malloc-generic.h" +#include "libqos/qgraph.h" #include "standard-headers/linux/virtio_ring.h" static uint8_t qvirtio_mmio_config_readb(QVirtioDevice *d, uint64_t off) { - QVirtioMMIODevice *dev = (QVirtioMMIODevice *)d; - return readb(dev->addr + QVIRTIO_MMIO_DEVICE_SPECIFIC + off); + QVirtioMMIODevice *dev = container_of(d, QVirtioMMIODevice, vdev); + return qtest_readb(dev->qts, dev->addr + QVIRTIO_MMIO_DEVICE_SPECIFIC + off); } static uint16_t qvirtio_mmio_config_readw(QVirtioDevice *d, uint64_t off) { - QVirtioMMIODevice *dev = (QVirtioMMIODevice *)d; - return readw(dev->addr + QVIRTIO_MMIO_DEVICE_SPECIFIC + off); + QVirtioMMIODevice *dev = container_of(d, QVirtioMMIODevice, vdev); + return qtest_readw(dev->qts, dev->addr + QVIRTIO_MMIO_DEVICE_SPECIFIC + off); } static uint32_t qvirtio_mmio_config_readl(QVirtioDevice *d, uint64_t off) { - QVirtioMMIODevice *dev = (QVirtioMMIODevice *)d; - return readl(dev->addr + QVIRTIO_MMIO_DEVICE_SPECIFIC + off); + QVirtioMMIODevice *dev = container_of(d, QVirtioMMIODevice, vdev); + return qtest_readl(dev->qts, dev->addr + QVIRTIO_MMIO_DEVICE_SPECIFIC + off); } static uint64_t qvirtio_mmio_config_readq(QVirtioDevice *d, uint64_t off) { - QVirtioMMIODevice *dev = (QVirtioMMIODevice *)d; - return readq(dev->addr + QVIRTIO_MMIO_DEVICE_SPECIFIC + off); + QVirtioMMIODevice *dev = container_of(d, QVirtioMMIODevice, vdev); + return qtest_readq(dev->qts, dev->addr + QVIRTIO_MMIO_DEVICE_SPECIFIC + off); } static uint32_t qvirtio_mmio_get_features(QVirtioDevice *d) { - QVirtioMMIODevice *dev = (QVirtioMMIODevice *)d; - writel(dev->addr + QVIRTIO_MMIO_HOST_FEATURES_SEL, 0); - return readl(dev->addr + QVIRTIO_MMIO_HOST_FEATURES); + QVirtioMMIODevice *dev = container_of(d, QVirtioMMIODevice, vdev); + qtest_writel(dev->qts, dev->addr + QVIRTIO_MMIO_HOST_FEATURES_SEL, 0); + return qtest_readl(dev->qts, dev->addr + QVIRTIO_MMIO_HOST_FEATURES); } static void qvirtio_mmio_set_features(QVirtioDevice *d, uint32_t features) { - QVirtioMMIODevice *dev = (QVirtioMMIODevice *)d; + QVirtioMMIODevice *dev = container_of(d, QVirtioMMIODevice, vdev); dev->features = features; - writel(dev->addr + QVIRTIO_MMIO_GUEST_FEATURES_SEL, 0); - writel(dev->addr + QVIRTIO_MMIO_GUEST_FEATURES, features); + qtest_writel(dev->qts, dev->addr + QVIRTIO_MMIO_GUEST_FEATURES_SEL, 0); + qtest_writel(dev->qts, dev->addr + QVIRTIO_MMIO_GUEST_FEATURES, features); } static uint32_t qvirtio_mmio_get_guest_features(QVirtioDevice *d) { - QVirtioMMIODevice *dev = (QVirtioMMIODevice *)d; + QVirtioMMIODevice *dev = container_of(d, QVirtioMMIODevice, vdev); return dev->features; } static uint8_t qvirtio_mmio_get_status(QVirtioDevice *d) { - QVirtioMMIODevice *dev = (QVirtioMMIODevice *)d; - return (uint8_t)readl(dev->addr + QVIRTIO_MMIO_DEVICE_STATUS); + QVirtioMMIODevice *dev = container_of(d, QVirtioMMIODevice, vdev); + return (uint8_t)qtest_readl(dev->qts, dev->addr + QVIRTIO_MMIO_DEVICE_STATUS); } static void qvirtio_mmio_set_status(QVirtioDevice *d, uint8_t status) { - QVirtioMMIODevice *dev = (QVirtioMMIODevice *)d; - writel(dev->addr + QVIRTIO_MMIO_DEVICE_STATUS, (uint32_t)status); + QVirtioMMIODevice *dev = container_of(d, QVirtioMMIODevice, vdev); + qtest_writel(dev->qts, dev->addr + QVIRTIO_MMIO_DEVICE_STATUS, (uint32_t)status); } static bool qvirtio_mmio_get_queue_isr_status(QVirtioDevice *d, QVirtQueue *vq) { - QVirtioMMIODevice *dev = (QVirtioMMIODevice *)d; + QVirtioMMIODevice *dev = container_of(d, QVirtioMMIODevice, vdev); uint32_t isr; - isr = readl(dev->addr + QVIRTIO_MMIO_INTERRUPT_STATUS) & 1; + isr = qtest_readl(dev->qts, dev->addr + QVIRTIO_MMIO_INTERRUPT_STATUS) & 1; if (isr != 0) { - writel(dev->addr + QVIRTIO_MMIO_INTERRUPT_ACK, 1); + qtest_writel(dev->qts, dev->addr + QVIRTIO_MMIO_INTERRUPT_ACK, 1); return true; } @@ -88,12 +88,12 @@ static bool qvirtio_mmio_get_queue_isr_status(QVirtioDevice *d, QVirtQueue *vq) static bool qvirtio_mmio_get_config_isr_status(QVirtioDevice *d) { - QVirtioMMIODevice *dev = (QVirtioMMIODevice *)d; + QVirtioMMIODevice *dev = container_of(d, QVirtioMMIODevice, vdev); uint32_t isr; - isr = readl(dev->addr + QVIRTIO_MMIO_INTERRUPT_STATUS) & 2; + isr = qtest_readl(dev->qts, dev->addr + QVIRTIO_MMIO_INTERRUPT_STATUS) & 2; if (isr != 0) { - writel(dev->addr + QVIRTIO_MMIO_INTERRUPT_ACK, 2); + qtest_writel(dev->qts, dev->addr + QVIRTIO_MMIO_INTERRUPT_ACK, 2); return true; } @@ -102,34 +102,34 @@ static bool qvirtio_mmio_get_config_isr_status(QVirtioDevice *d) static void qvirtio_mmio_queue_select(QVirtioDevice *d, uint16_t index) { - QVirtioMMIODevice *dev = (QVirtioMMIODevice *)d; - writel(dev->addr + QVIRTIO_MMIO_QUEUE_SEL, (uint32_t)index); + QVirtioMMIODevice *dev = container_of(d, QVirtioMMIODevice, vdev); + qtest_writel(dev->qts, dev->addr + QVIRTIO_MMIO_QUEUE_SEL, (uint32_t)index); - g_assert_cmphex(readl(dev->addr + QVIRTIO_MMIO_QUEUE_PFN), ==, 0); + g_assert_cmphex(qtest_readl(dev->qts, dev->addr + QVIRTIO_MMIO_QUEUE_PFN), ==, 0); } static uint16_t qvirtio_mmio_get_queue_size(QVirtioDevice *d) { - QVirtioMMIODevice *dev = (QVirtioMMIODevice *)d; - return (uint16_t)readl(dev->addr + QVIRTIO_MMIO_QUEUE_NUM_MAX); + QVirtioMMIODevice *dev = container_of(d, QVirtioMMIODevice, vdev); + return (uint16_t)qtest_readl(dev->qts, dev->addr + QVIRTIO_MMIO_QUEUE_NUM_MAX); } static void qvirtio_mmio_set_queue_address(QVirtioDevice *d, uint32_t pfn) { - QVirtioMMIODevice *dev = (QVirtioMMIODevice *)d; - writel(dev->addr + QVIRTIO_MMIO_QUEUE_PFN, pfn); + QVirtioMMIODevice *dev = container_of(d, QVirtioMMIODevice, vdev); + qtest_writel(dev->qts, dev->addr + QVIRTIO_MMIO_QUEUE_PFN, pfn); } static QVirtQueue *qvirtio_mmio_virtqueue_setup(QVirtioDevice *d, QGuestAllocator *alloc, uint16_t index) { - QVirtioMMIODevice *dev = (QVirtioMMIODevice *)d; + QVirtioMMIODevice *dev = container_of(d, QVirtioMMIODevice, vdev); QVirtQueue *vq; uint64_t addr; vq = g_malloc0(sizeof(*vq)); qvirtio_mmio_queue_select(d, index); - writel(dev->addr + QVIRTIO_MMIO_QUEUE_ALIGN, dev->page_size); + qtest_writel(dev->qts, dev->addr + QVIRTIO_MMIO_QUEUE_ALIGN, dev->page_size); vq->index = index; vq->size = qvirtio_mmio_get_queue_size(d); @@ -139,7 +139,7 @@ static QVirtQueue *qvirtio_mmio_virtqueue_setup(QVirtioDevice *d, vq->indirect = (dev->features & (1u << VIRTIO_RING_F_INDIRECT_DESC)) != 0; vq->event = (dev->features & (1u << VIRTIO_RING_F_EVENT_IDX)) != 0; - writel(dev->addr + QVIRTIO_MMIO_QUEUE_NUM, vq->size); + qtest_writel(dev->qts, dev->addr + QVIRTIO_MMIO_QUEUE_NUM, vq->size); /* Check different than 0 */ g_assert_cmpint(vq->size, !=, 0); @@ -163,8 +163,8 @@ static void qvirtio_mmio_virtqueue_cleanup(QVirtQueue *vq, static void qvirtio_mmio_virtqueue_kick(QVirtioDevice *d, QVirtQueue *vq) { - QVirtioMMIODevice *dev = (QVirtioMMIODevice *)d; - writel(dev->addr + QVIRTIO_MMIO_QUEUE_NOTIFY, vq->index); + QVirtioMMIODevice *dev = container_of(d, QVirtioMMIODevice, vdev); + qtest_writel(dev->qts, dev->addr + QVIRTIO_MMIO_QUEUE_NOTIFY, vq->index); } const QVirtioBus qvirtio_mmio = { @@ -187,21 +187,45 @@ const QVirtioBus qvirtio_mmio = { .virtqueue_kick = qvirtio_mmio_virtqueue_kick, }; -QVirtioMMIODevice *qvirtio_mmio_init_device(uint64_t addr, uint32_t page_size) +static void *qvirtio_mmio_get_driver(void *obj, const char *interface) { - QVirtioMMIODevice *dev; - uint32_t magic; - dev = g_malloc0(sizeof(*dev)); + QVirtioMMIODevice *virtio_mmio = obj; + if (!g_strcmp0(interface, "virtio-bus")) { + return &virtio_mmio->vdev; + } + fprintf(stderr, "%s not present in virtio-mmio\n", interface); + g_assert_not_reached(); +} + +static void qvirtio_mmio_start_hw(QOSGraphObject *obj) +{ + QVirtioMMIODevice *dev = (QVirtioMMIODevice *) obj; + qvirtio_start_device(&dev->vdev); +} - magic = readl(addr + QVIRTIO_MMIO_MAGIC_VALUE); +void qvirtio_mmio_init_device(QVirtioMMIODevice *dev, QTestState *qts, + uint64_t addr, uint32_t page_size) +{ + uint32_t magic; + magic = qtest_readl(qts, addr + QVIRTIO_MMIO_MAGIC_VALUE); g_assert(magic == ('v' | 'i' << 8 | 'r' << 16 | 't' << 24)); + dev->qts = qts; dev->addr = addr; dev->page_size = page_size; - dev->vdev.device_type = readl(addr + QVIRTIO_MMIO_DEVICE_ID); + dev->vdev.device_type = qtest_readl(qts, addr + QVIRTIO_MMIO_DEVICE_ID); dev->vdev.bus = &qvirtio_mmio; - writel(addr + QVIRTIO_MMIO_GUEST_PAGE_SIZE, page_size); + qtest_writel(qts, addr + QVIRTIO_MMIO_GUEST_PAGE_SIZE, page_size); + + dev->obj.get_driver = qvirtio_mmio_get_driver; + dev->obj.start_hw = qvirtio_mmio_start_hw; +} - return dev; +static void virtio_mmio_register_nodes(void) +{ + qos_node_create_driver("virtio-mmio", NULL); + qos_node_produces("virtio-mmio", "virtio-bus"); } + +libqos_init(virtio_mmio_register_nodes); diff --git a/tests/libqos/virtio-mmio.h b/tests/libqos/virtio-mmio.h index e3e52b9ce1..17a17141c3 100644 --- a/tests/libqos/virtio-mmio.h +++ b/tests/libqos/virtio-mmio.h @@ -11,6 +11,7 @@ #define LIBQOS_VIRTIO_MMIO_H #include "libqos/virtio.h" +#include "libqos/qgraph.h" #define QVIRTIO_MMIO_MAGIC_VALUE 0x000 #define QVIRTIO_MMIO_VERSION 0x004 @@ -33,7 +34,9 @@ #define QVIRTIO_MMIO_DEVICE_SPECIFIC 0x100 typedef struct QVirtioMMIODevice { + QOSGraphObject obj; QVirtioDevice vdev; + QTestState *qts; uint64_t addr; uint32_t page_size; uint32_t features; /* As it cannot be read later, save it */ @@ -41,6 +44,7 @@ typedef struct QVirtioMMIODevice { extern const QVirtioBus qvirtio_mmio; -QVirtioMMIODevice *qvirtio_mmio_init_device(uint64_t addr, uint32_t page_size); +void qvirtio_mmio_init_device(QVirtioMMIODevice *dev, QTestState *qts, + uint64_t addr, uint32_t page_size); #endif diff --git a/tests/libqos/virtio-net.c b/tests/libqos/virtio-net.c new file mode 100644 index 0000000000..61c56170e9 --- /dev/null +++ b/tests/libqos/virtio-net.c @@ -0,0 +1,195 @@ +/* + * libqos driver framework + * + * Copyright (c) 2018 Emanuele Giuseppe Esposito <e.emanuelegiuseppe@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/> + */ + +#include "qemu/osdep.h" +#include "libqtest.h" +#include "libqos/qgraph.h" +#include "libqos/virtio-net.h" +#include "hw/virtio/virtio-net.h" + + +static QGuestAllocator *alloc; + +static void virtio_net_cleanup(QVirtioNet *interface) +{ + int i; + + for (i = 0; i < interface->n_queues; i++) { + qvirtqueue_cleanup(interface->vdev->bus, interface->queues[i], alloc); + } + g_free(interface->queues); +} + +static void virtio_net_setup(QVirtioNet *interface) +{ + QVirtioDevice *vdev = interface->vdev; + uint64_t features; + int i; + + features = qvirtio_get_features(vdev); + features &= ~(QVIRTIO_F_BAD_FEATURE | + (1u << VIRTIO_RING_F_INDIRECT_DESC) | + (1u << VIRTIO_RING_F_EVENT_IDX)); + qvirtio_set_features(vdev, features); + + if (features & (1u << VIRTIO_NET_F_MQ)) { + interface->n_queues = qvirtio_config_readw(vdev, 8) * 2; + } else { + interface->n_queues = 2; + } + + interface->queues = g_new(QVirtQueue *, interface->n_queues); + for (i = 0; i < interface->n_queues; i++) { + interface->queues[i] = qvirtqueue_setup(vdev, alloc, i); + } + qvirtio_set_driver_ok(vdev); +} + +/* virtio-net-device */ +static void qvirtio_net_device_destructor(QOSGraphObject *obj) +{ + QVirtioNetDevice *v_net = (QVirtioNetDevice *) obj; + virtio_net_cleanup(&v_net->net); +} + +static void qvirtio_net_device_start_hw(QOSGraphObject *obj) +{ + QVirtioNetDevice *v_net = (QVirtioNetDevice *) obj; + QVirtioNet *interface = &v_net->net; + + virtio_net_setup(interface); +} + +static void *qvirtio_net_get_driver(QVirtioNet *v_net, + const char *interface) +{ + if (!g_strcmp0(interface, "virtio-net")) { + return v_net; + } + if (!g_strcmp0(interface, "virtio")) { + return v_net->vdev; + } + + fprintf(stderr, "%s not present in virtio-net-device\n", interface); + g_assert_not_reached(); +} + +static void *qvirtio_net_device_get_driver(void *object, + const char *interface) +{ + QVirtioNetDevice *v_net = object; + return qvirtio_net_get_driver(&v_net->net, interface); +} + +static void *virtio_net_device_create(void *virtio_dev, + QGuestAllocator *t_alloc, + void *addr) +{ + QVirtioNetDevice *virtio_ndevice = g_new0(QVirtioNetDevice, 1); + QVirtioNet *interface = &virtio_ndevice->net; + + interface->vdev = virtio_dev; + alloc = t_alloc; + + virtio_ndevice->obj.destructor = qvirtio_net_device_destructor; + virtio_ndevice->obj.get_driver = qvirtio_net_device_get_driver; + virtio_ndevice->obj.start_hw = qvirtio_net_device_start_hw; + + return &virtio_ndevice->obj; +} + +/* virtio-net-pci */ +static void qvirtio_net_pci_destructor(QOSGraphObject *obj) +{ + QVirtioNetPCI *v_net = (QVirtioNetPCI *) obj; + QVirtioNet *interface = &v_net->net; + QOSGraphObject *pci_vobj = &v_net->pci_vdev.obj; + + virtio_net_cleanup(interface); + qvirtio_pci_destructor(pci_vobj); +} + +static void qvirtio_net_pci_start_hw(QOSGraphObject *obj) +{ + QVirtioNetPCI *v_net = (QVirtioNetPCI *) obj; + QVirtioNet *interface = &v_net->net; + QOSGraphObject *pci_vobj = &v_net->pci_vdev.obj; + + qvirtio_pci_start_hw(pci_vobj); + virtio_net_setup(interface); +} + +static void *qvirtio_net_pci_get_driver(void *object, + const char *interface) +{ + QVirtioNetPCI *v_net = object; + if (!g_strcmp0(interface, "pci-device")) { + return v_net->pci_vdev.pdev; + } + return qvirtio_net_get_driver(&v_net->net, interface); +} + +static void *virtio_net_pci_create(void *pci_bus, QGuestAllocator *t_alloc, + void *addr) +{ + QVirtioNetPCI *virtio_bpci = g_new0(QVirtioNetPCI, 1); + QVirtioNet *interface = &virtio_bpci->net; + QOSGraphObject *obj = &virtio_bpci->pci_vdev.obj; + + virtio_pci_init(&virtio_bpci->pci_vdev, pci_bus, addr); + interface->vdev = &virtio_bpci->pci_vdev.vdev; + alloc = t_alloc; + + g_assert_cmphex(interface->vdev->device_type, ==, VIRTIO_ID_NET); + + obj->destructor = qvirtio_net_pci_destructor; + obj->start_hw = qvirtio_net_pci_start_hw; + obj->get_driver = qvirtio_net_pci_get_driver; + + return obj; +} + +static void virtio_net_register_nodes(void) +{ + /* FIXME: every test using these nodes needs to setup a + * -netdev socket,id=hs0 otherwise QEMU is not going to start. + * Therefore, we do not include "produces" edge for virtio + * and pci-device yet. + */ + QPCIAddress addr = { + .devfn = QPCI_DEVFN(4, 0), + }; + + QOSGraphEdgeOptions opts = { }; + + /* virtio-net-device */ + opts.extra_device_opts = "netdev=hs0"; + qos_node_create_driver("virtio-net-device", + virtio_net_device_create); + qos_node_consumes("virtio-net-device", "virtio-bus", &opts); + qos_node_produces("virtio-net-device", "virtio-net"); + + /* virtio-net-pci */ + opts.extra_device_opts = "netdev=hs0,addr=04.0"; + add_qpci_address(&opts, &addr); + qos_node_create_driver("virtio-net-pci", virtio_net_pci_create); + qos_node_consumes("virtio-net-pci", "pci-bus", &opts); + qos_node_produces("virtio-net-pci", "virtio-net"); +} + +libqos_init(virtio_net_register_nodes); diff --git a/tests/libqos/virtio-net.h b/tests/libqos/virtio-net.h new file mode 100644 index 0000000000..28238a1b20 --- /dev/null +++ b/tests/libqos/virtio-net.h @@ -0,0 +1,41 @@ +/* + * libqos driver framework + * + * Copyright (c) 2018 Emanuele Giuseppe Esposito <e.emanuelegiuseppe@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/> + */ + +#include "libqos/qgraph.h" +#include "libqos/virtio.h" +#include "libqos/virtio-pci.h" + +typedef struct QVirtioNet QVirtioNet; +typedef struct QVirtioNetPCI QVirtioNetPCI; +typedef struct QVirtioNetDevice QVirtioNetDevice; + +struct QVirtioNet { + QVirtioDevice *vdev; + int n_queues; + QVirtQueue **queues; +}; + +struct QVirtioNetPCI { + QVirtioPCIDevice pci_vdev; + QVirtioNet net; +}; + +struct QVirtioNetDevice { + QOSGraphObject obj; + QVirtioNet net; +}; diff --git a/tests/libqos/virtio-pci.c b/tests/libqos/virtio-pci.c index 550dede0a2..993d347830 100644 --- a/tests/libqos/virtio-pci.c +++ b/tests/libqos/virtio-pci.c @@ -15,68 +15,39 @@ #include "libqos/pci-pc.h" #include "libqos/malloc.h" #include "libqos/malloc-pc.h" +#include "libqos/qgraph.h" #include "standard-headers/linux/virtio_ring.h" #include "standard-headers/linux/virtio_pci.h" #include "hw/pci/pci.h" #include "hw/pci/pci_regs.h" -typedef struct QVirtioPCIForeachData { - void (*func)(QVirtioDevice *d, void *data); - uint16_t device_type; - bool has_slot; - int slot; - void *user_data; -} QVirtioPCIForeachData; - -void qvirtio_pci_device_free(QVirtioPCIDevice *dev) -{ - g_free(dev->pdev); - g_free(dev); -} - -static QVirtioPCIDevice *qpcidevice_to_qvirtiodevice(QPCIDevice *pdev) -{ - QVirtioPCIDevice *vpcidev; - vpcidev = g_malloc0(sizeof(*vpcidev)); - - if (pdev) { - vpcidev->pdev = pdev; - vpcidev->vdev.device_type = - qpci_config_readw(vpcidev->pdev, PCI_SUBSYSTEM_ID); - } - - vpcidev->config_msix_entry = -1; - - return vpcidev; -} +/* virtio-pci is a superclass of all virtio-xxx-pci devices; + * the relation between virtio-pci and virtio-xxx-pci is implicit, + * and therefore virtio-pci does not produce virtio and is not + * reached by any edge, not even as a "contains" edge. + * In facts, every device is a QVirtioPCIDevice with + * additional fields, since every one has its own + * number of queues and various attributes. + * Virtio-pci provides default functions to start the + * hw and destroy the object, and nodes that want to + * override them should always remember to call the + * original qvirtio_pci_destructor and qvirtio_pci_start_hw. + */ -static void qvirtio_pci_foreach_callback( - QPCIDevice *dev, int devfn, void *data) +static inline bool qvirtio_pci_is_big_endian(QVirtioPCIDevice *dev) { - QVirtioPCIForeachData *d = data; - QVirtioPCIDevice *vpcidev = qpcidevice_to_qvirtiodevice(dev); - - if (vpcidev->vdev.device_type == d->device_type && - (!d->has_slot || vpcidev->pdev->devfn == d->slot << 3)) { - d->func(&vpcidev->vdev, d->user_data); - } else { - qvirtio_pci_device_free(vpcidev); - } -} + QPCIBus *bus = dev->pdev->bus; -static void qvirtio_pci_assign_device(QVirtioDevice *d, void *data) -{ - QVirtioPCIDevice **vpcidev = data; - assert(!*vpcidev); - *vpcidev = (QVirtioPCIDevice *)d; + /* FIXME: virtio 1.0 is always little-endian */ + return qtest_big_endian(bus->qts); } #define CONFIG_BASE(dev) (VIRTIO_PCI_CONFIG_OFF((dev)->pdev->msix_enabled)) static uint8_t qvirtio_pci_config_readb(QVirtioDevice *d, uint64_t off) { - QVirtioPCIDevice *dev = (QVirtioPCIDevice *)d; + QVirtioPCIDevice *dev = container_of(d, QVirtioPCIDevice, vdev); return qpci_io_readb(dev->pdev, dev->bar, CONFIG_BASE(dev) + off); } @@ -85,12 +56,12 @@ static uint8_t qvirtio_pci_config_readb(QVirtioDevice *d, uint64_t off) * so with a big-endian guest the order has been reversed, * reverse it again * virtio-1.0 is always little-endian, like PCI, but this - * case will be managed inside qvirtio_is_big_endian() + * case will be managed inside qvirtio_pci_is_big_endian() */ static uint16_t qvirtio_pci_config_readw(QVirtioDevice *d, uint64_t off) { - QVirtioPCIDevice *dev = (QVirtioPCIDevice *)d; + QVirtioPCIDevice *dev = container_of(d, QVirtioPCIDevice, vdev); uint16_t value; value = qpci_io_readw(dev->pdev, dev->bar, CONFIG_BASE(dev) + off); @@ -102,7 +73,7 @@ static uint16_t qvirtio_pci_config_readw(QVirtioDevice *d, uint64_t off) static uint32_t qvirtio_pci_config_readl(QVirtioDevice *d, uint64_t off) { - QVirtioPCIDevice *dev = (QVirtioPCIDevice *)d; + QVirtioPCIDevice *dev = container_of(d, QVirtioPCIDevice, vdev); uint32_t value; value = qpci_io_readl(dev->pdev, dev->bar, CONFIG_BASE(dev) + off); @@ -114,7 +85,7 @@ static uint32_t qvirtio_pci_config_readl(QVirtioDevice *d, uint64_t off) static uint64_t qvirtio_pci_config_readq(QVirtioDevice *d, uint64_t off) { - QVirtioPCIDevice *dev = (QVirtioPCIDevice *)d; + QVirtioPCIDevice *dev = container_of(d, QVirtioPCIDevice, vdev); uint64_t val; val = qpci_io_readq(dev->pdev, dev->bar, CONFIG_BASE(dev) + off); @@ -127,37 +98,37 @@ static uint64_t qvirtio_pci_config_readq(QVirtioDevice *d, uint64_t off) static uint32_t qvirtio_pci_get_features(QVirtioDevice *d) { - QVirtioPCIDevice *dev = (QVirtioPCIDevice *)d; + QVirtioPCIDevice *dev = container_of(d, QVirtioPCIDevice, vdev); return qpci_io_readl(dev->pdev, dev->bar, VIRTIO_PCI_HOST_FEATURES); } static void qvirtio_pci_set_features(QVirtioDevice *d, uint32_t features) { - QVirtioPCIDevice *dev = (QVirtioPCIDevice *)d; + QVirtioPCIDevice *dev = container_of(d, QVirtioPCIDevice, vdev); qpci_io_writel(dev->pdev, dev->bar, VIRTIO_PCI_GUEST_FEATURES, features); } static uint32_t qvirtio_pci_get_guest_features(QVirtioDevice *d) { - QVirtioPCIDevice *dev = (QVirtioPCIDevice *)d; + QVirtioPCIDevice *dev = container_of(d, QVirtioPCIDevice, vdev); return qpci_io_readl(dev->pdev, dev->bar, VIRTIO_PCI_GUEST_FEATURES); } static uint8_t qvirtio_pci_get_status(QVirtioDevice *d) { - QVirtioPCIDevice *dev = (QVirtioPCIDevice *)d; + QVirtioPCIDevice *dev = container_of(d, QVirtioPCIDevice, vdev); return qpci_io_readb(dev->pdev, dev->bar, VIRTIO_PCI_STATUS); } static void qvirtio_pci_set_status(QVirtioDevice *d, uint8_t status) { - QVirtioPCIDevice *dev = (QVirtioPCIDevice *)d; + QVirtioPCIDevice *dev = container_of(d, QVirtioPCIDevice, vdev); qpci_io_writeb(dev->pdev, dev->bar, VIRTIO_PCI_STATUS, status); } static bool qvirtio_pci_get_queue_isr_status(QVirtioDevice *d, QVirtQueue *vq) { - QVirtioPCIDevice *dev = (QVirtioPCIDevice *)d; + QVirtioPCIDevice *dev = container_of(d, QVirtioPCIDevice, vdev); QVirtQueuePCI *vqpci = (QVirtQueuePCI *)vq; uint32_t data; @@ -182,7 +153,7 @@ static bool qvirtio_pci_get_queue_isr_status(QVirtioDevice *d, QVirtQueue *vq) static bool qvirtio_pci_get_config_isr_status(QVirtioDevice *d) { - QVirtioPCIDevice *dev = (QVirtioPCIDevice *)d; + QVirtioPCIDevice *dev = container_of(d, QVirtioPCIDevice, vdev); uint32_t data; if (dev->pdev->msix_enabled) { @@ -206,19 +177,19 @@ static bool qvirtio_pci_get_config_isr_status(QVirtioDevice *d) static void qvirtio_pci_queue_select(QVirtioDevice *d, uint16_t index) { - QVirtioPCIDevice *dev = (QVirtioPCIDevice *)d; + QVirtioPCIDevice *dev = container_of(d, QVirtioPCIDevice, vdev); qpci_io_writeb(dev->pdev, dev->bar, VIRTIO_PCI_QUEUE_SEL, index); } static uint16_t qvirtio_pci_get_queue_size(QVirtioDevice *d) { - QVirtioPCIDevice *dev = (QVirtioPCIDevice *)d; + QVirtioPCIDevice *dev = container_of(d, QVirtioPCIDevice, vdev); return qpci_io_readw(dev->pdev, dev->bar, VIRTIO_PCI_QUEUE_NUM); } static void qvirtio_pci_set_queue_address(QVirtioDevice *d, uint32_t pfn) { - QVirtioPCIDevice *dev = (QVirtioPCIDevice *)d; + QVirtioPCIDevice *dev = container_of(d, QVirtioPCIDevice, vdev); qpci_io_writel(dev->pdev, dev->bar, VIRTIO_PCI_QUEUE_PFN, pfn); } @@ -270,7 +241,7 @@ static void qvirtio_pci_virtqueue_cleanup(QVirtQueue *vq, static void qvirtio_pci_virtqueue_kick(QVirtioDevice *d, QVirtQueue *vq) { - QVirtioPCIDevice *dev = (QVirtioPCIDevice *)d; + QVirtioPCIDevice *dev = container_of(d, QVirtioPCIDevice, vdev); qpci_io_writew(dev->pdev, dev->bar, VIRTIO_PCI_QUEUE_NOTIFY, vq->index); } @@ -294,47 +265,6 @@ const QVirtioBus qvirtio_pci = { .virtqueue_kick = qvirtio_pci_virtqueue_kick, }; -static void qvirtio_pci_foreach(QPCIBus *bus, uint16_t device_type, - bool has_slot, int slot, - void (*func)(QVirtioDevice *d, void *data), void *data) -{ - QVirtioPCIForeachData d = { .func = func, - .device_type = device_type, - .has_slot = has_slot, - .slot = slot, - .user_data = data }; - - qpci_device_foreach(bus, PCI_VENDOR_ID_REDHAT_QUMRANET, -1, - qvirtio_pci_foreach_callback, &d); -} - -QVirtioPCIDevice *qvirtio_pci_device_find(QPCIBus *bus, uint16_t device_type) -{ - QVirtioPCIDevice *dev = NULL; - - qvirtio_pci_foreach(bus, device_type, false, 0, - qvirtio_pci_assign_device, &dev); - - if (dev) { - dev->vdev.bus = &qvirtio_pci; - } - - return dev; -} - -QVirtioPCIDevice *qvirtio_pci_device_find_slot(QPCIBus *bus, - uint16_t device_type, int slot) -{ - QVirtioPCIDevice *dev = NULL; - - qvirtio_pci_foreach(bus, device_type, true, slot, - qvirtio_pci_assign_device, &dev); - - dev->vdev.bus = &qvirtio_pci; - - return dev; -} - void qvirtio_pci_device_enable(QVirtioPCIDevice *d) { qpci_device_enable(d->pdev); @@ -416,3 +346,54 @@ void qvirtio_pci_set_msix_configuration_vector(QVirtioPCIDevice *d, vector = qpci_io_readw(d->pdev, d->bar, VIRTIO_MSI_CONFIG_VECTOR); g_assert_cmphex(vector, !=, VIRTIO_MSI_NO_VECTOR); } + +void qvirtio_pci_destructor(QOSGraphObject *obj) +{ + QVirtioPCIDevice *dev = (QVirtioPCIDevice *)obj; + qvirtio_pci_device_disable(dev); + g_free(dev->pdev); +} + +void qvirtio_pci_start_hw(QOSGraphObject *obj) +{ + QVirtioPCIDevice *dev = (QVirtioPCIDevice *)obj; + qvirtio_pci_device_enable(dev); + qvirtio_start_device(&dev->vdev); +} + +static void qvirtio_pci_init_from_pcidev(QVirtioPCIDevice *dev, QPCIDevice *pci_dev) +{ + dev->pdev = pci_dev; + dev->vdev.device_type = qpci_config_readw(pci_dev, PCI_SUBSYSTEM_ID); + + dev->config_msix_entry = -1; + + dev->vdev.bus = &qvirtio_pci; + dev->vdev.big_endian = qvirtio_pci_is_big_endian(dev); + + /* each virtio-xxx-pci device should override at least this function */ + dev->obj.get_driver = NULL; + dev->obj.start_hw = qvirtio_pci_start_hw; + dev->obj.destructor = qvirtio_pci_destructor; +} + +void virtio_pci_init(QVirtioPCIDevice *dev, QPCIBus *bus, QPCIAddress * addr) +{ + QPCIDevice *pci_dev = qpci_device_find(bus, addr->devfn); + g_assert_nonnull(pci_dev); + qvirtio_pci_init_from_pcidev(dev, pci_dev); +} + +QVirtioPCIDevice *virtio_pci_new(QPCIBus *bus, QPCIAddress * addr) +{ + QVirtioPCIDevice *dev; + QPCIDevice *pci_dev = qpci_device_find(bus, addr->devfn); + if (!pci_dev) { + return NULL; + } + + dev = g_new0(QVirtioPCIDevice, 1); + qvirtio_pci_init_from_pcidev(dev, pci_dev); + dev->obj.free = g_free; + return dev; +} diff --git a/tests/libqos/virtio-pci.h b/tests/libqos/virtio-pci.h index 6ef19094cb..728b4715f1 100644 --- a/tests/libqos/virtio-pci.h +++ b/tests/libqos/virtio-pci.h @@ -12,8 +12,10 @@ #include "libqos/virtio.h" #include "libqos/pci.h" +#include "libqos/qgraph.h" typedef struct QVirtioPCIDevice { + QOSGraphObject obj; QVirtioDevice vdev; QPCIDevice *pdev; QPCIBar bar; @@ -31,10 +33,18 @@ typedef struct QVirtQueuePCI { extern const QVirtioBus qvirtio_pci; -QVirtioPCIDevice *qvirtio_pci_device_find(QPCIBus *bus, uint16_t device_type); -QVirtioPCIDevice *qvirtio_pci_device_find_slot(QPCIBus *bus, - uint16_t device_type, int slot); -void qvirtio_pci_device_free(QVirtioPCIDevice *dev); +void virtio_pci_init(QVirtioPCIDevice *dev, QPCIBus *bus, QPCIAddress * addr); +QVirtioPCIDevice *virtio_pci_new(QPCIBus *bus, QPCIAddress * addr); + +/* virtio-pci object functions available for subclasses that + * override the original start_hw and destroy + * function. All virtio-xxx-pci subclass that override must + * take care of calling these two functions in the respective + * places + */ +void qvirtio_pci_destructor(QOSGraphObject *obj); +void qvirtio_pci_start_hw(QOSGraphObject *obj); + void qvirtio_pci_device_enable(QVirtioPCIDevice *d); void qvirtio_pci_device_disable(QVirtioPCIDevice *d); diff --git a/tests/libqos/virtio-rng.c b/tests/libqos/virtio-rng.c new file mode 100644 index 0000000000..a1d2c7671c --- /dev/null +++ b/tests/libqos/virtio-rng.c @@ -0,0 +1,110 @@ +/* + * libqos driver framework + * + * Copyright (c) 2018 Emanuele Giuseppe Esposito <e.emanuelegiuseppe@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/> + */ + +#include "qemu/osdep.h" +#include "libqtest.h" +#include "libqos/qgraph.h" +#include "libqos/virtio-rng.h" + +/* virtio-rng-device */ +static void *qvirtio_rng_get_driver(QVirtioRng *v_rng, + const char *interface) +{ + if (!g_strcmp0(interface, "virtio-rng")) { + return v_rng; + } + if (!g_strcmp0(interface, "virtio")) { + return v_rng->vdev; + } + + fprintf(stderr, "%s not present in virtio-rng-device\n", interface); + g_assert_not_reached(); +} + +static void *qvirtio_rng_device_get_driver(void *object, + const char *interface) +{ + QVirtioRngDevice *v_rng = object; + return qvirtio_rng_get_driver(&v_rng->rng, interface); +} + +static void *virtio_rng_device_create(void *virtio_dev, + QGuestAllocator *t_alloc, + void *addr) +{ + QVirtioRngDevice *virtio_rdevice = g_new0(QVirtioRngDevice, 1); + QVirtioRng *interface = &virtio_rdevice->rng; + + interface->vdev = virtio_dev; + + virtio_rdevice->obj.get_driver = qvirtio_rng_device_get_driver; + + return &virtio_rdevice->obj; +} + +/* virtio-rng-pci */ +static void *qvirtio_rng_pci_get_driver(void *object, const char *interface) +{ + QVirtioRngPCI *v_rng = object; + if (!g_strcmp0(interface, "pci-device")) { + return v_rng->pci_vdev.pdev; + } + return qvirtio_rng_get_driver(&v_rng->rng, interface); +} + +static void *virtio_rng_pci_create(void *pci_bus, QGuestAllocator *t_alloc, + void *addr) +{ + QVirtioRngPCI *virtio_rpci = g_new0(QVirtioRngPCI, 1); + QVirtioRng *interface = &virtio_rpci->rng; + QOSGraphObject *obj = &virtio_rpci->pci_vdev.obj; + + virtio_pci_init(&virtio_rpci->pci_vdev, pci_bus, addr); + interface->vdev = &virtio_rpci->pci_vdev.vdev; + + obj->get_driver = qvirtio_rng_pci_get_driver; + + return obj; +} + +static void virtio_rng_register_nodes(void) +{ + QPCIAddress addr = { + .devfn = QPCI_DEVFN(4, 0), + }; + + QOSGraphEdgeOptions opts = { + .extra_device_opts = "addr=04.0", + }; + + /* virtio-rng-device */ + qos_node_create_driver("virtio-rng-device", virtio_rng_device_create); + qos_node_consumes("virtio-rng-device", "virtio-bus", NULL); + qos_node_produces("virtio-rng-device", "virtio"); + qos_node_produces("virtio-rng-device", "virtio-rng"); + + /* virtio-rng-pci */ + add_qpci_address(&opts, &addr); + qos_node_create_driver("virtio-rng-pci", virtio_rng_pci_create); + qos_node_consumes("virtio-rng-pci", "pci-bus", &opts); + qos_node_produces("virtio-rng-pci", "pci-device"); + qos_node_produces("virtio-rng-pci", "virtio"); + qos_node_produces("virtio-rng-pci", "virtio-rng"); +} + +libqos_init(virtio_rng_register_nodes); diff --git a/tests/libqos/virtio-rng.h b/tests/libqos/virtio-rng.h new file mode 100644 index 0000000000..fbba988875 --- /dev/null +++ b/tests/libqos/virtio-rng.h @@ -0,0 +1,39 @@ +/* + * libqos driver framework + * + * Copyright (c) 2018 Emanuele Giuseppe Esposito <e.emanuelegiuseppe@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/> + */ + +#include "libqos/qgraph.h" +#include "libqos/virtio.h" +#include "libqos/virtio-pci.h" + +typedef struct QVirtioRng QVirtioRng; +typedef struct QVirtioRngPCI QVirtioRngPCI; +typedef struct QVirtioRngDevice QVirtioRngDevice; + +struct QVirtioRng { + QVirtioDevice *vdev; +}; + +struct QVirtioRngPCI { + QVirtioPCIDevice pci_vdev; + QVirtioRng rng; +}; + +struct QVirtioRngDevice { + QOSGraphObject obj; + QVirtioRng rng; +}; diff --git a/tests/libqos/virtio-scsi.c b/tests/libqos/virtio-scsi.c new file mode 100644 index 0000000000..482684d0bc --- /dev/null +++ b/tests/libqos/virtio-scsi.c @@ -0,0 +1,117 @@ +/* + * libqos driver framework + * + * Copyright (c) 2018 Emanuele Giuseppe Esposito <e.emanuelegiuseppe@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/> + */ + +#include "qemu/osdep.h" +#include "libqtest.h" +#include "standard-headers/linux/virtio_ids.h" +#include "libqos/qgraph.h" +#include "libqos/virtio-scsi.h" + +/* virtio-scsi-device */ +static void *qvirtio_scsi_get_driver(QVirtioSCSI *v_scsi, + const char *interface) +{ + if (!g_strcmp0(interface, "virtio-scsi")) { + return v_scsi; + } + if (!g_strcmp0(interface, "virtio")) { + return v_scsi->vdev; + } + + fprintf(stderr, "%s not present in virtio-scsi-device\n", interface); + g_assert_not_reached(); +} + +static void *qvirtio_scsi_device_get_driver(void *object, + const char *interface) +{ + QVirtioSCSIDevice *v_scsi = object; + return qvirtio_scsi_get_driver(&v_scsi->scsi, interface); +} + +static void *virtio_scsi_device_create(void *virtio_dev, + QGuestAllocator *t_alloc, + void *addr) +{ + QVirtioSCSIDevice *virtio_bdevice = g_new0(QVirtioSCSIDevice, 1); + QVirtioSCSI *interface = &virtio_bdevice->scsi; + + interface->vdev = virtio_dev; + + virtio_bdevice->obj.get_driver = qvirtio_scsi_device_get_driver; + + return &virtio_bdevice->obj; +} + +/* virtio-scsi-pci */ +static void *qvirtio_scsi_pci_get_driver(void *object, + const char *interface) +{ + QVirtioSCSIPCI *v_scsi = object; + if (!g_strcmp0(interface, "pci-device")) { + return v_scsi->pci_vdev.pdev; + } + return qvirtio_scsi_get_driver(&v_scsi->scsi, interface); +} + +static void *virtio_scsi_pci_create(void *pci_bus, + QGuestAllocator *t_alloc, + void *addr) +{ + QVirtioSCSIPCI *virtio_spci = g_new0(QVirtioSCSIPCI, 1); + QVirtioSCSI *interface = &virtio_spci->scsi; + QOSGraphObject *obj = &virtio_spci->pci_vdev.obj; + + virtio_pci_init(&virtio_spci->pci_vdev, pci_bus, addr); + interface->vdev = &virtio_spci->pci_vdev.vdev; + + g_assert_cmphex(interface->vdev->device_type, ==, VIRTIO_ID_SCSI); + + obj->get_driver = qvirtio_scsi_pci_get_driver; + + return obj; +} + +static void virtio_scsi_register_nodes(void) +{ + QPCIAddress addr = { + .devfn = QPCI_DEVFN(4, 0), + }; + + QOSGraphEdgeOptions opts = { + .before_cmd_line = "-drive id=drv0,if=none,file=null-co://,format=raw", + .after_cmd_line = "-device scsi-hd,bus=vs0.0,drive=drv0", + }; + + /* virtio-scsi-device */ + opts.extra_device_opts = "id=vs0"; + qos_node_create_driver("virtio-scsi-device", + virtio_scsi_device_create); + qos_node_consumes("virtio-scsi-device", "virtio-bus", &opts); + qos_node_produces("virtio-scsi-device", "virtio-scsi"); + + /* virtio-scsi-pci */ + opts.extra_device_opts = "id=vs0,addr=04.0"; + add_qpci_address(&opts, &addr); + qos_node_create_driver("virtio-scsi-pci", virtio_scsi_pci_create); + qos_node_consumes("virtio-scsi-pci", "pci-bus", &opts); + qos_node_produces("virtio-scsi-pci", "pci-device"); + qos_node_produces("virtio-scsi-pci", "virtio-scsi"); +} + +libqos_init(virtio_scsi_register_nodes); diff --git a/tests/libqos/virtio-scsi.h b/tests/libqos/virtio-scsi.h new file mode 100644 index 0000000000..17a47beddc --- /dev/null +++ b/tests/libqos/virtio-scsi.h @@ -0,0 +1,39 @@ +/* + * libqos driver framework + * + * Copyright (c) 2018 Emanuele Giuseppe Esposito <e.emanuelegiuseppe@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/> + */ + +#include "libqos/qgraph.h" +#include "libqos/virtio.h" +#include "libqos/virtio-pci.h" + +typedef struct QVirtioSCSI QVirtioSCSI; +typedef struct QVirtioSCSIPCI QVirtioSCSIPCI; +typedef struct QVirtioSCSIDevice QVirtioSCSIDevice; + +struct QVirtioSCSI { + QVirtioDevice *vdev; +}; + +struct QVirtioSCSIPCI { + QVirtioPCIDevice pci_vdev; + QVirtioSCSI scsi; +}; + +struct QVirtioSCSIDevice { + QOSGraphObject obj; + QVirtioSCSI scsi; +}; diff --git a/tests/libqos/virtio-serial.c b/tests/libqos/virtio-serial.c new file mode 100644 index 0000000000..91cedefb8d --- /dev/null +++ b/tests/libqos/virtio-serial.c @@ -0,0 +1,110 @@ +/* + * libqos driver framework + * + * Copyright (c) 2018 Emanuele Giuseppe Esposito <e.emanuelegiuseppe@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/> + */ + +#include "qemu/osdep.h" +#include "libqtest.h" +#include "libqos/qgraph.h" +#include "libqos/virtio-serial.h" + +static void *qvirtio_serial_get_driver(QVirtioSerial *v_serial, + const char *interface) +{ + if (!g_strcmp0(interface, "virtio-serial")) { + return v_serial; + } + if (!g_strcmp0(interface, "virtio")) { + return v_serial->vdev; + } + + fprintf(stderr, "%s not present in virtio-serial-device\n", interface); + g_assert_not_reached(); +} + +static void *qvirtio_serial_device_get_driver(void *object, + const char *interface) +{ + QVirtioSerialDevice *v_serial = object; + return qvirtio_serial_get_driver(&v_serial->serial, interface); +} + +static void *virtio_serial_device_create(void *virtio_dev, + QGuestAllocator *t_alloc, + void *addr) +{ + QVirtioSerialDevice *virtio_device = g_new0(QVirtioSerialDevice, 1); + QVirtioSerial *interface = &virtio_device->serial; + + interface->vdev = virtio_dev; + + virtio_device->obj.get_driver = qvirtio_serial_device_get_driver; + + return &virtio_device->obj; +} + +/* virtio-serial-pci */ +static void *qvirtio_serial_pci_get_driver(void *object, const char *interface) +{ + QVirtioSerialPCI *v_serial = object; + if (!g_strcmp0(interface, "pci-device")) { + return v_serial->pci_vdev.pdev; + } + return qvirtio_serial_get_driver(&v_serial->serial, interface); +} + +static void *virtio_serial_pci_create(void *pci_bus, QGuestAllocator *t_alloc, + void *addr) +{ + QVirtioSerialPCI *virtio_spci = g_new0(QVirtioSerialPCI, 1); + QVirtioSerial *interface = &virtio_spci->serial; + QOSGraphObject *obj = &virtio_spci->pci_vdev.obj; + + virtio_pci_init(&virtio_spci->pci_vdev, pci_bus, addr); + interface->vdev = &virtio_spci->pci_vdev.vdev; + + obj->get_driver = qvirtio_serial_pci_get_driver; + + return obj; +} + +static void virtio_serial_register_nodes(void) +{ + QPCIAddress addr = { + .devfn = QPCI_DEVFN(4, 0), + }; + + QOSGraphEdgeOptions edge_opts = { }; + + /* virtio-serial-device */ + edge_opts.extra_device_opts = "id=vser0"; + qos_node_create_driver("virtio-serial-device", + virtio_serial_device_create); + qos_node_consumes("virtio-serial-device", "virtio-bus", &edge_opts); + qos_node_produces("virtio-serial-device", "virtio"); + qos_node_produces("virtio-serial-device", "virtio-serial"); + + /* virtio-serial-pci */ + edge_opts.extra_device_opts = "id=vser0,addr=04.0"; + add_qpci_address(&edge_opts, &addr); + qos_node_create_driver("virtio-serial-pci", virtio_serial_pci_create); + qos_node_consumes("virtio-serial-pci", "pci-bus", &edge_opts); + qos_node_produces("virtio-serial-pci", "pci-device"); + qos_node_produces("virtio-serial-pci", "virtio"); + qos_node_produces("virtio-serial-pci", "virtio-serial"); +} + +libqos_init(virtio_serial_register_nodes); diff --git a/tests/libqos/virtio-serial.h b/tests/libqos/virtio-serial.h new file mode 100644 index 0000000000..b7e2a5d178 --- /dev/null +++ b/tests/libqos/virtio-serial.h @@ -0,0 +1,39 @@ +/* + * libqos driver framework + * + * Copyright (c) 2018 Emanuele Giuseppe Esposito <e.emanuelegiuseppe@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/> + */ + +#include "libqos/qgraph.h" +#include "libqos/virtio.h" +#include "libqos/virtio-pci.h" + +typedef struct QVirtioSerial QVirtioSerial; +typedef struct QVirtioSerialPCI QVirtioSerialPCI; +typedef struct QVirtioSerialDevice QVirtioSerialDevice; + +struct QVirtioSerial { + QVirtioDevice *vdev; +}; + +struct QVirtioSerialPCI { + QVirtioPCIDevice pci_vdev; + QVirtioSerial serial; +}; + +struct QVirtioSerialDevice { + QOSGraphObject obj; + QVirtioSerial serial; +}; diff --git a/tests/libqos/virtio.c b/tests/libqos/virtio.c index 0dad5c19ac..5e8f39b4d3 100644 --- a/tests/libqos/virtio.c +++ b/tests/libqos/virtio.c @@ -40,6 +40,7 @@ uint32_t qvirtio_get_features(QVirtioDevice *d) void qvirtio_set_features(QVirtioDevice *d, uint32_t features) { + d->features = features; d->bus->set_features(d, features); } @@ -349,19 +350,14 @@ void qvirtqueue_set_used_event(QVirtQueue *vq, uint16_t idx) writew(vq->avail + 4 + (2 * vq->size), idx); } -/* - * qvirtio_get_dev_type: - * Returns: the preferred virtio bus/device type for the current architecture. - */ -const char *qvirtio_get_dev_type(void) +void qvirtio_start_device(QVirtioDevice *vdev) { - const char *arch = qtest_get_arch(); - - if (g_str_equal(arch, "arm") || g_str_equal(arch, "aarch64")) { - return "device"; /* for virtio-mmio */ - } else if (g_str_equal(arch, "s390x")) { - return "ccw"; - } else { - return "pci"; - } + qvirtio_reset(vdev); + qvirtio_set_acknowledge(vdev); + qvirtio_set_driver(vdev); +} + +bool qvirtio_is_big_endian(QVirtioDevice *d) +{ + return d->big_endian; } diff --git a/tests/libqos/virtio.h b/tests/libqos/virtio.h index 69b5b13840..51d2359ace 100644 --- a/tests/libqos/virtio.h +++ b/tests/libqos/virtio.h @@ -21,6 +21,8 @@ typedef struct QVirtioDevice { const QVirtioBus *bus; /* Device type */ uint16_t device_type; + uint64_t features; + bool big_endian; } QVirtioDevice; typedef struct QVirtQueue { @@ -90,12 +92,6 @@ struct QVirtioBus { void (*virtqueue_kick)(QVirtioDevice *d, QVirtQueue *vq); }; -static inline bool qvirtio_is_big_endian(QVirtioDevice *d) -{ - /* FIXME: virtio 1.0 is always little-endian */ - return qtest_big_endian(global_qtest); -} - static inline uint32_t qvring_size(uint32_t num, uint32_t align) { return ((sizeof(struct vring_desc) * num + sizeof(uint16_t) * (3 + num) @@ -109,6 +105,7 @@ uint32_t qvirtio_config_readl(QVirtioDevice *d, uint64_t addr); uint64_t qvirtio_config_readq(QVirtioDevice *d, uint64_t addr); uint32_t qvirtio_get_features(QVirtioDevice *d); void qvirtio_set_features(QVirtioDevice *d, uint32_t features); +bool qvirtio_is_big_endian(QVirtioDevice *d); void qvirtio_reset(QVirtioDevice *d); void qvirtio_set_acknowledge(QVirtioDevice *d); @@ -145,6 +142,6 @@ bool qvirtqueue_get_buf(QVirtQueue *vq, uint32_t *desc_idx, uint32_t *len); void qvirtqueue_set_used_event(QVirtQueue *vq, uint16_t idx); -const char *qvirtio_get_dev_type(void); +void qvirtio_start_device(QVirtioDevice *vdev); #endif diff --git a/tests/libqos/x86_64_pc-machine.c b/tests/libqos/x86_64_pc-machine.c new file mode 100644 index 0000000000..8bd0360ba9 --- /dev/null +++ b/tests/libqos/x86_64_pc-machine.c @@ -0,0 +1,114 @@ +/* + * libqos driver framework + * + * Copyright (c) 2018 Emanuele Giuseppe Esposito <e.emanuelegiuseppe@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/> + */ + +#include "qemu/osdep.h" +#include "libqtest.h" +#include "libqos/qgraph.h" +#include "pci-pc.h" +#include "malloc-pc.h" + +typedef struct QX86PCMachine QX86PCMachine; +typedef struct i440FX_pcihost i440FX_pcihost; +typedef struct QSDHCI_PCI QSDHCI_PCI; + +struct i440FX_pcihost { + QOSGraphObject obj; + QPCIBusPC pci; +}; + +struct QX86PCMachine { + QOSGraphObject obj; + QGuestAllocator alloc; + i440FX_pcihost bridge; +}; + +/* i440FX_pcihost */ + +static QOSGraphObject *i440FX_host_get_device(void *obj, const char *device) +{ + i440FX_pcihost *host = obj; + if (!g_strcmp0(device, "pci-bus-pc")) { + return &host->pci.obj; + } + fprintf(stderr, "%s not present in i440FX-pcihost\n", device); + g_assert_not_reached(); +} + +static void qos_create_i440FX_host(i440FX_pcihost *host, + QTestState *qts, + QGuestAllocator *alloc) +{ + host->obj.get_device = i440FX_host_get_device; + qpci_init_pc(&host->pci, qts, alloc); +} + +/* x86_64/pc machine */ + +static void pc_destructor(QOSGraphObject *obj) +{ + QX86PCMachine *machine = (QX86PCMachine *) obj; + alloc_destroy(&machine->alloc); +} + +static void *pc_get_driver(void *object, const char *interface) +{ + QX86PCMachine *machine = object; + if (!g_strcmp0(interface, "memory")) { + return &machine->alloc; + } + + fprintf(stderr, "%s not present in x86_64/pc\n", interface); + g_assert_not_reached(); +} + +static QOSGraphObject *pc_get_device(void *obj, const char *device) +{ + QX86PCMachine *machine = obj; + if (!g_strcmp0(device, "i440FX-pcihost")) { + return &machine->bridge.obj; + } + + fprintf(stderr, "%s not present in x86_64/pc\n", device); + g_assert_not_reached(); +} + +static void *qos_create_machine_pc(QTestState *qts) +{ + QX86PCMachine *machine = g_new0(QX86PCMachine, 1); + machine->obj.get_device = pc_get_device; + machine->obj.get_driver = pc_get_driver; + machine->obj.destructor = pc_destructor; + pc_alloc_init(&machine->alloc, qts, ALLOC_NO_FLAGS); + qos_create_i440FX_host(&machine->bridge, qts, &machine->alloc); + + return &machine->obj; +} + +static void pc_machine_register_nodes(void) +{ + qos_node_create_machine("i386/pc", qos_create_machine_pc); + qos_node_contains("i386/pc", "i440FX-pcihost", NULL); + + qos_node_create_machine("x86_64/pc", qos_create_machine_pc); + qos_node_contains("x86_64/pc", "i440FX-pcihost", NULL); + + qos_node_create_driver("i440FX-pcihost", NULL); + qos_node_contains("i440FX-pcihost", "pci-bus-pc", NULL); +} + +libqos_init(pc_machine_register_nodes); diff --git a/tests/libqtest.h b/tests/libqtest.h index 5937f91912..a16acd58a6 100644 --- a/tests/libqtest.h +++ b/tests/libqtest.h @@ -17,6 +17,9 @@ #ifndef LIBQTEST_H #define LIBQTEST_H +#include "qapi/qmp/qobject.h" +#include "qapi/qmp/qdict.h" + typedef struct QTestState QTestState; extern QTestState *global_qtest; @@ -598,6 +601,9 @@ static inline QTestState *qtest_start(const char *args) */ static inline void qtest_end(void) { + if (!global_qtest) { + return; + } qtest_quit(global_qtest); global_qtest = NULL; } diff --git a/tests/m48t59-test.c b/tests/m48t59-test.c index 4abf9c605c..b94a1230f7 100644 --- a/tests/m48t59-test.c +++ b/tests/m48t59-test.c @@ -199,9 +199,9 @@ static void bcd_check_time(void) t = (long)mktime(datep); s = (long)mktime(&start); if (t < s) { - g_test_message("RTC is %ld second(s) behind wall-clock\n", (s - t)); + g_test_message("RTC is %ld second(s) behind wall-clock", (s - t)); } else { - g_test_message("RTC is %ld second(s) ahead of wall-clock\n", (t - s)); + g_test_message("RTC is %ld second(s) ahead of wall-clock", (t - s)); } g_assert_cmpint(ABS(t - s), <=, wiggle); diff --git a/tests/megasas-test.c b/tests/megasas-test.c index 81837e14af..33aa97042c 100644 --- a/tests/megasas-test.c +++ b/tests/megasas-test.c @@ -10,55 +10,49 @@ #include "qemu/osdep.h" #include "libqtest.h" #include "qemu/bswap.h" -#include "libqos/libqos-pc.h" -#include "libqos/libqos-spapr.h" +#include "libqos/qgraph.h" +#include "libqos/pci.h" -static QOSState *qmegasas_start(const char *extra_opts) +typedef struct QMegasas QMegasas; + +struct QMegasas { + QOSGraphObject obj; + QPCIDevice dev; +}; + +static void *megasas_get_driver(void *obj, const char *interface) { - QOSState *qs; - const char *arch = qtest_get_arch(); - const char *cmd = "-drive id=hd0,if=none,file=null-co://,format=raw " - "-device megasas,id=scsi0,addr=04.0 " - "-device scsi-hd,bus=scsi0.0,drive=hd0 %s"; - - if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) { - qs = qtest_pc_boot(cmd, extra_opts ? : ""); - global_qtest = qs->qts; - return qs; + QMegasas *megasas = obj; + + if (!g_strcmp0(interface, "pci-device")) { + return &megasas->dev; } - g_printerr("virtio-scsi tests are only available on x86 or ppc64\n"); - exit(EXIT_FAILURE); + fprintf(stderr, "%s not present in megasas\n", interface); + g_assert_not_reached(); } -static void qmegasas_stop(QOSState *qs) +static void *megasas_create(void *pci_bus, QGuestAllocator *alloc, void *addr) { - qtest_shutdown(qs); -} + QMegasas *megasas = g_new0(QMegasas, 1); + QPCIBus *bus = pci_bus; -/* Tests only initialization so far. TODO: Replace with functional tests */ -static void pci_nop(void) -{ - QOSState *qs; + qpci_device_init(&megasas->dev, bus, addr); + megasas->obj.get_driver = megasas_get_driver; - qs = qmegasas_start(NULL); - qmegasas_stop(qs); + return &megasas->obj; } /* This used to cause a NULL pointer dereference. */ -static void megasas_pd_get_info_fuzz(void) +static void megasas_pd_get_info_fuzz(void *obj, void *data, QGuestAllocator *alloc) { - QPCIDevice *dev; - QOSState *qs; + QMegasas *megasas = obj; + QPCIDevice *dev = &megasas->dev; QPCIBar bar; uint32_t context[256]; uint64_t context_pa; int i; - qs = qmegasas_start(NULL); - dev = qpci_device_find(qs->pcibus, QPCI_DEVFN(4,0)); - g_assert(dev != NULL); - qpci_device_enable(dev); bar = qpci_iomap(dev, 0, NULL); @@ -71,19 +65,25 @@ static void megasas_pd_get_info_fuzz(void) context[6] = cpu_to_le32(0x02020000); context[7] = cpu_to_le32(0); - context_pa = qmalloc(qs, sizeof(context)); + context_pa = guest_alloc(alloc, sizeof(context)); memwrite(context_pa, context, sizeof(context)); qpci_io_writel(dev, bar, 0x40, context_pa); - - g_free(dev); - qmegasas_stop(qs); } -int main(int argc, char **argv) +static void megasas_register_nodes(void) { - g_test_init(&argc, &argv, NULL); - qtest_add_func("/megasas/pci/nop", pci_nop); - qtest_add_func("/megasas/dcmd/pd-get-info/fuzz", megasas_pd_get_info_fuzz); + QOSGraphEdgeOptions opts = { + .extra_device_opts = "addr=04.0,id=scsi0", + .before_cmd_line = "-drive id=drv0,if=none,file=null-co://,format=raw", + .after_cmd_line = "-device scsi-hd,bus=scsi0.0,drive=drv0", + }; + + add_qpci_address(&opts, &(QPCIAddress) { .devfn = QPCI_DEVFN(4, 0) }); + + qos_node_create_driver("megasas", megasas_create); + qos_node_consumes("megasas", "pci-bus", &opts); + qos_node_produces("megasas", "pci-device"); - return g_test_run(); + qos_add_test("dcmd/pd-get-info/fuzz", "megasas", megasas_pd_get_info_fuzz, NULL); } +libqos_init(megasas_register_nodes); diff --git a/tests/migration-test.c b/tests/migration-test.c index e3617ceaca..48dc20a2ae 100644 --- a/tests/migration-test.c +++ b/tests/migration-test.c @@ -1066,7 +1066,7 @@ int main(int argc, char **argv) tmpfs = mkdtemp(template); if (!tmpfs) { - g_test_message("mkdtemp on path (%s): %s\n", template, strerror(errno)); + g_test_message("mkdtemp on path (%s): %s", template, strerror(errno)); } g_assert(tmpfs); @@ -1087,7 +1087,7 @@ int main(int argc, char **argv) ret = rmdir(tmpfs); if (ret != 0) { - g_test_message("unable to rmdir: path (%s): %s\n", + g_test_message("unable to rmdir: path (%s): %s", tmpfs, strerror(errno)); } diff --git a/tests/ne2000-test.c b/tests/ne2000-test.c index b7cf3dd2f5..097c2eec6c 100644 --- a/tests/ne2000-test.c +++ b/tests/ne2000-test.c @@ -9,23 +9,49 @@ #include "qemu/osdep.h" #include "libqtest.h" +#include "libqos/qgraph.h" +#include "libqos/pci.h" -/* Tests only initialization so far. TODO: Replace with functional tests */ -static void pci_nop(void) +typedef struct QNe2k_pci QNe2k_pci; + +struct QNe2k_pci { + QOSGraphObject obj; + QPCIDevice dev; +}; + +static void *ne2k_pci_get_driver(void *obj, const char *interface) { + QNe2k_pci *ne2k_pci = obj; + + if (!g_strcmp0(interface, "pci-device")) { + return &ne2k_pci->dev; + } + + fprintf(stderr, "%s not present in ne2k_pci\n", interface); + g_assert_not_reached(); } -int main(int argc, char **argv) +static void *ne2k_pci_create(void *pci_bus, QGuestAllocator *alloc, void *addr) { - int ret; + QNe2k_pci *ne2k_pci = g_new0(QNe2k_pci, 1); + QPCIBus *bus = pci_bus; - g_test_init(&argc, &argv, NULL); - qtest_add_func("/ne2000/pci/nop", pci_nop); + qpci_device_init(&ne2k_pci->dev, bus, addr); + ne2k_pci->obj.get_driver = ne2k_pci_get_driver; - qtest_start("-device ne2k_pci"); - ret = g_test_run(); + return &ne2k_pci->obj; +} - qtest_end(); +static void ne2000_register_nodes(void) +{ + QOSGraphEdgeOptions opts = { + .extra_device_opts = "addr=04.0", + }; + add_qpci_address(&opts, &(QPCIAddress) { .devfn = QPCI_DEVFN(4, 0) }); - return ret; + qos_node_create_driver("ne2k_pci", ne2k_pci_create); + qos_node_consumes("ne2k_pci", "pci-bus", &opts); + qos_node_produces("ne2k_pci", "pci-device"); } + +libqos_init(ne2000_register_nodes); diff --git a/tests/nvme-test.c b/tests/nvme-test.c index 2700ba838a..b48d3a24b9 100644 --- a/tests/nvme-test.c +++ b/tests/nvme-test.c @@ -10,49 +10,47 @@ #include "qemu/osdep.h" #include "qemu/units.h" #include "libqtest.h" -#include "libqos/libqos-pc.h" +#include "libqos/qgraph.h" +#include "libqos/pci.h" -static QOSState *qnvme_start(const char *extra_opts) +typedef struct QNvme QNvme; + +struct QNvme { + QOSGraphObject obj; + QPCIDevice dev; +}; + +static void *nvme_get_driver(void *obj, const char *interface) { - QOSState *qs; - const char *arch = qtest_get_arch(); - const char *cmd = "-drive id=drv0,if=none,file=null-co://,format=raw " - "-device nvme,addr=0x4.0,serial=foo,drive=drv0 %s"; - - if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) { - qs = qtest_pc_boot(cmd, extra_opts ? : ""); - global_qtest = qs->qts; - return qs; + QNvme *nvme = obj; + + if (!g_strcmp0(interface, "pci-device")) { + return &nvme->dev; } - g_printerr("nvme tests are only available on x86\n"); - exit(EXIT_FAILURE); + fprintf(stderr, "%s not present in nvme\n", interface); + g_assert_not_reached(); } -static void qnvme_stop(QOSState *qs) +static void *nvme_create(void *pci_bus, QGuestAllocator *alloc, void *addr) { - qtest_shutdown(qs); -} + QNvme *nvme = g_new0(QNvme, 1); + QPCIBus *bus = pci_bus; -static void nop(void) -{ - QOSState *qs; + qpci_device_init(&nvme->dev, bus, addr); + nvme->obj.get_driver = nvme_get_driver; - qs = qnvme_start(NULL); - qnvme_stop(qs); + return &nvme->obj; } -static void nvmetest_cmb_test(void) +/* This used to cause a NULL pointer dereference. */ +static void nvmetest_oob_cmb_test(void *obj, void *data, QGuestAllocator *alloc) { const int cmb_bar_size = 2 * MiB; - QOSState *qs; - QPCIDevice *pdev; + QNvme *nvme = obj; + QPCIDevice *pdev = &nvme->dev; QPCIBar bar; - qs = qnvme_start("-global nvme.cmb_size_mb=2"); - pdev = qpci_device_find(qs->pcibus, QPCI_DEVFN(4,0)); - g_assert(pdev != NULL); - qpci_device_enable(pdev); bar = qpci_iomap(pdev, 2, NULL); @@ -65,16 +63,24 @@ static void nvmetest_cmb_test(void) g_assert_cmpint(qpci_io_readb(pdev, bar, cmb_bar_size - 1), ==, 0x11); g_assert_cmpint(qpci_io_readw(pdev, bar, cmb_bar_size - 1), !=, 0x2211); g_assert_cmpint(qpci_io_readl(pdev, bar, cmb_bar_size - 1), !=, 0x44332211); - g_free(pdev); - - qnvme_stop(qs); } -int main(int argc, char **argv) +static void nvme_register_nodes(void) { - g_test_init(&argc, &argv, NULL); - qtest_add_func("/nvme/nop", nop); - qtest_add_func("/nvme/cmb_test", nvmetest_cmb_test); + QOSGraphEdgeOptions opts = { + .extra_device_opts = "addr=04.0,drive=drv0,serial=foo", + .before_cmd_line = "-drive id=drv0,if=none,file=null-co://,format=raw", + }; + + add_qpci_address(&opts, &(QPCIAddress) { .devfn = QPCI_DEVFN(4, 0) }); - return g_test_run(); + qos_node_create_driver("nvme", nvme_create); + qos_node_consumes("nvme", "pci-bus", &opts); + qos_node_produces("nvme", "pci-device"); + + qos_add_test("oob-cmb-access", "nvme", nvmetest_oob_cmb_test, &(QOSGraphTestOptions) { + .edge.extra_device_opts = "cmb_size_mb=2" + }); } + +libqos_init(nvme_register_nodes); diff --git a/tests/pci-test.c b/tests/pci-test.c new file mode 100644 index 0000000000..ff80985093 --- /dev/null +++ b/tests/pci-test.c @@ -0,0 +1,25 @@ +/* + * QTest testcase for PCI + * + * Copyright (c) 2018 Red Hat, Inc. + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#include "qemu/osdep.h" +#include "libqtest.h" +#include "libqos/qgraph.h" +#include "libqos/pci.h" + +/* Tests only initialization so far. TODO: Replace with functional tests */ +static void nop(void *obj, void *data, QGuestAllocator *alloc) +{ +} + +static void register_pci_test(void) +{ + qos_add_test("nop", "pci-device", nop, NULL); +} + +libqos_init(register_pci_test); diff --git a/tests/pcnet-test.c b/tests/pcnet-test.c index efb1ef44e9..484448cc64 100644 --- a/tests/pcnet-test.c +++ b/tests/pcnet-test.c @@ -9,23 +9,49 @@ #include "qemu/osdep.h" #include "libqtest.h" +#include "libqos/qgraph.h" +#include "libqos/pci.h" -/* Tests only initialization so far. TODO: Replace with functional tests */ -static void pci_nop(void) +typedef struct QPCNet QPCNet; + +struct QPCNet { + QOSGraphObject obj; + QPCIDevice dev; +}; + +static void *pcnet_get_driver(void *obj, const char *interface) { + QPCNet *pcnet = obj; + + if (!g_strcmp0(interface, "pci-device")) { + return &pcnet->dev; + } + + fprintf(stderr, "%s not present in pcnet\n", interface); + g_assert_not_reached(); } -int main(int argc, char **argv) +static void *pcnet_create(void *pci_bus, QGuestAllocator *alloc, void *addr) { - int ret; + QPCNet *pcnet = g_new0(QPCNet, 1); + QPCIBus *bus = pci_bus; - g_test_init(&argc, &argv, NULL); - qtest_add_func("/pcnet/pci/nop", pci_nop); + qpci_device_init(&pcnet->dev, bus, addr); + pcnet->obj.get_driver = pcnet_get_driver; - qtest_start("-device pcnet"); - ret = g_test_run(); + return &pcnet->obj; +} - qtest_end(); +static void pcnet_register_nodes(void) +{ + QOSGraphEdgeOptions opts = { + .extra_device_opts = "addr=04.0", + }; + add_qpci_address(&opts, &(QPCIAddress) { .devfn = QPCI_DEVFN(4, 0) }); - return ret; + qos_node_create_driver("pcnet", pcnet_create); + qos_node_consumes("pcnet", "pci-bus", &opts); + qos_node_produces("pcnet", "pci-device"); } + +libqos_init(pcnet_register_nodes); diff --git a/tests/q35-test.c b/tests/q35-test.c index 7ea7acc9d8..34b34bc2b9 100644 --- a/tests/q35-test.c +++ b/tests/q35-test.c @@ -87,7 +87,7 @@ static void test_smram_lock(void) qtest_start("-M q35"); - pcibus = qpci_init_pc(global_qtest, NULL); + pcibus = qpci_new_pc(global_qtest, NULL); g_assert(pcibus != NULL); pcidev = qpci_device_find(pcibus, 0); @@ -146,7 +146,7 @@ static void test_tseg_size(const void *data) g_free(cmdline); /* locate the DRAM controller */ - pcibus = qpci_init_pc(global_qtest, NULL); + pcibus = qpci_new_pc(global_qtest, NULL); g_assert(pcibus != NULL); pcidev = qpci_device_find(pcibus, 0); g_assert(pcidev != NULL); diff --git a/tests/qos-test.c b/tests/qos-test.c new file mode 100644 index 0000000000..6b1145eccc --- /dev/null +++ b/tests/qos-test.c @@ -0,0 +1,445 @@ +/* + * libqos driver framework + * + * Copyright (c) 2018 Emanuele Giuseppe Esposito <e.emanuelegiuseppe@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/> + */ + +#include <getopt.h> +#include "qemu/osdep.h" +#include "libqtest.h" +#include "qapi/qmp/qdict.h" +#include "qapi/qmp/qbool.h" +#include "qapi/qmp/qstring.h" +#include "qapi/qmp/qlist.h" +#include "libqos/malloc.h" +#include "libqos/qgraph.h" +#include "libqos/qgraph_internal.h" + +static char *old_path; + +static void apply_to_node(const char *name, bool is_machine, bool is_abstract) +{ + char *machine_name = NULL; + if (is_machine) { + const char *arch = qtest_get_arch(); + machine_name = g_strconcat(arch, "/", name, NULL); + name = machine_name; + } + qos_graph_node_set_availability(name, true); + if (is_abstract) { + qos_delete_cmd_line(name); + } + g_free(machine_name); +} + +/** + * apply_to_qlist(): using QMP queries QEMU for a list of + * machines and devices available, and sets the respective node + * as true. If a node is found, also all its produced and contained + * child are marked available. + * + * See qos_graph_node_set_availability() for more info + */ +static void apply_to_qlist(QList *list, bool is_machine) +{ + const QListEntry *p; + const char *name; + bool abstract; + QDict *minfo; + QObject *qobj; + QString *qstr; + QBool *qbool; + + for (p = qlist_first(list); p; p = qlist_next(p)) { + minfo = qobject_to(QDict, qlist_entry_obj(p)); + qobj = qdict_get(minfo, "name"); + qstr = qobject_to(QString, qobj); + name = qstring_get_str(qstr); + + qobj = qdict_get(minfo, "abstract"); + if (qobj) { + qbool = qobject_to(QBool, qobj); + abstract = qbool_get_bool(qbool); + } else { + abstract = false; + } + + apply_to_node(name, is_machine, abstract); + qobj = qdict_get(minfo, "alias"); + if (qobj) { + qstr = qobject_to(QString, qobj); + name = qstring_get_str(qstr); + apply_to_node(name, is_machine, abstract); + } + } +} + +/** + * qos_set_machines_devices_available(): sets availability of qgraph + * machines and devices. + * + * This function firstly starts QEMU with "-machine none" option, + * and then executes the QMP protocol asking for the list of devices + * and machines available. + * + * for each of these items, it looks up the corresponding qgraph node, + * setting it as available. The list currently returns all devices that + * are either machines or QEDGE_CONSUMED_BY other nodes. + * Therefore, in order to mark all other nodes, it recursively sets + * all its QEDGE_CONTAINS and QEDGE_PRODUCES child as available too. + */ +static void qos_set_machines_devices_available(void) +{ + QDict *response; + QDict *args = qdict_new(); + QList *list; + + qtest_start("-machine none"); + response = qmp("{ 'execute': 'query-machines' }"); + list = qdict_get_qlist(response, "return"); + + apply_to_qlist(list, true); + + qobject_unref(response); + + qdict_put_bool(args, "abstract", true); + qdict_put_str(args, "implements", "device"); + + response = qmp("{'execute': 'qom-list-types'," + " 'arguments': %p }", args); + g_assert(qdict_haskey(response, "return")); + list = qdict_get_qlist(response, "return"); + + apply_to_qlist(list, false); + + qtest_end(); + qobject_unref(response); +} + +static QGuestAllocator *get_machine_allocator(QOSGraphObject *obj) +{ + return obj->get_driver(obj, "memory"); +} + +static void restart_qemu_or_continue(char *path) +{ + /* compares the current command line with the + * one previously executed: if they are the same, + * don't restart QEMU, if they differ, stop previous + * QEMU subprocess (if active) and start over with + * the new command line + */ + if (g_strcmp0(old_path, path)) { + qtest_end(); + qos_invalidate_command_line(); + old_path = g_strdup(path); + qtest_start(path); + } else { /* if cmd line is the same, reset the guest */ + qobject_unref(qmp("{ 'execute': 'system_reset' }")); + qmp_eventwait("RESET"); + } +} + +void qos_invalidate_command_line(void) +{ + g_free(old_path); + old_path = NULL; +} + +/** + * allocate_objects(): given an array of nodes @arg, + * walks the path invoking all constructors and + * passing the corresponding parameter in order to + * continue the objects allocation. + * Once the test is reached, return the object it consumes. + * + * Since the machine and QEDGE_CONSUMED_BY nodes allocate + * memory in the constructor, g_test_queue_destroy is used so + * that after execution they can be safely free'd. (The test's + * ->before callback is also welcome to use g_test_queue_destroy). + * + * Note: as specified in walk_path() too, @arg is an array of + * char *, where arg[0] is a pointer to the command line + * string that will be used to properly start QEMU when executing + * the test, and the remaining elements represent the actual objects + * that will be allocated. + */ +static void *allocate_objects(QTestState *qts, char **path, QGuestAllocator **p_alloc) +{ + int current = 0; + QGuestAllocator *alloc; + QOSGraphObject *parent = NULL; + QOSGraphEdge *edge; + QOSGraphNode *node; + void *edge_arg; + void *obj; + + node = qos_graph_get_node(path[current]); + g_assert(node->type == QNODE_MACHINE); + + obj = qos_machine_new(node, qts); + qos_object_queue_destroy(obj); + + alloc = get_machine_allocator(obj); + if (p_alloc) { + *p_alloc = alloc; + } + + for (;;) { + if (node->type != QNODE_INTERFACE) { + qos_object_start_hw(obj); + parent = obj; + } + + /* follow edge and get object for next node constructor */ + current++; + edge = qos_graph_get_edge(path[current - 1], path[current]); + node = qos_graph_get_node(path[current]); + + if (node->type == QNODE_TEST) { + g_assert(qos_graph_edge_get_type(edge) == QEDGE_CONSUMED_BY); + return obj; + } + + switch (qos_graph_edge_get_type(edge)) { + case QEDGE_PRODUCES: + obj = parent->get_driver(parent, path[current]); + break; + + case QEDGE_CONSUMED_BY: + edge_arg = qos_graph_edge_get_arg(edge); + obj = qos_driver_new(node, obj, alloc, edge_arg); + qos_object_queue_destroy(obj); + break; + + case QEDGE_CONTAINS: + obj = parent->get_device(parent, path[current]); + break; + } + } +} + +/* The argument to run_one_test, which is the test function that is registered + * with GTest, is a vector of strings. The first item is the initial command + * line (before it is modified by the test's "before" function), the remaining + * items are node names forming the path to the test node. + */ +static char **current_path; + +const char *qos_get_current_command_line(void) +{ + return current_path[0]; +} + +void *qos_allocate_objects(QTestState *qts, QGuestAllocator **p_alloc) +{ + return allocate_objects(qts, current_path + 1, p_alloc); +} + +/** + * run_one_test(): given an array of nodes @arg, + * walks the path invoking all constructors and + * passing the corresponding parameter in order to + * continue the objects allocation. + * Once the test is reached, its function is executed. + * + * Since the machine and QEDGE_CONSUMED_BY nodes allocate + * memory in the constructor, g_test_queue_destroy is used so + * that after execution they can be safely free'd. The test's + * ->before callback is also welcome to use g_test_queue_destroy. + * + * Note: as specified in walk_path() too, @arg is an array of + * char *, where arg[0] is a pointer to the command line + * string that will be used to properly start QEMU when executing + * the test, and the remaining elements represent the actual objects + * that will be allocated. + * + * The order of execution is the following: + * 1) @before test function as defined in the given QOSGraphTestOptions + * 2) start QEMU + * 3) call all nodes constructor and get_driver/get_device depending on edge, + * start the hardware (*_device_enable functions) + * 4) start test + */ +static void run_one_test(const void *arg) +{ + QOSGraphNode *test_node; + QGuestAllocator *alloc = NULL; + void *obj; + char **path = (char **) arg; + GString *cmd_line = g_string_new(path[0]); + void *test_arg; + + /* Before test */ + current_path = path; + test_node = qos_graph_get_node(path[(g_strv_length(path) - 1)]); + test_arg = test_node->u.test.arg; + if (test_node->u.test.before) { + test_arg = test_node->u.test.before(cmd_line, test_arg); + } + + restart_qemu_or_continue(cmd_line->str); + g_string_free(cmd_line, true); + + obj = qos_allocate_objects(global_qtest, &alloc); + test_node->u.test.function(obj, test_arg, alloc); +} + +static void subprocess_run_one_test(const void *arg) +{ + const gchar *path = arg; + g_test_trap_subprocess(path, 0, 0); + g_test_trap_assert_passed(); +} + +/* + * in this function, 2 path will be built: + * path_str, a one-string path (ex "pc/i440FX-pcihost/...") + * path_vec, a string-array path (ex [0] = "pc", [1] = "i440FX-pcihost"). + * + * path_str will be only used to build the test name, and won't need the + * architecture name at beginning, since it will be added by qtest_add_func(). + * + * path_vec is used to allocate all constructors of the path nodes. + * Each name in this array except position 0 must correspond to a valid + * QOSGraphNode name. + * Position 0 is special, initially contains just the <machine> name of + * the node, (ex for "x86_64/pc" it will be "pc"), used to build the test + * path (see below). After it will contain the command line used to start + * qemu with all required devices. + * + * Note that the machine node name must be with format <arch>/<machine> + * (ex "x86_64/pc"), because it will identify the node "x86_64/pc" + * and start QEMU with "-M pc". For this reason, + * when building path_str, path_vec + * initially contains the <machine> at position 0 ("pc"), + * and the node name at position 1 (<arch>/<machine>) + * ("x86_64/pc"), followed by the rest of the nodes. + */ +static void walk_path(QOSGraphNode *orig_path, int len) +{ + QOSGraphNode *path; + QOSGraphEdge *edge; + + /* etype set to QEDGE_CONSUMED_BY so that machine can add to the command line */ + QOSEdgeType etype = QEDGE_CONSUMED_BY; + + /* twice QOS_PATH_MAX_ELEMENT_SIZE since each edge can have its arg */ + char **path_vec = g_new0(char *, (QOS_PATH_MAX_ELEMENT_SIZE * 2)); + int path_vec_size = 0; + + char *after_cmd = NULL, *before_cmd = NULL, *after_device = NULL; + char *node_name = orig_path->name, *path_str; + + GString *cmd_line = g_string_new(""); + GString *cmd_line2 = g_string_new(""); + + path = qos_graph_get_node(node_name); /* root */ + node_name = qos_graph_edge_get_dest(path->path_edge); /* machine name */ + + path_vec[path_vec_size++] = node_name; + path_vec[path_vec_size++] = qos_get_machine_type(node_name); + + for (;;) { + path = qos_graph_get_node(node_name); + if (!path->path_edge) { + break; + } + + node_name = qos_graph_edge_get_dest(path->path_edge); + + /* append node command line + previous edge command line */ + if (path->command_line && etype == QEDGE_CONSUMED_BY) { + g_string_append(cmd_line, path->command_line); + if (after_device) { + g_string_append(cmd_line, after_device); + } + } + + path_vec[path_vec_size++] = qos_graph_edge_get_name(path->path_edge); + /* detect if edge has command line args */ + after_cmd = qos_graph_edge_get_after_cmd_line(path->path_edge); + after_device = qos_graph_edge_get_extra_device_opts(path->path_edge); + before_cmd = qos_graph_edge_get_before_cmd_line(path->path_edge); + edge = qos_graph_get_edge(path->name, node_name); + etype = qos_graph_edge_get_type(edge); + + if (before_cmd) { + g_string_append(cmd_line, before_cmd); + } + if (after_cmd) { + g_string_append(cmd_line2, after_cmd); + } + } + + path_vec[path_vec_size++] = NULL; + if (after_device) { + g_string_append(cmd_line, after_device); + } + g_string_append(cmd_line, cmd_line2->str); + g_string_free(cmd_line2, true); + + /* here position 0 has <arch>/<machine>, position 1 has <machine>. + * The path must not have the <arch>, qtest_add_data_func adds it. + */ + path_str = g_strjoinv("/", path_vec + 1); + + /* put arch/machine in position 1 so run_one_test can do its work + * and add the command line at position 0. + */ + path_vec[1] = path_vec[0]; + path_vec[0] = g_string_free(cmd_line, false); + + if (path->u.test.subprocess) { + gchar *subprocess_path = g_strdup_printf("/%s/%s/subprocess", + qtest_get_arch(), path_str); + qtest_add_data_func(path_str, subprocess_path, subprocess_run_one_test); + g_test_add_data_func(subprocess_path, path_vec, run_one_test); + } else { + qtest_add_data_func(path_str, path_vec, run_one_test); + } + + g_free(path_str); +} + + + +/** + * main(): heart of the qgraph framework. + * + * - Initializes the glib test framework + * - Creates the graph by invoking the various _init constructors + * - Starts QEMU to mark the available devices + * - Walks the graph, and each path is added to + * the glib test framework (walk_path) + * - Runs the tests, calling allocate_object() and allocating the + * machine/drivers/test objects + * - Cleans up everything + */ +int main(int argc, char **argv) +{ + g_test_init(&argc, &argv, NULL); + qos_graph_init(); + module_call_init(MODULE_INIT_QOM); + module_call_init(MODULE_INIT_LIBQOS); + qos_set_machines_devices_available(); + + qos_graph_foreach_test_path(walk_path); + g_test_run(); + qtest_end(); + qos_graph_destroy(); + g_free(old_path); + return 0; +} diff --git a/tests/rtas-test.c b/tests/rtas-test.c index 009bda6d23..ee888676ed 100644 --- a/tests/rtas-test.c +++ b/tests/rtas-test.c @@ -17,7 +17,7 @@ static void test_rtas_get_time_of_day(void) global_qtest = qs->qts; t1 = time(NULL); - ret = qrtas_get_time_of_day(qs->qts, qs->alloc, &tm, &ns); + ret = qrtas_get_time_of_day(qs->qts, &qs->alloc, &tm, &ns); g_assert_cmpint(ret, ==, 0); t2 = mktimegm(&tm); g_assert(t2 - t1 < 5); /* 5 sec max to run the test */ diff --git a/tests/rtc-test.c b/tests/rtc-test.c index d7a96cbd79..509be707e3 100644 --- a/tests/rtc-test.c +++ b/tests/rtc-test.c @@ -165,9 +165,9 @@ static void check_time(int wiggle) t = (long)mktime(datep); s = (long)mktime(&start); if (t < s) { - g_test_message("RTC is %ld second(s) behind wall-clock\n", (s - t)); + g_test_message("RTC is %ld second(s) behind wall-clock", (s - t)); } else { - g_test_message("RTC is %ld second(s) ahead of wall-clock\n", (t - s)); + g_test_message("RTC is %ld second(s) ahead of wall-clock", (t - s)); } g_assert_cmpint(ABS(t - s), <=, wiggle); diff --git a/tests/rtl8139-test.c b/tests/rtl8139-test.c index 68bfc42178..d6d0c24909 100644 --- a/tests/rtl8139-test.c +++ b/tests/rtl8139-test.c @@ -35,7 +35,7 @@ static QPCIDevice *get_device(void) { QPCIDevice *dev; - pcibus = qpci_init_pc(global_qtest, NULL); + pcibus = qpci_new_pc(global_qtest, NULL); qpci_device_foreach(pcibus, 0x10ec, 0x8139, save_fn, &dev); g_assert(dev != NULL); @@ -46,12 +46,12 @@ static QPCIDevice *get_device(void) static unsigned __attribute__((unused)) in_##name(void) \ { \ unsigned res = qpci_io_read##len(dev, dev_bar, (val)); \ - g_test_message("*%s -> %x\n", #name, res); \ + g_test_message("*%s -> %x", #name, res); \ return res; \ } \ static void out_##name(unsigned v) \ { \ - g_test_message("%x -> *%s\n", v, #name); \ + g_test_message("%x -> *%s", v, #name); \ qpci_io_write##len(dev, dev_bar, (val), v); \ } @@ -176,7 +176,7 @@ static void test_timer(void) } } - g_test_message("Everythink is ok!\n"); + g_test_message("Everythink is ok!"); } diff --git a/tests/sdhci-test.c b/tests/sdhci-test.c index 982f5ebbb2..2f177e569f 100644 --- a/tests/sdhci-test.c +++ b/tests/sdhci-test.c @@ -12,6 +12,8 @@ #include "libqtest.h" #include "libqos/pci-pc.h" #include "hw/pci/pci.h" +#include "libqos/qgraph.h" +#include "libqos/sdhci.h" #define SDHC_CAPAB 0x40 FIELD(SDHC_CAPAB, BASECLKFREQ, 8, 8); /* since v2 */ @@ -20,99 +22,11 @@ FIELD(SDHC_CAPAB, SDR, 32, 3); /* since v3 */ FIELD(SDHC_CAPAB, DRIVER, 36, 3); /* since v3 */ #define SDHC_HCVER 0xFE -static const struct sdhci_t { - const char *arch, *machine; - struct { - uintptr_t addr; - uint8_t version; - uint8_t baseclock; - struct { - bool sdma; - uint64_t reg; - } capab; - } sdhci; - struct { - uint16_t vendor_id, device_id; - } pci; -} models[] = { - /* PC via PCI */ - { "x86_64", "pc", - {-1, 2, 0, {1, 0x057834b4} }, - .pci = { PCI_VENDOR_ID_REDHAT, PCI_DEVICE_ID_REDHAT_SDHCI } }, - - /* Exynos4210 */ - { "arm", "smdkc210", - {0x12510000, 2, 0, {1, 0x5e80080} } }, - - /* i.MX 6 */ - { "arm", "sabrelite", - {0x02190000, 3, 0, {1, 0x057834b4} } }, - - /* BCM2835 */ - { "arm", "raspi2", - {0x3f300000, 3, 52, {0, 0x052134b4} } }, - - /* Zynq-7000 */ - { "arm", "xilinx-zynq-a9", /* Datasheet: UG585 (v1.12.1) */ - {0xe0100000, 2, 0, {1, 0x69ec0080} } }, - - /* ZynqMP */ - { "aarch64", "xlnx-zcu102", /* Datasheet: UG1085 (v1.7) */ - {0xff160000, 3, 0, {1, 0x280737ec6481} } }, - -}; - -typedef struct QSDHCI { - struct { - QPCIBus *bus; - QPCIDevice *dev; - } pci; - union { - QPCIBar mem_bar; - uint64_t addr; - }; -} QSDHCI; - -static uint16_t sdhci_readw(QSDHCI *s, uint32_t reg) -{ - uint16_t val; - - if (s->pci.dev) { - val = qpci_io_readw(s->pci.dev, s->mem_bar, reg); - } else { - val = qtest_readw(global_qtest, s->addr + reg); - } - - return val; -} - -static uint64_t sdhci_readq(QSDHCI *s, uint32_t reg) -{ - uint64_t val; - - if (s->pci.dev) { - val = qpci_io_readq(s->pci.dev, s->mem_bar, reg); - } else { - val = qtest_readq(global_qtest, s->addr + reg); - } - - return val; -} - -static void sdhci_writeq(QSDHCI *s, uint32_t reg, uint64_t val) -{ - if (s->pci.dev) { - qpci_io_writeq(s->pci.dev, s->mem_bar, reg, val); - } else { - qtest_writeq(global_qtest, s->addr + reg, val); - } -} - static void check_specs_version(QSDHCI *s, uint8_t version) { uint32_t v; - v = sdhci_readw(s, SDHC_HCVER); + v = s->readw(s, SDHC_HCVER); v &= 0xff; v += 1; g_assert_cmpuint(v, ==, version); @@ -122,7 +36,7 @@ static void check_capab_capareg(QSDHCI *s, uint64_t expec_capab) { uint64_t capab; - capab = sdhci_readq(s, SDHC_CAPAB); + capab = s->readq(s, SDHC_CAPAB); g_assert_cmphex(capab, ==, expec_capab); } @@ -131,11 +45,11 @@ static void check_capab_readonly(QSDHCI *s) const uint64_t vrand = 0x123456789abcdef; uint64_t capab0, capab1; - capab0 = sdhci_readq(s, SDHC_CAPAB); + capab0 = s->readq(s, SDHC_CAPAB); g_assert_cmpuint(capab0, !=, vrand); - sdhci_writeq(s, SDHC_CAPAB, vrand); - capab1 = sdhci_readq(s, SDHC_CAPAB); + s->writeq(s, SDHC_CAPAB, vrand); + capab1 = s->readq(s, SDHC_CAPAB); g_assert_cmpuint(capab1, !=, vrand); g_assert_cmpuint(capab1, ==, capab0); } @@ -147,7 +61,7 @@ static void check_capab_baseclock(QSDHCI *s, uint8_t expec_freq) if (!expec_freq) { return; } - capab = sdhci_readq(s, SDHC_CAPAB); + capab = s->readq(s, SDHC_CAPAB); capab_freq = FIELD_EX64(capab, SDHC_CAPAB, BASECLKFREQ); g_assert_cmpuint(capab_freq, ==, expec_freq); } @@ -156,7 +70,7 @@ static void check_capab_sdma(QSDHCI *s, bool supported) { uint64_t capab, capab_sdma; - capab = sdhci_readq(s, SDHC_CAPAB); + capab = s->readq(s, SDHC_CAPAB); capab_sdma = FIELD_EX64(capab, SDHC_CAPAB, SDMA); g_assert_cmpuint(capab_sdma, ==, supported); } @@ -167,7 +81,7 @@ static void check_capab_v3(QSDHCI *s, uint8_t version) if (version < 3) { /* before v3 those fields are RESERVED */ - capab = sdhci_readq(s, SDHC_CAPAB); + capab = s->readq(s, SDHC_CAPAB); capab_v3 = FIELD_EX64(capab, SDHC_CAPAB, SDR); g_assert_cmpuint(capab_v3, ==, 0); capab_v3 = FIELD_EX64(capab, SDHC_CAPAB, DRIVER); @@ -175,78 +89,21 @@ static void check_capab_v3(QSDHCI *s, uint8_t version) } } -static QSDHCI *machine_start(const struct sdhci_t *test) -{ - QSDHCI *s = g_new0(QSDHCI, 1); - - if (test->pci.vendor_id) { - /* PCI */ - uint16_t vendor_id, device_id; - uint64_t barsize; - - global_qtest = qtest_initf("-machine %s -device sdhci-pci", - test->machine); - - s->pci.bus = qpci_init_pc(global_qtest, NULL); - - /* Find PCI device and verify it's the right one */ - s->pci.dev = qpci_device_find(s->pci.bus, QPCI_DEVFN(4, 0)); - g_assert_nonnull(s->pci.dev); - vendor_id = qpci_config_readw(s->pci.dev, PCI_VENDOR_ID); - device_id = qpci_config_readw(s->pci.dev, PCI_DEVICE_ID); - g_assert(vendor_id == test->pci.vendor_id); - g_assert(device_id == test->pci.device_id); - s->mem_bar = qpci_iomap(s->pci.dev, 0, &barsize); - qpci_device_enable(s->pci.dev); - } else { - /* SysBus */ - global_qtest = qtest_initf("-machine %s", test->machine); - s->addr = test->sdhci.addr; - } - - return s; -} - -static void machine_stop(QSDHCI *s) -{ - qpci_free_pc(s->pci.bus); - g_free(s->pci.dev); - qtest_quit(global_qtest); - g_free(s); -} - -static void test_machine(const void *data) +static void test_registers(void *obj, void *data, QGuestAllocator *alloc) { - const struct sdhci_t *test = data; - QSDHCI *s; + QSDHCI *s = obj; - s = machine_start(test); - - check_specs_version(s, test->sdhci.version); - check_capab_capareg(s, test->sdhci.capab.reg); + check_specs_version(s, s->props.version); + check_capab_capareg(s, s->props.capab.reg); check_capab_readonly(s); - check_capab_v3(s, test->sdhci.version); - check_capab_sdma(s, test->sdhci.capab.sdma); - check_capab_baseclock(s, test->sdhci.baseclock); - - machine_stop(s); + check_capab_v3(s, s->props.version); + check_capab_sdma(s, s->props.capab.sdma); + check_capab_baseclock(s, s->props.baseclock); } -int main(int argc, char *argv[]) +static void register_sdhci_test(void) { - const char *arch = qtest_get_arch(); - char *name; - int i; - - g_test_init(&argc, &argv, NULL); - for (i = 0; i < ARRAY_SIZE(models); i++) { - if (strcmp(arch, models[i].arch)) { - continue; - } - name = g_strdup_printf("sdhci/%s", models[i].machine); - qtest_add_data_func(name, &models[i], test_machine); - g_free(name); - } - - return g_test_run(); + qos_add_test("registers", "sdhci", test_registers, NULL); } + +libqos_init(register_sdhci_test); diff --git a/tests/spapr-phb-test.c b/tests/spapr-phb-test.c index d3522ea093..39b5766710 100644 --- a/tests/spapr-phb-test.c +++ b/tests/spapr-phb-test.c @@ -7,29 +7,25 @@ * This work is licensed under the terms of the GNU GPL, version 2 or later. * See the COPYING file in the top-level directory. */ -#include "qemu/osdep.h" +#include "qemu/osdep.h" #include "libqtest.h" +#include "libqos/qgraph.h" -#define TYPE_SPAPR_PCI_HOST_BRIDGE "spapr-pci-host-bridge" - -/* Tests only initialization so far. TODO: Replace with functional tests */ -static void test_phb_device(void) +/* Tests only initialization so far. TODO: Replace with functional tests, + * for example by producing pci-bus. + */ +static void test_phb_device(void *obj, void *data, QGuestAllocator *alloc) { } -int main(int argc, char **argv) +static void register_phb_test(void) { - int ret; - - g_test_init(&argc, &argv, NULL); - qtest_add_func("/spapr-phb/device", test_phb_device); - - qtest_start("-device " TYPE_SPAPR_PCI_HOST_BRIDGE ",index=30"); - - ret = g_test_run(); - - qtest_end(); - - return ret; + qos_add_test("spapr-phb-test", "ppc64/pseries", + test_phb_device, &(QOSGraphTestOptions) { + .edge.before_cmd_line = "-device spapr-pci-host-bridge" + ",index=30", + }); } + +libqos_init(register_phb_test); diff --git a/tests/tco-test.c b/tests/tco-test.c index 6bee9a37d3..f89a42cdcc 100644 --- a/tests/tco-test.c +++ b/tests/tco-test.c @@ -64,7 +64,7 @@ static void test_init(TestData *d) global_qtest = qs; qtest_irq_intercept_in(qs, "ioapic"); - d->bus = qpci_init_pc(qs, NULL); + d->bus = qpci_new_pc(qs, NULL); d->dev = qpci_device_find(d->bus, QPCI_DEVFN(0x1f, 0x00)); g_assert(d->dev != NULL); diff --git a/tests/test-aio-multithread.c b/tests/test-aio-multithread.c index 6440d54ac3..d3144be7e0 100644 --- a/tests/test-aio-multithread.c +++ b/tests/test-aio-multithread.c @@ -178,7 +178,7 @@ static void test_multi_co_schedule(int seconds) } join_aio_contexts(); - g_test_message("scheduled %d, queued %d, retry %d, total %d\n", + g_test_message("scheduled %d, queued %d, retry %d, total %d", count_other, count_here, count_retry, count_here + count_other + count_retry); } @@ -242,7 +242,7 @@ static void test_multi_co_mutex(int threads, int seconds) } join_aio_contexts(); - g_test_message("%d iterations/second\n", counter / seconds); + g_test_message("%d iterations/second", counter / seconds); g_assert_cmpint(counter, ==, atomic_counter); } @@ -361,7 +361,7 @@ static void test_multi_fair_mutex(int threads, int seconds) } join_aio_contexts(); - g_test_message("%d iterations/second\n", counter / seconds); + g_test_message("%d iterations/second", counter / seconds); g_assert_cmpint(counter, ==, atomic_counter); } @@ -417,7 +417,7 @@ static void test_multi_mutex(int threads, int seconds) } join_aio_contexts(); - g_test_message("%d iterations/second\n", counter / seconds); + g_test_message("%d iterations/second", counter / seconds); g_assert_cmpint(counter, ==, atomic_counter); } diff --git a/tests/test-char.c b/tests/test-char.c index 63b4d3289d..de328380c1 100644 --- a/tests/test-char.c +++ b/tests/test-char.c @@ -1003,6 +1003,103 @@ static void char_socket_client_test(gconstpointer opaque) g_free(optstr); } +static void +count_closed_event(void *opaque, int event) +{ + int *count = opaque; + if (event == CHR_EVENT_CLOSED) { + (*count)++; + } +} + +static void +char_socket_discard_read(void *opaque, const uint8_t *buf, int size) +{ +} + +static void char_socket_server_two_clients_test(gconstpointer opaque) +{ + SocketAddress *incoming_addr = (gpointer) opaque; + Chardev *chr; + CharBackend be = {0}; + QObject *qaddr; + SocketAddress *addr; + Visitor *v; + char *optstr; + QemuOpts *opts; + QIOChannelSocket *ioc1, *ioc2; + int closed = 0; + + g_setenv("QTEST_SILENT_ERRORS", "1", 1); + /* + * We rely on addr containing "nowait", otherwise + * qemu_chr_new() will block until a client connects. We + * can't spawn our client thread though, because until + * qemu_chr_new() returns we don't know what TCP port was + * allocated by the OS + */ + optstr = char_socket_addr_to_opt_str(incoming_addr, + false, + NULL, + true); + opts = qemu_opts_parse_noisily(qemu_find_opts("chardev"), + optstr, true); + g_assert_nonnull(opts); + chr = qemu_chr_new_from_opts(opts, NULL, &error_abort); + qemu_opts_del(opts); + g_assert_nonnull(chr); + g_assert(!object_property_get_bool(OBJECT(chr), "connected", &error_abort)); + + qaddr = object_property_get_qobject(OBJECT(chr), "addr", &error_abort); + g_assert_nonnull(qaddr); + + v = qobject_input_visitor_new(qaddr); + visit_type_SocketAddress(v, "addr", &addr, &error_abort); + visit_free(v); + qobject_unref(qaddr); + + qemu_chr_fe_init(&be, chr, &error_abort); + + qemu_chr_fe_set_handlers(&be, char_socket_can_read, char_socket_discard_read, + count_closed_event, NULL, + &closed, NULL, true); + + ioc1 = qio_channel_socket_new(); + qio_channel_socket_connect_sync(ioc1, addr, &error_abort); + qemu_chr_wait_connected(chr, &error_abort); + + /* switch the chardev to another context */ + GMainContext *ctx = g_main_context_new(); + qemu_chr_fe_set_handlers(&be, char_socket_can_read, char_socket_discard_read, + count_closed_event, NULL, + &closed, ctx, true); + + /* Start a second connection while the first is still connected. + * It will be placed in the listen() backlog, and connect() will + * succeed immediately. + */ + ioc2 = qio_channel_socket_new(); + qio_channel_socket_connect_sync(ioc2, addr, &error_abort); + + object_unref(OBJECT(ioc1)); + /* The two connections should now be processed serially. */ + while (g_main_context_iteration(ctx, TRUE)) { + if (closed == 1 && ioc2) { + object_unref(OBJECT(ioc2)); + ioc2 = NULL; + } + if (closed == 2) { + break; + } + } + + qapi_free_SocketAddress(addr); + object_unparent(OBJECT(chr)); + g_main_context_unref(ctx); + g_free(optstr); + g_unsetenv("QTEST_SILENT_ERRORS"); +} + #ifdef HAVE_CHARDEV_SERIAL static void char_serial_test(void) @@ -1342,12 +1439,15 @@ int main(int argc, char **argv) SOCKET_SERVER_TEST(tcp, &tcpaddr); SOCKET_CLIENT_TEST(tcp, &tcpaddr); + g_test_add_data_func("/char/socket/server/two-clients/tcp", &tcpaddr, + char_socket_server_two_clients_test); #ifndef WIN32 SOCKET_SERVER_TEST(unix, &unixaddr); SOCKET_CLIENT_TEST(unix, &unixaddr); + g_test_add_data_func("/char/socket/server/two-clients/unix", &unixaddr, + char_socket_server_two_clients_test); #endif - g_test_add_func("/char/udp", char_udp_test); #ifdef HAVE_CHARDEV_SERIAL g_test_add_func("/char/serial", char_serial_test); diff --git a/tests/test-coroutine.c b/tests/test-coroutine.c index 28e79b3210..e946d93a65 100644 --- a/tests/test-coroutine.c +++ b/tests/test-coroutine.c @@ -369,7 +369,7 @@ static void perf_lifecycle(void) } duration = g_test_timer_elapsed(); - g_test_message("Lifecycle %u iterations: %f s\n", max, duration); + g_test_message("Lifecycle %u iterations: %f s", max, duration); } static void perf_nesting(void) @@ -393,7 +393,7 @@ static void perf_nesting(void) } duration = g_test_timer_elapsed(); - g_test_message("Nesting %u iterations of %u depth each: %f s\n", + g_test_message("Nesting %u iterations of %u depth each: %f s", maxcycles, maxnesting, duration); } @@ -426,8 +426,7 @@ static void perf_yield(void) } duration = g_test_timer_elapsed(); - g_test_message("Yield %u iterations: %f s\n", - maxcycles, duration); + g_test_message("Yield %u iterations: %f s", maxcycles, duration); } static __attribute__((noinline)) void dummy(unsigned *i) @@ -449,8 +448,7 @@ static void perf_baseline(void) } duration = g_test_timer_elapsed(); - g_test_message("Function call %u iterations: %f s\n", - maxcycles, duration); + g_test_message("Function call %u iterations: %f s", maxcycles, duration); } static __attribute__((noinline)) void perf_cost_func(void *opaque) diff --git a/tests/test-qgraph.c b/tests/test-qgraph.c new file mode 100644 index 0000000000..f6a6565e31 --- /dev/null +++ b/tests/test-qgraph.c @@ -0,0 +1,434 @@ +/* + * libqos driver framework + * + * Copyright (c) 2018 Emanuele Giuseppe Esposito <e.emanuelegiuseppe@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/> + */ + +#include "qemu/osdep.h" +#include "libqtest.h" +#include "libqos/qgraph.h" +#include "libqos/qgraph_internal.h" + +#define MACHINE_PC "x86_64/pc" +#define MACHINE_RASPI2 "arm/raspi2" +#define I440FX "i440FX-pcihost" +#define PCIBUS_PC "pcibus-pc" +#define SDHCI "sdhci" +#define PCIBUS "pci-bus" +#define SDHCI_PCI "sdhci-pci" +#define SDHCI_MM "generic-sdhci" +#define REGISTER_TEST "register-test" + +int npath; + +static void *machinefunct(QTestState *qts) +{ + return NULL; +} + +static void *driverfunct(void *obj, QGuestAllocator *machine, void *arg) +{ + return NULL; +} + +static void testfunct(void *obj, void *arg, QGuestAllocator *alloc) +{ + return; +} + +static void check_interface(const char *interface) +{ + g_assert_cmpint(qos_graph_has_machine(interface), ==, FALSE); + g_assert_nonnull(qos_graph_get_node(interface)); + g_assert_cmpint(qos_graph_has_node(interface), ==, TRUE); + g_assert_cmpint(qos_graph_get_node_type(interface), ==, QNODE_INTERFACE); + qos_graph_node_set_availability(interface, TRUE); + g_assert_cmpint(qos_graph_get_node_availability(interface), ==, TRUE); +} + +static void check_machine(const char *machine) +{ + qos_node_create_machine(machine, machinefunct); + g_assert_nonnull(qos_graph_get_machine(machine)); + g_assert_cmpint(qos_graph_has_machine(machine), ==, TRUE); + g_assert_nonnull(qos_graph_get_node(machine)); + g_assert_cmpint(qos_graph_get_node_availability(machine), ==, FALSE); + qos_graph_node_set_availability(machine, TRUE); + g_assert_cmpint(qos_graph_get_node_availability(machine), ==, TRUE); + g_assert_cmpint(qos_graph_has_node(machine), ==, TRUE); + g_assert_cmpint(qos_graph_get_node_type(machine), ==, QNODE_MACHINE); +} + +static void check_contains(const char *machine, const char *driver) +{ + QOSGraphEdge *edge; + qos_node_contains(machine, driver, NULL); + + edge = qos_graph_get_edge(machine, driver); + g_assert_nonnull(edge); + g_assert_cmpint(qos_graph_edge_get_type(edge), ==, QEDGE_CONTAINS); + g_assert_cmpint(qos_graph_has_edge(machine, driver), ==, TRUE); +} + +static void check_produces(const char *machine, const char *interface) +{ + QOSGraphEdge *edge; + + qos_node_produces(machine, interface); + check_interface(interface); + edge = qos_graph_get_edge(machine, interface); + g_assert_nonnull(edge); + g_assert_cmpint(qos_graph_edge_get_type(edge), ==, + QEDGE_PRODUCES); + g_assert_cmpint(qos_graph_has_edge(machine, interface), ==, TRUE); +} + +static void check_consumes(const char *driver, const char *interface) +{ + QOSGraphEdge *edge; + + qos_node_consumes(driver, interface, NULL); + check_interface(interface); + edge = qos_graph_get_edge(interface, driver); + g_assert_nonnull(edge); + g_assert_cmpint(qos_graph_edge_get_type(edge), ==, QEDGE_CONSUMED_BY); + g_assert_cmpint(qos_graph_has_edge(interface, driver), ==, TRUE); +} + +static void check_driver(const char *driver) +{ + qos_node_create_driver(driver, driverfunct); + g_assert_cmpint(qos_graph_has_machine(driver), ==, FALSE); + g_assert_nonnull(qos_graph_get_node(driver)); + g_assert_cmpint(qos_graph_has_node(driver), ==, TRUE); + g_assert_cmpint(qos_graph_get_node_type(driver), ==, QNODE_DRIVER); + g_assert_cmpint(qos_graph_get_node_availability(driver), ==, FALSE); + qos_graph_node_set_availability(driver, TRUE); + g_assert_cmpint(qos_graph_get_node_availability(driver), ==, TRUE); +} + +static void check_test(const char *test, const char *interface) +{ + QOSGraphEdge *edge; + const char *full_name = g_strdup_printf("%s-tests/%s", interface, test); + + qos_add_test(test, interface, testfunct, NULL); + g_assert_cmpint(qos_graph_has_machine(test), ==, FALSE); + g_assert_cmpint(qos_graph_has_machine(full_name), ==, FALSE); + g_assert_nonnull(qos_graph_get_node(full_name)); + g_assert_cmpint(qos_graph_has_node(full_name), ==, TRUE); + g_assert_cmpint(qos_graph_get_node_type(full_name), ==, QNODE_TEST); + edge = qos_graph_get_edge(interface, full_name); + g_assert_nonnull(edge); + g_assert_cmpint(qos_graph_edge_get_type(edge), ==, + QEDGE_CONSUMED_BY); + g_assert_cmpint(qos_graph_has_edge(interface, full_name), ==, TRUE); + g_assert_cmpint(qos_graph_get_node_availability(full_name), ==, TRUE); + qos_graph_node_set_availability(full_name, FALSE); + g_assert_cmpint(qos_graph_get_node_availability(full_name), ==, FALSE); +} + +static void count_each_test(QOSGraphNode *path, int len) +{ + npath++; +} + +static void check_leaf_discovered(int n) +{ + npath = 0; + qos_graph_foreach_test_path(count_each_test); + g_assert_cmpint(n, ==, npath); +} + +/* G_Test functions */ + +static void init_nop(void) +{ + qos_graph_init(); + qos_graph_destroy(); +} + +static void test_machine(void) +{ + qos_graph_init(); + check_machine(MACHINE_PC); + qos_graph_destroy(); +} + +static void test_contains(void) +{ + qos_graph_init(); + check_contains(MACHINE_PC, I440FX); + g_assert_null(qos_graph_get_machine(MACHINE_PC)); + g_assert_null(qos_graph_get_machine(I440FX)); + g_assert_null(qos_graph_get_node(MACHINE_PC)); + g_assert_null(qos_graph_get_node(I440FX)); + qos_graph_destroy(); +} + +static void test_multiple_contains(void) +{ + qos_graph_init(); + check_contains(MACHINE_PC, I440FX); + check_contains(MACHINE_PC, PCIBUS_PC); + qos_graph_destroy(); +} + +static void test_produces(void) +{ + qos_graph_init(); + check_produces(MACHINE_PC, I440FX); + g_assert_null(qos_graph_get_machine(MACHINE_PC)); + g_assert_null(qos_graph_get_machine(I440FX)); + g_assert_null(qos_graph_get_node(MACHINE_PC)); + g_assert_nonnull(qos_graph_get_node(I440FX)); + qos_graph_destroy(); +} + +static void test_multiple_produces(void) +{ + qos_graph_init(); + check_produces(MACHINE_PC, I440FX); + check_produces(MACHINE_PC, PCIBUS_PC); + qos_graph_destroy(); +} + +static void test_consumes(void) +{ + qos_graph_init(); + check_consumes(I440FX, SDHCI); + g_assert_null(qos_graph_get_machine(I440FX)); + g_assert_null(qos_graph_get_machine(SDHCI)); + g_assert_null(qos_graph_get_node(I440FX)); + g_assert_nonnull(qos_graph_get_node(SDHCI)); + qos_graph_destroy(); +} + +static void test_multiple_consumes(void) +{ + qos_graph_init(); + check_consumes(I440FX, SDHCI); + check_consumes(PCIBUS_PC, SDHCI); + qos_graph_destroy(); +} + +static void test_driver(void) +{ + qos_graph_init(); + check_driver(I440FX); + qos_graph_destroy(); +} + +static void test_test(void) +{ + qos_graph_init(); + check_test(REGISTER_TEST, SDHCI); + qos_graph_destroy(); +} + +static void test_machine_contains_driver(void) +{ + qos_graph_init(); + check_machine(MACHINE_PC); + check_driver(I440FX); + check_contains(MACHINE_PC, I440FX); + qos_graph_destroy(); +} + +static void test_driver_contains_driver(void) +{ + qos_graph_init(); + check_driver(PCIBUS_PC); + check_driver(I440FX); + check_contains(PCIBUS_PC, I440FX); + qos_graph_destroy(); +} + +static void test_machine_produces_interface(void) +{ + qos_graph_init(); + check_machine(MACHINE_PC); + check_produces(MACHINE_PC, SDHCI); + qos_graph_destroy(); +} + +static void test_driver_produces_interface(void) +{ + qos_graph_init(); + check_driver(I440FX); + check_produces(I440FX, SDHCI); + qos_graph_destroy(); +} + +static void test_machine_consumes_interface(void) +{ + qos_graph_init(); + check_machine(MACHINE_PC); + check_consumes(MACHINE_PC, SDHCI); + qos_graph_destroy(); +} + +static void test_driver_consumes_interface(void) +{ + qos_graph_init(); + check_driver(I440FX); + check_consumes(I440FX, SDHCI); + qos_graph_destroy(); +} + +static void test_test_consumes_interface(void) +{ + qos_graph_init(); + check_test(REGISTER_TEST, SDHCI); + qos_graph_destroy(); +} + +static void test_full_sample(void) +{ + qos_graph_init(); + check_machine(MACHINE_PC); + check_contains(MACHINE_PC, I440FX); + check_driver(I440FX); + check_driver(PCIBUS_PC); + check_contains(I440FX, PCIBUS_PC); + check_produces(PCIBUS_PC, PCIBUS); + check_driver(SDHCI_PCI); + qos_node_consumes(SDHCI_PCI, PCIBUS, NULL); + check_produces(SDHCI_PCI, SDHCI); + check_driver(SDHCI_MM); + check_produces(SDHCI_MM, SDHCI); + qos_add_test(REGISTER_TEST, SDHCI, testfunct, NULL); + check_leaf_discovered(1); + qos_print_graph(); + qos_graph_destroy(); +} + +static void test_full_sample_raspi(void) +{ + qos_graph_init(); + check_machine(MACHINE_PC); + check_contains(MACHINE_PC, I440FX); + check_driver(I440FX); + check_driver(PCIBUS_PC); + check_contains(I440FX, PCIBUS_PC); + check_produces(PCIBUS_PC, PCIBUS); + check_driver(SDHCI_PCI); + qos_node_consumes(SDHCI_PCI, PCIBUS, NULL); + check_produces(SDHCI_PCI, SDHCI); + check_machine(MACHINE_RASPI2); + check_contains(MACHINE_RASPI2, SDHCI_MM); + check_driver(SDHCI_MM); + check_produces(SDHCI_MM, SDHCI); + qos_add_test(REGISTER_TEST, SDHCI, testfunct, NULL); + qos_print_graph(); + check_leaf_discovered(2); + qos_graph_destroy(); +} + +static void test_cycle(void) +{ + qos_graph_init(); + check_machine(MACHINE_RASPI2); + check_driver("B"); + check_driver("C"); + check_driver("D"); + check_contains(MACHINE_RASPI2, "B"); + check_contains("B", "C"); + check_contains("C", "D"); + check_contains("D", MACHINE_RASPI2); + check_leaf_discovered(0); + qos_print_graph(); + qos_graph_destroy(); +} + +static void test_two_test_same_interface(void) +{ + qos_graph_init(); + check_machine(MACHINE_RASPI2); + check_produces(MACHINE_RASPI2, "B"); + qos_add_test("C", "B", testfunct, NULL); + qos_add_test("D", "B", testfunct, NULL); + check_contains(MACHINE_RASPI2, "B"); + check_leaf_discovered(4); + qos_print_graph(); + qos_graph_destroy(); +} + +static void test_test_in_path(void) +{ + qos_graph_init(); + check_machine(MACHINE_RASPI2); + check_produces(MACHINE_RASPI2, "B"); + qos_add_test("C", "B", testfunct, NULL); + check_driver("D"); + check_consumes("D", "B"); + check_produces("D", "E"); + qos_add_test("F", "E", testfunct, NULL); + check_leaf_discovered(2); + qos_print_graph(); + qos_graph_destroy(); +} + +static void test_double_edge(void) +{ + qos_graph_init(); + check_machine(MACHINE_RASPI2); + check_produces("B", "C"); + qos_node_consumes("C", "B", NULL); + qos_add_test("D", "C", testfunct, NULL); + check_contains(MACHINE_RASPI2, "B"); + qos_print_graph(); + qos_graph_destroy(); +} + +int main(int argc, char **argv) +{ + g_test_init(&argc, &argv, NULL); + g_test_add_func("/qgraph/init_nop", init_nop); + g_test_add_func("/qgraph/test_machine", test_machine); + g_test_add_func("/qgraph/test_contains", test_contains); + g_test_add_func("/qgraph/test_multiple_contains", test_multiple_contains); + g_test_add_func("/qgraph/test_produces", test_produces); + g_test_add_func("/qgraph/test_multiple_produces", test_multiple_produces); + g_test_add_func("/qgraph/test_consumes", test_consumes); + g_test_add_func("/qgraph/test_multiple_consumes", + test_multiple_consumes); + g_test_add_func("/qgraph/test_driver", test_driver); + g_test_add_func("/qgraph/test_test", test_test); + g_test_add_func("/qgraph/test_machine_contains_driver", + test_machine_contains_driver); + g_test_add_func("/qgraph/test_driver_contains_driver", + test_driver_contains_driver); + g_test_add_func("/qgraph/test_machine_produces_interface", + test_machine_produces_interface); + g_test_add_func("/qgraph/test_driver_produces_interface", + test_driver_produces_interface); + g_test_add_func("/qgraph/test_machine_consumes_interface", + test_machine_consumes_interface); + g_test_add_func("/qgraph/test_driver_consumes_interface", + test_driver_consumes_interface); + g_test_add_func("/qgraph/test_test_consumes_interface", + test_test_consumes_interface); + g_test_add_func("/qgraph/test_full_sample", test_full_sample); + g_test_add_func("/qgraph/test_full_sample_raspi", test_full_sample_raspi); + g_test_add_func("/qgraph/test_cycle", test_cycle); + g_test_add_func("/qgraph/test_two_test_same_interface", + test_two_test_same_interface); + g_test_add_func("/qgraph/test_test_in_path", test_test_in_path); + g_test_add_func("/qgraph/test_double_edge", test_double_edge); + + g_test_run(); + return 0; +} diff --git a/tests/tpci200-test.c b/tests/tpci200-test.c deleted file mode 100644 index 0321ec27ec..0000000000 --- a/tests/tpci200-test.c +++ /dev/null @@ -1,31 +0,0 @@ -/* - * QTest testcase for tpci200 PCI-IndustryPack bridge - * - * Copyright (c) 2014 SUSE LINUX Products GmbH - * - * This work is licensed under the terms of the GNU GPL, version 2 or later. - * See the COPYING file in the top-level directory. - */ - -#include "qemu/osdep.h" -#include "libqtest.h" - -/* Tests only initialization so far. TODO: Replace with functional tests */ -static void nop(void) -{ -} - -int main(int argc, char **argv) -{ - int ret; - - g_test_init(&argc, &argv, NULL); - qtest_add_func("/tpci200/nop", nop); - - qtest_start("-device tpci200"); - ret = g_test_run(); - - qtest_end(); - - return ret; -} diff --git a/tests/usb-hcd-ehci-test.c b/tests/usb-hcd-ehci-test.c index f28ea27f37..8bc3e44189 100644 --- a/tests/usb-hcd-ehci-test.c +++ b/tests/usb-hcd-ehci-test.c @@ -52,7 +52,7 @@ static void ehci_port_test(struct qhc *hc, int port, uint32_t expect) static void test_init(void) { - pcibus = qpci_init_pc(global_qtest, NULL); + pcibus = qpci_new_pc(global_qtest, NULL); g_assert(pcibus != NULL); qusb_pci_init_one(pcibus, &uhci1, QPCI_DEVFN(0x1d, 0), 4); diff --git a/tests/usb-hcd-ohci-test.c b/tests/usb-hcd-ohci-test.c index 48ddbfd26d..98af02e898 100644 --- a/tests/usb-hcd-ohci-test.c +++ b/tests/usb-hcd-ohci-test.c @@ -10,30 +10,58 @@ #include "qemu/osdep.h" #include "libqtest.h" #include "libqos/usb.h" +#include "libqos/qgraph.h" +#include "libqos/pci.h" +typedef struct QOHCI_PCI QOHCI_PCI; -static void test_ohci_init(void) -{ +struct QOHCI_PCI { + QOSGraphObject obj; + QPCIDevice dev; +}; +static void test_ohci_hotplug(void *obj, void *data, QGuestAllocator *alloc) +{ + usb_test_hotplug("ohci", "1", NULL); } -static void test_ohci_hotplug(void) +static void *ohci_pci_get_driver(void *obj, const char *interface) { - usb_test_hotplug("ohci", "1", NULL); + QOHCI_PCI *ohci_pci = obj; + + if (!g_strcmp0(interface, "pci-device")) { + return &ohci_pci->dev; + } + + fprintf(stderr, "%s not present in pci-ohci\n", interface); + g_assert_not_reached(); } -int main(int argc, char **argv) +static void *ohci_pci_create(void *pci_bus, QGuestAllocator *alloc, void *addr) { - int ret; + QOHCI_PCI *ohci_pci = g_new0(QOHCI_PCI, 1); + ohci_pci->obj.get_driver = ohci_pci_get_driver; - g_test_init(&argc, &argv, NULL); + return &ohci_pci->obj; +} + +static void ohci_pci_register_nodes(void) +{ + QOSGraphEdgeOptions opts = { + .extra_device_opts = "addr=04.0,id=ohci", + }; + add_qpci_address(&opts, &(QPCIAddress) { .devfn = QPCI_DEVFN(4, 0) }); - qtest_add_func("/ohci/pci/init", test_ohci_init); - qtest_add_func("/ohci/pci/hotplug", test_ohci_hotplug); + qos_node_create_driver("pci-ohci", ohci_pci_create); + qos_node_consumes("pci-ohci", "pci-bus", &opts); + qos_node_produces("pci-ohci", "pci-device"); +} - qtest_start("-device pci-ohci,id=ohci"); - ret = g_test_run(); - qtest_end(); +libqos_init(ohci_pci_register_nodes); - return ret; +static void register_ohci_pci_test(void) +{ + qos_add_test("ohci_pci-test-hotplug", "pci-ohci", test_ohci_hotplug, NULL); } + +libqos_init(register_ohci_pci_test); diff --git a/tests/vhost-user-test.c b/tests/vhost-user-test.c index 4cd0a97f13..0c965b3b1e 100644 --- a/tests/vhost-user-test.c +++ b/tests/vhost-user-test.c @@ -41,8 +41,7 @@ #define QEMU_CMD_MEMFD " -m %d -object memory-backend-memfd,id=mem,size=%dM," \ " -numa node,memdev=mem" #define QEMU_CMD_CHR " -chardev socket,id=%s,path=%s%s" -#define QEMU_CMD_NETDEV " -netdev vhost-user,id=net0,chardev=%s,vhostforce" -#define QEMU_CMD_NET " -device virtio-net-pci,netdev=net0" +#define QEMU_CMD_NETDEV " -netdev vhost-user,id=hs0,chardev=%s,vhostforce" #define HUGETLBFS_MAGIC 0x958458f6 @@ -136,13 +135,9 @@ enum { }; typedef struct TestServer { - QPCIBus *bus; - QVirtioPCIDevice *dev; - QVirtQueue *vq[VHOST_MAX_VIRTQUEUES]; gchar *socket_path; gchar *mig_path; gchar *chr_name; - const gchar *mem_path; gchar *tmpfs; CharBackend chr; int fds_num; @@ -158,9 +153,9 @@ typedef struct TestServer { bool test_fail; int test_flags; int queues; - QGuestAllocator *alloc; } TestServer; +static const char *init_hugepagefs(void); static TestServer *test_server_new(const gchar *name); static void test_server_free(TestServer *server); static void test_server_listen(TestServer *server); @@ -171,66 +166,28 @@ enum test_memfd { TEST_MEMFD_NO, }; -static char *get_qemu_cmd(TestServer *s, - int mem, enum test_memfd memfd, - const char *chr_opts, const char *extra) +static void append_vhost_opts(TestServer *s, GString *cmd_line, + const char *chr_opts) { - if (memfd == TEST_MEMFD_AUTO && qemu_memfd_check(0)) { - memfd = TEST_MEMFD_YES; - } - - if (memfd == TEST_MEMFD_YES) { - return g_strdup_printf(QEMU_CMD_MEMFD QEMU_CMD_CHR - QEMU_CMD_NETDEV QEMU_CMD_NET "%s", mem, mem, - s->chr_name, s->socket_path, - chr_opts, s->chr_name, extra); - } else { - return g_strdup_printf(QEMU_CMD_MEM QEMU_CMD_CHR - QEMU_CMD_NETDEV QEMU_CMD_NET "%s", mem, mem, - s->mem_path, s->chr_name, s->socket_path, - chr_opts, s->chr_name, extra); - } + g_string_append_printf(cmd_line, QEMU_CMD_CHR QEMU_CMD_NETDEV, + s->chr_name, s->socket_path, + chr_opts, s->chr_name); } -static void init_virtio_dev(QTestState *qts, TestServer *s, uint32_t features_mask) +static void append_mem_opts(TestServer *server, GString *cmd_line, + int size, enum test_memfd memfd) { - uint32_t features; - int i; - - s->bus = qpci_init_pc(qts, NULL); - g_assert_nonnull(s->bus); - - s->dev = qvirtio_pci_device_find(s->bus, VIRTIO_ID_NET); - g_assert_nonnull(s->dev); - - qvirtio_pci_device_enable(s->dev); - qvirtio_reset(&s->dev->vdev); - qvirtio_set_acknowledge(&s->dev->vdev); - qvirtio_set_driver(&s->dev->vdev); - - s->alloc = pc_alloc_init(qts); - - for (i = 0; i < s->queues * 2; i++) { - s->vq[i] = qvirtqueue_setup(&s->dev->vdev, s->alloc, i); + if (memfd == TEST_MEMFD_AUTO) { + memfd = qemu_memfd_check(0) ? TEST_MEMFD_YES : TEST_MEMFD_NO; } - features = qvirtio_get_features(&s->dev->vdev); - features = features & features_mask; - qvirtio_set_features(&s->dev->vdev, features); - - qvirtio_set_driver_ok(&s->dev->vdev); -} - -static void uninit_virtio_dev(TestServer *s) -{ - int i; + if (memfd == TEST_MEMFD_YES) { + g_string_append_printf(cmd_line, QEMU_CMD_MEMFD, size, size); + } else { + const char *root = init_hugepagefs() ? : server->tmpfs; - for (i = 0; i < s->queues * 2; i++) { - qvirtqueue_cleanup(s->dev->vdev.bus, s->vq[i], s->alloc); + g_string_append_printf(cmd_line, QEMU_CMD_MEM, size, size, root); } - pc_alloc_uninit(s->alloc); - - qvirtio_pci_device_free(s->dev); } static bool wait_for_fds(TestServer *s) @@ -337,7 +294,7 @@ static void chr_read(void *opaque, const uint8_t *buf, int size) } if (size != VHOST_USER_HDR_SIZE) { - g_test_message("Wrong message size received %d\n", size); + g_test_message("Wrong message size received %d", size); return; } @@ -348,7 +305,7 @@ static void chr_read(void *opaque, const uint8_t *buf, int size) p += VHOST_USER_HDR_SIZE; size = qemu_chr_fe_read_all(chr, p, msg.size); if (size != msg.size) { - g_test_message("Wrong message size received %d != %d\n", + g_test_message("Wrong message size received %d != %d", size, msg.size); return; } @@ -467,17 +424,21 @@ static void chr_read(void *opaque, const uint8_t *buf, int size) static const char *init_hugepagefs(void) { #ifdef CONFIG_LINUX + static const char *hugepagefs; const char *path = getenv("QTEST_HUGETLBFS_PATH"); struct statfs fs; int ret; + if (hugepagefs) { + return hugepagefs; + } if (!path) { return NULL; } if (access(path, R_OK | W_OK | X_OK)) { - g_test_message("access on path (%s): %s\n", path, strerror(errno)); - abort(); + g_test_message("access on path (%s): %s", path, strerror(errno)); + g_test_fail(); return NULL; } @@ -486,18 +447,19 @@ static const char *init_hugepagefs(void) } while (ret != 0 && errno == EINTR); if (ret != 0) { - g_test_message("statfs on path (%s): %s\n", path, strerror(errno)); - abort(); + g_test_message("statfs on path (%s): %s", path, strerror(errno)); + g_test_fail(); return NULL; } if (fs.f_type != HUGETLBFS_MAGIC) { - g_test_message("Warning: path not on HugeTLBFS: %s\n", path); - abort(); + g_test_message("Warning: path not on HugeTLBFS: %s", path); + g_test_fail(); return NULL; } - return path; + hugepagefs = path; + return hugepagefs; #else return NULL; #endif @@ -522,7 +484,6 @@ static TestServer *test_server_new(const gchar *name) g_assert(tmpfs); server->tmpfs = g_strdup(tmpfs); - server->mem_path = init_hugepagefs() ? : server->tmpfs; server->socket_path = g_strdup_printf("%s/%s.sock", tmpfs, name); server->mig_path = g_strdup_printf("%s/%s.mig", tmpfs, name); server->chr_name = g_strdup_printf("chr-%s", name); @@ -588,6 +549,7 @@ static void test_server_free(TestServer *server) g_test_message("unable to rmdir: path (%s): %s", server->tmpfs, strerror(errno)); } + g_free(server->tmpfs); qemu_chr_fe_deinit(&server->chr, true); @@ -600,11 +562,11 @@ static void test_server_free(TestServer *server) } g_free(server->chr_name); - g_assert(server->bus); - qpci_free_pc(server->bus); g_main_loop_unref(server->loop); g_main_context_unref(server->context); + g_cond_clear(&server->data_cond); + g_mutex_clear(&server->data_mutex); g_free(server); } @@ -695,70 +657,79 @@ GSourceFuncs test_migrate_source_funcs = { .check = test_migrate_source_check, }; -static void test_read_guest_mem(const void *arg) +static void vhost_user_test_cleanup(void *s) +{ + TestServer *server = s; + + qos_invalidate_command_line(); + test_server_free(server); +} + +static void *vhost_user_test_setup(GString *cmd_line, void *arg) { - enum test_memfd memfd = GPOINTER_TO_INT(arg); - TestServer *server = NULL; - char *qemu_cmd = NULL; - QTestState *s = NULL; + TestServer *server = test_server_new("vhost-user-test"); + test_server_listen(server); + + append_mem_opts(server, cmd_line, 256, TEST_MEMFD_AUTO); + append_vhost_opts(server, cmd_line, ""); + + g_test_queue_destroy(vhost_user_test_cleanup, server); + + return server; +} - server = test_server_new(memfd == TEST_MEMFD_YES ? - "read-guest-memfd" : "read-guest-mem"); +static void *vhost_user_test_setup_memfd(GString *cmd_line, void *arg) +{ + TestServer *server = test_server_new("vhost-user-test"); test_server_listen(server); - qemu_cmd = get_qemu_cmd(server, 512, memfd, "", ""); + append_mem_opts(server, cmd_line, 256, TEST_MEMFD_YES); + append_vhost_opts(server, cmd_line, ""); + + g_test_queue_destroy(vhost_user_test_cleanup, server); - s = qtest_start(qemu_cmd); - g_free(qemu_cmd); + return server; +} - init_virtio_dev(global_qtest, server, 1u << VIRTIO_NET_F_MAC); +static void test_read_guest_mem(void *obj, void *arg, QGuestAllocator *alloc) +{ + TestServer *server = arg; if (!wait_for_fds(server)) { - goto exit; + return; } read_guest_mem_server(global_qtest, server); - -exit: - uninit_virtio_dev(server); - - qtest_quit(s); - test_server_free(server); } -static void test_migrate(void) +static void test_migrate(void *obj, void *arg, QGuestAllocator *alloc) { - TestServer *s = test_server_new("src"); + TestServer *s = arg; TestServer *dest = test_server_new("dest"); + GString *dest_cmdline = g_string_new(qos_get_current_command_line()); char *uri = g_strdup_printf("%s%s", "unix:", dest->mig_path); - QTestState *from, *to; + QTestState *to; GSource *source; - gchar *cmd, *tmp; QDict *rsp; guint8 *log; guint64 size; - test_server_listen(s); - test_server_listen(dest); - - cmd = get_qemu_cmd(s, 2, TEST_MEMFD_AUTO, "", ""); - from = qtest_start(cmd); - g_free(cmd); - - init_virtio_dev(from, s, 1u << VIRTIO_NET_F_MAC); if (!wait_for_fds(s)) { - goto exit; + return; } size = get_log_size(s); - g_assert_cmpint(size, ==, (2 * 1024 * 1024) / (VHOST_LOG_PAGE * 8)); + g_assert_cmpint(size, ==, (256 * 1024 * 1024) / (VHOST_LOG_PAGE * 8)); + + test_server_listen(dest); + g_string_append_printf(dest_cmdline, " -incoming %s", uri); + append_mem_opts(dest, dest_cmdline, 256, TEST_MEMFD_AUTO); + append_vhost_opts(dest, dest_cmdline, ""); + to = qtest_init(dest_cmdline->str); - tmp = g_strdup_printf(" -incoming %s", uri); - cmd = get_qemu_cmd(dest, 2, TEST_MEMFD_AUTO, "", tmp); - g_free(tmp); - to = qtest_init(cmd); - g_free(cmd); - init_virtio_dev(to, dest, 1u << VIRTIO_NET_F_MAC); + /* This would be where you call qos_allocate_objects(to, NULL), if you want + * to talk to the QVirtioNet object on the destination. + */ source = g_source_new(&test_migrate_source_funcs, sizeof(TestMigrateSource)); @@ -799,18 +770,11 @@ static void test_migrate(void) g_assert(wait_for_fds(dest)); read_guest_mem_server(to, dest); - uninit_virtio_dev(dest); - qtest_quit(to); - g_source_destroy(source); g_source_unref(source); -exit: - uninit_virtio_dev(s); - + qtest_quit(to); test_server_free(dest); - qtest_quit(from); - test_server_free(s); g_free(uri); } @@ -858,20 +822,26 @@ connect_thread(gpointer data) return NULL; } -static void test_reconnect_subprocess(void) +static void *vhost_user_test_setup_reconnect(GString *cmd_line, void *arg) { TestServer *s = test_server_new("reconnect"); - GSource *src; - char *cmd; g_thread_new("connect", connect_thread, s); - cmd = get_qemu_cmd(s, 2, TEST_MEMFD_AUTO, ",server", ""); - qtest_start(cmd); - g_free(cmd); + append_mem_opts(s, cmd_line, 256, TEST_MEMFD_AUTO); + append_vhost_opts(s, cmd_line, ",server"); + + g_test_queue_destroy(vhost_user_test_cleanup, s); + + return s; +} + +static void test_reconnect(void *obj, void *arg, QGuestAllocator *alloc) +{ + TestServer *s = arg; + GSource *src; - init_virtio_dev(global_qtest, s, 1u << VIRTIO_NET_F_MAC); if (!wait_for_fds(s)) { - goto exit; + return; } wait_for_rings_started(s, 2); @@ -885,159 +855,111 @@ static void test_reconnect_subprocess(void) g_source_unref(src); g_assert(wait_for_fds(s)); wait_for_rings_started(s, 2); - -exit: - uninit_virtio_dev(s); - - qtest_end(); - test_server_free(s); - return; } -static void test_reconnect(void) -{ - gchar *path = g_strdup_printf("/%s/vhost-user/reconnect/subprocess", - qtest_get_arch()); - g_test_trap_subprocess(path, 0, 0); - g_test_trap_assert_passed(); - g_free(path); -} - -static void test_connect_fail_subprocess(void) +static void *vhost_user_test_setup_connect_fail(GString *cmd_line, void *arg) { TestServer *s = test_server_new("connect-fail"); - char *cmd; s->test_fail = true; - g_thread_new("connect", connect_thread, s); - cmd = get_qemu_cmd(s, 2, TEST_MEMFD_AUTO, ",server", ""); - qtest_start(cmd); - g_free(cmd); - - init_virtio_dev(global_qtest, s, 1u << VIRTIO_NET_F_MAC); - if (!wait_for_fds(s)) { - goto exit; - } - wait_for_rings_started(s, 2); -exit: - uninit_virtio_dev(s); + g_thread_new("connect", connect_thread, s); + append_mem_opts(s, cmd_line, 256, TEST_MEMFD_AUTO); + append_vhost_opts(s, cmd_line, ",server"); - qtest_end(); - test_server_free(s); -} + g_test_queue_destroy(vhost_user_test_cleanup, s); -static void test_connect_fail(void) -{ - gchar *path = g_strdup_printf("/%s/vhost-user/connect-fail/subprocess", - qtest_get_arch()); - g_test_trap_subprocess(path, 0, 0); - g_test_trap_assert_passed(); - g_free(path); + return s; } -static void test_flags_mismatch_subprocess(void) +static void *vhost_user_test_setup_flags_mismatch(GString *cmd_line, void *arg) { TestServer *s = test_server_new("flags-mismatch"); - char *cmd; s->test_flags = TEST_FLAGS_DISCONNECT; - g_thread_new("connect", connect_thread, s); - cmd = get_qemu_cmd(s, 2, TEST_MEMFD_AUTO, ",server", ""); - qtest_start(cmd); - g_free(cmd); - init_virtio_dev(global_qtest, s, 1u << VIRTIO_NET_F_MAC); - if (!wait_for_fds(s)) { - goto exit; - } - wait_for_rings_started(s, 2); + g_thread_new("connect", connect_thread, s); + append_mem_opts(s, cmd_line, 256, TEST_MEMFD_AUTO); + append_vhost_opts(s, cmd_line, ",server"); -exit: - uninit_virtio_dev(s); + g_test_queue_destroy(vhost_user_test_cleanup, s); - qtest_end(); - test_server_free(s); + return s; } -static void test_flags_mismatch(void) +static void test_vhost_user_started(void *obj, void *arg, QGuestAllocator *alloc) { - gchar *path = g_strdup_printf("/%s/vhost-user/flags-mismatch/subprocess", - qtest_get_arch()); - g_test_trap_subprocess(path, 0, 0); - g_test_trap_assert_passed(); - g_free(path); -} + TestServer *s = arg; + if (!wait_for_fds(s)) { + return; + } + wait_for_rings_started(s, 2); +} -static void test_multiqueue(void) +static void *vhost_user_test_setup_multiqueue(GString *cmd_line, void *arg) { - TestServer *s = test_server_new("mq"); - char *cmd; - uint32_t features_mask = ~(QVIRTIO_F_BAD_FEATURE | - (1u << VIRTIO_RING_F_INDIRECT_DESC) | - (1u << VIRTIO_RING_F_EVENT_IDX)); + TestServer *s = vhost_user_test_setup(cmd_line, arg); + s->queues = 2; - test_server_listen(s); + g_string_append_printf(cmd_line, + " -set netdev.hs0.queues=%d" + " -global virtio-net-pci.vectors=%d", + s->queues, s->queues * 2 + 2); - if (qemu_memfd_check(0)) { - cmd = g_strdup_printf( - QEMU_CMD_MEMFD QEMU_CMD_CHR QEMU_CMD_NETDEV ",queues=%d " - "-device virtio-net-pci,netdev=net0,mq=on,vectors=%d", - 512, 512, s->chr_name, - s->socket_path, "", s->chr_name, - s->queues, s->queues * 2 + 2); - } else { - cmd = g_strdup_printf( - QEMU_CMD_MEM QEMU_CMD_CHR QEMU_CMD_NETDEV ",queues=%d " - "-device virtio-net-pci,netdev=net0,mq=on,vectors=%d", - 512, 512, s->mem_path, s->chr_name, - s->socket_path, "", s->chr_name, - s->queues, s->queues * 2 + 2); - } - qtest_start(cmd); - g_free(cmd); + return s; +} - init_virtio_dev(global_qtest, s, features_mask); +static void test_multiqueue(void *obj, void *arg, QGuestAllocator *alloc) +{ + TestServer *s = arg; wait_for_rings_started(s, s->queues * 2); - - uninit_virtio_dev(s); - - qtest_end(); - - test_server_free(s); } -int main(int argc, char **argv) +static void register_vhost_user_test(void) { - g_test_init(&argc, &argv, NULL); + QOSGraphTestOptions opts = { + .before = vhost_user_test_setup, + .subprocess = true, + }; - module_call_init(MODULE_INIT_QOM); qemu_add_opts(&qemu_chardev_opts); + qos_add_test("vhost-user/read-guest-mem/memfile", + "virtio-net", + test_read_guest_mem, &opts); + if (qemu_memfd_check(0)) { - qtest_add_data_func("/vhost-user/read-guest-mem/memfd", - GINT_TO_POINTER(TEST_MEMFD_YES), - test_read_guest_mem); + opts.before = vhost_user_test_setup_memfd; + qos_add_test("vhost-user/read-guest-mem/memfd", + "virtio-net", + test_read_guest_mem, &opts); } - qtest_add_data_func("/vhost-user/read-guest-mem/memfile", - GINT_TO_POINTER(TEST_MEMFD_NO), test_read_guest_mem); - qtest_add_func("/vhost-user/migrate", test_migrate); - qtest_add_func("/vhost-user/multiqueue", test_multiqueue); + + qos_add_test("vhost-user/migrate", + "virtio-net", + test_migrate, &opts); /* keeps failing on build-system since Aug 15 2017 */ if (getenv("QTEST_VHOST_USER_FIXME")) { - qtest_add_func("/vhost-user/reconnect/subprocess", - test_reconnect_subprocess); - qtest_add_func("/vhost-user/reconnect", test_reconnect); - qtest_add_func("/vhost-user/connect-fail/subprocess", - test_connect_fail_subprocess); - qtest_add_func("/vhost-user/connect-fail", test_connect_fail); - qtest_add_func("/vhost-user/flags-mismatch/subprocess", - test_flags_mismatch_subprocess); - qtest_add_func("/vhost-user/flags-mismatch", test_flags_mismatch); + opts.before = vhost_user_test_setup_reconnect; + qos_add_test("vhost-user/reconnect", "virtio-net", + test_reconnect, &opts); + + opts.before = vhost_user_test_setup_connect_fail; + qos_add_test("vhost-user/connect-fail", "virtio-net", + test_vhost_user_started, &opts); + + opts.before = vhost_user_test_setup_flags_mismatch; + qos_add_test("vhost-user/flags-mismatch", "virtio-net", + test_vhost_user_started, &opts); } - return g_test_run(); + opts.before = vhost_user_test_setup_multiqueue; + opts.edge.extra_device_opts = "mq=on"; + qos_add_test("vhost-user/multiqueue", + "virtio-net", + test_multiqueue, &opts); } +libqos_init(register_vhost_user_test); diff --git a/tests/virtio-9p-test.c b/tests/virtio-9p-test.c index a2b31085f6..16107ad280 100644 --- a/tests/virtio-9p-test.c +++ b/tests/virtio-9p-test.c @@ -9,101 +9,36 @@ #include "qemu/osdep.h" #include "libqtest.h" -#include "qemu-common.h" -#include "libqos/libqos-pc.h" -#include "libqos/libqos-spapr.h" -#include "libqos/virtio.h" -#include "libqos/virtio-pci.h" -#include "standard-headers/linux/virtio_ids.h" -#include "standard-headers/linux/virtio_pci.h" #include "hw/9pfs/9p.h" #include "hw/9pfs/9p-synth.h" +#include "libqos/virtio-9p.h" +#include "libqos/qgraph.h" #define QVIRTIO_9P_TIMEOUT_US (10 * 1000 * 1000) +static QGuestAllocator *alloc; -static const char mount_tag[] = "qtest"; - -typedef struct { - QVirtioDevice *dev; - QOSState *qs; - QVirtQueue *vq; -} QVirtIO9P; - -static QVirtIO9P *qvirtio_9p_start(const char *driver) -{ - const char *arch = qtest_get_arch(); - const char *cmd = "-fsdev synth,id=fsdev0 " - "-device %s,fsdev=fsdev0,mount_tag=%s"; - QVirtIO9P *v9p = g_new0(QVirtIO9P, 1); - - if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) { - v9p->qs = qtest_pc_boot(cmd, driver, mount_tag); - } else if (strcmp(arch, "ppc64") == 0) { - v9p->qs = qtest_spapr_boot(cmd, driver, mount_tag); - } else { - g_printerr("virtio-9p tests are only available on x86 or ppc64\n"); - exit(EXIT_FAILURE); - } - global_qtest = v9p->qs->qts; - - return v9p; -} - -static void qvirtio_9p_stop(QVirtIO9P *v9p) -{ - qtest_shutdown(v9p->qs); - g_free(v9p); -} - -static QVirtIO9P *qvirtio_9p_pci_start(void) -{ - QVirtIO9P *v9p = qvirtio_9p_start("virtio-9p-pci"); - QVirtioPCIDevice *dev = qvirtio_pci_device_find(v9p->qs->pcibus, - VIRTIO_ID_9P); - g_assert_nonnull(dev); - g_assert_cmphex(dev->vdev.device_type, ==, VIRTIO_ID_9P); - v9p->dev = (QVirtioDevice *) dev; - - qvirtio_pci_device_enable(dev); - qvirtio_reset(v9p->dev); - qvirtio_set_acknowledge(v9p->dev); - qvirtio_set_driver(v9p->dev); - - v9p->vq = qvirtqueue_setup(v9p->dev, v9p->qs->alloc, 0); - - qvirtio_set_driver_ok(v9p->dev); - - return v9p; -} - -static void qvirtio_9p_pci_stop(QVirtIO9P *v9p) -{ - qvirtqueue_cleanup(v9p->dev->bus, v9p->vq, v9p->qs->alloc); - qvirtio_pci_device_disable(container_of(v9p->dev, QVirtioPCIDevice, vdev)); - qvirtio_pci_device_free((QVirtioPCIDevice *)v9p->dev); - qvirtio_9p_stop(v9p); -} - -static void pci_config(QVirtIO9P *v9p) +static void pci_config(void *obj, void *data, QGuestAllocator *t_alloc) { - size_t tag_len = qvirtio_config_readw(v9p->dev, 0); + QVirtio9P *v9p = obj; + alloc = t_alloc; + size_t tag_len = qvirtio_config_readw(v9p->vdev, 0); char *tag; int i; - g_assert_cmpint(tag_len, ==, strlen(mount_tag)); + g_assert_cmpint(tag_len, ==, strlen(MOUNT_TAG)); tag = g_malloc(tag_len); for (i = 0; i < tag_len; i++) { - tag[i] = qvirtio_config_readb(v9p->dev, i + 2); + tag[i] = qvirtio_config_readb(v9p->vdev, i + 2); } - g_assert_cmpmem(tag, tag_len, mount_tag, tag_len); + g_assert_cmpmem(tag, tag_len, MOUNT_TAG, tag_len); g_free(tag); } #define P9_MAX_SIZE 4096 /* Max size of a T-message or R-message */ typedef struct { - QVirtIO9P *v9p; + QVirtio9P *v9p; uint16_t tag; uint64_t t_msg; uint32_t t_size; @@ -206,7 +141,7 @@ static void v9fs_string_read(P9Req *req, uint16_t *len, char **string) uint16_t tag; } QEMU_PACKED P9Hdr; -static P9Req *v9fs_req_init(QVirtIO9P *v9p, uint32_t size, uint8_t id, +static P9Req *v9fs_req_init(QVirtio9P *v9p, uint32_t size, uint8_t id, uint16_t tag) { P9Req *req = g_new0(P9Req, 1); @@ -224,7 +159,7 @@ static P9Req *v9fs_req_init(QVirtIO9P *v9p, uint32_t size, uint8_t id, req->v9p = v9p; req->t_size = total_size; - req->t_msg = guest_alloc(v9p->qs->alloc, req->t_size); + req->t_msg = guest_alloc(alloc, req->t_size); v9fs_memwrite(req, &hdr, 7); req->tag = tag; return req; @@ -232,13 +167,13 @@ static P9Req *v9fs_req_init(QVirtIO9P *v9p, uint32_t size, uint8_t id, static void v9fs_req_send(P9Req *req) { - QVirtIO9P *v9p = req->v9p; + QVirtio9P *v9p = req->v9p; - req->r_msg = guest_alloc(v9p->qs->alloc, P9_MAX_SIZE); + req->r_msg = guest_alloc(alloc, P9_MAX_SIZE); req->free_head = qvirtqueue_add(v9p->vq, req->t_msg, req->t_size, false, true); qvirtqueue_add(v9p->vq, req->r_msg, P9_MAX_SIZE, true, false); - qvirtqueue_kick(v9p->dev, v9p->vq, req->free_head); + qvirtqueue_kick(v9p->vdev, v9p->vq, req->free_head); req->t_off = 0; } @@ -257,9 +192,9 @@ static const char *rmessage_name(uint8_t id) static void v9fs_req_wait_for_reply(P9Req *req, uint32_t *len) { - QVirtIO9P *v9p = req->v9p; + QVirtio9P *v9p = req->v9p; - qvirtio_wait_used_elem(v9p->dev, v9p->vq, req->free_head, len, + qvirtio_wait_used_elem(v9p->vdev, v9p->vq, req->free_head, len, QVIRTIO_9P_TIMEOUT_US); } @@ -290,10 +225,8 @@ static void v9fs_req_recv(P9Req *req, uint8_t id) static void v9fs_req_free(P9Req *req) { - QVirtIO9P *v9p = req->v9p; - - guest_free(v9p->qs->alloc, req->t_msg); - guest_free(v9p->qs->alloc, req->r_msg); + guest_free(alloc, req->t_msg); + guest_free(alloc, req->r_msg); g_free(req); } @@ -306,7 +239,7 @@ static void v9fs_rlerror(P9Req *req, uint32_t *err) } /* size[4] Tversion tag[2] msize[4] version[s] */ -static P9Req *v9fs_tversion(QVirtIO9P *v9p, uint32_t msize, const char *version, +static P9Req *v9fs_tversion(QVirtio9P *v9p, uint32_t msize, const char *version, uint16_t tag) { P9Req *req; @@ -341,7 +274,7 @@ static void v9fs_rversion(P9Req *req, uint16_t *len, char **version) } /* size[4] Tattach tag[2] fid[4] afid[4] uname[s] aname[s] n_uname[4] */ -static P9Req *v9fs_tattach(QVirtIO9P *v9p, uint32_t fid, uint32_t n_uname, +static P9Req *v9fs_tattach(QVirtio9P *v9p, uint32_t fid, uint32_t n_uname, uint16_t tag) { const char *uname = ""; /* ignored by QEMU */ @@ -370,7 +303,7 @@ static void v9fs_rattach(P9Req *req, v9fs_qid *qid) } /* size[4] Twalk tag[2] fid[4] newfid[4] nwname[2] nwname*(wname[s]) */ -static P9Req *v9fs_twalk(QVirtIO9P *v9p, uint32_t fid, uint32_t newfid, +static P9Req *v9fs_twalk(QVirtio9P *v9p, uint32_t fid, uint32_t newfid, uint16_t nwname, char *const wnames[], uint16_t tag) { P9Req *req; @@ -412,7 +345,7 @@ static void v9fs_rwalk(P9Req *req, uint16_t *nwqid, v9fs_qid **wqid) } /* size[4] Tlopen tag[2] fid[4] flags[4] */ -static P9Req *v9fs_tlopen(QVirtIO9P *v9p, uint32_t fid, uint32_t flags, +static P9Req *v9fs_tlopen(QVirtio9P *v9p, uint32_t fid, uint32_t flags, uint16_t tag) { P9Req *req; @@ -440,7 +373,7 @@ static void v9fs_rlopen(P9Req *req, v9fs_qid *qid, uint32_t *iounit) } /* size[4] Twrite tag[2] fid[4] offset[8] count[4] data[count] */ -static P9Req *v9fs_twrite(QVirtIO9P *v9p, uint32_t fid, uint64_t offset, +static P9Req *v9fs_twrite(QVirtio9P *v9p, uint32_t fid, uint64_t offset, uint32_t count, const void *data, uint16_t tag) { P9Req *req; @@ -468,7 +401,7 @@ static void v9fs_rwrite(P9Req *req, uint32_t *count) } /* size[4] Tflush tag[2] oldtag[2] */ -static P9Req *v9fs_tflush(QVirtIO9P *v9p, uint16_t oldtag, uint16_t tag) +static P9Req *v9fs_tflush(QVirtio9P *v9p, uint16_t oldtag, uint16_t tag) { P9Req *req; @@ -485,8 +418,10 @@ static void v9fs_rflush(P9Req *req) v9fs_req_free(req); } -static void fs_version(QVirtIO9P *v9p) +static void fs_version(void *obj, void *data, QGuestAllocator *t_alloc) { + QVirtio9P *v9p = obj; + alloc = t_alloc; const char *version = "9P2000.L"; uint16_t server_len; char *server_version; @@ -501,18 +436,22 @@ static void fs_version(QVirtIO9P *v9p) g_free(server_version); } -static void fs_attach(QVirtIO9P *v9p) +static void fs_attach(void *obj, void *data, QGuestAllocator *t_alloc) { + QVirtio9P *v9p = obj; + alloc = t_alloc; P9Req *req; - fs_version(v9p); + fs_version(v9p, NULL, t_alloc); req = v9fs_tattach(v9p, 0, getuid(), 0); v9fs_req_wait_for_reply(req, NULL); v9fs_rattach(req, NULL); } -static void fs_walk(QVirtIO9P *v9p) +static void fs_walk(void *obj, void *data, QGuestAllocator *t_alloc) { + QVirtio9P *v9p = obj; + alloc = t_alloc; char *wnames[P9_MAXWELEM]; uint16_t nwqid; v9fs_qid *wqid; @@ -523,7 +462,7 @@ static void fs_walk(QVirtIO9P *v9p) wnames[i] = g_strdup_printf(QTEST_V9FS_SYNTH_WALK_FILE, i); } - fs_attach(v9p); + fs_attach(v9p, NULL, t_alloc); req = v9fs_twalk(v9p, 0, 1, P9_MAXWELEM, wnames, 0); v9fs_req_wait_for_reply(req, NULL); v9fs_rwalk(req, &nwqid, &wqid); @@ -537,13 +476,15 @@ static void fs_walk(QVirtIO9P *v9p) g_free(wqid); } -static void fs_walk_no_slash(QVirtIO9P *v9p) +static void fs_walk_no_slash(void *obj, void *data, QGuestAllocator *t_alloc) { + QVirtio9P *v9p = obj; + alloc = t_alloc; char *const wnames[] = { g_strdup(" /") }; P9Req *req; uint32_t err; - fs_attach(v9p); + fs_attach(v9p, NULL, t_alloc); req = v9fs_twalk(v9p, 0, 1, 1, wnames, 0); v9fs_req_wait_for_reply(req, NULL); v9fs_rlerror(req, &err); @@ -553,13 +494,15 @@ static void fs_walk_no_slash(QVirtIO9P *v9p) g_free(wnames[0]); } -static void fs_walk_dotdot(QVirtIO9P *v9p) +static void fs_walk_dotdot(void *obj, void *data, QGuestAllocator *t_alloc) { + QVirtio9P *v9p = obj; + alloc = t_alloc; char *const wnames[] = { g_strdup("..") }; v9fs_qid root_qid, *wqid; P9Req *req; - fs_version(v9p); + fs_version(v9p, NULL, t_alloc); req = v9fs_tattach(v9p, 0, getuid(), 0); v9fs_req_wait_for_reply(req, NULL); v9fs_rattach(req, &root_qid); @@ -574,12 +517,14 @@ static void fs_walk_dotdot(QVirtIO9P *v9p) g_free(wnames[0]); } -static void fs_lopen(QVirtIO9P *v9p) +static void fs_lopen(void *obj, void *data, QGuestAllocator *t_alloc) { + QVirtio9P *v9p = obj; + alloc = t_alloc; char *const wnames[] = { g_strdup(QTEST_V9FS_SYNTH_LOPEN_FILE) }; P9Req *req; - fs_attach(v9p); + fs_attach(v9p, NULL, t_alloc); req = v9fs_twalk(v9p, 0, 1, 1, wnames, 0); v9fs_req_wait_for_reply(req, NULL); v9fs_rwalk(req, NULL, NULL); @@ -591,15 +536,17 @@ static void fs_lopen(QVirtIO9P *v9p) g_free(wnames[0]); } -static void fs_write(QVirtIO9P *v9p) +static void fs_write(void *obj, void *data, QGuestAllocator *t_alloc) { + QVirtio9P *v9p = obj; + alloc = t_alloc; static const uint32_t write_count = P9_MAX_SIZE / 2; char *const wnames[] = { g_strdup(QTEST_V9FS_SYNTH_WRITE_FILE) }; char *buf = g_malloc0(write_count); uint32_t count; P9Req *req; - fs_attach(v9p); + fs_attach(v9p, NULL, t_alloc); req = v9fs_twalk(v9p, 0, 1, 1, wnames, 0); v9fs_req_wait_for_reply(req, NULL); v9fs_rwalk(req, NULL, NULL); @@ -617,14 +564,16 @@ static void fs_write(QVirtIO9P *v9p) g_free(wnames[0]); } -static void fs_flush_success(QVirtIO9P *v9p) +static void fs_flush_success(void *obj, void *data, QGuestAllocator *t_alloc) { + QVirtio9P *v9p = obj; + alloc = t_alloc; char *const wnames[] = { g_strdup(QTEST_V9FS_SYNTH_FLUSH_FILE) }; P9Req *req, *flush_req; uint32_t reply_len; uint8_t should_block; - fs_attach(v9p); + fs_attach(v9p, NULL, t_alloc); req = v9fs_twalk(v9p, 0, 1, 1, wnames, 0); v9fs_req_wait_for_reply(req, NULL); v9fs_rwalk(req, NULL, NULL); @@ -652,14 +601,16 @@ static void fs_flush_success(QVirtIO9P *v9p) g_free(wnames[0]); } -static void fs_flush_ignored(QVirtIO9P *v9p) +static void fs_flush_ignored(void *obj, void *data, QGuestAllocator *t_alloc) { + QVirtio9P *v9p = obj; + alloc = t_alloc; char *const wnames[] = { g_strdup(QTEST_V9FS_SYNTH_FLUSH_FILE) }; P9Req *req, *flush_req; uint32_t count; uint8_t should_block; - fs_attach(v9p); + fs_attach(v9p, NULL, t_alloc); req = v9fs_twalk(v9p, 0, 1, 1, wnames, 0); v9fs_req_wait_for_reply(req, NULL); v9fs_rwalk(req, NULL, NULL); @@ -687,39 +638,22 @@ static void fs_flush_ignored(QVirtIO9P *v9p) g_free(wnames[0]); } -typedef void (*v9fs_test_fn)(QVirtIO9P *v9p); - -static void v9fs_run_pci_test(gconstpointer data) +static void register_virtio_9p_test(void) { - v9fs_test_fn fn = data; - QVirtIO9P *v9p = qvirtio_9p_pci_start(); - - if (fn) { - fn(v9p); - } - qvirtio_9p_pci_stop(v9p); -} - -static void v9fs_qtest_pci_add(const char *path, v9fs_test_fn fn) -{ - qtest_add_data_func(path, fn, v9fs_run_pci_test); + qos_add_test("config", "virtio-9p", pci_config, NULL); + qos_add_test("fs/version/basic", "virtio-9p", fs_version, NULL); + qos_add_test("fs/attach/basic", "virtio-9p", fs_attach, NULL); + qos_add_test("fs/walk/basic", "virtio-9p", fs_walk, NULL); + qos_add_test("fs/walk/no_slash", "virtio-9p", fs_walk_no_slash, + NULL); + qos_add_test("fs/walk/dotdot_from_root", "virtio-9p", + fs_walk_dotdot, NULL); + qos_add_test("fs/lopen/basic", "virtio-9p", fs_lopen, NULL); + qos_add_test("fs/write/basic", "virtio-9p", fs_write, NULL); + qos_add_test("fs/flush/success", "virtio-9p", fs_flush_success, + NULL); + qos_add_test("fs/flush/ignored", "virtio-9p", fs_flush_ignored, + NULL); } -int main(int argc, char **argv) -{ - g_test_init(&argc, &argv, NULL); - v9fs_qtest_pci_add("/virtio/9p/pci/nop", NULL); - v9fs_qtest_pci_add("/virtio/9p/pci/config", pci_config); - v9fs_qtest_pci_add("/virtio/9p/pci/fs/version/basic", fs_version); - v9fs_qtest_pci_add("/virtio/9p/pci/fs/attach/basic", fs_attach); - v9fs_qtest_pci_add("/virtio/9p/pci/fs/walk/basic", fs_walk); - v9fs_qtest_pci_add("/virtio/9p/pci/fs/walk/no_slash", fs_walk_no_slash); - v9fs_qtest_pci_add("/virtio/9p/pci/fs/walk/dotdot_from_root", - fs_walk_dotdot); - v9fs_qtest_pci_add("/virtio/9p/pci/fs/lopen/basic", fs_lopen); - v9fs_qtest_pci_add("/virtio/9p/pci/fs/write/basic", fs_write); - v9fs_qtest_pci_add("/virtio/9p/pci/fs/flush/success", fs_flush_success); - v9fs_qtest_pci_add("/virtio/9p/pci/fs/flush/ignored", fs_flush_ignored); - - return g_test_run(); -} +libqos_init(register_virtio_9p_test); diff --git a/tests/virtio-balloon-test.c b/tests/virtio-balloon-test.c deleted file mode 100644 index 5a1d0ccbb7..0000000000 --- a/tests/virtio-balloon-test.c +++ /dev/null @@ -1,33 +0,0 @@ -/* - * QTest testcase for VirtIO Balloon - * - * Copyright (c) 2014 SUSE LINUX Products GmbH - * - * This work is licensed under the terms of the GNU GPL, version 2 or later. - * See the COPYING file in the top-level directory. - */ - -#include "qemu/osdep.h" -#include "libqtest.h" -#include "libqos/virtio.h" - -/* Tests only initialization so far. TODO: Replace with functional tests */ -static void balloon_nop(void) -{ -} - -int main(int argc, char **argv) -{ - int ret; - - g_test_init(&argc, &argv, NULL); - qtest_add_func("/virtio/balloon/nop", balloon_nop); - - global_qtest = qtest_initf("-device virtio-balloon-%s", - qvirtio_get_dev_type()); - ret = g_test_run(); - - qtest_end(); - - return ret; -} diff --git a/tests/virtio-blk-test.c b/tests/virtio-blk-test.c index 8d2fc9c710..b02be0274e 100644 --- a/tests/virtio-blk-test.c +++ b/tests/virtio-blk-test.c @@ -10,19 +10,11 @@ #include "qemu/osdep.h" #include "libqtest.h" -#include "libqos/libqos-pc.h" -#include "libqos/libqos-spapr.h" -#include "libqos/virtio.h" -#include "libqos/virtio-pci.h" -#include "libqos/virtio-mmio.h" -#include "libqos/malloc-generic.h" -#include "qapi/qmp/qdict.h" #include "qemu/bswap.h" -#include "standard-headers/linux/virtio_ids.h" -#include "standard-headers/linux/virtio_config.h" -#include "standard-headers/linux/virtio_ring.h" #include "standard-headers/linux/virtio_blk.h" #include "standard-headers/linux/virtio_pci.h" +#include "libqos/qgraph.h" +#include "libqos/virtio-blk.h" /* TODO actually test the results and get rid of this */ #define qmp_discard_response(...) qobject_unref(qmp(__VA_ARGS__)) @@ -30,13 +22,6 @@ #define TEST_IMAGE_SIZE (64 * 1024 * 1024) #define QVIRTIO_BLK_TIMEOUT_US (30 * 1000 * 1000) #define PCI_SLOT_HP 0x06 -#define PCI_SLOT 0x04 -#define PCI_FN 0x00 - -#define MMIO_PAGE_SIZE 4096 -#define MMIO_DEV_BASE_ADDR 0x0A003E00 -#define MMIO_RAM_ADDR 0x40000000 -#define MMIO_RAM_SIZE 0x20000000 typedef struct QVirtioBlkReq { uint32_t type; @@ -46,87 +31,34 @@ typedef struct QVirtioBlkReq { uint8_t status; } QVirtioBlkReq; + #ifdef HOST_WORDS_BIGENDIAN const bool host_is_big_endian = true; #else const bool host_is_big_endian; /* false */ #endif +static void drive_destroy(void *path) +{ + unlink(path); + g_free(path); + qos_invalidate_command_line(); +} + static char *drive_create(void) { int fd, ret; - char *tmp_path = g_strdup("/tmp/qtest.XXXXXX"); + char *t_path = g_strdup("/tmp/qtest.XXXXXX"); /* Create a temporary raw image */ - fd = mkstemp(tmp_path); + fd = mkstemp(t_path); g_assert_cmpint(fd, >=, 0); ret = ftruncate(fd, TEST_IMAGE_SIZE); g_assert_cmpint(ret, ==, 0); close(fd); - return tmp_path; -} - -static QOSState *pci_test_start(void) -{ - QOSState *qs; - const char *arch = qtest_get_arch(); - char *tmp_path; - const char *cmd = "-drive if=none,id=drive0,file=%s,format=raw " - "-drive if=none,id=drive1,file=null-co://,format=raw " - "-device virtio-blk-pci,id=drv0,drive=drive0," - "addr=%x.%x"; - - tmp_path = drive_create(); - - if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) { - qs = qtest_pc_boot(cmd, tmp_path, PCI_SLOT, PCI_FN); - } else if (strcmp(arch, "ppc64") == 0) { - qs = qtest_spapr_boot(cmd, tmp_path, PCI_SLOT, PCI_FN); - } else { - g_printerr("virtio-blk tests are only available on x86 or ppc64\n"); - exit(EXIT_FAILURE); - } - global_qtest = qs->qts; - unlink(tmp_path); - g_free(tmp_path); - return qs; -} - -static void arm_test_start(void) -{ - char *tmp_path; - - tmp_path = drive_create(); - - global_qtest = qtest_initf("-machine virt " - "-drive if=none,id=drive0,file=%s,format=raw " - "-device virtio-blk-device,drive=drive0", - tmp_path); - unlink(tmp_path); - g_free(tmp_path); -} - -static void test_end(void) -{ - qtest_end(); -} - -static QVirtioPCIDevice *virtio_blk_pci_init(QPCIBus *bus, int slot) -{ - QVirtioPCIDevice *dev; - - dev = qvirtio_pci_device_find_slot(bus, VIRTIO_ID_BLOCK, slot); - g_assert(dev != NULL); - g_assert_cmphex(dev->vdev.device_type, ==, VIRTIO_ID_BLOCK); - g_assert_cmphex(dev->pdev->devfn, ==, ((slot << 3) | PCI_FN)); - - qvirtio_pci_device_enable(dev); - qvirtio_reset(&dev->vdev); - qvirtio_set_acknowledge(&dev->vdev); - qvirtio_set_driver(&dev->vdev); - - return dev; + g_test_queue_destroy(drive_destroy, t_path); + return t_path; } static inline void virtio_blk_fix_request(QVirtioDevice *d, QVirtioBlkReq *req) @@ -397,31 +329,21 @@ static void test_basic(QVirtioDevice *dev, QGuestAllocator *alloc, } } -static void pci_basic(void) +static void basic(void *obj, void *data, QGuestAllocator *t_alloc) { - QVirtioPCIDevice *dev; - QOSState *qs; - QVirtQueuePCI *vqpci; - - qs = pci_test_start(); - dev = virtio_blk_pci_init(qs->pcibus, PCI_SLOT); - - vqpci = (QVirtQueuePCI *)qvirtqueue_setup(&dev->vdev, qs->alloc, 0); - - test_basic(&dev->vdev, qs->alloc, &vqpci->vq); + QVirtioBlk *blk_if = obj; + QVirtQueue *vq; + vq = qvirtqueue_setup(blk_if->vdev, t_alloc, 0); + test_basic(blk_if->vdev, t_alloc, vq); + qvirtqueue_cleanup(blk_if->vdev->bus, vq, t_alloc); - /* End test */ - qvirtqueue_cleanup(dev->vdev.bus, &vqpci->vq, qs->alloc); - qvirtio_pci_device_disable(dev); - qvirtio_pci_device_free(dev); - qtest_shutdown(qs); } -static void pci_indirect(void) +static void indirect(void *obj, void *u_data, QGuestAllocator *t_alloc) { - QVirtioPCIDevice *dev; - QVirtQueuePCI *vqpci; - QOSState *qs; + QVirtQueue *vq; + QVirtioBlk *blk_if = obj; + QVirtioDevice *dev = blk_if->vdev; QVirtioBlkReq req; QVRingIndirectDesc *indirect; uint64_t req_addr; @@ -431,22 +353,18 @@ static void pci_indirect(void) uint8_t status; char *data; - qs = pci_test_start(); - - dev = virtio_blk_pci_init(qs->pcibus, PCI_SLOT); - - capacity = qvirtio_config_readq(&dev->vdev, 0); + capacity = qvirtio_config_readq(dev, 0); g_assert_cmpint(capacity, ==, TEST_IMAGE_SIZE / 512); - features = qvirtio_get_features(&dev->vdev); + features = qvirtio_get_features(dev); g_assert_cmphex(features & (1u << VIRTIO_RING_F_INDIRECT_DESC), !=, 0); features = features & ~(QVIRTIO_F_BAD_FEATURE | (1u << VIRTIO_RING_F_EVENT_IDX) | (1u << VIRTIO_BLK_F_SCSI)); - qvirtio_set_features(&dev->vdev, features); + qvirtio_set_features(dev, features); - vqpci = (QVirtQueuePCI *)qvirtqueue_setup(&dev->vdev, qs->alloc, 0); - qvirtio_set_driver_ok(&dev->vdev); + vq = qvirtqueue_setup(dev, t_alloc, 0); + qvirtio_set_driver_ok(dev); /* Write request */ req.type = VIRTIO_BLK_T_OUT; @@ -455,23 +373,23 @@ static void pci_indirect(void) req.data = g_malloc0(512); strcpy(req.data, "TEST"); - req_addr = virtio_blk_request(qs->alloc, &dev->vdev, &req, 512); + req_addr = virtio_blk_request(t_alloc, dev, &req, 512); g_free(req.data); - indirect = qvring_indirect_desc_setup(&dev->vdev, qs->alloc, 2); + indirect = qvring_indirect_desc_setup(dev, t_alloc, 2); qvring_indirect_desc_add(indirect, req_addr, 528, false); qvring_indirect_desc_add(indirect, req_addr + 528, 1, true); - free_head = qvirtqueue_add_indirect(&vqpci->vq, indirect); - qvirtqueue_kick(&dev->vdev, &vqpci->vq, free_head); + free_head = qvirtqueue_add_indirect(vq, indirect); + qvirtqueue_kick(dev, vq, free_head); - qvirtio_wait_used_elem(&dev->vdev, &vqpci->vq, free_head, NULL, + qvirtio_wait_used_elem(dev, vq, free_head, NULL, QVIRTIO_BLK_TIMEOUT_US); status = readb(req_addr + 528); g_assert_cmpint(status, ==, 0); g_free(indirect); - guest_free(qs->alloc, req_addr); + guest_free(t_alloc, req_addr); /* Read request */ req.type = VIRTIO_BLK_T_IN; @@ -480,17 +398,17 @@ static void pci_indirect(void) req.data = g_malloc0(512); strcpy(req.data, "TEST"); - req_addr = virtio_blk_request(qs->alloc, &dev->vdev, &req, 512); + req_addr = virtio_blk_request(t_alloc, dev, &req, 512); g_free(req.data); - indirect = qvring_indirect_desc_setup(&dev->vdev, qs->alloc, 2); + indirect = qvring_indirect_desc_setup(dev, t_alloc, 2); qvring_indirect_desc_add(indirect, req_addr, 16, false); qvring_indirect_desc_add(indirect, req_addr + 16, 513, true); - free_head = qvirtqueue_add_indirect(&vqpci->vq, indirect); - qvirtqueue_kick(&dev->vdev, &vqpci->vq, free_head); + free_head = qvirtqueue_add_indirect(vq, indirect); + qvirtqueue_kick(dev, vq, free_head); - qvirtio_wait_used_elem(&dev->vdev, &vqpci->vq, free_head, NULL, + qvirtio_wait_used_elem(dev, vq, free_head, NULL, QVIRTIO_BLK_TIMEOUT_US); status = readb(req_addr + 528); g_assert_cmpint(status, ==, 0); @@ -501,50 +419,37 @@ static void pci_indirect(void) g_free(data); g_free(indirect); - guest_free(qs->alloc, req_addr); - - /* End test */ - qvirtqueue_cleanup(dev->vdev.bus, &vqpci->vq, qs->alloc); - qvirtio_pci_device_disable(dev); - qvirtio_pci_device_free(dev); - qtest_shutdown(qs); + guest_free(t_alloc, req_addr); + qvirtqueue_cleanup(dev->bus, vq, t_alloc); } -static void pci_config(void) +static void config(void *obj, void *data, QGuestAllocator *t_alloc) { - QVirtioPCIDevice *dev; - QOSState *qs; + QVirtioBlk *blk_if = obj; + QVirtioDevice *dev = blk_if->vdev; int n_size = TEST_IMAGE_SIZE / 2; uint64_t capacity; - qs = pci_test_start(); - - dev = virtio_blk_pci_init(qs->pcibus, PCI_SLOT); - - capacity = qvirtio_config_readq(&dev->vdev, 0); + capacity = qvirtio_config_readq(dev, 0); g_assert_cmpint(capacity, ==, TEST_IMAGE_SIZE / 512); - qvirtio_set_driver_ok(&dev->vdev); + qvirtio_set_driver_ok(dev); qmp_discard_response("{ 'execute': 'block_resize', " " 'arguments': { 'device': 'drive0', " " 'size': %d } }", n_size); - qvirtio_wait_config_isr(&dev->vdev, QVIRTIO_BLK_TIMEOUT_US); + qvirtio_wait_config_isr(dev, QVIRTIO_BLK_TIMEOUT_US); - capacity = qvirtio_config_readq(&dev->vdev, 0); + capacity = qvirtio_config_readq(dev, 0); g_assert_cmpint(capacity, ==, n_size / 512); - - qvirtio_pci_device_disable(dev); - qvirtio_pci_device_free(dev); - - qtest_shutdown(qs); } -static void pci_msix(void) +static void msix(void *obj, void *u_data, QGuestAllocator *t_alloc) { - QVirtioPCIDevice *dev; - QOSState *qs; - QVirtQueuePCI *vqpci; + QVirtQueue *vq; + QVirtioBlkPCI *blk = obj; + QVirtioPCIDevice *pdev = &blk->pci_vdev; + QVirtioDevice *dev = &pdev->vdev; QVirtioBlkReq req; int n_size = TEST_IMAGE_SIZE / 2; uint64_t req_addr; @@ -553,36 +458,38 @@ static void pci_msix(void) uint32_t free_head; uint8_t status; char *data; + QOSGraphObject *blk_object = obj; + QPCIDevice *pci_dev = blk_object->get_driver(blk_object, "pci-device"); - qs = pci_test_start(); - - dev = virtio_blk_pci_init(qs->pcibus, PCI_SLOT); - qpci_msix_enable(dev->pdev); + if (qpci_check_buggy_msi(pci_dev)) { + return; + } - qvirtio_pci_set_msix_configuration_vector(dev, qs->alloc, 0); + qpci_msix_enable(pdev->pdev); + qvirtio_pci_set_msix_configuration_vector(pdev, t_alloc, 0); - capacity = qvirtio_config_readq(&dev->vdev, 0); + capacity = qvirtio_config_readq(dev, 0); g_assert_cmpint(capacity, ==, TEST_IMAGE_SIZE / 512); - features = qvirtio_get_features(&dev->vdev); + features = qvirtio_get_features(dev); features = features & ~(QVIRTIO_F_BAD_FEATURE | (1u << VIRTIO_RING_F_INDIRECT_DESC) | (1u << VIRTIO_RING_F_EVENT_IDX) | (1u << VIRTIO_BLK_F_SCSI)); - qvirtio_set_features(&dev->vdev, features); + qvirtio_set_features(dev, features); - vqpci = (QVirtQueuePCI *)qvirtqueue_setup(&dev->vdev, qs->alloc, 0); - qvirtqueue_pci_msix_setup(dev, vqpci, qs->alloc, 1); + vq = qvirtqueue_setup(dev, t_alloc, 0); + qvirtqueue_pci_msix_setup(pdev, (QVirtQueuePCI *)vq, t_alloc, 1); - qvirtio_set_driver_ok(&dev->vdev); + qvirtio_set_driver_ok(dev); qmp_discard_response("{ 'execute': 'block_resize', " " 'arguments': { 'device': 'drive0', " " 'size': %d } }", n_size); - qvirtio_wait_config_isr(&dev->vdev, QVIRTIO_BLK_TIMEOUT_US); + qvirtio_wait_config_isr(dev, QVIRTIO_BLK_TIMEOUT_US); - capacity = qvirtio_config_readq(&dev->vdev, 0); + capacity = qvirtio_config_readq(dev, 0); g_assert_cmpint(capacity, ==, n_size / 512); /* Write request */ @@ -592,22 +499,22 @@ static void pci_msix(void) req.data = g_malloc0(512); strcpy(req.data, "TEST"); - req_addr = virtio_blk_request(qs->alloc, &dev->vdev, &req, 512); + req_addr = virtio_blk_request(t_alloc, dev, &req, 512); g_free(req.data); - free_head = qvirtqueue_add(&vqpci->vq, req_addr, 16, false, true); - qvirtqueue_add(&vqpci->vq, req_addr + 16, 512, false, true); - qvirtqueue_add(&vqpci->vq, req_addr + 528, 1, true, false); - qvirtqueue_kick(&dev->vdev, &vqpci->vq, free_head); + free_head = qvirtqueue_add(vq, req_addr, 16, false, true); + qvirtqueue_add(vq, req_addr + 16, 512, false, true); + qvirtqueue_add(vq, req_addr + 528, 1, true, false); + qvirtqueue_kick(dev, vq, free_head); - qvirtio_wait_used_elem(&dev->vdev, &vqpci->vq, free_head, NULL, + qvirtio_wait_used_elem(dev, vq, free_head, NULL, QVIRTIO_BLK_TIMEOUT_US); status = readb(req_addr + 528); g_assert_cmpint(status, ==, 0); - guest_free(qs->alloc, req_addr); + guest_free(t_alloc, req_addr); /* Read request */ req.type = VIRTIO_BLK_T_IN; @@ -615,18 +522,18 @@ static void pci_msix(void) req.sector = 0; req.data = g_malloc0(512); - req_addr = virtio_blk_request(qs->alloc, &dev->vdev, &req, 512); + req_addr = virtio_blk_request(t_alloc, dev, &req, 512); g_free(req.data); - free_head = qvirtqueue_add(&vqpci->vq, req_addr, 16, false, true); - qvirtqueue_add(&vqpci->vq, req_addr + 16, 512, true, true); - qvirtqueue_add(&vqpci->vq, req_addr + 528, 1, true, false); + free_head = qvirtqueue_add(vq, req_addr, 16, false, true); + qvirtqueue_add(vq, req_addr + 16, 512, true, true); + qvirtqueue_add(vq, req_addr + 528, 1, true, false); - qvirtqueue_kick(&dev->vdev, &vqpci->vq, free_head); + qvirtqueue_kick(dev, vq, free_head); - qvirtio_wait_used_elem(&dev->vdev, &vqpci->vq, free_head, NULL, + qvirtio_wait_used_elem(dev, vq, free_head, NULL, QVIRTIO_BLK_TIMEOUT_US); status = readb(req_addr + 528); @@ -637,21 +544,19 @@ static void pci_msix(void) g_assert_cmpstr(data, ==, "TEST"); g_free(data); - guest_free(qs->alloc, req_addr); + guest_free(t_alloc, req_addr); /* End test */ - qvirtqueue_cleanup(dev->vdev.bus, &vqpci->vq, qs->alloc); - qpci_msix_disable(dev->pdev); - qvirtio_pci_device_disable(dev); - qvirtio_pci_device_free(dev); - qtest_shutdown(qs); + qpci_msix_disable(pdev->pdev); + qvirtqueue_cleanup(dev->bus, vq, t_alloc); } -static void pci_idx(void) +static void idx(void *obj, void *u_data, QGuestAllocator *t_alloc) { - QVirtioPCIDevice *dev; - QOSState *qs; - QVirtQueuePCI *vqpci; + QVirtQueue *vq; + QVirtioBlkPCI *blk = obj; + QVirtioPCIDevice *pdev = &blk->pci_vdev; + QVirtioDevice *dev = &pdev->vdev; QVirtioBlkReq req; uint64_t req_addr; uint64_t capacity; @@ -661,28 +566,30 @@ static void pci_idx(void) uint32_t desc_idx; uint8_t status; char *data; + QOSGraphObject *blk_object = obj; + QPCIDevice *pci_dev = blk_object->get_driver(blk_object, "pci-device"); - qs = pci_test_start(); - - dev = virtio_blk_pci_init(qs->pcibus, PCI_SLOT); - qpci_msix_enable(dev->pdev); + if (qpci_check_buggy_msi(pci_dev)) { + return; + } - qvirtio_pci_set_msix_configuration_vector(dev, qs->alloc, 0); + qpci_msix_enable(pdev->pdev); + qvirtio_pci_set_msix_configuration_vector(pdev, t_alloc, 0); - capacity = qvirtio_config_readq(&dev->vdev, 0); + capacity = qvirtio_config_readq(dev, 0); g_assert_cmpint(capacity, ==, TEST_IMAGE_SIZE / 512); - features = qvirtio_get_features(&dev->vdev); + features = qvirtio_get_features(dev); features = features & ~(QVIRTIO_F_BAD_FEATURE | (1u << VIRTIO_RING_F_INDIRECT_DESC) | (1u << VIRTIO_F_NOTIFY_ON_EMPTY) | (1u << VIRTIO_BLK_F_SCSI)); - qvirtio_set_features(&dev->vdev, features); + qvirtio_set_features(dev, features); - vqpci = (QVirtQueuePCI *)qvirtqueue_setup(&dev->vdev, qs->alloc, 0); - qvirtqueue_pci_msix_setup(dev, vqpci, qs->alloc, 1); + vq = qvirtqueue_setup(dev, t_alloc, 0); + qvirtqueue_pci_msix_setup(pdev, (QVirtQueuePCI *)vq, t_alloc, 1); - qvirtio_set_driver_ok(&dev->vdev); + qvirtio_set_driver_ok(dev); /* Write request */ req.type = VIRTIO_BLK_T_OUT; @@ -691,16 +598,16 @@ static void pci_idx(void) req.data = g_malloc0(512); strcpy(req.data, "TEST"); - req_addr = virtio_blk_request(qs->alloc, &dev->vdev, &req, 512); + req_addr = virtio_blk_request(t_alloc, dev, &req, 512); g_free(req.data); - free_head = qvirtqueue_add(&vqpci->vq, req_addr, 16, false, true); - qvirtqueue_add(&vqpci->vq, req_addr + 16, 512, false, true); - qvirtqueue_add(&vqpci->vq, req_addr + 528, 1, true, false); - qvirtqueue_kick(&dev->vdev, &vqpci->vq, free_head); + free_head = qvirtqueue_add(vq, req_addr, 16, false, true); + qvirtqueue_add(vq, req_addr + 16, 512, false, true); + qvirtqueue_add(vq, req_addr + 528, 1, true, false); + qvirtqueue_kick(dev, vq, free_head); - qvirtio_wait_used_elem(&dev->vdev, &vqpci->vq, free_head, NULL, + qvirtio_wait_used_elem(dev, vq, free_head, NULL, QVIRTIO_BLK_TIMEOUT_US); /* Write request */ @@ -710,25 +617,25 @@ static void pci_idx(void) req.data = g_malloc0(512); strcpy(req.data, "TEST"); - req_addr = virtio_blk_request(qs->alloc, &dev->vdev, &req, 512); + req_addr = virtio_blk_request(t_alloc, dev, &req, 512); g_free(req.data); /* Notify after processing the third request */ - qvirtqueue_set_used_event(&vqpci->vq, 2); - free_head = qvirtqueue_add(&vqpci->vq, req_addr, 16, false, true); - qvirtqueue_add(&vqpci->vq, req_addr + 16, 512, false, true); - qvirtqueue_add(&vqpci->vq, req_addr + 528, 1, true, false); - qvirtqueue_kick(&dev->vdev, &vqpci->vq, free_head); + qvirtqueue_set_used_event(vq, 2); + free_head = qvirtqueue_add(vq, req_addr, 16, false, true); + qvirtqueue_add(vq, req_addr + 16, 512, false, true); + qvirtqueue_add(vq, req_addr + 528, 1, true, false); + qvirtqueue_kick(dev, vq, free_head); write_head = free_head; /* No notification expected */ - status = qvirtio_wait_status_byte_no_isr(&dev->vdev, - &vqpci->vq, req_addr + 528, + status = qvirtio_wait_status_byte_no_isr(dev, + vq, req_addr + 528, QVIRTIO_BLK_TIMEOUT_US); g_assert_cmpint(status, ==, 0); - guest_free(qs->alloc, req_addr); + guest_free(t_alloc, req_addr); /* Read request */ req.type = VIRTIO_BLK_T_IN; @@ -736,20 +643,20 @@ static void pci_idx(void) req.sector = 1; req.data = g_malloc0(512); - req_addr = virtio_blk_request(qs->alloc, &dev->vdev, &req, 512); + req_addr = virtio_blk_request(t_alloc, dev, &req, 512); g_free(req.data); - free_head = qvirtqueue_add(&vqpci->vq, req_addr, 16, false, true); - qvirtqueue_add(&vqpci->vq, req_addr + 16, 512, true, true); - qvirtqueue_add(&vqpci->vq, req_addr + 528, 1, true, false); + free_head = qvirtqueue_add(vq, req_addr, 16, false, true); + qvirtqueue_add(vq, req_addr + 16, 512, true, true); + qvirtqueue_add(vq, req_addr + 528, 1, true, false); - qvirtqueue_kick(&dev->vdev, &vqpci->vq, free_head); + qvirtqueue_kick(dev, vq, free_head); /* We get just one notification for both requests */ - qvirtio_wait_used_elem(&dev->vdev, &vqpci->vq, write_head, NULL, + qvirtio_wait_used_elem(dev, vq, write_head, NULL, QVIRTIO_BLK_TIMEOUT_US); - g_assert(qvirtqueue_get_buf(&vqpci->vq, &desc_idx, NULL)); + g_assert(qvirtqueue_get_buf(vq, &desc_idx, NULL)); g_assert_cmpint(desc_idx, ==, free_head); status = readb(req_addr + 528); @@ -760,124 +667,114 @@ static void pci_idx(void) g_assert_cmpstr(data, ==, "TEST"); g_free(data); - guest_free(qs->alloc, req_addr); + guest_free(t_alloc, req_addr); /* End test */ - qvirtqueue_cleanup(dev->vdev.bus, &vqpci->vq, qs->alloc); - qpci_msix_disable(dev->pdev); - qvirtio_pci_device_disable(dev); - qvirtio_pci_device_free(dev); - qtest_shutdown(qs); + qpci_msix_disable(pdev->pdev); + + qvirtqueue_cleanup(dev->bus, vq, t_alloc); } -static void pci_hotplug(void) +static void pci_hotplug(void *obj, void *data, QGuestAllocator *t_alloc) { + QVirtioPCIDevice *dev1 = obj; QVirtioPCIDevice *dev; - QOSState *qs; - const char *arch = qtest_get_arch(); - - qs = pci_test_start(); /* plug secondary disk */ qtest_qmp_device_add("virtio-blk-pci", "drv1", "{'addr': %s, 'drive': 'drive1'}", - stringify(PCI_SLOT_HP)); + stringify(PCI_SLOT_HP) ".0"); - dev = virtio_blk_pci_init(qs->pcibus, PCI_SLOT_HP); - g_assert(dev); + dev = virtio_pci_new(dev1->pdev->bus, + &(QPCIAddress) { .devfn = QPCI_DEVFN(PCI_SLOT_HP, 0) }); + g_assert_nonnull(dev); + g_assert_cmpint(dev->vdev.device_type, ==, VIRTIO_ID_BLOCK); qvirtio_pci_device_disable(dev); - qvirtio_pci_device_free(dev); + qos_object_destroy((QOSGraphObject *)dev); /* unplug secondary disk */ - if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) { - qpci_unplug_acpi_device_test("drv1", PCI_SLOT_HP); - } - qtest_shutdown(qs); + qpci_unplug_acpi_device_test("drv1", PCI_SLOT_HP); } /* * Check that setting the vring addr on a non-existent virtqueue does * not crash. */ -static void test_nonexistent_virtqueue(void) +static void test_nonexistent_virtqueue(void *obj, void *data, + QGuestAllocator *t_alloc) { + QVirtioBlkPCI *blk = obj; + QVirtioPCIDevice *pdev = &blk->pci_vdev; QPCIBar bar0; - QOSState *qs; QPCIDevice *dev; - qs = pci_test_start(); - dev = qpci_device_find(qs->pcibus, QPCI_DEVFN(4, 0)); + dev = qpci_device_find(pdev->pdev->bus, QPCI_DEVFN(4, 0)); g_assert(dev != NULL); - qpci_device_enable(dev); + bar0 = qpci_iomap(dev, 0, NULL); qpci_io_writeb(dev, bar0, VIRTIO_PCI_QUEUE_SEL, 2); qpci_io_writel(dev, bar0, VIRTIO_PCI_QUEUE_PFN, 1); + g_free(dev); - qtest_shutdown(qs); } -static void mmio_basic(void) +static void resize(void *obj, void *data, QGuestAllocator *t_alloc) { - QVirtioMMIODevice *dev; - QVirtQueue *vq; - QGuestAllocator *alloc; + QVirtioBlk *blk_if = obj; + QVirtioDevice *dev = blk_if->vdev; int n_size = TEST_IMAGE_SIZE / 2; uint64_t capacity; + QVirtQueue *vq; - arm_test_start(); - - dev = qvirtio_mmio_init_device(MMIO_DEV_BASE_ADDR, MMIO_PAGE_SIZE); - g_assert(dev != NULL); - g_assert_cmphex(dev->vdev.device_type, ==, VIRTIO_ID_BLOCK); - - qvirtio_reset(&dev->vdev); - qvirtio_set_acknowledge(&dev->vdev); - qvirtio_set_driver(&dev->vdev); - - alloc = generic_alloc_init(MMIO_RAM_ADDR, MMIO_RAM_SIZE, MMIO_PAGE_SIZE); - vq = qvirtqueue_setup(&dev->vdev, alloc, 0); + vq = qvirtqueue_setup(dev, t_alloc, 0); - test_basic(&dev->vdev, alloc, vq); + test_basic(dev, t_alloc, vq); qmp_discard_response("{ 'execute': 'block_resize', " " 'arguments': { 'device': 'drive0', " " 'size': %d } }", n_size); - qvirtio_wait_queue_isr(&dev->vdev, vq, QVIRTIO_BLK_TIMEOUT_US); + qvirtio_wait_queue_isr(dev, vq, QVIRTIO_BLK_TIMEOUT_US); - capacity = qvirtio_config_readq(&dev->vdev, 0); + capacity = qvirtio_config_readq(dev, 0); g_assert_cmpint(capacity, ==, n_size / 512); - /* End test */ - qvirtqueue_cleanup(dev->vdev.bus, vq, alloc); - g_free(dev); - generic_alloc_uninit(alloc); - test_end(); + qvirtqueue_cleanup(dev->bus, vq, t_alloc); + } -int main(int argc, char **argv) +static void *virtio_blk_test_setup(GString *cmd_line, void *arg) { - const char *arch = qtest_get_arch(); - - g_test_init(&argc, &argv, NULL); - - if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0 || - strcmp(arch, "ppc64") == 0) { - qtest_add_func("/virtio/blk/pci/basic", pci_basic); - qtest_add_func("/virtio/blk/pci/indirect", pci_indirect); - qtest_add_func("/virtio/blk/pci/config", pci_config); - qtest_add_func("/virtio/blk/pci/nxvirtq", test_nonexistent_virtqueue); - if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) { - qtest_add_func("/virtio/blk/pci/msix", pci_msix); - qtest_add_func("/virtio/blk/pci/idx", pci_idx); - } - qtest_add_func("/virtio/blk/pci/hotplug", pci_hotplug); - } else if (strcmp(arch, "arm") == 0) { - qtest_add_func("/virtio/blk/mmio/basic", mmio_basic); - } + char *tmp_path = drive_create(); - return g_test_run(); + g_string_append_printf(cmd_line, + " -drive if=none,id=drive0,file=%s,format=raw " + "-drive if=none,id=drive1,file=null-co://,format=raw ", + tmp_path); + + return arg; } + +static void register_virtio_blk_test(void) +{ + QOSGraphTestOptions opts = { + .before = virtio_blk_test_setup, + }; + + qos_add_test("indirect", "virtio-blk", indirect, &opts); + qos_add_test("config", "virtio-blk", config, &opts); + qos_add_test("basic", "virtio-blk", basic, &opts); + qos_add_test("resize", "virtio-blk", resize, &opts); + + /* tests just for virtio-blk-pci */ + qos_add_test("msix", "virtio-blk-pci", msix, &opts); + qos_add_test("idx", "virtio-blk-pci", idx, &opts); + qos_add_test("nxvirtq", "virtio-blk-pci", + test_nonexistent_virtqueue, &opts); + qos_add_test("hotplug", "virtio-blk-pci", pci_hotplug, &opts); +} + +libqos_init(register_virtio_blk_test); diff --git a/tests/virtio-console-test.c b/tests/virtio-console-test.c deleted file mode 100644 index a7c6f167c3..0000000000 --- a/tests/virtio-console-test.c +++ /dev/null @@ -1,38 +0,0 @@ -/* - * QTest testcase for VirtIO Console - * - * Copyright (c) 2014 SUSE LINUX Products GmbH - * - * This work is licensed under the terms of the GNU GPL, version 2 or later. - * See the COPYING file in the top-level directory. - */ - -#include "qemu/osdep.h" -#include "libqtest.h" -#include "libqos/virtio.h" - -/* Tests only initialization so far. TODO: Replace with functional tests */ -static void console_nop(void) -{ - global_qtest = qtest_initf("-device virtio-serial-%s,id=vser0 " - "-device virtconsole,bus=vser0.0", - qvirtio_get_dev_type()); - qtest_end(); -} - -static void serialport_nop(void) -{ - global_qtest = qtest_initf("-device virtio-serial-%s,id=vser0 " - "-device virtserialport,bus=vser0.0", - qvirtio_get_dev_type()); - qtest_end(); -} - -int main(int argc, char **argv) -{ - g_test_init(&argc, &argv, NULL); - qtest_add_func("/virtio/console/nop", console_nop); - qtest_add_func("/virtio/serialport/nop", serialport_nop); - - return g_test_run(); -} diff --git a/tests/virtio-net-test.c b/tests/virtio-net-test.c index e9783e6707..c58e670e2f 100644 --- a/tests/virtio-net-test.c +++ b/tests/virtio-net-test.c @@ -9,18 +9,11 @@ #include "qemu/osdep.h" #include "libqtest.h" -#include "qemu-common.h" -#include "qemu/sockets.h" #include "qemu/iov.h" -#include "libqos/libqos-pc.h" -#include "libqos/libqos-spapr.h" -#include "libqos/virtio.h" -#include "libqos/virtio-pci.h" #include "qapi/qmp/qdict.h" -#include "qemu/bswap.h" #include "hw/virtio/virtio-net.h" -#include "standard-headers/linux/virtio_ids.h" -#include "standard-headers/linux/virtio_ring.h" +#include "libqos/qgraph.h" +#include "libqos/virtio-net.h" #define PCI_SLOT_HP 0x06 #define PCI_SLOT 0x04 @@ -28,65 +21,8 @@ #define QVIRTIO_NET_TIMEOUT_US (30 * 1000 * 1000) #define VNET_HDR_SIZE sizeof(struct virtio_net_hdr_mrg_rxbuf) -static void test_end(void) -{ - qtest_end(); -} - #ifndef _WIN32 -static QVirtioPCIDevice *virtio_net_pci_init(QPCIBus *bus, int slot) -{ - QVirtioPCIDevice *dev; - - dev = qvirtio_pci_device_find(bus, VIRTIO_ID_NET); - g_assert(dev != NULL); - g_assert_cmphex(dev->vdev.device_type, ==, VIRTIO_ID_NET); - - qvirtio_pci_device_enable(dev); - qvirtio_reset(&dev->vdev); - qvirtio_set_acknowledge(&dev->vdev); - qvirtio_set_driver(&dev->vdev); - - return dev; -} - -GCC_FMT_ATTR(1, 2) -static QOSState *pci_test_start(const char *cmd, ...) -{ - QOSState *qs; - va_list ap; - const char *arch = qtest_get_arch(); - - if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) { - va_start(ap, cmd); - qs = qtest_pc_vboot(cmd, ap); - va_end(ap); - } else if (strcmp(arch, "ppc64") == 0) { - va_start(ap, cmd); - qs = qtest_spapr_vboot(cmd, ap); - va_end(ap); - } else { - g_printerr("virtio-net tests are only available on x86 or ppc64\n"); - exit(EXIT_FAILURE); - } - global_qtest = qs->qts; - return qs; -} - -static void driver_init(QVirtioDevice *dev) -{ - uint32_t features; - - features = qvirtio_get_features(dev); - features = features & ~(QVIRTIO_F_BAD_FEATURE | - (1u << VIRTIO_RING_F_INDIRECT_DESC) | - (1u << VIRTIO_RING_F_EVENT_IDX)); - qvirtio_set_features(dev, features); - - qvirtio_set_driver_ok(dev); -} - static void rx_test(QVirtioDevice *dev, QGuestAllocator *alloc, QVirtQueue *vq, int socket) @@ -196,128 +132,114 @@ static void rx_stop_cont_test(QVirtioDevice *dev, guest_free(alloc, req_addr); } -static void send_recv_test(QVirtioDevice *dev, - QGuestAllocator *alloc, QVirtQueue *rvq, - QVirtQueue *tvq, int socket) +static void send_recv_test(void *obj, void *data, QGuestAllocator *t_alloc) { - rx_test(dev, alloc, rvq, socket); - tx_test(dev, alloc, tvq, socket); + QVirtioNet *net_if = obj; + QVirtioDevice *dev = net_if->vdev; + QVirtQueue *rx = net_if->queues[0]; + QVirtQueue *tx = net_if->queues[1]; + int *sv = data; + + rx_test(dev, t_alloc, rx, sv[0]); + tx_test(dev, t_alloc, tx, sv[0]); } -static void stop_cont_test(QVirtioDevice *dev, - QGuestAllocator *alloc, QVirtQueue *rvq, - QVirtQueue *tvq, int socket) +static void stop_cont_test(void *obj, void *data, QGuestAllocator *t_alloc) { - rx_stop_cont_test(dev, alloc, rvq, socket); + QVirtioNet *net_if = obj; + QVirtioDevice *dev = net_if->vdev; + QVirtQueue *rx = net_if->queues[0]; + int *sv = data; + + rx_stop_cont_test(dev, t_alloc, rx, sv[0]); } -static void pci_basic(gconstpointer data) -{ - QVirtioPCIDevice *dev; - QOSState *qs; - QVirtQueuePCI *tx, *rx; - void (*func) (QVirtioDevice *dev, - QGuestAllocator *alloc, - QVirtQueue *rvq, - QVirtQueue *tvq, - int socket) = data; - int sv[2], ret; +#endif - ret = socketpair(PF_UNIX, SOCK_STREAM, 0, sv); - g_assert_cmpint(ret, !=, -1); +static void hotplug(void *obj, void *data, QGuestAllocator *t_alloc) +{ + const char *arch = qtest_get_arch(); - qs = pci_test_start("-netdev socket,fd=%d,id=hs0 -device " - "virtio-net-pci,netdev=hs0", sv[1]); - dev = virtio_net_pci_init(qs->pcibus, PCI_SLOT); + qtest_qmp_device_add("virtio-net-pci", "net1", + "{'addr': %s}", stringify(PCI_SLOT_HP)); - rx = (QVirtQueuePCI *)qvirtqueue_setup(&dev->vdev, qs->alloc, 0); - tx = (QVirtQueuePCI *)qvirtqueue_setup(&dev->vdev, qs->alloc, 1); + if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) { + qpci_unplug_acpi_device_test("net1", PCI_SLOT_HP); + } +} - driver_init(&dev->vdev); - func(&dev->vdev, qs->alloc, &rx->vq, &tx->vq, sv[0]); +static void virtio_net_test_cleanup(void *sockets) +{ + int *sv = sockets; - /* End test */ close(sv[0]); - qvirtqueue_cleanup(dev->vdev.bus, &tx->vq, qs->alloc); - qvirtqueue_cleanup(dev->vdev.bus, &rx->vq, qs->alloc); - qvirtio_pci_device_disable(dev); - g_free(dev->pdev); - g_free(dev); - qtest_shutdown(qs); + qos_invalidate_command_line(); + close(sv[1]); + g_free(sv); +} + +static void *virtio_net_test_setup(GString *cmd_line, void *arg) +{ + int ret; + int *sv = g_new(int, 2); + + ret = socketpair(PF_UNIX, SOCK_STREAM, 0, sv); + g_assert_cmpint(ret, !=, -1); + + g_string_append_printf(cmd_line, " -netdev socket,fd=%d,id=hs0 ", sv[1]); + + g_test_queue_destroy(virtio_net_test_cleanup, sv); + return sv; } -static void large_tx(gconstpointer data) +static void large_tx(void *obj, void *data, QGuestAllocator *t_alloc) { - QVirtioPCIDevice *dev; - QOSState *qs; - QVirtQueuePCI *tx, *rx; - QVirtQueue *vq; + QVirtioNet *dev = obj; + QVirtQueue *vq = dev->queues[1]; uint64_t req_addr; uint32_t free_head; size_t alloc_size = (size_t)data / 64; int i; - qs = pci_test_start("-netdev hubport,id=hp0,hubid=0 " - "-device virtio-net-pci,netdev=hp0"); - dev = virtio_net_pci_init(qs->pcibus, PCI_SLOT); - - rx = (QVirtQueuePCI *)qvirtqueue_setup(&dev->vdev, qs->alloc, 0); - tx = (QVirtQueuePCI *)qvirtqueue_setup(&dev->vdev, qs->alloc, 1); - - driver_init(&dev->vdev); - vq = &tx->vq; - /* Bypass the limitation by pointing several descriptors to a single * smaller area */ - req_addr = guest_alloc(qs->alloc, alloc_size); + req_addr = guest_alloc(t_alloc, alloc_size); free_head = qvirtqueue_add(vq, req_addr, alloc_size, false, true); for (i = 0; i < 64; i++) { qvirtqueue_add(vq, req_addr, alloc_size, false, i != 63); } - qvirtqueue_kick(&dev->vdev, vq, free_head); + qvirtqueue_kick(dev->vdev, vq, free_head); - qvirtio_wait_used_elem(&dev->vdev, vq, free_head, NULL, + qvirtio_wait_used_elem(dev->vdev, vq, free_head, NULL, QVIRTIO_NET_TIMEOUT_US); - - qvirtqueue_cleanup(dev->vdev.bus, &tx->vq, qs->alloc); - qvirtqueue_cleanup(dev->vdev.bus, &rx->vq, qs->alloc); - qvirtio_pci_device_disable(dev); - g_free(dev->pdev); - g_free(dev); - qtest_shutdown(qs); + guest_free(t_alloc, req_addr); } -#endif -static void hotplug(void) +static void *virtio_net_test_setup_nosocket(GString *cmd_line, void *arg) { - const char *arch = qtest_get_arch(); - - qtest_start("-device virtio-net-pci"); - - qtest_qmp_device_add("virtio-net-pci", "net1", - "{'addr': %s}", stringify(PCI_SLOT_HP)); - - if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) { - qpci_unplug_acpi_device_test("net1", PCI_SLOT_HP); - } - - test_end(); + g_string_append(cmd_line, " -netdev hubport,hubid=0,id=hs0 "); + return arg; } -int main(int argc, char **argv) +static void register_virtio_net_test(void) { - g_test_init(&argc, &argv, NULL); + QOSGraphTestOptions opts = { + .before = virtio_net_test_setup, + }; + + qos_add_test("hotplug", "virtio-pci", hotplug, &opts); #ifndef _WIN32 - qtest_add_data_func("/virtio/net/pci/basic", send_recv_test, pci_basic); - qtest_add_data_func("/virtio/net/pci/rx_stop_cont", - stop_cont_test, pci_basic); - qtest_add_data_func("/virtio/net/pci/large_tx_uint_max", - (gconstpointer)UINT_MAX, large_tx); - qtest_add_data_func("/virtio/net/pci/large_tx_net_bufsize", - (gconstpointer)NET_BUFSIZE, large_tx); + qos_add_test("basic", "virtio-net", send_recv_test, &opts); + qos_add_test("rx_stop_cont", "virtio-net", stop_cont_test, &opts); #endif - qtest_add_func("/virtio/net/pci/hotplug", hotplug); - return g_test_run(); + /* These tests do not need a loopback backend. */ + opts.before = virtio_net_test_setup_nosocket; + opts.arg = (gpointer)UINT_MAX; + qos_add_test("large_tx/uint_max", "virtio-net", large_tx, &opts); + opts.arg = (gpointer)NET_BUFSIZE; + qos_add_test("large_tx/net_bufsize", "virtio-net", large_tx, &opts); } + +libqos_init(register_virtio_net_test); diff --git a/tests/virtio-rng-test.c b/tests/virtio-rng-test.c index 657d9a4105..5309c7c8ab 100644 --- a/tests/virtio-rng-test.c +++ b/tests/virtio-rng-test.c @@ -9,16 +9,12 @@ #include "qemu/osdep.h" #include "libqtest.h" -#include "libqos/pci.h" +#include "libqos/qgraph.h" +#include "libqos/virtio-rng.h" #define PCI_SLOT_HP 0x06 -/* Tests only initialization so far. TODO: Replace with functional tests */ -static void pci_nop(void) -{ -} - -static void hotplug(void) +static void rng_hotplug(void *obj, void *data, QGuestAllocator *alloc) { const char *arch = qtest_get_arch(); @@ -30,18 +26,9 @@ static void hotplug(void) } } -int main(int argc, char **argv) +static void register_virtio_rng_test(void) { - int ret; - - g_test_init(&argc, &argv, NULL); - qtest_add_func("/virtio/rng/pci/nop", pci_nop); - qtest_add_func("/virtio/rng/pci/hotplug", hotplug); - - qtest_start("-device virtio-rng-pci"); - ret = g_test_run(); - - qtest_end(); - - return ret; + qos_add_test("hotplug", "virtio-rng-pci", rng_hotplug, NULL); } + +libqos_init(register_virtio_rng_test); diff --git a/tests/virtio-scsi-test.c b/tests/virtio-scsi-test.c index 0d4f25d369..162b31c88d 100644 --- a/tests/virtio-scsi-test.c +++ b/tests/virtio-scsi-test.c @@ -18,6 +18,8 @@ #include "standard-headers/linux/virtio_ids.h" #include "standard-headers/linux/virtio_pci.h" #include "standard-headers/linux/virtio_scsi.h" +#include "libqos/virtio-scsi.h" +#include "libqos/qgraph.h" #define PCI_SLOT 0x02 #define PCI_FN 0x00 @@ -27,55 +29,28 @@ typedef struct { QVirtioDevice *dev; - QOSState *qs; int num_queues; QVirtQueue *vq[MAX_NUM_QUEUES + 2]; -} QVirtIOSCSI; +} QVirtioSCSIQueues; -static QOSState *qvirtio_scsi_start(const char *extra_opts) -{ - QOSState *qs; - const char *arch = qtest_get_arch(); - const char *cmd = "-drive id=drv0,if=none,file=null-co://,format=raw " - "-device virtio-scsi-pci,id=vs0 " - "-device scsi-hd,bus=vs0.0,drive=drv0 %s"; - - if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) { - qs = qtest_pc_boot(cmd, extra_opts ? : ""); - } else if (strcmp(arch, "ppc64") == 0) { - qs = qtest_spapr_boot(cmd, extra_opts ? : ""); - } else { - g_printerr("virtio-scsi tests are only available on x86 or ppc64\n"); - exit(EXIT_FAILURE); - } - global_qtest = qs->qts; - return qs; -} - -static void qvirtio_scsi_stop(QOSState *qs) -{ - qtest_shutdown(qs); -} +static QGuestAllocator *alloc; -static void qvirtio_scsi_pci_free(QVirtIOSCSI *vs) +static void qvirtio_scsi_pci_free(QVirtioSCSIQueues *vs) { int i; for (i = 0; i < vs->num_queues + 2; i++) { - qvirtqueue_cleanup(vs->dev->bus, vs->vq[i], vs->qs->alloc); + qvirtqueue_cleanup(vs->dev->bus, vs->vq[i], alloc); } - qvirtio_pci_device_disable(container_of(vs->dev, QVirtioPCIDevice, vdev)); - qvirtio_pci_device_free((QVirtioPCIDevice *)vs->dev); - qvirtio_scsi_stop(vs->qs); g_free(vs); } -static uint64_t qvirtio_scsi_alloc(QVirtIOSCSI *vs, size_t alloc_size, +static uint64_t qvirtio_scsi_alloc(QVirtioSCSIQueues *vs, size_t alloc_size, const void *data) { uint64_t addr; - addr = guest_alloc(vs->qs->alloc, alloc_size); + addr = guest_alloc(alloc, alloc_size); if (data) { memwrite(addr, data, alloc_size); } @@ -83,7 +58,8 @@ static uint64_t qvirtio_scsi_alloc(QVirtIOSCSI *vs, size_t alloc_size, return addr; } -static uint8_t virtio_scsi_do_command(QVirtIOSCSI *vs, const uint8_t *cdb, +static uint8_t virtio_scsi_do_command(QVirtioSCSIQueues *vs, + const uint8_t *cdb, const uint8_t *data_in, size_t data_in_len, uint8_t *data_out, size_t data_out_len, @@ -133,42 +109,28 @@ static uint8_t virtio_scsi_do_command(QVirtIOSCSI *vs, const uint8_t *cdb, memread(resp_addr, resp_out, sizeof(*resp_out)); } - guest_free(vs->qs->alloc, req_addr); - guest_free(vs->qs->alloc, resp_addr); - guest_free(vs->qs->alloc, data_in_addr); - guest_free(vs->qs->alloc, data_out_addr); + guest_free(alloc, req_addr); + guest_free(alloc, resp_addr); + guest_free(alloc, data_in_addr); + guest_free(alloc, data_out_addr); return response; } -static QVirtIOSCSI *qvirtio_scsi_pci_init(int slot) +static QVirtioSCSIQueues *qvirtio_scsi_init(QVirtioDevice *dev) { + QVirtioSCSIQueues *vs; const uint8_t test_unit_ready_cdb[VIRTIO_SCSI_CDB_SIZE] = {}; - QVirtIOSCSI *vs; - QVirtioPCIDevice *dev; struct virtio_scsi_cmd_resp resp; int i; - vs = g_new0(QVirtIOSCSI, 1); - - vs->qs = qvirtio_scsi_start("-drive file=blkdebug::null-co://," - "if=none,id=dr1,format=raw,file.align=4k " - "-device scsi-hd,drive=dr1,lun=0,scsi-id=1"); - dev = qvirtio_pci_device_find(vs->qs->pcibus, VIRTIO_ID_SCSI); - vs->dev = (QVirtioDevice *)dev; - g_assert(dev != NULL); - g_assert_cmphex(vs->dev->device_type, ==, VIRTIO_ID_SCSI); - - qvirtio_pci_device_enable(dev); - qvirtio_reset(vs->dev); - qvirtio_set_acknowledge(vs->dev); - qvirtio_set_driver(vs->dev); - - vs->num_queues = qvirtio_config_readl(vs->dev, 0); + vs = g_new0(QVirtioSCSIQueues, 1); + vs->dev = dev; + vs->num_queues = qvirtio_config_readl(dev, 0); g_assert_cmpint(vs->num_queues, <, MAX_NUM_QUEUES); for (i = 0; i < vs->num_queues + 2; i++) { - vs->vq[i] = qvirtqueue_setup(vs->dev, vs->qs->alloc, i); + vs->vq[i] = qvirtqueue_setup(dev, alloc, i); } /* Clear the POWER ON OCCURRED unit attention */ @@ -184,30 +146,18 @@ static QVirtIOSCSI *qvirtio_scsi_pci_init(int slot) return vs; } -/* Tests only initialization so far. TODO: Replace with functional tests */ -static void pci_nop(void) -{ - QOSState *qs; - - qs = qvirtio_scsi_start(NULL); - qvirtio_scsi_stop(qs); -} - -static void hotplug(void) +static void hotplug(void *obj, void *data, QGuestAllocator *alloc) { - QOSState *qs; - - qs = qvirtio_scsi_start( - "-drive id=drv1,if=none,file=null-co://,format=raw"); qtest_qmp_device_add("scsi-hd", "scsihd", "{'drive': 'drv1'}"); qtest_qmp_device_del("scsihd"); - qvirtio_scsi_stop(qs); } /* Test WRITE SAME with the lba not aligned */ -static void test_unaligned_write_same(void) +static void test_unaligned_write_same(void *obj, void *data, + QGuestAllocator *t_alloc) { - QVirtIOSCSI *vs; + QVirtioSCSI *scsi = obj; + QVirtioSCSIQueues *vs; uint8_t buf1[512] = { 0 }; uint8_t buf2[512] = { 1 }; const uint8_t write_same_cdb_1[VIRTIO_SCSI_CDB_SIZE] = { @@ -220,27 +170,50 @@ static void test_unaligned_write_same(void) 0x41, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x33, 0x00, 0x00 }; - vs = qvirtio_scsi_pci_init(PCI_SLOT); + alloc = t_alloc; + vs = qvirtio_scsi_init(scsi->vdev); g_assert_cmphex(0, ==, - virtio_scsi_do_command(vs, write_same_cdb_1, NULL, 0, buf1, 512, NULL)); + virtio_scsi_do_command(vs, write_same_cdb_1, NULL, 0, buf1, 512, + NULL)); g_assert_cmphex(0, ==, - virtio_scsi_do_command(vs, write_same_cdb_2, NULL, 0, buf2, 512, NULL)); + virtio_scsi_do_command(vs, write_same_cdb_2, NULL, 0, buf2, 512, + NULL)); g_assert_cmphex(0, ==, - virtio_scsi_do_command(vs, write_same_cdb_ndob, NULL, 0, NULL, 0, NULL)); + virtio_scsi_do_command(vs, write_same_cdb_ndob, NULL, 0, NULL, 0, + NULL)); qvirtio_scsi_pci_free(vs); } -int main(int argc, char **argv) +static void *virtio_scsi_hotplug_setup(GString *cmd_line, void *arg) { - g_test_init(&argc, &argv, NULL); - qtest_add_func("/virtio/scsi/pci/nop", pci_nop); - qtest_add_func("/virtio/scsi/pci/hotplug", hotplug); - qtest_add_func("/virtio/scsi/pci/scsi-disk/unaligned-write-same", - test_unaligned_write_same); + g_string_append(cmd_line, + " -drive id=drv1,if=none,file=null-co://,format=raw"); + return arg; +} - return g_test_run(); +static void *virtio_scsi_setup(GString *cmd_line, void *arg) +{ + g_string_append(cmd_line, + " -drive file=blkdebug::null-co://," + "if=none,id=dr1,format=raw,file.align=4k " + "-device scsi-hd,drive=dr1,lun=0,scsi-id=1"); + return arg; } + +static void register_virtio_scsi_test(void) +{ + QOSGraphTestOptions opts = { }; + + opts.before = virtio_scsi_hotplug_setup; + qos_add_test("hotplug", "virtio-scsi", hotplug, &opts); + + opts.before = virtio_scsi_setup; + qos_add_test("unaligned-write-same", "virtio-scsi", + test_unaligned_write_same, &opts); +} + +libqos_init(register_virtio_scsi_test); diff --git a/tests/virtio-serial-test.c b/tests/virtio-serial-test.c index 8da9980a24..85f35e09b7 100644 --- a/tests/virtio-serial-test.c +++ b/tests/virtio-serial-test.c @@ -9,33 +9,30 @@ #include "qemu/osdep.h" #include "libqtest.h" -#include "libqos/virtio.h" +#include "libqos/virtio-serial.h" /* Tests only initialization so far. TODO: Replace with functional tests */ -static void virtio_serial_nop(void) +static void virtio_serial_nop(void *obj, void *data, QGuestAllocator *alloc) { + /* no operation */ } -static void hotplug(void) +static void serial_hotplug(void *obj, void *data, QGuestAllocator *alloc) { qtest_qmp_device_add("virtserialport", "hp-port", "{}"); - qtest_qmp_device_del("hp-port"); } -int main(int argc, char **argv) +static void register_virtio_serial_test(void) { - int ret; - - g_test_init(&argc, &argv, NULL); - qtest_add_func("/virtio/serial/nop", virtio_serial_nop); - qtest_add_func("/virtio/serial/hotplug", hotplug); + QOSGraphTestOptions opts = { }; - global_qtest = qtest_initf("-device virtio-serial-%s", - qvirtio_get_dev_type()); - ret = g_test_run(); + opts.edge.before_cmd_line = "-device virtconsole,bus=vser0.0"; + qos_add_test("console-nop", "virtio-serial", virtio_serial_nop, &opts); - qtest_end(); + opts.edge.before_cmd_line = "-device virtserialport,bus=vser0.0"; + qos_add_test("serialport-nop", "virtio-serial", virtio_serial_nop, &opts); - return ret; + qos_add_test("hotplug", "virtio-serial", serial_hotplug, NULL); } +libqos_init(register_virtio_serial_test); diff --git a/tests/virtio-test.c b/tests/virtio-test.c new file mode 100644 index 0000000000..804e5371dc --- /dev/null +++ b/tests/virtio-test.c @@ -0,0 +1,25 @@ +/* + * QTest testcase for virtio + * + * Copyright (c) 2018 Red Hat, Inc. + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#include "qemu/osdep.h" +#include "libqtest.h" +#include "libqos/qgraph.h" +#include "libqos/pci.h" + +/* Tests only initialization so far. TODO: Replace with functional tests */ +static void nop(void *obj, void *data, QGuestAllocator *alloc) +{ +} + +static void register_virtio_test(void) +{ + qos_add_test("nop", "virtio", nop, NULL); +} + +libqos_init(register_virtio_test); diff --git a/tests/vmxnet3-test.c b/tests/vmxnet3-test.c index 159c0ad728..35cdea939b 100644 --- a/tests/vmxnet3-test.c +++ b/tests/vmxnet3-test.c @@ -9,23 +9,49 @@ #include "qemu/osdep.h" #include "libqtest.h" +#include "libqos/qgraph.h" +#include "libqos/pci.h" -/* Tests only initialization so far. TODO: Replace with functional tests */ -static void nop(void) +typedef struct QVmxnet3 QVmxnet3; + +struct QVmxnet3 { + QOSGraphObject obj; + QPCIDevice dev; +}; + +static void *vmxnet3_get_driver(void *obj, const char *interface) { + QVmxnet3 *vmxnet3 = obj; + + if (!g_strcmp0(interface, "pci-device")) { + return &vmxnet3->dev; + } + + fprintf(stderr, "%s not present in vmxnet3\n", interface); + g_assert_not_reached(); } -int main(int argc, char **argv) +static void *vmxnet3_create(void *pci_bus, QGuestAllocator *alloc, void *addr) { - int ret; + QVmxnet3 *vmxnet3 = g_new0(QVmxnet3, 1); + QPCIBus *bus = pci_bus; - g_test_init(&argc, &argv, NULL); - qtest_add_func("/vmxnet3/nop", nop); + qpci_device_init(&vmxnet3->dev, bus, addr); + vmxnet3->obj.get_driver = vmxnet3_get_driver; - qtest_start("-device vmxnet3"); - ret = g_test_run(); + return &vmxnet3->obj; +} - qtest_end(); +static void vmxnet3_register_nodes(void) +{ + QOSGraphEdgeOptions opts = { + .extra_device_opts = "addr=04.0", + }; + add_qpci_address(&opts, &(QPCIAddress) { .devfn = QPCI_DEVFN(4, 0) }); - return ret; + qos_node_create_driver("vmxnet3", vmxnet3_create); + qos_node_consumes("vmxnet3", "pci-bus", &opts); + qos_node_produces("vmxnet3", "pci-device"); } + +libqos_init(vmxnet3_register_nodes); |