qemu/tests/qtest/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", "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