xref: /openbmc/qemu/tests/qtest/erst-test.c (revision 45bef95ca5e9d649e432f2acd82163fb5bccbe47)
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  
save_fn(QPCIDevice * dev,int devfn,void * data)17  static void save_fn(QPCIDevice *dev, int devfn, void *data)
18  {
19      QPCIDevice **pdev = (QPCIDevice **) data;
20  
21      *pdev = dev;
22  }
23  
get_erst_device(QPCIBus * pcibus)24  static 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  
38  typedef 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  
reg2str(unsigned reg)48  static 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  
in_reg32(ERSTState * s,unsigned reg)60  static 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  
in_reg64(ERSTState * s,unsigned reg)71  static 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  
out_reg32(ERSTState * s,unsigned reg,uint32_t v)82  static 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  
cleanup_vm(ERSTState * s)90  static void cleanup_vm(ERSTState *s)
91  {
92      g_free(s->dev);
93      qtest_shutdown(s->qs);
94  }
95  
setup_vm_cmd(ERSTState * s,const char * cmd)96  static 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("%s", 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_cmphex(s->mem_barsize, ==, 0x2000);
113  
114      qpci_device_enable(s->dev);
115  }
116  
test_acpi_erst_basic(void)117  static 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  
main(int argc,char ** argv)155  int main(int argc, char **argv)
156  {
157      g_test_init(&argc, &argv, NULL);
158      qtest_add_func("/acpi-erst/basic", test_acpi_erst_basic);
159      return g_test_run();
160  }
161