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 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 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 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 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 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 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 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 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 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 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