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#include <glib.h>
  16
  17#include "libqtest.h"
  18#include "qemu/bswap.h"
  19
  20typedef struct TestCase TestCase;
  21struct TestCase {
  22    const char *arch;
  23    const char *machine;
  24    uint64_t isa_base;
  25    bool bswap;
  26    const char *superio;
  27};
  28
  29static const TestCase test_cases[] = {
  30    { "i386", "pc", -1 },
  31    { "mips", "mips", 0x14000000, .bswap = true },
  32    { "mips", "malta", 0x10000000, .bswap = true },
  33    { "mips64", "magnum", 0x90000000, .bswap = true },
  34    { "mips64", "pica61", 0x90000000, .bswap = true },
  35    { "mips64", "mips", 0x14000000, .bswap = true },
  36    { "mips64", "malta", 0x10000000, .bswap = true },
  37    { "mips64el", "fulong2e", 0x1fd00000 },
  38    { "ppc", "g3beige", 0xfe000000, .bswap = true, .superio = "i82378" },
  39    { "ppc", "prep", 0x80000000, .bswap = true },
  40    { "ppc", "bamboo", 0xe8000000, .bswap = true, .superio = "i82378" },
  41    { "ppc64", "mac99", 0xf2000000, .bswap = true, .superio = "i82378" },
  42    { "ppc64", "pseries", 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    char *args;
 118
 119    args = g_strdup_printf("-M %s%s%s -device pc-testdev",
 120                           test->machine,
 121                           test->superio ? " -device " : "",
 122                           test->superio ?: "");
 123    qtest_start(args);
 124    isa_outl(test, 0xe0, 0x87654321);
 125    g_assert_cmphex(isa_inl(test, 0xe0), ==, 0x87654321);
 126    g_assert_cmphex(isa_inw(test, 0xe2), ==, 0x8765);
 127    g_assert_cmphex(isa_inw(test, 0xe0), ==, 0x4321);
 128    g_assert_cmphex(isa_inb(test, 0xe3), ==, 0x87);
 129    g_assert_cmphex(isa_inb(test, 0xe2), ==, 0x65);
 130    g_assert_cmphex(isa_inb(test, 0xe1), ==, 0x43);
 131    g_assert_cmphex(isa_inb(test, 0xe0), ==, 0x21);
 132
 133    isa_outw(test, 0xe2, 0x8866);
 134    g_assert_cmphex(isa_inl(test, 0xe0), ==, 0x88664321);
 135    g_assert_cmphex(isa_inw(test, 0xe2), ==, 0x8866);
 136    g_assert_cmphex(isa_inw(test, 0xe0), ==, 0x4321);
 137    g_assert_cmphex(isa_inb(test, 0xe3), ==, 0x88);
 138    g_assert_cmphex(isa_inb(test, 0xe2), ==, 0x66);
 139    g_assert_cmphex(isa_inb(test, 0xe1), ==, 0x43);
 140    g_assert_cmphex(isa_inb(test, 0xe0), ==, 0x21);
 141
 142    isa_outw(test, 0xe0, 0x4422);
 143    g_assert_cmphex(isa_inl(test, 0xe0), ==, 0x88664422);
 144    g_assert_cmphex(isa_inw(test, 0xe2), ==, 0x8866);
 145    g_assert_cmphex(isa_inw(test, 0xe0), ==, 0x4422);
 146    g_assert_cmphex(isa_inb(test, 0xe3), ==, 0x88);
 147    g_assert_cmphex(isa_inb(test, 0xe2), ==, 0x66);
 148    g_assert_cmphex(isa_inb(test, 0xe1), ==, 0x44);
 149    g_assert_cmphex(isa_inb(test, 0xe0), ==, 0x22);
 150
 151    isa_outb(test, 0xe3, 0x87);
 152    g_assert_cmphex(isa_inl(test, 0xe0), ==, 0x87664422);
 153    g_assert_cmphex(isa_inw(test, 0xe2), ==, 0x8766);
 154    g_assert_cmphex(isa_inb(test, 0xe3), ==, 0x87);
 155    g_assert_cmphex(isa_inb(test, 0xe2), ==, 0x66);
 156    g_assert_cmphex(isa_inb(test, 0xe1), ==, 0x44);
 157    g_assert_cmphex(isa_inb(test, 0xe0), ==, 0x22);
 158
 159    isa_outb(test, 0xe2, 0x65);
 160    g_assert_cmphex(isa_inl(test, 0xe0), ==, 0x87654422);
 161    g_assert_cmphex(isa_inw(test, 0xe2), ==, 0x8765);
 162    g_assert_cmphex(isa_inw(test, 0xe0), ==, 0x4422);
 163    g_assert_cmphex(isa_inb(test, 0xe3), ==, 0x87);
 164    g_assert_cmphex(isa_inb(test, 0xe2), ==, 0x65);
 165    g_assert_cmphex(isa_inb(test, 0xe1), ==, 0x44);
 166    g_assert_cmphex(isa_inb(test, 0xe0), ==, 0x22);
 167
 168    isa_outb(test, 0xe1, 0x43);
 169    g_assert_cmphex(isa_inl(test, 0xe0), ==, 0x87654322);
 170    g_assert_cmphex(isa_inw(test, 0xe2), ==, 0x8765);
 171    g_assert_cmphex(isa_inw(test, 0xe0), ==, 0x4322);
 172    g_assert_cmphex(isa_inb(test, 0xe3), ==, 0x87);
 173    g_assert_cmphex(isa_inb(test, 0xe2), ==, 0x65);
 174    g_assert_cmphex(isa_inb(test, 0xe1), ==, 0x43);
 175    g_assert_cmphex(isa_inb(test, 0xe0), ==, 0x22);
 176
 177    isa_outb(test, 0xe0, 0x21);
 178    g_assert_cmphex(isa_inl(test, 0xe0), ==, 0x87654321);
 179    g_assert_cmphex(isa_inw(test, 0xe2), ==, 0x8765);
 180    g_assert_cmphex(isa_inw(test, 0xe0), ==, 0x4321);
 181    g_assert_cmphex(isa_inb(test, 0xe3), ==, 0x87);
 182    g_assert_cmphex(isa_inb(test, 0xe2), ==, 0x65);
 183    g_assert_cmphex(isa_inb(test, 0xe1), ==, 0x43);
 184    g_assert_cmphex(isa_inb(test, 0xe0), ==, 0x21);
 185    qtest_quit(global_qtest);
 186    g_free(args);
 187}
 188
 189static void test_endianness_split(gconstpointer data)
 190{
 191    const TestCase *test = data;
 192    char *args;
 193
 194    args = g_strdup_printf("-M %s%s%s -device pc-testdev",
 195                           test->machine,
 196                           test->superio ? " -device " : "",
 197                           test->superio ?: "");
 198    qtest_start(args);
 199    isa_outl(test, 0xe8, 0x87654321);
 200    g_assert_cmphex(isa_inl(test, 0xe0), ==, 0x87654321);
 201    g_assert_cmphex(isa_inw(test, 0xe2), ==, 0x8765);
 202    g_assert_cmphex(isa_inw(test, 0xe0), ==, 0x4321);
 203
 204    isa_outw(test, 0xea, 0x8866);
 205    g_assert_cmphex(isa_inl(test, 0xe0), ==, 0x88664321);
 206    g_assert_cmphex(isa_inw(test, 0xe2), ==, 0x8866);
 207    g_assert_cmphex(isa_inw(test, 0xe0), ==, 0x4321);
 208
 209    isa_outw(test, 0xe8, 0x4422);
 210    g_assert_cmphex(isa_inl(test, 0xe0), ==, 0x88664422);
 211    g_assert_cmphex(isa_inw(test, 0xe2), ==, 0x8866);
 212    g_assert_cmphex(isa_inw(test, 0xe0), ==, 0x4422);
 213
 214    isa_outb(test, 0xeb, 0x87);
 215    g_assert_cmphex(isa_inl(test, 0xe0), ==, 0x87664422);
 216    g_assert_cmphex(isa_inw(test, 0xe2), ==, 0x8766);
 217
 218    isa_outb(test, 0xea, 0x65);
 219    g_assert_cmphex(isa_inl(test, 0xe0), ==, 0x87654422);
 220    g_assert_cmphex(isa_inw(test, 0xe2), ==, 0x8765);
 221    g_assert_cmphex(isa_inw(test, 0xe0), ==, 0x4422);
 222
 223    isa_outb(test, 0xe9, 0x43);
 224    g_assert_cmphex(isa_inl(test, 0xe0), ==, 0x87654322);
 225    g_assert_cmphex(isa_inw(test, 0xe2), ==, 0x8765);
 226    g_assert_cmphex(isa_inw(test, 0xe0), ==, 0x4322);
 227
 228    isa_outb(test, 0xe8, 0x21);
 229    g_assert_cmphex(isa_inl(test, 0xe0), ==, 0x87654321);
 230    g_assert_cmphex(isa_inw(test, 0xe2), ==, 0x8765);
 231    g_assert_cmphex(isa_inw(test, 0xe0), ==, 0x4321);
 232    qtest_quit(global_qtest);
 233    g_free(args);
 234}
 235
 236static void test_endianness_combine(gconstpointer data)
 237{
 238    const TestCase *test = data;
 239    char *args;
 240
 241    args = g_strdup_printf("-M %s%s%s -device pc-testdev",
 242                           test->machine,
 243                           test->superio ? " -device " : "",
 244                           test->superio ?: "");
 245    qtest_start(args);
 246    isa_outl(test, 0xe0, 0x87654321);
 247    g_assert_cmphex(isa_inl(test, 0xe8), ==, 0x87654321);
 248    g_assert_cmphex(isa_inw(test, 0xea), ==, 0x8765);
 249    g_assert_cmphex(isa_inw(test, 0xe8), ==, 0x4321);
 250
 251    isa_outw(test, 0xe2, 0x8866);
 252    g_assert_cmphex(isa_inl(test, 0xe8), ==, 0x88664321);
 253    g_assert_cmphex(isa_inw(test, 0xea), ==, 0x8866);
 254    g_assert_cmphex(isa_inw(test, 0xe8), ==, 0x4321);
 255
 256    isa_outw(test, 0xe0, 0x4422);
 257    g_assert_cmphex(isa_inl(test, 0xe8), ==, 0x88664422);
 258    g_assert_cmphex(isa_inw(test, 0xea), ==, 0x8866);
 259    g_assert_cmphex(isa_inw(test, 0xe8), ==, 0x4422);
 260
 261    isa_outb(test, 0xe3, 0x87);
 262    g_assert_cmphex(isa_inl(test, 0xe8), ==, 0x87664422);
 263    g_assert_cmphex(isa_inw(test, 0xea), ==, 0x8766);
 264
 265    isa_outb(test, 0xe2, 0x65);
 266    g_assert_cmphex(isa_inl(test, 0xe8), ==, 0x87654422);
 267    g_assert_cmphex(isa_inw(test, 0xea), ==, 0x8765);
 268    g_assert_cmphex(isa_inw(test, 0xe8), ==, 0x4422);
 269
 270    isa_outb(test, 0xe1, 0x43);
 271    g_assert_cmphex(isa_inl(test, 0xe8), ==, 0x87654322);
 272    g_assert_cmphex(isa_inw(test, 0xea), ==, 0x8765);
 273    g_assert_cmphex(isa_inw(test, 0xe8), ==, 0x4322);
 274
 275    isa_outb(test, 0xe0, 0x21);
 276    g_assert_cmphex(isa_inl(test, 0xe8), ==, 0x87654321);
 277    g_assert_cmphex(isa_inw(test, 0xea), ==, 0x8765);
 278    g_assert_cmphex(isa_inw(test, 0xe8), ==, 0x4321);
 279    qtest_quit(global_qtest);
 280    g_free(args);
 281}
 282
 283int main(int argc, char **argv)
 284{
 285    const char *arch = qtest_get_arch();
 286    int ret;
 287    int i;
 288
 289    g_test_init(&argc, &argv, NULL);
 290
 291    for (i = 0; test_cases[i].arch; i++) {
 292        gchar *path;
 293        if (strcmp(test_cases[i].arch, arch) != 0) {
 294            continue;
 295        }
 296        path = g_strdup_printf("endianness/%s",
 297                               test_cases[i].machine);
 298        qtest_add_data_func(path, &test_cases[i], test_endianness);
 299
 300        path = g_strdup_printf("endianness/split/%s",
 301                               test_cases[i].machine);
 302        qtest_add_data_func(path, &test_cases[i], test_endianness_split);
 303
 304        path = g_strdup_printf("endianness/combine/%s",
 305                               test_cases[i].machine);
 306        qtest_add_data_func(path, &test_cases[i], test_endianness_combine);
 307    }
 308
 309    ret = g_test_run();
 310
 311    return ret;
 312}
 313