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 "libqos/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", "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
  49static 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
  60static 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
  71static 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
  82static 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
  92static 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
 103static 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
 115static 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
 187static 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
 231static 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
 275int 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        if (strcmp(test_cases[i].arch, arch) != 0) {
 285            continue;
 286        }
 287        path = g_strdup_printf("endianness/%s",
 288                               test_cases[i].machine);
 289        qtest_add_data_func(path, &test_cases[i], test_endianness);
 290        g_free(path);
 291
 292        path = g_strdup_printf("endianness/split/%s",
 293                               test_cases[i].machine);
 294        qtest_add_data_func(path, &test_cases[i], test_endianness_split);
 295        g_free(path);
 296
 297        path = g_strdup_printf("endianness/combine/%s",
 298                               test_cases[i].machine);
 299        qtest_add_data_func(path, &test_cases[i], test_endianness_combine);
 300        g_free(path);
 301    }
 302
 303    return g_test_run();
 304}
 305