summaryrefslogtreecommitdiff
path: root/tests/virtio-9p-test.c
blob: 693920af5f3cfdf66e38f5aa6fac3d41ab68d919 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
/*
 * QTest testcase for VirtIO 9P
 *
 * 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 "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"

static const char mount_tag[] = "qtest";
static char *test_share;


static QOSState *qvirtio_9p_start(void)
{
    const char *arch = qtest_get_arch();
    const char *cmd = "-fsdev local,id=fsdev0,security_model=none,path=%s "
                      "-device virtio-9p-pci,fsdev=fsdev0,mount_tag=%s";

    test_share = g_strdup("/tmp/qtest.XXXXXX");
    g_assert_nonnull(mkdtemp(test_share));

    if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) {
        return qtest_pc_boot(cmd, test_share, mount_tag);
    }
    if (strcmp(arch, "ppc64") == 0) {
        return qtest_spapr_boot(cmd, test_share, mount_tag);
    }

    g_printerr("virtio-9p tests are only available on x86 or ppc64\n");
    exit(EXIT_FAILURE);
}

static void qvirtio_9p_stop(QOSState *qs)
{
    qtest_shutdown(qs);
    rmdir(test_share);
    g_free(test_share);
}

static void pci_nop(void)
{
    QOSState *qs;

    qs = qvirtio_9p_start();
    qvirtio_9p_stop(qs);
}

typedef struct {
    QVirtioDevice *dev;
    QOSState *qs;
    QVirtQueue *vq;
} QVirtIO9P;

static QVirtIO9P *qvirtio_9p_pci_init(QOSState *qs)
{
    QVirtIO9P *v9p;
    QVirtioPCIDevice *dev;

    v9p = g_new0(QVirtIO9P, 1);

    v9p->qs = qs;
    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);
    return v9p;
}

static void qvirtio_9p_pci_free(QVirtIO9P *v9p)
{
    qvirtqueue_cleanup(v9p->dev->bus, v9p->vq, v9p->qs->alloc);
    qvirtio_pci_device_disable(container_of(v9p->dev, QVirtioPCIDevice, vdev));
    g_free(v9p->dev);
    g_free(v9p);
}

static void pci_basic_config(void)
{
    QVirtIO9P *v9p;
    void *addr;
    size_t tag_len;
    char *tag;
    int i;
    QOSState *qs;

    qs = qvirtio_9p_start();
    v9p = qvirtio_9p_pci_init(qs);

    addr = ((QVirtioPCIDevice *) v9p->dev)->addr + VIRTIO_PCI_CONFIG_OFF(false);
    tag_len = qvirtio_config_readw(v9p->dev,
                                   (uint64_t)(uintptr_t)addr);
    g_assert_cmpint(tag_len, ==, strlen(mount_tag));
    addr += sizeof(uint16_t);

    tag = g_malloc(tag_len);
    for (i = 0; i < tag_len; i++) {
        tag[i] = qvirtio_config_readb(v9p->dev, (uint64_t)(uintptr_t)addr + i);
    }
    g_assert_cmpmem(tag, tag_len, mount_tag, tag_len);
    g_free(tag);

    qvirtio_9p_pci_free(v9p);
    qvirtio_9p_stop(qs);
}

int main(int argc, char **argv)
{
    g_test_init(&argc, &argv, NULL);
    qtest_add_func("/virtio/9p/pci/nop", pci_nop);
    qtest_add_func("/virtio/9p/pci/basic/configuration", pci_basic_config);

    return g_test_run();
}