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