2 * QTest testcase for NVMe
4 * Copyright (c) 2014 SUSE LINUX Products GmbH
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.
10 #include "qemu/osdep.h"
11 #include "qemu/units.h"
13 #include "libqos/qgraph.h"
14 #include "libqos/pci.h"
16 typedef struct QNvme QNvme
;
23 static void *nvme_get_driver(void *obj
, const char *interface
)
27 if (!g_strcmp0(interface
, "pci-device")) {
31 fprintf(stderr
, "%s not present in nvme\n", interface
);
32 g_assert_not_reached();
35 static void *nvme_create(void *pci_bus
, QGuestAllocator
*alloc
, void *addr
)
37 QNvme
*nvme
= g_new0(QNvme
, 1);
38 QPCIBus
*bus
= pci_bus
;
40 qpci_device_init(&nvme
->dev
, bus
, addr
);
41 nvme
->obj
.get_driver
= nvme_get_driver
;
46 /* This used to cause a NULL pointer dereference. */
47 static void nvmetest_oob_cmb_test(void *obj
, void *data
, QGuestAllocator
*alloc
)
49 const int cmb_bar_size
= 2 * MiB
;
51 QPCIDevice
*pdev
= &nvme
->dev
;
54 qpci_device_enable(pdev
);
55 bar
= qpci_iomap(pdev
, 2, NULL
);
57 qpci_io_writel(pdev
, bar
, 0, 0xccbbaa99);
58 g_assert_cmpint(qpci_io_readb(pdev
, bar
, 0), ==, 0x99);
59 g_assert_cmpint(qpci_io_readw(pdev
, bar
, 0), ==, 0xaa99);
61 /* Test partially out-of-bounds accesses. */
62 qpci_io_writel(pdev
, bar
, cmb_bar_size
- 1, 0x44332211);
63 g_assert_cmpint(qpci_io_readb(pdev
, bar
, cmb_bar_size
- 1), ==, 0x11);
64 g_assert_cmpint(qpci_io_readw(pdev
, bar
, cmb_bar_size
- 1), !=, 0x2211);
65 g_assert_cmpint(qpci_io_readl(pdev
, bar
, cmb_bar_size
- 1), !=, 0x44332211);
68 static void nvme_register_nodes(void)
70 QOSGraphEdgeOptions opts
= {
71 .extra_device_opts
= "addr=04.0,drive=drv0,serial=foo",
72 .before_cmd_line
= "-drive id=drv0,if=none,file=null-co://,format=raw",
75 add_qpci_address(&opts
, &(QPCIAddress
) { .devfn
= QPCI_DEVFN(4, 0) });
77 qos_node_create_driver("nvme", nvme_create
);
78 qos_node_consumes("nvme", "pci-bus", &opts
);
79 qos_node_produces("nvme", "pci-device");
81 qos_add_test("oob-cmb-access", "nvme", nvmetest_oob_cmb_test
, &(QOSGraphTestOptions
) {
82 .edge
.extra_device_opts
= "cmb_size_mb=2"
86 libqos_init(nvme_register_nodes
);