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", "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", "fulong2e", 0x1fd00000 }, 37 { "ppc", "g3beige", 0xfe000000, .bswap = true, .superio = "i82378" }, 38 { "ppc", "prep", 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