1 /* 2 * QTest testcase for VirtIO 9P 3 * 4 * Copyright (c) 2014 SUSE LINUX Products GmbH 5 * 6 * This work is licensed under the terms of the GNU GPL, version 2 or later. 7 * See the COPYING file in the top-level directory. 8 */ 9 10 #include "qemu/osdep.h" 11 #include "libqtest.h" 12 #include "qemu-common.h" 13 #include "libqos/libqos-pc.h" 14 #include "libqos/libqos-spapr.h" 15 #include "libqos/virtio.h" 16 #include "libqos/virtio-pci.h" 17 #include "standard-headers/linux/virtio_ids.h" 18 #include "standard-headers/linux/virtio_pci.h" 19 20 static const char mount_tag[] = "qtest"; 21 22 typedef struct { 23 QVirtioDevice *dev; 24 QOSState *qs; 25 QVirtQueue *vq; 26 char *test_share; 27 } QVirtIO9P; 28 29 static QVirtIO9P *qvirtio_9p_start(const char *driver) 30 { 31 const char *arch = qtest_get_arch(); 32 const char *cmd = "-fsdev local,id=fsdev0,security_model=none,path=%s " 33 "-device %s,fsdev=fsdev0,mount_tag=%s"; 34 QVirtIO9P *v9p = g_new0(QVirtIO9P, 1); 35 36 v9p->test_share = g_strdup("/tmp/qtest.XXXXXX"); 37 g_assert_nonnull(mkdtemp(v9p->test_share)); 38 39 if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) { 40 v9p->qs = qtest_pc_boot(cmd, v9p->test_share, driver, mount_tag); 41 } else if (strcmp(arch, "ppc64") == 0) { 42 v9p->qs = qtest_spapr_boot(cmd, v9p->test_share, driver, mount_tag); 43 } else { 44 g_printerr("virtio-9p tests are only available on x86 or ppc64\n"); 45 exit(EXIT_FAILURE); 46 } 47 48 return v9p; 49 } 50 51 static void qvirtio_9p_stop(QVirtIO9P *v9p) 52 { 53 qtest_shutdown(v9p->qs); 54 rmdir(v9p->test_share); 55 g_free(v9p->test_share); 56 g_free(v9p); 57 } 58 59 static QVirtIO9P *qvirtio_9p_pci_start(void) 60 { 61 QVirtIO9P *v9p = qvirtio_9p_start("virtio-9p-pci"); 62 QVirtioPCIDevice *dev = qvirtio_pci_device_find(v9p->qs->pcibus, 63 VIRTIO_ID_9P); 64 g_assert_nonnull(dev); 65 g_assert_cmphex(dev->vdev.device_type, ==, VIRTIO_ID_9P); 66 v9p->dev = (QVirtioDevice *) dev; 67 68 qvirtio_pci_device_enable(dev); 69 qvirtio_reset(v9p->dev); 70 qvirtio_set_acknowledge(v9p->dev); 71 qvirtio_set_driver(v9p->dev); 72 73 v9p->vq = qvirtqueue_setup(v9p->dev, v9p->qs->alloc, 0); 74 return v9p; 75 } 76 77 static void qvirtio_9p_pci_stop(QVirtIO9P *v9p) 78 { 79 qvirtqueue_cleanup(v9p->dev->bus, v9p->vq, v9p->qs->alloc); 80 qvirtio_pci_device_disable(container_of(v9p->dev, QVirtioPCIDevice, vdev)); 81 g_free(v9p->dev); 82 qvirtio_9p_stop(v9p); 83 } 84 85 static void pci_config(QVirtIO9P *v9p) 86 { 87 size_t tag_len = qvirtio_config_readw(v9p->dev, 0); 88 char *tag; 89 int i; 90 91 g_assert_cmpint(tag_len, ==, strlen(mount_tag)); 92 93 tag = g_malloc(tag_len); 94 for (i = 0; i < tag_len; i++) { 95 tag[i] = qvirtio_config_readb(v9p->dev, i + 2); 96 } 97 g_assert_cmpmem(tag, tag_len, mount_tag, tag_len); 98 g_free(tag); 99 } 100 101 typedef void (*v9fs_test_fn)(QVirtIO9P *v9p); 102 103 static void v9fs_run_pci_test(gconstpointer data) 104 { 105 v9fs_test_fn fn = data; 106 QVirtIO9P *v9p = qvirtio_9p_pci_start(); 107 108 if (fn) { 109 fn(v9p); 110 } 111 qvirtio_9p_pci_stop(v9p); 112 } 113 114 static void v9fs_qtest_pci_add(const char *path, v9fs_test_fn fn) 115 { 116 qtest_add_data_func(path, fn, v9fs_run_pci_test); 117 } 118 119 int main(int argc, char **argv) 120 { 121 g_test_init(&argc, &argv, NULL); 122 v9fs_qtest_pci_add("/virtio/9p/pci/nop", NULL); 123 v9fs_qtest_pci_add("/virtio/9p/pci/config", pci_config); 124 125 return g_test_run(); 126 } 127