qemu/tests/qtest/erst-test.c
<<
>>
Prefs
   1/*
   2 * QTest testcase for acpi-erst
   3 *
   4 * Copyright (c) 2021 Oracle
   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 <glib/gstdio.h>
  12#include "libqos/libqos-pc.h"
  13#include "libqtest.h"
  14
  15#include "hw/pci/pci.h"
  16
  17static void save_fn(QPCIDevice *dev, int devfn, void *data)
  18{
  19    QPCIDevice **pdev = (QPCIDevice **) data;
  20
  21    *pdev = dev;
  22}
  23
  24static QPCIDevice *get_erst_device(QPCIBus *pcibus)
  25{
  26    QPCIDevice *dev;
  27
  28    dev = NULL;
  29    qpci_device_foreach(pcibus,
  30        PCI_VENDOR_ID_REDHAT,
  31        PCI_DEVICE_ID_REDHAT_ACPI_ERST,
  32        save_fn, &dev);
  33    g_assert(dev != NULL);
  34
  35    return dev;
  36}
  37
  38typedef struct _ERSTState {
  39    QOSState *qs;
  40    QPCIBar reg_bar, mem_bar;
  41    uint64_t reg_barsize, mem_barsize;
  42    QPCIDevice *dev;
  43} ERSTState;
  44
  45#define ACTION 0
  46#define VALUE 8
  47
  48static const char *reg2str(unsigned reg)
  49{
  50    switch (reg) {
  51    case 0:
  52        return "ACTION";
  53    case 8:
  54        return "VALUE";
  55    default:
  56        return NULL;
  57    }
  58}
  59
  60static inline uint32_t in_reg32(ERSTState *s, unsigned reg)
  61{
  62    const char *name = reg2str(reg);
  63    uint32_t res;
  64
  65    res = qpci_io_readl(s->dev, s->reg_bar, reg);
  66    g_test_message("*%s -> %08x", name, res);
  67
  68    return res;
  69}
  70
  71static inline uint64_t in_reg64(ERSTState *s, unsigned reg)
  72{
  73    const char *name = reg2str(reg);
  74    uint64_t res;
  75
  76    res = qpci_io_readq(s->dev, s->reg_bar, reg);
  77    g_test_message("*%s -> %016" PRIx64, name, res);
  78
  79    return res;
  80}
  81
  82static inline void out_reg32(ERSTState *s, unsigned reg, uint32_t v)
  83{
  84    const char *name = reg2str(reg);
  85
  86    g_test_message("%08x -> *%s", v, name);
  87    qpci_io_writel(s->dev, s->reg_bar, reg, v);
  88}
  89
  90static void cleanup_vm(ERSTState *s)
  91{
  92    g_free(s->dev);
  93    qtest_shutdown(s->qs);
  94}
  95
  96static void setup_vm_cmd(ERSTState *s, const char *cmd)
  97{
  98    const char *arch = qtest_get_arch();
  99
 100    if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) {
 101        s->qs = qtest_pc_boot(cmd);
 102    } else {
 103        g_printerr("erst-test tests are only available on x86\n");
 104        exit(EXIT_FAILURE);
 105    }
 106    s->dev = get_erst_device(s->qs->pcibus);
 107
 108    s->reg_bar = qpci_iomap(s->dev, 0, &s->reg_barsize);
 109    g_assert_cmpuint(s->reg_barsize, ==, 16);
 110
 111    s->mem_bar = qpci_iomap(s->dev, 1, &s->mem_barsize);
 112    g_assert_cmpuint(s->mem_barsize, ==, 0x2000);
 113
 114    qpci_device_enable(s->dev);
 115}
 116
 117static void test_acpi_erst_basic(void)
 118{
 119    ERSTState state;
 120    uint64_t log_address_range;
 121    uint64_t log_address_length;
 122    uint32_t log_address_attr;
 123
 124    setup_vm_cmd(&state,
 125        "-object memory-backend-file,"
 126            "mem-path=acpi-erst.XXXXXX,"
 127            "size=64K,"
 128            "share=on,"
 129            "id=nvram "
 130        "-device acpi-erst,"
 131            "memdev=nvram");
 132
 133    out_reg32(&state, ACTION, 0xD);
 134    log_address_range = in_reg64(&state, VALUE);
 135    out_reg32(&state, ACTION, 0xE);
 136    log_address_length = in_reg64(&state, VALUE);
 137    out_reg32(&state, ACTION, 0xF);
 138    log_address_attr = in_reg32(&state, VALUE);
 139
 140    /* Check log_address_range is not 0, ~0 or base */
 141    g_assert_cmpuint(log_address_range, !=,  0ULL);
 142    g_assert_cmpuint(log_address_range, !=, ~0ULL);
 143    g_assert_cmpuint(log_address_range, !=, state.reg_bar.addr);
 144    g_assert_cmpuint(log_address_range, ==, state.mem_bar.addr);
 145
 146    /* Check log_address_length is bar1_size */
 147    g_assert_cmpuint(log_address_length, ==, state.mem_barsize);
 148
 149    /* Check log_address_attr is 0 */
 150    g_assert_cmpuint(log_address_attr, ==, 0);
 151
 152    cleanup_vm(&state);
 153}
 154
 155int main(int argc, char **argv)
 156{
 157    int ret;
 158
 159    g_test_init(&argc, &argv, NULL);
 160    qtest_add_func("/acpi-erst/basic", test_acpi_erst_basic);
 161    ret = g_test_run();
 162    return ret;
 163}
 164