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