The 'addr' parameter to qvirtio_config_read*() doesn't have a consistent meaning: when using the virtio-pci versions, it's a full PCI space address, but for virtio-mmio, it's an offset from the device's base mmio address. This means that the callers need to do different things to calculate the addresses in the two cases, which rather defeats the purpose of function pointer backends. All the current users of these functions are using them to retrieve variables from the device specific portion of the virtio config space. So, this patch alters the semantics to always be an offset into that device specific config area. Signed-off-by: David Gibson <david@gibson.dropbear.id.au> Reviewed-by: Laurent Vivier <lvivier@redhat.com> Reviewed-by: Greg Kurz <groug@kaod.org>
128 lines
3.1 KiB
C
128 lines
3.1 KiB
C
/*
|
|
* 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;
|
|
size_t tag_len;
|
|
char *tag;
|
|
int i;
|
|
QOSState *qs;
|
|
|
|
qs = qvirtio_9p_start();
|
|
v9p = qvirtio_9p_pci_init(qs);
|
|
|
|
tag_len = qvirtio_config_readw(v9p->dev, 0);
|
|
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);
|
|
}
|
|
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();
|
|
}
|