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