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