xref: /openbmc/qemu/tests/qtest/endianness-test.c (revision 0fbb5d2d)
1 /*
2  * QTest testcase for ISA endianness
3  *
4  * Copyright Red Hat, Inc. 2012
5  *
6  * Authors:
7  *  Paolo Bonzini <pbonzini@redhat.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 
16 #include "libqos/libqtest.h"
17 #include "qemu/bswap.h"
18 
19 typedef struct TestCase TestCase;
20 struct TestCase {
21     const char *arch;
22     const char *machine;
23     uint64_t isa_base;
24     bool bswap;
25     const char *superio;
26 };
27 
28 static const TestCase test_cases[] = {
29     { "i386", "pc", -1 },
30     { "mips", "malta", 0x10000000, .bswap = true },
31     { "mips64", "magnum", 0x90000000, .bswap = true },
32     { "mips64", "pica61", 0x90000000, .bswap = true },
33     { "mips64", "malta", 0x10000000, .bswap = true },
34     { "mips64el", "fuloong2e", 0x1fd00000 },
35     { "ppc", "g3beige", 0xfe000000, .bswap = true, .superio = "i82378" },
36     { "ppc", "40p", 0x80000000, .bswap = true },
37     { "ppc", "bamboo", 0xe8000000, .bswap = true, .superio = "i82378" },
38     { "ppc64", "mac99", 0xf2000000, .bswap = true, .superio = "i82378" },
39     { "ppc64", "pseries", (1ULL << 45), .bswap = true, .superio = "i82378" },
40     { "ppc64", "pseries-2.7", 0x10080000000ULL,
41       .bswap = true, .superio = "i82378" },
42     { "sh4", "r2d", 0xfe240000, .superio = "i82378" },
43     { "sh4eb", "r2d", 0xfe240000, .bswap = true, .superio = "i82378" },
44     { "sparc64", "sun4u", 0x1fe02000000LL, .bswap = true },
45     { "x86_64", "pc", -1 },
46     {}
47 };
48 
49 static uint8_t isa_inb(QTestState *qts, const TestCase *test, uint16_t addr)
50 {
51     uint8_t value;
52     if (test->isa_base == -1) {
53         value = qtest_inb(qts, addr);
54     } else {
55         value = qtest_readb(qts, test->isa_base + addr);
56     }
57     return value;
58 }
59 
60 static uint16_t isa_inw(QTestState *qts, const TestCase *test, uint16_t addr)
61 {
62     uint16_t value;
63     if (test->isa_base == -1) {
64         value = qtest_inw(qts, addr);
65     } else {
66         value = qtest_readw(qts, test->isa_base + addr);
67     }
68     return test->bswap ? bswap16(value) : value;
69 }
70 
71 static uint32_t isa_inl(QTestState *qts, const TestCase *test, uint16_t addr)
72 {
73     uint32_t value;
74     if (test->isa_base == -1) {
75         value = qtest_inl(qts, addr);
76     } else {
77         value = qtest_readl(qts, test->isa_base + addr);
78     }
79     return test->bswap ? bswap32(value) : value;
80 }
81 
82 static void isa_outb(QTestState *qts, const TestCase *test, uint16_t addr,
83                      uint8_t value)
84 {
85     if (test->isa_base == -1) {
86         qtest_outb(qts, addr, value);
87     } else {
88         qtest_writeb(qts, test->isa_base + addr, value);
89     }
90 }
91 
92 static void isa_outw(QTestState *qts, const TestCase *test, uint16_t addr,
93                      uint16_t value)
94 {
95     value = test->bswap ? bswap16(value) : value;
96     if (test->isa_base == -1) {
97         qtest_outw(qts, addr, value);
98     } else {
99         qtest_writew(qts, test->isa_base + addr, value);
100     }
101 }
102 
103 static void isa_outl(QTestState *qts, const TestCase *test, uint16_t addr,
104                      uint32_t value)
105 {
106     value = test->bswap ? bswap32(value) : value;
107     if (test->isa_base == -1) {
108         qtest_outl(qts, addr, value);
109     } else {
110         qtest_writel(qts, test->isa_base + addr, value);
111     }
112 }
113 
114 
115 static void test_endianness(gconstpointer data)
116 {
117     const TestCase *test = data;
118     QTestState *qts;
119 
120     qts = qtest_initf("-M %s%s%s -device pc-testdev", test->machine,
121                       test->superio ? " -device " : "",
122                       test->superio ?: "");
123     isa_outl(qts, test, 0xe0, 0x87654321);
124     g_assert_cmphex(isa_inl(qts, test, 0xe0), ==, 0x87654321);
125     g_assert_cmphex(isa_inw(qts, test, 0xe2), ==, 0x8765);
126     g_assert_cmphex(isa_inw(qts, test, 0xe0), ==, 0x4321);
127     g_assert_cmphex(isa_inb(qts, test, 0xe3), ==, 0x87);
128     g_assert_cmphex(isa_inb(qts, test, 0xe2), ==, 0x65);
129     g_assert_cmphex(isa_inb(qts, test, 0xe1), ==, 0x43);
130     g_assert_cmphex(isa_inb(qts, test, 0xe0), ==, 0x21);
131 
132     isa_outw(qts, test, 0xe2, 0x8866);
133     g_assert_cmphex(isa_inl(qts, test, 0xe0), ==, 0x88664321);
134     g_assert_cmphex(isa_inw(qts, test, 0xe2), ==, 0x8866);
135     g_assert_cmphex(isa_inw(qts, test, 0xe0), ==, 0x4321);
136     g_assert_cmphex(isa_inb(qts, test, 0xe3), ==, 0x88);
137     g_assert_cmphex(isa_inb(qts, test, 0xe2), ==, 0x66);
138     g_assert_cmphex(isa_inb(qts, test, 0xe1), ==, 0x43);
139     g_assert_cmphex(isa_inb(qts, test, 0xe0), ==, 0x21);
140 
141     isa_outw(qts, test, 0xe0, 0x4422);
142     g_assert_cmphex(isa_inl(qts, test, 0xe0), ==, 0x88664422);
143     g_assert_cmphex(isa_inw(qts, test, 0xe2), ==, 0x8866);
144     g_assert_cmphex(isa_inw(qts, test, 0xe0), ==, 0x4422);
145     g_assert_cmphex(isa_inb(qts, test, 0xe3), ==, 0x88);
146     g_assert_cmphex(isa_inb(qts, test, 0xe2), ==, 0x66);
147     g_assert_cmphex(isa_inb(qts, test, 0xe1), ==, 0x44);
148     g_assert_cmphex(isa_inb(qts, test, 0xe0), ==, 0x22);
149 
150     isa_outb(qts, test, 0xe3, 0x87);
151     g_assert_cmphex(isa_inl(qts, test, 0xe0), ==, 0x87664422);
152     g_assert_cmphex(isa_inw(qts, test, 0xe2), ==, 0x8766);
153     g_assert_cmphex(isa_inb(qts, test, 0xe3), ==, 0x87);
154     g_assert_cmphex(isa_inb(qts, test, 0xe2), ==, 0x66);
155     g_assert_cmphex(isa_inb(qts, test, 0xe1), ==, 0x44);
156     g_assert_cmphex(isa_inb(qts, test, 0xe0), ==, 0x22);
157 
158     isa_outb(qts, test, 0xe2, 0x65);
159     g_assert_cmphex(isa_inl(qts, test, 0xe0), ==, 0x87654422);
160     g_assert_cmphex(isa_inw(qts, test, 0xe2), ==, 0x8765);
161     g_assert_cmphex(isa_inw(qts, test, 0xe0), ==, 0x4422);
162     g_assert_cmphex(isa_inb(qts, test, 0xe3), ==, 0x87);
163     g_assert_cmphex(isa_inb(qts, test, 0xe2), ==, 0x65);
164     g_assert_cmphex(isa_inb(qts, test, 0xe1), ==, 0x44);
165     g_assert_cmphex(isa_inb(qts, test, 0xe0), ==, 0x22);
166 
167     isa_outb(qts, test, 0xe1, 0x43);
168     g_assert_cmphex(isa_inl(qts, test, 0xe0), ==, 0x87654322);
169     g_assert_cmphex(isa_inw(qts, test, 0xe2), ==, 0x8765);
170     g_assert_cmphex(isa_inw(qts, test, 0xe0), ==, 0x4322);
171     g_assert_cmphex(isa_inb(qts, test, 0xe3), ==, 0x87);
172     g_assert_cmphex(isa_inb(qts, test, 0xe2), ==, 0x65);
173     g_assert_cmphex(isa_inb(qts, test, 0xe1), ==, 0x43);
174     g_assert_cmphex(isa_inb(qts, test, 0xe0), ==, 0x22);
175 
176     isa_outb(qts, test, 0xe0, 0x21);
177     g_assert_cmphex(isa_inl(qts, test, 0xe0), ==, 0x87654321);
178     g_assert_cmphex(isa_inw(qts, test, 0xe2), ==, 0x8765);
179     g_assert_cmphex(isa_inw(qts, test, 0xe0), ==, 0x4321);
180     g_assert_cmphex(isa_inb(qts, test, 0xe3), ==, 0x87);
181     g_assert_cmphex(isa_inb(qts, test, 0xe2), ==, 0x65);
182     g_assert_cmphex(isa_inb(qts, test, 0xe1), ==, 0x43);
183     g_assert_cmphex(isa_inb(qts, test, 0xe0), ==, 0x21);
184     qtest_quit(qts);
185 }
186 
187 static void test_endianness_split(gconstpointer data)
188 {
189     const TestCase *test = data;
190     QTestState *qts;
191 
192     qts = qtest_initf("-M %s%s%s -device pc-testdev", test->machine,
193                       test->superio ? " -device " : "",
194                       test->superio ?: "");
195     isa_outl(qts, test, 0xe8, 0x87654321);
196     g_assert_cmphex(isa_inl(qts, test, 0xe0), ==, 0x87654321);
197     g_assert_cmphex(isa_inw(qts, test, 0xe2), ==, 0x8765);
198     g_assert_cmphex(isa_inw(qts, test, 0xe0), ==, 0x4321);
199 
200     isa_outw(qts, test, 0xea, 0x8866);
201     g_assert_cmphex(isa_inl(qts, test, 0xe0), ==, 0x88664321);
202     g_assert_cmphex(isa_inw(qts, test, 0xe2), ==, 0x8866);
203     g_assert_cmphex(isa_inw(qts, test, 0xe0), ==, 0x4321);
204 
205     isa_outw(qts, test, 0xe8, 0x4422);
206     g_assert_cmphex(isa_inl(qts, test, 0xe0), ==, 0x88664422);
207     g_assert_cmphex(isa_inw(qts, test, 0xe2), ==, 0x8866);
208     g_assert_cmphex(isa_inw(qts, test, 0xe0), ==, 0x4422);
209 
210     isa_outb(qts, test, 0xeb, 0x87);
211     g_assert_cmphex(isa_inl(qts, test, 0xe0), ==, 0x87664422);
212     g_assert_cmphex(isa_inw(qts, test, 0xe2), ==, 0x8766);
213 
214     isa_outb(qts, test, 0xea, 0x65);
215     g_assert_cmphex(isa_inl(qts, test, 0xe0), ==, 0x87654422);
216     g_assert_cmphex(isa_inw(qts, test, 0xe2), ==, 0x8765);
217     g_assert_cmphex(isa_inw(qts, test, 0xe0), ==, 0x4422);
218 
219     isa_outb(qts, test, 0xe9, 0x43);
220     g_assert_cmphex(isa_inl(qts, test, 0xe0), ==, 0x87654322);
221     g_assert_cmphex(isa_inw(qts, test, 0xe2), ==, 0x8765);
222     g_assert_cmphex(isa_inw(qts, test, 0xe0), ==, 0x4322);
223 
224     isa_outb(qts, test, 0xe8, 0x21);
225     g_assert_cmphex(isa_inl(qts, test, 0xe0), ==, 0x87654321);
226     g_assert_cmphex(isa_inw(qts, test, 0xe2), ==, 0x8765);
227     g_assert_cmphex(isa_inw(qts, test, 0xe0), ==, 0x4321);
228     qtest_quit(qts);
229 }
230 
231 static void test_endianness_combine(gconstpointer data)
232 {
233     const TestCase *test = data;
234     QTestState *qts;
235 
236     qts = qtest_initf("-M %s%s%s -device pc-testdev", test->machine,
237                       test->superio ? " -device " : "",
238                       test->superio ?: "");
239     isa_outl(qts, test, 0xe0, 0x87654321);
240     g_assert_cmphex(isa_inl(qts, test, 0xe8), ==, 0x87654321);
241     g_assert_cmphex(isa_inw(qts, test, 0xea), ==, 0x8765);
242     g_assert_cmphex(isa_inw(qts, test, 0xe8), ==, 0x4321);
243 
244     isa_outw(qts, test, 0xe2, 0x8866);
245     g_assert_cmphex(isa_inl(qts, test, 0xe8), ==, 0x88664321);
246     g_assert_cmphex(isa_inw(qts, test, 0xea), ==, 0x8866);
247     g_assert_cmphex(isa_inw(qts, test, 0xe8), ==, 0x4321);
248 
249     isa_outw(qts, test, 0xe0, 0x4422);
250     g_assert_cmphex(isa_inl(qts, test, 0xe8), ==, 0x88664422);
251     g_assert_cmphex(isa_inw(qts, test, 0xea), ==, 0x8866);
252     g_assert_cmphex(isa_inw(qts, test, 0xe8), ==, 0x4422);
253 
254     isa_outb(qts, test, 0xe3, 0x87);
255     g_assert_cmphex(isa_inl(qts, test, 0xe8), ==, 0x87664422);
256     g_assert_cmphex(isa_inw(qts, test, 0xea), ==, 0x8766);
257 
258     isa_outb(qts, test, 0xe2, 0x65);
259     g_assert_cmphex(isa_inl(qts, test, 0xe8), ==, 0x87654422);
260     g_assert_cmphex(isa_inw(qts, test, 0xea), ==, 0x8765);
261     g_assert_cmphex(isa_inw(qts, test, 0xe8), ==, 0x4422);
262 
263     isa_outb(qts, test, 0xe1, 0x43);
264     g_assert_cmphex(isa_inl(qts, test, 0xe8), ==, 0x87654322);
265     g_assert_cmphex(isa_inw(qts, test, 0xea), ==, 0x8765);
266     g_assert_cmphex(isa_inw(qts, test, 0xe8), ==, 0x4322);
267 
268     isa_outb(qts, test, 0xe0, 0x21);
269     g_assert_cmphex(isa_inl(qts, test, 0xe8), ==, 0x87654321);
270     g_assert_cmphex(isa_inw(qts, test, 0xea), ==, 0x8765);
271     g_assert_cmphex(isa_inw(qts, test, 0xe8), ==, 0x4321);
272     qtest_quit(qts);
273 }
274 
275 int main(int argc, char **argv)
276 {
277     const char *arch = qtest_get_arch();
278     int i;
279 
280     g_test_init(&argc, &argv, NULL);
281 
282     for (i = 0; test_cases[i].arch; i++) {
283         gchar *path;
284 
285         if (!g_str_equal(test_cases[i].arch, arch) ||
286             !qtest_has_machine(test_cases[i].machine) ||
287             (test_cases[i].superio && !qtest_has_device(test_cases[i].superio))) {
288             continue;
289         }
290         path = g_strdup_printf("endianness/%s",
291                                test_cases[i].machine);
292         qtest_add_data_func(path, &test_cases[i], test_endianness);
293         g_free(path);
294 
295         path = g_strdup_printf("endianness/split/%s",
296                                test_cases[i].machine);
297         qtest_add_data_func(path, &test_cases[i], test_endianness_split);
298         g_free(path);
299 
300         path = g_strdup_printf("endianness/combine/%s",
301                                test_cases[i].machine);
302         qtest_add_data_func(path, &test_cases[i], test_endianness_combine);
303         g_free(path);
304     }
305 
306     return g_test_run();
307 }
308