qemu/qtest.c
<<
>>
Prefs
   1/*
   2 * Test Server
   3 *
   4 * Copyright IBM, Corp. 2011
   5 *
   6 * Authors:
   7 *  Anthony Liguori   <aliguori@us.ibm.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 "qapi/error.h"
  16#include "sysemu/qtest.h"
  17#include "hw/qdev.h"
  18#include "sysemu/char.h"
  19#include "exec/ioport.h"
  20#include "exec/memory.h"
  21#include "hw/irq.h"
  22#include "sysemu/accel.h"
  23#include "sysemu/sysemu.h"
  24#include "sysemu/cpus.h"
  25#include "qemu/config-file.h"
  26#include "qemu/option.h"
  27#include "qemu/error-report.h"
  28
  29#define MAX_IRQ 256
  30
  31bool qtest_allowed;
  32
  33static DeviceState *irq_intercept_dev;
  34static FILE *qtest_log_fp;
  35static CharDriverState *qtest_chr;
  36static GString *inbuf;
  37static int irq_levels[MAX_IRQ];
  38static qemu_timeval start_time;
  39static bool qtest_opened;
  40
  41#define FMT_timeval "%ld.%06ld"
  42
  43/**
  44 * QTest Protocol
  45 *
  46 * Line based protocol, request/response based.  Server can send async messages
  47 * so clients should always handle many async messages before the response
  48 * comes in.
  49 *
  50 * Valid requests
  51 *
  52 * Clock management:
  53 *
  54 * The qtest client is completely in charge of the QEMU_CLOCK_VIRTUAL.  qtest commands
  55 * let you adjust the value of the clock (monotonically).  All the commands
  56 * return the current value of the clock in nanoseconds.
  57 *
  58 *  > clock_step
  59 *  < OK VALUE
  60 *
  61 *     Advance the clock to the next deadline.  Useful when waiting for
  62 *     asynchronous events.
  63 *
  64 *  > clock_step NS
  65 *  < OK VALUE
  66 *
  67 *     Advance the clock by NS nanoseconds.
  68 *
  69 *  > clock_set NS
  70 *  < OK VALUE
  71 *
  72 *     Advance the clock to NS nanoseconds (do nothing if it's already past).
  73 *
  74 * PIO and memory access:
  75 *
  76 *  > outb ADDR VALUE
  77 *  < OK
  78 *
  79 *  > outw ADDR VALUE
  80 *  < OK
  81 *
  82 *  > outl ADDR VALUE
  83 *  < OK
  84 *
  85 *  > inb ADDR
  86 *  < OK VALUE
  87 *
  88 *  > inw ADDR
  89 *  < OK VALUE
  90 *
  91 *  > inl ADDR
  92 *  < OK VALUE
  93 *
  94 *  > writeb ADDR VALUE
  95 *  < OK
  96 *
  97 *  > writew ADDR VALUE
  98 *  < OK
  99 *
 100 *  > writel ADDR VALUE
 101 *  < OK
 102 *
 103 *  > writeq ADDR VALUE
 104 *  < OK
 105 *
 106 *  > readb ADDR
 107 *  < OK VALUE
 108 *
 109 *  > readw ADDR
 110 *  < OK VALUE
 111 *
 112 *  > readl ADDR
 113 *  < OK VALUE
 114 *
 115 *  > readq ADDR
 116 *  < OK VALUE
 117 *
 118 *  > read ADDR SIZE
 119 *  < OK DATA
 120 *
 121 *  > write ADDR SIZE DATA
 122 *  < OK
 123 *
 124 *  > b64read ADDR SIZE
 125 *  < OK B64_DATA
 126 *
 127 *  > b64write ADDR SIZE B64_DATA
 128 *  < OK
 129 *
 130 *  > memset ADDR SIZE VALUE
 131 *  < OK
 132 *
 133 * ADDR, SIZE, VALUE are all integers parsed with strtoul() with a base of 0.
 134 *
 135 * DATA is an arbitrarily long hex number prefixed with '0x'.  If it's smaller
 136 * than the expected size, the value will be zero filled at the end of the data
 137 * sequence.
 138 *
 139 * B64_DATA is an arbitrarily long base64 encoded string.
 140 * If the sizes do not match, the data will be truncated.
 141 *
 142 * IRQ management:
 143 *
 144 *  > irq_intercept_in QOM-PATH
 145 *  < OK
 146 *
 147 *  > irq_intercept_out QOM-PATH
 148 *  < OK
 149 *
 150 * Attach to the gpio-in (resp. gpio-out) pins exported by the device at
 151 * QOM-PATH.  When the pin is triggered, one of the following async messages
 152 * will be printed to the qtest stream:
 153 *
 154 *  IRQ raise NUM
 155 *  IRQ lower NUM
 156 *
 157 * where NUM is an IRQ number.  For the PC, interrupts can be intercepted
 158 * simply with "irq_intercept_in ioapic" (note that IRQ0 comes out with
 159 * NUM=0 even though it is remapped to GSI 2).
 160 */
 161
 162static int hex2nib(char ch)
 163{
 164    if (ch >= '0' && ch <= '9') {
 165        return ch - '0';
 166    } else if (ch >= 'a' && ch <= 'f') {
 167        return 10 + (ch - 'a');
 168    } else if (ch >= 'A' && ch <= 'F') {
 169        return 10 + (ch - 'A');
 170    } else {
 171        return -1;
 172    }
 173}
 174
 175static void qtest_get_time(qemu_timeval *tv)
 176{
 177    qemu_gettimeofday(tv);
 178    tv->tv_sec -= start_time.tv_sec;
 179    tv->tv_usec -= start_time.tv_usec;
 180    if (tv->tv_usec < 0) {
 181        tv->tv_usec += 1000000;
 182        tv->tv_sec -= 1;
 183    }
 184}
 185
 186static void qtest_send_prefix(CharDriverState *chr)
 187{
 188    qemu_timeval tv;
 189
 190    if (!qtest_log_fp || !qtest_opened) {
 191        return;
 192    }
 193
 194    qtest_get_time(&tv);
 195    fprintf(qtest_log_fp, "[S +" FMT_timeval "] ",
 196            (long) tv.tv_sec, (long) tv.tv_usec);
 197}
 198
 199static void GCC_FMT_ATTR(1, 2) qtest_log_send(const char *fmt, ...)
 200{
 201    va_list ap;
 202
 203    if (!qtest_log_fp || !qtest_opened) {
 204        return;
 205    }
 206
 207    qtest_send_prefix(NULL);
 208
 209    va_start(ap, fmt);
 210    vfprintf(qtest_log_fp, fmt, ap);
 211    va_end(ap);
 212}
 213
 214static void do_qtest_send(CharDriverState *chr, const char *str, size_t len)
 215{
 216    qemu_chr_fe_write_all(chr, (uint8_t *)str, len);
 217    if (qtest_log_fp && qtest_opened) {
 218        fprintf(qtest_log_fp, "%s", str);
 219    }
 220}
 221
 222static void qtest_send(CharDriverState *chr, const char *str)
 223{
 224    do_qtest_send(chr, str, strlen(str));
 225}
 226
 227static void GCC_FMT_ATTR(2, 3) qtest_sendf(CharDriverState *chr,
 228                                           const char *fmt, ...)
 229{
 230    va_list ap;
 231    gchar *buffer;
 232
 233    va_start(ap, fmt);
 234    buffer = g_strdup_vprintf(fmt, ap);
 235    qtest_send(chr, buffer);
 236    va_end(ap);
 237}
 238
 239static void qtest_irq_handler(void *opaque, int n, int level)
 240{
 241    qemu_irq old_irq = *(qemu_irq *)opaque;
 242    qemu_set_irq(old_irq, level);
 243
 244    if (irq_levels[n] != level) {
 245        CharDriverState *chr = qtest_chr;
 246        irq_levels[n] = level;
 247        qtest_send_prefix(chr);
 248        qtest_sendf(chr, "IRQ %s %d\n",
 249                    level ? "raise" : "lower", n);
 250    }
 251}
 252
 253static void qtest_process_command(CharDriverState *chr, gchar **words)
 254{
 255    const gchar *command;
 256
 257    g_assert(words);
 258
 259    command = words[0];
 260
 261    if (qtest_log_fp) {
 262        qemu_timeval tv;
 263        int i;
 264
 265        qtest_get_time(&tv);
 266        fprintf(qtest_log_fp, "[R +" FMT_timeval "]",
 267                (long) tv.tv_sec, (long) tv.tv_usec);
 268        for (i = 0; words[i]; i++) {
 269            fprintf(qtest_log_fp, " %s", words[i]);
 270        }
 271        fprintf(qtest_log_fp, "\n");
 272    }
 273
 274    g_assert(command);
 275    if (strcmp(words[0], "irq_intercept_out") == 0
 276        || strcmp(words[0], "irq_intercept_in") == 0) {
 277        DeviceState *dev;
 278        NamedGPIOList *ngl;
 279
 280        g_assert(words[1]);
 281        dev = DEVICE(object_resolve_path(words[1], NULL));
 282        if (!dev) {
 283            qtest_send_prefix(chr);
 284            qtest_send(chr, "FAIL Unknown device\n");
 285            return;
 286        }
 287
 288        if (irq_intercept_dev) {
 289            qtest_send_prefix(chr);
 290            if (irq_intercept_dev != dev) {
 291                qtest_send(chr, "FAIL IRQ intercept already enabled\n");
 292            } else {
 293                qtest_send(chr, "OK\n");
 294            }
 295            return;
 296        }
 297
 298        QLIST_FOREACH(ngl, &dev->gpios, node) {
 299            /* We don't support intercept of named GPIOs yet */
 300            if (ngl->name) {
 301                continue;
 302            }
 303            if (words[0][14] == 'o') {
 304                int i;
 305                for (i = 0; i < ngl->num_out; ++i) {
 306                    qemu_irq *disconnected = g_new0(qemu_irq, 1);
 307                    qemu_irq icpt = qemu_allocate_irq(qtest_irq_handler,
 308                                                      disconnected, i);
 309
 310                    *disconnected = qdev_intercept_gpio_out(dev, icpt,
 311                                                            ngl->name, i);
 312                }
 313            } else {
 314                qemu_irq_intercept_in(ngl->in, qtest_irq_handler,
 315                                      ngl->num_in);
 316            }
 317        }
 318        irq_intercept_dev = dev;
 319        qtest_send_prefix(chr);
 320        qtest_send(chr, "OK\n");
 321
 322    } else if (strcmp(words[0], "outb") == 0 ||
 323               strcmp(words[0], "outw") == 0 ||
 324               strcmp(words[0], "outl") == 0) {
 325        uint16_t addr;
 326        uint32_t value;
 327
 328        g_assert(words[1] && words[2]);
 329        addr = strtoul(words[1], NULL, 0);
 330        value = strtoul(words[2], NULL, 0);
 331
 332        if (words[0][3] == 'b') {
 333            cpu_outb(addr, value);
 334        } else if (words[0][3] == 'w') {
 335            cpu_outw(addr, value);
 336        } else if (words[0][3] == 'l') {
 337            cpu_outl(addr, value);
 338        }
 339        qtest_send_prefix(chr);
 340        qtest_send(chr, "OK\n");
 341    } else if (strcmp(words[0], "inb") == 0 ||
 342        strcmp(words[0], "inw") == 0 ||
 343        strcmp(words[0], "inl") == 0) {
 344        uint16_t addr;
 345        uint32_t value = -1U;
 346
 347        g_assert(words[1]);
 348        addr = strtoul(words[1], NULL, 0);
 349
 350        if (words[0][2] == 'b') {
 351            value = cpu_inb(addr);
 352        } else if (words[0][2] == 'w') {
 353            value = cpu_inw(addr);
 354        } else if (words[0][2] == 'l') {
 355            value = cpu_inl(addr);
 356        }
 357        qtest_send_prefix(chr);
 358        qtest_sendf(chr, "OK 0x%04x\n", value);
 359    } else if (strcmp(words[0], "writeb") == 0 ||
 360               strcmp(words[0], "writew") == 0 ||
 361               strcmp(words[0], "writel") == 0 ||
 362               strcmp(words[0], "writeq") == 0) {
 363        uint64_t addr;
 364        uint64_t value;
 365
 366        g_assert(words[1] && words[2]);
 367        addr = strtoull(words[1], NULL, 0);
 368        value = strtoull(words[2], NULL, 0);
 369
 370        if (words[0][5] == 'b') {
 371            uint8_t data = value;
 372            cpu_physical_memory_write(addr, &data, 1);
 373        } else if (words[0][5] == 'w') {
 374            uint16_t data = value;
 375            tswap16s(&data);
 376            cpu_physical_memory_write(addr, &data, 2);
 377        } else if (words[0][5] == 'l') {
 378            uint32_t data = value;
 379            tswap32s(&data);
 380            cpu_physical_memory_write(addr, &data, 4);
 381        } else if (words[0][5] == 'q') {
 382            uint64_t data = value;
 383            tswap64s(&data);
 384            cpu_physical_memory_write(addr, &data, 8);
 385        }
 386        qtest_send_prefix(chr);
 387        qtest_send(chr, "OK\n");
 388    } else if (strcmp(words[0], "readb") == 0 ||
 389               strcmp(words[0], "readw") == 0 ||
 390               strcmp(words[0], "readl") == 0 ||
 391               strcmp(words[0], "readq") == 0) {
 392        uint64_t addr;
 393        uint64_t value = UINT64_C(-1);
 394
 395        g_assert(words[1]);
 396        addr = strtoull(words[1], NULL, 0);
 397
 398        if (words[0][4] == 'b') {
 399            uint8_t data;
 400            cpu_physical_memory_read(addr, &data, 1);
 401            value = data;
 402        } else if (words[0][4] == 'w') {
 403            uint16_t data;
 404            cpu_physical_memory_read(addr, &data, 2);
 405            value = tswap16(data);
 406        } else if (words[0][4] == 'l') {
 407            uint32_t data;
 408            cpu_physical_memory_read(addr, &data, 4);
 409            value = tswap32(data);
 410        } else if (words[0][4] == 'q') {
 411            cpu_physical_memory_read(addr, &value, 8);
 412            tswap64s(&value);
 413        }
 414        qtest_send_prefix(chr);
 415        qtest_sendf(chr, "OK 0x%016" PRIx64 "\n", value);
 416    } else if (strcmp(words[0], "read") == 0) {
 417        uint64_t addr, len, i;
 418        uint8_t *data;
 419        char *enc;
 420
 421        g_assert(words[1] && words[2]);
 422        addr = strtoull(words[1], NULL, 0);
 423        len = strtoull(words[2], NULL, 0);
 424
 425        data = g_malloc(len);
 426        cpu_physical_memory_read(addr, data, len);
 427
 428        enc = g_malloc(2 * len + 1);
 429        for (i = 0; i < len; i++) {
 430            sprintf(&enc[i * 2], "%02x", data[i]);
 431        }
 432
 433        qtest_send_prefix(chr);
 434        qtest_sendf(chr, "OK 0x%s\n", enc);
 435
 436        g_free(data);
 437        g_free(enc);
 438    } else if (strcmp(words[0], "b64read") == 0) {
 439        uint64_t addr, len;
 440        uint8_t *data;
 441        gchar *b64_data;
 442
 443        g_assert(words[1] && words[2]);
 444        addr = strtoull(words[1], NULL, 0);
 445        len = strtoull(words[2], NULL, 0);
 446
 447        data = g_malloc(len);
 448        cpu_physical_memory_read(addr, data, len);
 449        b64_data = g_base64_encode(data, len);
 450        qtest_send_prefix(chr);
 451        qtest_sendf(chr, "OK %s\n", b64_data);
 452
 453        g_free(data);
 454        g_free(b64_data);
 455    } else if (strcmp(words[0], "write") == 0) {
 456        uint64_t addr, len, i;
 457        uint8_t *data;
 458        size_t data_len;
 459
 460        g_assert(words[1] && words[2] && words[3]);
 461        addr = strtoull(words[1], NULL, 0);
 462        len = strtoull(words[2], NULL, 0);
 463
 464        data_len = strlen(words[3]);
 465        if (data_len < 3) {
 466            qtest_send(chr, "ERR invalid argument size\n");
 467            return;
 468        }
 469
 470        data = g_malloc(len);
 471        for (i = 0; i < len; i++) {
 472            if ((i * 2 + 4) <= data_len) {
 473                data[i] = hex2nib(words[3][i * 2 + 2]) << 4;
 474                data[i] |= hex2nib(words[3][i * 2 + 3]);
 475            } else {
 476                data[i] = 0;
 477            }
 478        }
 479        cpu_physical_memory_write(addr, data, len);
 480        g_free(data);
 481
 482        qtest_send_prefix(chr);
 483        qtest_send(chr, "OK\n");
 484    } else if (strcmp(words[0], "memset") == 0) {
 485        uint64_t addr, len;
 486        uint8_t *data;
 487        uint8_t pattern;
 488
 489        g_assert(words[1] && words[2] && words[3]);
 490        addr = strtoull(words[1], NULL, 0);
 491        len = strtoull(words[2], NULL, 0);
 492        pattern = strtoull(words[3], NULL, 0);
 493
 494        data = g_malloc(len);
 495        memset(data, pattern, len);
 496        cpu_physical_memory_write(addr, data, len);
 497        g_free(data);
 498
 499        qtest_send_prefix(chr);
 500        qtest_send(chr, "OK\n");
 501    }  else if (strcmp(words[0], "b64write") == 0) {
 502        uint64_t addr, len;
 503        uint8_t *data;
 504        size_t data_len;
 505        gsize out_len;
 506
 507        g_assert(words[1] && words[2] && words[3]);
 508        addr = strtoull(words[1], NULL, 0);
 509        len = strtoull(words[2], NULL, 0);
 510
 511        data_len = strlen(words[3]);
 512        if (data_len < 3) {
 513            qtest_send(chr, "ERR invalid argument size\n");
 514            return;
 515        }
 516
 517        data = g_base64_decode_inplace(words[3], &out_len);
 518        if (out_len != len) {
 519            qtest_log_send("b64write: data length mismatch (told %"PRIu64", "
 520                           "found %zu)\n",
 521                           len, out_len);
 522            out_len = MIN(out_len, len);
 523        }
 524
 525        cpu_physical_memory_write(addr, data, out_len);
 526
 527        qtest_send_prefix(chr);
 528        qtest_send(chr, "OK\n");
 529    } else if (qtest_enabled() && strcmp(words[0], "clock_step") == 0) {
 530        int64_t ns;
 531
 532        if (words[1]) {
 533            ns = strtoll(words[1], NULL, 0);
 534        } else {
 535            ns = qemu_clock_deadline_ns_all(QEMU_CLOCK_VIRTUAL);
 536        }
 537        qtest_clock_warp(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + ns);
 538        qtest_send_prefix(chr);
 539        qtest_sendf(chr, "OK %"PRIi64"\n",
 540                    (int64_t)qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL));
 541    } else if (qtest_enabled() && strcmp(words[0], "clock_set") == 0) {
 542        int64_t ns;
 543
 544        g_assert(words[1]);
 545        ns = strtoll(words[1], NULL, 0);
 546        qtest_clock_warp(ns);
 547        qtest_send_prefix(chr);
 548        qtest_sendf(chr, "OK %"PRIi64"\n",
 549                    (int64_t)qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL));
 550    } else {
 551        qtest_send_prefix(chr);
 552        qtest_sendf(chr, "FAIL Unknown command '%s'\n", words[0]);
 553    }
 554}
 555
 556static void qtest_process_inbuf(CharDriverState *chr, GString *inbuf)
 557{
 558    char *end;
 559
 560    while ((end = strchr(inbuf->str, '\n')) != NULL) {
 561        size_t offset;
 562        GString *cmd;
 563        gchar **words;
 564
 565        offset = end - inbuf->str;
 566
 567        cmd = g_string_new_len(inbuf->str, offset);
 568        g_string_erase(inbuf, 0, offset + 1);
 569
 570        words = g_strsplit(cmd->str, " ", 0);
 571        qtest_process_command(chr, words);
 572        g_strfreev(words);
 573
 574        g_string_free(cmd, TRUE);
 575    }
 576}
 577
 578static void qtest_read(void *opaque, const uint8_t *buf, int size)
 579{
 580    CharDriverState *chr = opaque;
 581
 582    g_string_append_len(inbuf, (const gchar *)buf, size);
 583    qtest_process_inbuf(chr, inbuf);
 584}
 585
 586static int qtest_can_read(void *opaque)
 587{
 588    return 1024;
 589}
 590
 591static void qtest_event(void *opaque, int event)
 592{
 593    int i;
 594
 595    switch (event) {
 596    case CHR_EVENT_OPENED:
 597        /*
 598         * We used to call qemu_system_reset() here, hoping we could
 599         * use the same process for multiple tests that way.  Never
 600         * used.  Injects an extra reset even when it's not used, and
 601         * that can mess up tests, e.g. -boot once.
 602         */
 603        for (i = 0; i < ARRAY_SIZE(irq_levels); i++) {
 604            irq_levels[i] = 0;
 605        }
 606        qemu_gettimeofday(&start_time);
 607        qtest_opened = true;
 608        if (qtest_log_fp) {
 609            fprintf(qtest_log_fp, "[I " FMT_timeval "] OPENED\n",
 610                    (long) start_time.tv_sec, (long) start_time.tv_usec);
 611        }
 612        break;
 613    case CHR_EVENT_CLOSED:
 614        qtest_opened = false;
 615        if (qtest_log_fp) {
 616            qemu_timeval tv;
 617            qtest_get_time(&tv);
 618            fprintf(qtest_log_fp, "[I +" FMT_timeval "] CLOSED\n",
 619                    (long) tv.tv_sec, (long) tv.tv_usec);
 620        }
 621        break;
 622    default:
 623        break;
 624    }
 625}
 626
 627static int qtest_init_accel(MachineState *ms)
 628{
 629    QemuOpts *opts = qemu_opts_create(qemu_find_opts("icount"), NULL, 0,
 630                                      &error_abort);
 631    qemu_opt_set(opts, "shift", "0", &error_abort);
 632    configure_icount(opts, &error_abort);
 633    qemu_opts_del(opts);
 634    return 0;
 635}
 636
 637void qtest_init(const char *qtest_chrdev, const char *qtest_log, Error **errp)
 638{
 639    CharDriverState *chr;
 640
 641    chr = qemu_chr_new("qtest", qtest_chrdev, NULL);
 642
 643    if (chr == NULL) {
 644        error_setg(errp, "Failed to initialize device for qtest: \"%s\"",
 645                   qtest_chrdev);
 646        return;
 647    }
 648
 649    if (qtest_log) {
 650        if (strcmp(qtest_log, "none") != 0) {
 651            qtest_log_fp = fopen(qtest_log, "w+");
 652        }
 653    } else {
 654        qtest_log_fp = stderr;
 655    }
 656
 657    qemu_chr_add_handlers(chr, qtest_can_read, qtest_read, qtest_event, chr);
 658    qemu_chr_fe_set_echo(chr, true);
 659
 660    inbuf = g_string_new("");
 661    qtest_chr = chr;
 662}
 663
 664bool qtest_driver(void)
 665{
 666    return qtest_chr;
 667}
 668
 669static void qtest_accel_class_init(ObjectClass *oc, void *data)
 670{
 671    AccelClass *ac = ACCEL_CLASS(oc);
 672    ac->name = "QTest";
 673    ac->available = qtest_available;
 674    ac->init_machine = qtest_init_accel;
 675    ac->allowed = &qtest_allowed;
 676}
 677
 678#define TYPE_QTEST_ACCEL ACCEL_CLASS_NAME("qtest")
 679
 680static const TypeInfo qtest_accel_type = {
 681    .name = TYPE_QTEST_ACCEL,
 682    .parent = TYPE_ACCEL,
 683    .class_init = qtest_accel_class_init,
 684};
 685
 686static void qtest_type_init(void)
 687{
 688    type_register_static(&qtest_accel_type);
 689}
 690
 691type_init(qtest_type_init);
 692