xref: /openbmc/qemu/tests/qtest/pvpanic-pci-test.c (revision 7d87775f)
1 /*
2  * QTest testcase for PV Panic PCI device
3  *
4  * Copyright (C) 2020 Oracle
5  *
6  * Authors:
7  *     Mihai Carabas <mihai.carabas@oracle.com>
8  *
9  * This work is licensed under the terms of the GNU GPL, version 2 or later.
10  * See the COPYING file in the top-level directory.
11  *
12  */
13 
14 #include "qemu/osdep.h"
15 #include "libqtest.h"
16 #include "qapi/qmp/qdict.h"
17 #include "libqos/pci.h"
18 #include "libqos/pci-pc.h"
19 #include "hw/misc/pvpanic.h"
20 #include "hw/pci/pci_regs.h"
21 
22 static void test_panic_nopause(void)
23 {
24     uint8_t val;
25     QDict *response, *data;
26     QTestState *qts;
27     QPCIBus *pcibus;
28     QPCIDevice *dev;
29     QPCIBar bar;
30 
31     qts = qtest_init("-device pvpanic-pci,addr=04.0 -action panic=none");
32     pcibus = qpci_new_pc(qts, NULL);
33     dev = qpci_device_find(pcibus, QPCI_DEVFN(0x4, 0x0));
34     qpci_device_enable(dev);
35     bar = qpci_iomap(dev, 0, NULL);
36 
37     qpci_memread(dev, bar, 0, &val, sizeof(val));
38     g_assert_cmpuint(val, ==, PVPANIC_EVENTS);
39 
40     val = 1;
41     qpci_memwrite(dev, bar, 0, &val, sizeof(val));
42 
43     response = qtest_qmp_eventwait_ref(qts, "GUEST_PANICKED");
44     g_assert(qdict_haskey(response, "data"));
45     data = qdict_get_qdict(response, "data");
46     g_assert(qdict_haskey(data, "action"));
47     g_assert_cmpstr(qdict_get_str(data, "action"), ==, "run");
48     qobject_unref(response);
49 
50     g_free(dev);
51     qpci_free_pc(pcibus);
52     qtest_quit(qts);
53 }
54 
55 static void test_panic(void)
56 {
57     uint8_t val;
58     QDict *response, *data;
59     QTestState *qts;
60     QPCIBus *pcibus;
61     QPCIDevice *dev;
62     QPCIBar bar;
63 
64     qts = qtest_init("-device pvpanic-pci,addr=04.0 -action panic=pause");
65     pcibus = qpci_new_pc(qts, NULL);
66     dev = qpci_device_find(pcibus, QPCI_DEVFN(0x4, 0x0));
67     qpci_device_enable(dev);
68     bar = qpci_iomap(dev, 0, NULL);
69 
70     qpci_memread(dev, bar, 0, &val, sizeof(val));
71     g_assert_cmpuint(val, ==, PVPANIC_EVENTS);
72 
73     val = 1;
74     qpci_memwrite(dev, bar, 0, &val, sizeof(val));
75 
76     response = qtest_qmp_eventwait_ref(qts, "GUEST_PANICKED");
77     g_assert(qdict_haskey(response, "data"));
78     data = qdict_get_qdict(response, "data");
79     g_assert(qdict_haskey(data, "action"));
80     g_assert_cmpstr(qdict_get_str(data, "action"), ==, "pause");
81     qobject_unref(response);
82 
83     g_free(dev);
84     qpci_free_pc(pcibus);
85     qtest_quit(qts);
86 }
87 
88 static void test_pvshutdown(void)
89 {
90     uint8_t val;
91     QDict *response, *data;
92     QTestState *qts;
93     QPCIBus *pcibus;
94     QPCIDevice *dev;
95     QPCIBar bar;
96 
97     qts = qtest_init("-device pvpanic-pci,addr=04.0");
98     pcibus = qpci_new_pc(qts, NULL);
99     dev = qpci_device_find(pcibus, QPCI_DEVFN(0x4, 0x0));
100     qpci_device_enable(dev);
101     bar = qpci_iomap(dev, 0, NULL);
102 
103     qpci_memread(dev, bar, 0, &val, sizeof(val));
104     g_assert_cmpuint(val, ==, PVPANIC_EVENTS);
105 
106     val = PVPANIC_SHUTDOWN;
107     qpci_memwrite(dev, bar, 0, &val, sizeof(val));
108 
109     response = qtest_qmp_eventwait_ref(qts, "GUEST_PVSHUTDOWN");
110     qobject_unref(response);
111 
112     response = qtest_qmp_eventwait_ref(qts, "SHUTDOWN");
113     g_assert(qdict_haskey(response, "data"));
114     data = qdict_get_qdict(response, "data");
115     g_assert(qdict_haskey(data, "guest"));
116     g_assert(qdict_get_bool(data, "guest"));
117     g_assert(qdict_haskey(data, "reason"));
118     g_assert_cmpstr(qdict_get_str(data, "reason"), ==, "guest-shutdown");
119     qobject_unref(response);
120 
121     g_free(dev);
122     qpci_free_pc(pcibus);
123     qtest_quit(qts);
124 }
125 
126 int main(int argc, char **argv)
127 {
128     g_test_init(&argc, &argv, NULL);
129     qtest_add_func("/pvpanic-pci/panic", test_panic);
130     qtest_add_func("/pvpanic-pci/panic-nopause", test_panic_nopause);
131     qtest_add_func("/pvpanic-pci/pvshutdown", test_pvshutdown);
132 
133     return g_test_run();
134 }
135