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