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