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", "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
  50static 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
  61static 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
  72static 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
  83static 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
  93static 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
 104static 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
 116static 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
 188static 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
 232static 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
 276int 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