1
2
3
4
5
6
7
8
9
10
11
12
13
14#include "qemu/osdep.h"
15
16#include "libqtest.h"
17#include "qemu/bswap.h"
18
19typedef struct TestCase TestCase;
20struct TestCase {
21 const char *arch;
22 const char *machine;
23 uint64_t isa_base;
24 bool bswap;
25 const char *superio;
26};
27
28static 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
51static 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
62static 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
73static 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
84static 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
94static 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
105static 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
117static 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
189static 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
233static 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
277int 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