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/module.h"
12 #include "qemu/units.h"
14 #include "libqos/qgraph.h"
15 #include "libqos/pci.h"
17 typedef struct QNvme QNvme
;
24 static void *nvme_get_driver(void *obj
, const char *interface
)
28 if (!g_strcmp0(interface
, "pci-device")) {
32 fprintf(stderr
, "%s not present in nvme\n", interface
);
33 g_assert_not_reached();
36 static void *nvme_create(void *pci_bus
, QGuestAllocator
*alloc
, void *addr
)
38 QNvme
*nvme
= g_new0(QNvme
, 1);
39 QPCIBus
*bus
= pci_bus
;
41 qpci_device_init(&nvme
->dev
, bus
, addr
);
42 nvme
->obj
.get_driver
= nvme_get_driver
;
47 /* This used to cause a NULL pointer dereference. */
48 static void nvmetest_oob_cmb_test(void *obj
, void *data
, QGuestAllocator
*alloc
)
50 const int cmb_bar_size
= 2 * MiB
;
52 QPCIDevice
*pdev
= &nvme
->dev
;
55 qpci_device_enable(pdev
);
56 bar
= qpci_iomap(pdev
, 2, NULL
);
58 qpci_io_writel(pdev
, bar
, 0, 0xccbbaa99);
59 g_assert_cmpint(qpci_io_readb(pdev
, bar
, 0), ==, 0x99);
60 g_assert_cmpint(qpci_io_readw(pdev
, bar
, 0), ==, 0xaa99);
62 /* Test partially out-of-bounds accesses. */
63 qpci_io_writel(pdev
, bar
, cmb_bar_size
- 1, 0x44332211);
64 g_assert_cmpint(qpci_io_readb(pdev
, bar
, cmb_bar_size
- 1), ==, 0x11);
65 g_assert_cmpint(qpci_io_readw(pdev
, bar
, cmb_bar_size
- 1), !=, 0x2211);
66 g_assert_cmpint(qpci_io_readl(pdev
, bar
, cmb_bar_size
- 1), !=, 0x44332211);
69 static void nvme_register_nodes(void)
71 QOSGraphEdgeOptions opts
= {
72 .extra_device_opts
= "addr=04.0,drive=drv0,serial=foo",
73 .before_cmd_line
= "-drive id=drv0,if=none,file=null-co://,format=raw",
76 add_qpci_address(&opts
, &(QPCIAddress
) { .devfn
= QPCI_DEVFN(4, 0) });
78 qos_node_create_driver("nvme", nvme_create
);
79 qos_node_consumes("nvme", "pci-bus", &opts
);
80 qos_node_produces("nvme", "pci-device");
82 qos_add_test("oob-cmb-access", "nvme", nvmetest_oob_cmb_test
, &(QOSGraphTestOptions
) {
83 .edge
.extra_device_opts
= "cmb_size_mb=2"
87 libqos_init(nvme_register_nodes
);