cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

nvme-test.c (5423B)


      1/*
      2 * QTest testcase for NVMe
      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 "qemu/module.h"
     12#include "qemu/units.h"
     13#include "libqos/libqtest.h"
     14#include "libqos/qgraph.h"
     15#include "libqos/pci.h"
     16#include "include/block/nvme.h"
     17
     18typedef struct QNvme QNvme;
     19
     20struct QNvme {
     21    QOSGraphObject obj;
     22    QPCIDevice dev;
     23};
     24
     25static void *nvme_get_driver(void *obj, const char *interface)
     26{
     27    QNvme *nvme = obj;
     28
     29    if (!g_strcmp0(interface, "pci-device")) {
     30        return &nvme->dev;
     31    }
     32
     33    fprintf(stderr, "%s not present in nvme\n", interface);
     34    g_assert_not_reached();
     35}
     36
     37static void *nvme_create(void *pci_bus, QGuestAllocator *alloc, void *addr)
     38{
     39    QNvme *nvme = g_new0(QNvme, 1);
     40    QPCIBus *bus = pci_bus;
     41
     42    qpci_device_init(&nvme->dev, bus, addr);
     43    nvme->obj.get_driver = nvme_get_driver;
     44
     45    return &nvme->obj;
     46}
     47
     48/* This used to cause a NULL pointer dereference.  */
     49static void nvmetest_oob_cmb_test(void *obj, void *data, QGuestAllocator *alloc)
     50{
     51    const int cmb_bar_size = 2 * MiB;
     52    QNvme *nvme = obj;
     53    QPCIDevice *pdev = &nvme->dev;
     54    QPCIBar bar;
     55
     56    qpci_device_enable(pdev);
     57    bar = qpci_iomap(pdev, 2, NULL);
     58
     59    qpci_io_writel(pdev, bar, 0, 0xccbbaa99);
     60    g_assert_cmpint(qpci_io_readb(pdev, bar, 0), ==, 0x99);
     61    g_assert_cmpint(qpci_io_readw(pdev, bar, 0), ==, 0xaa99);
     62
     63    /* Test partially out-of-bounds accesses.  */
     64    qpci_io_writel(pdev, bar, cmb_bar_size - 1, 0x44332211);
     65    g_assert_cmpint(qpci_io_readb(pdev, bar, cmb_bar_size - 1), ==, 0x11);
     66    g_assert_cmpint(qpci_io_readw(pdev, bar, cmb_bar_size - 1), !=, 0x2211);
     67    g_assert_cmpint(qpci_io_readl(pdev, bar, cmb_bar_size - 1), !=, 0x44332211);
     68}
     69
     70static void nvmetest_reg_read_test(void *obj, void *data, QGuestAllocator *alloc)
     71{
     72    QNvme *nvme = obj;
     73    QPCIDevice *pdev = &nvme->dev;
     74    QPCIBar bar;
     75    uint32_t cap_lo, cap_hi;
     76    uint64_t cap;
     77
     78    qpci_device_enable(pdev);
     79    bar = qpci_iomap(pdev, 0, NULL);
     80
     81    cap_lo = qpci_io_readl(pdev, bar, 0x0);
     82    g_assert_cmpint(NVME_CAP_MQES(cap_lo), ==, 0x7ff);
     83
     84    cap_hi = qpci_io_readl(pdev, bar, 0x4);
     85    g_assert_cmpint(NVME_CAP_MPSMAX((uint64_t)cap_hi << 32), ==, 0x4);
     86
     87    cap = qpci_io_readq(pdev, bar, 0x0);
     88    g_assert_cmpint(NVME_CAP_MQES(cap), ==, 0x7ff);
     89    g_assert_cmpint(NVME_CAP_MPSMAX(cap), ==, 0x4);
     90
     91    qpci_iounmap(pdev, bar);
     92}
     93
     94static void nvmetest_pmr_reg_test(void *obj, void *data, QGuestAllocator *alloc)
     95{
     96    QNvme *nvme = obj;
     97    QPCIDevice *pdev = &nvme->dev;
     98    QPCIBar pmr_bar, nvme_bar;
     99    uint32_t pmrcap, pmrsts;
    100
    101    qpci_device_enable(pdev);
    102    pmr_bar = qpci_iomap(pdev, 4, NULL);
    103
    104    /* Without Enabling PMRCTL check bar enablemet */
    105    qpci_io_writel(pdev, pmr_bar, 0, 0xccbbaa99);
    106    g_assert_cmpint(qpci_io_readb(pdev, pmr_bar, 0), !=, 0x99);
    107    g_assert_cmpint(qpci_io_readw(pdev, pmr_bar, 0), !=, 0xaa99);
    108
    109    /* Map NVMe Bar Register to Enable the Mem Region */
    110    nvme_bar = qpci_iomap(pdev, 0, NULL);
    111
    112    pmrcap = qpci_io_readl(pdev, nvme_bar, 0xe00);
    113    g_assert_cmpint(NVME_PMRCAP_RDS(pmrcap), ==, 0x1);
    114    g_assert_cmpint(NVME_PMRCAP_WDS(pmrcap), ==, 0x1);
    115    g_assert_cmpint(NVME_PMRCAP_BIR(pmrcap), ==, 0x4);
    116    g_assert_cmpint(NVME_PMRCAP_PMRWBM(pmrcap), ==, 0x2);
    117    g_assert_cmpint(NVME_PMRCAP_CMSS(pmrcap), ==, 0x1);
    118
    119    /* Enable PMRCTRL */
    120    qpci_io_writel(pdev, nvme_bar, 0xe04, 0x1);
    121
    122    qpci_io_writel(pdev, pmr_bar, 0, 0x44332211);
    123    g_assert_cmpint(qpci_io_readb(pdev, pmr_bar, 0), ==, 0x11);
    124    g_assert_cmpint(qpci_io_readw(pdev, pmr_bar, 0), ==, 0x2211);
    125    g_assert_cmpint(qpci_io_readl(pdev, pmr_bar, 0), ==, 0x44332211);
    126
    127    pmrsts = qpci_io_readl(pdev, nvme_bar, 0xe08);
    128    g_assert_cmpint(NVME_PMRSTS_NRDY(pmrsts), ==, 0x0);
    129
    130    /* Disable PMRCTRL */
    131    qpci_io_writel(pdev, nvme_bar, 0xe04, 0x0);
    132
    133    qpci_io_writel(pdev, pmr_bar, 0, 0x88776655);
    134    g_assert_cmpint(qpci_io_readb(pdev, pmr_bar, 0), !=, 0x55);
    135    g_assert_cmpint(qpci_io_readw(pdev, pmr_bar, 0), !=, 0x6655);
    136    g_assert_cmpint(qpci_io_readl(pdev, pmr_bar, 0), !=, 0x88776655);
    137
    138    pmrsts = qpci_io_readl(pdev, nvme_bar, 0xe08);
    139    g_assert_cmpint(NVME_PMRSTS_NRDY(pmrsts), ==, 0x1);
    140
    141    qpci_iounmap(pdev, nvme_bar);
    142    qpci_iounmap(pdev, pmr_bar);
    143}
    144
    145static void nvme_register_nodes(void)
    146{
    147    QOSGraphEdgeOptions opts = {
    148        .extra_device_opts = "addr=04.0,drive=drv0,serial=foo",
    149        .before_cmd_line = "-drive id=drv0,if=none,file=null-co://,"
    150                           "file.read-zeroes=on,format=raw "
    151                           "-object memory-backend-ram,id=pmr0,"
    152                           "share=on,size=8",
    153    };
    154
    155    add_qpci_address(&opts, &(QPCIAddress) { .devfn = QPCI_DEVFN(4, 0) });
    156
    157    qos_node_create_driver("nvme", nvme_create);
    158    qos_node_consumes("nvme", "pci-bus", &opts);
    159    qos_node_produces("nvme", "pci-device");
    160
    161    qos_add_test("oob-cmb-access", "nvme", nvmetest_oob_cmb_test, &(QOSGraphTestOptions) {
    162        .edge.extra_device_opts = "cmb_size_mb=2"
    163    });
    164
    165    qos_add_test("pmr-test-access", "nvme", nvmetest_pmr_reg_test,
    166                 &(QOSGraphTestOptions) {
    167        .edge.extra_device_opts = "pmrdev=pmr0"
    168    });
    169
    170    qos_add_test("reg-read", "nvme", nvmetest_reg_read_test, NULL);
    171}
    172
    173libqos_init(nvme_register_nodes);