Statistics
| Branch: | Revision:

root / qtest.c @ bf0842b7

History | View | Annotate | Download (11 kB)

1 c7f0f3b1 Anthony Liguori
/*
2 c7f0f3b1 Anthony Liguori
 * Test Server
3 c7f0f3b1 Anthony Liguori
 *
4 c7f0f3b1 Anthony Liguori
 * Copyright IBM, Corp. 2011
5 c7f0f3b1 Anthony Liguori
 *
6 c7f0f3b1 Anthony Liguori
 * Authors:
7 c7f0f3b1 Anthony Liguori
 *  Anthony Liguori   <aliguori@us.ibm.com>
8 c7f0f3b1 Anthony Liguori
 *
9 c7f0f3b1 Anthony Liguori
 * This work is licensed under the terms of the GNU GPL, version 2 or later.
10 c7f0f3b1 Anthony Liguori
 * See the COPYING file in the top-level directory.
11 c7f0f3b1 Anthony Liguori
 *
12 c7f0f3b1 Anthony Liguori
 */
13 c7f0f3b1 Anthony Liguori
14 9c17d615 Paolo Bonzini
#include "sysemu/qtest.h"
15 20288345 Paolo Bonzini
#include "hw/qdev.h"
16 927d4878 Paolo Bonzini
#include "char/char.h"
17 022c62cb Paolo Bonzini
#include "exec/ioport.h"
18 022c62cb Paolo Bonzini
#include "exec/memory.h"
19 c7f0f3b1 Anthony Liguori
#include "hw/irq.h"
20 9c17d615 Paolo Bonzini
#include "sysemu/sysemu.h"
21 9c17d615 Paolo Bonzini
#include "sysemu/cpus.h"
22 c7f0f3b1 Anthony Liguori
23 c7f0f3b1 Anthony Liguori
#define MAX_IRQ 256
24 c7f0f3b1 Anthony Liguori
25 c7f0f3b1 Anthony Liguori
const char *qtest_chrdev;
26 c7f0f3b1 Anthony Liguori
const char *qtest_log;
27 c7f0f3b1 Anthony Liguori
int qtest_allowed = 0;
28 c7f0f3b1 Anthony Liguori
29 20288345 Paolo Bonzini
static DeviceState *irq_intercept_dev;
30 c7f0f3b1 Anthony Liguori
static FILE *qtest_log_fp;
31 c7f0f3b1 Anthony Liguori
static CharDriverState *qtest_chr;
32 c7f0f3b1 Anthony Liguori
static GString *inbuf;
33 c7f0f3b1 Anthony Liguori
static int irq_levels[MAX_IRQ];
34 6e92466a Anthony Liguori
static qemu_timeval start_time;
35 c7f0f3b1 Anthony Liguori
static bool qtest_opened;
36 c7f0f3b1 Anthony Liguori
37 6b7cff76 Anthony Liguori
#define FMT_timeval "%ld.%06ld"
38 c7f0f3b1 Anthony Liguori
39 c7f0f3b1 Anthony Liguori
/**
40 c7f0f3b1 Anthony Liguori
 * QTest Protocol
41 c7f0f3b1 Anthony Liguori
 *
42 c7f0f3b1 Anthony Liguori
 * Line based protocol, request/response based.  Server can send async messages
43 c7f0f3b1 Anthony Liguori
 * so clients should always handle many async messages before the response
44 c7f0f3b1 Anthony Liguori
 * comes in.
45 c7f0f3b1 Anthony Liguori
 *
46 c7f0f3b1 Anthony Liguori
 * Valid requests
47 c7f0f3b1 Anthony Liguori
 *
48 8156be56 Paolo Bonzini
 * Clock management:
49 8156be56 Paolo Bonzini
 *
50 8156be56 Paolo Bonzini
 * The qtest client is completely in charge of the vm_clock.  qtest commands
51 8156be56 Paolo Bonzini
 * let you adjust the value of the clock (monotonically).  All the commands
52 8156be56 Paolo Bonzini
 * return the current value of the clock in nanoseconds.
53 8156be56 Paolo Bonzini
 *
54 8156be56 Paolo Bonzini
 *  > clock_step
55 8156be56 Paolo Bonzini
 *  < OK VALUE
56 8156be56 Paolo Bonzini
 *
57 8156be56 Paolo Bonzini
 *     Advance the clock to the next deadline.  Useful when waiting for
58 8156be56 Paolo Bonzini
 *     asynchronous events.
59 8156be56 Paolo Bonzini
 *
60 8156be56 Paolo Bonzini
 *  > clock_step NS
61 8156be56 Paolo Bonzini
 *  < OK VALUE
62 8156be56 Paolo Bonzini
 *
63 8156be56 Paolo Bonzini
 *     Advance the clock by NS nanoseconds.
64 8156be56 Paolo Bonzini
 *
65 8156be56 Paolo Bonzini
 *  > clock_set NS
66 8156be56 Paolo Bonzini
 *  < OK VALUE
67 8156be56 Paolo Bonzini
 *
68 8156be56 Paolo Bonzini
 *     Advance the clock to NS nanoseconds (do nothing if it's already past).
69 8156be56 Paolo Bonzini
 *
70 8156be56 Paolo Bonzini
 * PIO and memory access:
71 8156be56 Paolo Bonzini
 *
72 c7f0f3b1 Anthony Liguori
 *  > outb ADDR VALUE
73 c7f0f3b1 Anthony Liguori
 *  < OK
74 c7f0f3b1 Anthony Liguori
 *
75 c7f0f3b1 Anthony Liguori
 *  > outw ADDR VALUE
76 c7f0f3b1 Anthony Liguori
 *  < OK
77 c7f0f3b1 Anthony Liguori
 *
78 c7f0f3b1 Anthony Liguori
 *  > outl ADDR VALUE
79 c7f0f3b1 Anthony Liguori
 *  < OK
80 c7f0f3b1 Anthony Liguori
 *
81 c7f0f3b1 Anthony Liguori
 *  > inb ADDR
82 c7f0f3b1 Anthony Liguori
 *  < OK VALUE
83 c7f0f3b1 Anthony Liguori
 *
84 c7f0f3b1 Anthony Liguori
 *  > inw ADDR
85 c7f0f3b1 Anthony Liguori
 *  < OK VALUE
86 c7f0f3b1 Anthony Liguori
 *
87 c7f0f3b1 Anthony Liguori
 *  > inl ADDR
88 c7f0f3b1 Anthony Liguori
 *  < OK VALUE
89 c7f0f3b1 Anthony Liguori
 *
90 c7f0f3b1 Anthony Liguori
 *  > read ADDR SIZE
91 c7f0f3b1 Anthony Liguori
 *  < OK DATA
92 c7f0f3b1 Anthony Liguori
 *
93 c7f0f3b1 Anthony Liguori
 *  > write ADDR SIZE DATA
94 c7f0f3b1 Anthony Liguori
 *  < OK
95 c7f0f3b1 Anthony Liguori
 *
96 c7f0f3b1 Anthony Liguori
 * ADDR, SIZE, VALUE are all integers parsed with strtoul() with a base of 0.
97 c7f0f3b1 Anthony Liguori
 *
98 c7f0f3b1 Anthony Liguori
 * DATA is an arbitrarily long hex number prefixed with '0x'.  If it's smaller
99 c7f0f3b1 Anthony Liguori
 * than the expected size, the value will be zero filled at the end of the data
100 c7f0f3b1 Anthony Liguori
 * sequence.
101 c7f0f3b1 Anthony Liguori
 *
102 20288345 Paolo Bonzini
 * IRQ management:
103 20288345 Paolo Bonzini
 *
104 20288345 Paolo Bonzini
 *  > irq_intercept_in QOM-PATH
105 20288345 Paolo Bonzini
 *  < OK
106 20288345 Paolo Bonzini
 *
107 20288345 Paolo Bonzini
 *  > irq_intercept_out QOM-PATH
108 20288345 Paolo Bonzini
 *  < OK
109 20288345 Paolo Bonzini
 *
110 20288345 Paolo Bonzini
 * Attach to the gpio-in (resp. gpio-out) pins exported by the device at
111 20288345 Paolo Bonzini
 * QOM-PATH.  When the pin is triggered, one of the following async messages
112 20288345 Paolo Bonzini
 * will be printed to the qtest stream:
113 20288345 Paolo Bonzini
 *
114 20288345 Paolo Bonzini
 *  IRQ raise NUM
115 20288345 Paolo Bonzini
 *  IRQ lower NUM
116 20288345 Paolo Bonzini
 *
117 20288345 Paolo Bonzini
 * where NUM is an IRQ number.  For the PC, interrupts can be intercepted
118 20288345 Paolo Bonzini
 * simply with "irq_intercept_in ioapic" (note that IRQ0 comes out with
119 20288345 Paolo Bonzini
 * NUM=0 even though it is remapped to GSI 2).
120 c7f0f3b1 Anthony Liguori
 */
121 c7f0f3b1 Anthony Liguori
122 c7f0f3b1 Anthony Liguori
static int hex2nib(char ch)
123 c7f0f3b1 Anthony Liguori
{
124 c7f0f3b1 Anthony Liguori
    if (ch >= '0' && ch <= '9') {
125 c7f0f3b1 Anthony Liguori
        return ch - '0';
126 c7f0f3b1 Anthony Liguori
    } else if (ch >= 'a' && ch <= 'f') {
127 c7f0f3b1 Anthony Liguori
        return 10 + (ch - 'a');
128 c7f0f3b1 Anthony Liguori
    } else if (ch >= 'A' && ch <= 'F') {
129 c7f0f3b1 Anthony Liguori
        return 10 + (ch - 'a');
130 c7f0f3b1 Anthony Liguori
    } else {
131 c7f0f3b1 Anthony Liguori
        return -1;
132 c7f0f3b1 Anthony Liguori
    }
133 c7f0f3b1 Anthony Liguori
}
134 c7f0f3b1 Anthony Liguori
135 6e92466a Anthony Liguori
static void qtest_get_time(qemu_timeval *tv)
136 c7f0f3b1 Anthony Liguori
{
137 6e92466a Anthony Liguori
    qemu_gettimeofday(tv);
138 c7f0f3b1 Anthony Liguori
    tv->tv_sec -= start_time.tv_sec;
139 c7f0f3b1 Anthony Liguori
    tv->tv_usec -= start_time.tv_usec;
140 c7f0f3b1 Anthony Liguori
    if (tv->tv_usec < 0) {
141 c7f0f3b1 Anthony Liguori
        tv->tv_usec += 1000000;
142 c7f0f3b1 Anthony Liguori
        tv->tv_sec -= 1;
143 c7f0f3b1 Anthony Liguori
    }
144 c7f0f3b1 Anthony Liguori
}
145 c7f0f3b1 Anthony Liguori
146 c7f0f3b1 Anthony Liguori
static void qtest_send_prefix(CharDriverState *chr)
147 c7f0f3b1 Anthony Liguori
{
148 6e92466a Anthony Liguori
    qemu_timeval tv;
149 c7f0f3b1 Anthony Liguori
150 c7f0f3b1 Anthony Liguori
    if (!qtest_log_fp || !qtest_opened) {
151 c7f0f3b1 Anthony Liguori
        return;
152 c7f0f3b1 Anthony Liguori
    }
153 c7f0f3b1 Anthony Liguori
154 c7f0f3b1 Anthony Liguori
    qtest_get_time(&tv);
155 c7f0f3b1 Anthony Liguori
    fprintf(qtest_log_fp, "[S +" FMT_timeval "] ",
156 7f3bf92f Richard Henderson
            tv.tv_sec, (long) tv.tv_usec);
157 c7f0f3b1 Anthony Liguori
}
158 c7f0f3b1 Anthony Liguori
159 3f97fd85 Stefan Weil
static void GCC_FMT_ATTR(2, 3) qtest_send(CharDriverState *chr,
160 3f97fd85 Stefan Weil
                                          const char *fmt, ...)
161 c7f0f3b1 Anthony Liguori
{
162 c7f0f3b1 Anthony Liguori
    va_list ap;
163 c7f0f3b1 Anthony Liguori
    char buffer[1024];
164 c7f0f3b1 Anthony Liguori
    size_t len;
165 c7f0f3b1 Anthony Liguori
166 c7f0f3b1 Anthony Liguori
    va_start(ap, fmt);
167 c7f0f3b1 Anthony Liguori
    len = vsnprintf(buffer, sizeof(buffer), fmt, ap);
168 c7f0f3b1 Anthony Liguori
    va_end(ap);
169 c7f0f3b1 Anthony Liguori
170 c7f0f3b1 Anthony Liguori
    qemu_chr_fe_write(chr, (uint8_t *)buffer, len);
171 c7f0f3b1 Anthony Liguori
    if (qtest_log_fp && qtest_opened) {
172 c7f0f3b1 Anthony Liguori
        fprintf(qtest_log_fp, "%s", buffer);
173 c7f0f3b1 Anthony Liguori
    }
174 c7f0f3b1 Anthony Liguori
}
175 c7f0f3b1 Anthony Liguori
176 20288345 Paolo Bonzini
static void qtest_irq_handler(void *opaque, int n, int level)
177 20288345 Paolo Bonzini
{
178 20288345 Paolo Bonzini
    qemu_irq *old_irqs = opaque;
179 20288345 Paolo Bonzini
    qemu_set_irq(old_irqs[n], level);
180 20288345 Paolo Bonzini
181 20288345 Paolo Bonzini
    if (irq_levels[n] != level) {
182 20288345 Paolo Bonzini
        CharDriverState *chr = qtest_chr;
183 20288345 Paolo Bonzini
        irq_levels[n] = level;
184 20288345 Paolo Bonzini
        qtest_send_prefix(chr);
185 20288345 Paolo Bonzini
        qtest_send(chr, "IRQ %s %d\n",
186 20288345 Paolo Bonzini
                   level ? "raise" : "lower", n);
187 20288345 Paolo Bonzini
    }
188 20288345 Paolo Bonzini
}
189 20288345 Paolo Bonzini
190 c7f0f3b1 Anthony Liguori
static void qtest_process_command(CharDriverState *chr, gchar **words)
191 c7f0f3b1 Anthony Liguori
{
192 c7f0f3b1 Anthony Liguori
    const gchar *command;
193 c7f0f3b1 Anthony Liguori
194 c7f0f3b1 Anthony Liguori
    g_assert(words);
195 c7f0f3b1 Anthony Liguori
196 c7f0f3b1 Anthony Liguori
    command = words[0];
197 c7f0f3b1 Anthony Liguori
198 c7f0f3b1 Anthony Liguori
    if (qtest_log_fp) {
199 6e92466a Anthony Liguori
        qemu_timeval tv;
200 c7f0f3b1 Anthony Liguori
        int i;
201 c7f0f3b1 Anthony Liguori
202 c7f0f3b1 Anthony Liguori
        qtest_get_time(&tv);
203 c7f0f3b1 Anthony Liguori
        fprintf(qtest_log_fp, "[R +" FMT_timeval "]",
204 7f3bf92f Richard Henderson
                tv.tv_sec, (long) tv.tv_usec);
205 c7f0f3b1 Anthony Liguori
        for (i = 0; words[i]; i++) {
206 c7f0f3b1 Anthony Liguori
            fprintf(qtest_log_fp, " %s", words[i]);
207 c7f0f3b1 Anthony Liguori
        }
208 c7f0f3b1 Anthony Liguori
        fprintf(qtest_log_fp, "\n");
209 c7f0f3b1 Anthony Liguori
    }
210 c7f0f3b1 Anthony Liguori
211 c7f0f3b1 Anthony Liguori
    g_assert(command);
212 20288345 Paolo Bonzini
    if (strcmp(words[0], "irq_intercept_out") == 0
213 20288345 Paolo Bonzini
        || strcmp(words[0], "irq_intercept_in") == 0) {
214 20288345 Paolo Bonzini
        DeviceState *dev;
215 20288345 Paolo Bonzini
216 20288345 Paolo Bonzini
        g_assert(words[1]);
217 20288345 Paolo Bonzini
        dev = DEVICE(object_resolve_path(words[1], NULL));
218 20288345 Paolo Bonzini
        if (!dev) {
219 20288345 Paolo Bonzini
            qtest_send_prefix(chr);
220 20288345 Paolo Bonzini
            qtest_send(chr, "FAIL Unknown device\n");
221 20288345 Paolo Bonzini
            return;
222 20288345 Paolo Bonzini
        }
223 20288345 Paolo Bonzini
224 20288345 Paolo Bonzini
        if (irq_intercept_dev) {
225 20288345 Paolo Bonzini
            qtest_send_prefix(chr);
226 20288345 Paolo Bonzini
            if (irq_intercept_dev != dev) {
227 20288345 Paolo Bonzini
                qtest_send(chr, "FAIL IRQ intercept already enabled\n");
228 20288345 Paolo Bonzini
            } else {
229 20288345 Paolo Bonzini
                qtest_send(chr, "OK\n");
230 20288345 Paolo Bonzini
            }
231 20288345 Paolo Bonzini
            return;
232 20288345 Paolo Bonzini
        }
233 20288345 Paolo Bonzini
234 20288345 Paolo Bonzini
        if (words[0][14] == 'o') {
235 20288345 Paolo Bonzini
            qemu_irq_intercept_out(&dev->gpio_out, qtest_irq_handler, dev->num_gpio_out);
236 20288345 Paolo Bonzini
        } else {
237 20288345 Paolo Bonzini
            qemu_irq_intercept_in(dev->gpio_in, qtest_irq_handler, dev->num_gpio_in);
238 20288345 Paolo Bonzini
        }
239 20288345 Paolo Bonzini
        irq_intercept_dev = dev;
240 20288345 Paolo Bonzini
        qtest_send_prefix(chr);
241 20288345 Paolo Bonzini
        qtest_send(chr, "OK\n");
242 20288345 Paolo Bonzini
243 20288345 Paolo Bonzini
    } else if (strcmp(words[0], "outb") == 0 ||
244 20288345 Paolo Bonzini
               strcmp(words[0], "outw") == 0 ||
245 20288345 Paolo Bonzini
               strcmp(words[0], "outl") == 0) {
246 c7f0f3b1 Anthony Liguori
        uint16_t addr;
247 c7f0f3b1 Anthony Liguori
        uint32_t value;
248 c7f0f3b1 Anthony Liguori
249 c7f0f3b1 Anthony Liguori
        g_assert(words[1] && words[2]);
250 c7f0f3b1 Anthony Liguori
        addr = strtol(words[1], NULL, 0);
251 c7f0f3b1 Anthony Liguori
        value = strtol(words[2], NULL, 0);
252 c7f0f3b1 Anthony Liguori
253 c7f0f3b1 Anthony Liguori
        if (words[0][3] == 'b') {
254 c7f0f3b1 Anthony Liguori
            cpu_outb(addr, value);
255 c7f0f3b1 Anthony Liguori
        } else if (words[0][3] == 'w') {
256 c7f0f3b1 Anthony Liguori
            cpu_outw(addr, value);
257 c7f0f3b1 Anthony Liguori
        } else if (words[0][3] == 'l') {
258 c7f0f3b1 Anthony Liguori
            cpu_outl(addr, value);
259 c7f0f3b1 Anthony Liguori
        }
260 c7f0f3b1 Anthony Liguori
        qtest_send_prefix(chr);
261 c7f0f3b1 Anthony Liguori
        qtest_send(chr, "OK\n");
262 c7f0f3b1 Anthony Liguori
    } else if (strcmp(words[0], "inb") == 0 ||
263 c7f0f3b1 Anthony Liguori
        strcmp(words[0], "inw") == 0 ||
264 c7f0f3b1 Anthony Liguori
        strcmp(words[0], "inl") == 0) {
265 c7f0f3b1 Anthony Liguori
        uint16_t addr;
266 c7f0f3b1 Anthony Liguori
        uint32_t value = -1U;
267 c7f0f3b1 Anthony Liguori
268 c7f0f3b1 Anthony Liguori
        g_assert(words[1]);
269 c7f0f3b1 Anthony Liguori
        addr = strtol(words[1], NULL, 0);
270 c7f0f3b1 Anthony Liguori
271 c7f0f3b1 Anthony Liguori
        if (words[0][2] == 'b') {
272 c7f0f3b1 Anthony Liguori
            value = cpu_inb(addr);
273 c7f0f3b1 Anthony Liguori
        } else if (words[0][2] == 'w') {
274 c7f0f3b1 Anthony Liguori
            value = cpu_inw(addr);
275 c7f0f3b1 Anthony Liguori
        } else if (words[0][2] == 'l') {
276 c7f0f3b1 Anthony Liguori
            value = cpu_inl(addr);
277 c7f0f3b1 Anthony Liguori
        }
278 c7f0f3b1 Anthony Liguori
        qtest_send_prefix(chr);
279 c7f0f3b1 Anthony Liguori
        qtest_send(chr, "OK 0x%04x\n", value);
280 c7f0f3b1 Anthony Liguori
    } else if (strcmp(words[0], "read") == 0) {
281 c7f0f3b1 Anthony Liguori
        uint64_t addr, len, i;
282 c7f0f3b1 Anthony Liguori
        uint8_t *data;
283 c7f0f3b1 Anthony Liguori
284 c7f0f3b1 Anthony Liguori
        g_assert(words[1] && words[2]);
285 c7f0f3b1 Anthony Liguori
        addr = strtoul(words[1], NULL, 0);
286 c7f0f3b1 Anthony Liguori
        len = strtoul(words[2], NULL, 0);
287 c7f0f3b1 Anthony Liguori
288 c7f0f3b1 Anthony Liguori
        data = g_malloc(len);
289 c7f0f3b1 Anthony Liguori
        cpu_physical_memory_read(addr, data, len);
290 c7f0f3b1 Anthony Liguori
291 c7f0f3b1 Anthony Liguori
        qtest_send_prefix(chr);
292 c7f0f3b1 Anthony Liguori
        qtest_send(chr, "OK 0x");
293 c7f0f3b1 Anthony Liguori
        for (i = 0; i < len; i++) {
294 c7f0f3b1 Anthony Liguori
            qtest_send(chr, "%02x", data[i]);
295 c7f0f3b1 Anthony Liguori
        }
296 c7f0f3b1 Anthony Liguori
        qtest_send(chr, "\n");
297 c7f0f3b1 Anthony Liguori
298 c7f0f3b1 Anthony Liguori
        g_free(data);
299 c7f0f3b1 Anthony Liguori
    } else if (strcmp(words[0], "write") == 0) {
300 c7f0f3b1 Anthony Liguori
        uint64_t addr, len, i;
301 c7f0f3b1 Anthony Liguori
        uint8_t *data;
302 c7f0f3b1 Anthony Liguori
        size_t data_len;
303 c7f0f3b1 Anthony Liguori
304 c7f0f3b1 Anthony Liguori
        g_assert(words[1] && words[2] && words[3]);
305 c7f0f3b1 Anthony Liguori
        addr = strtoul(words[1], NULL, 0);
306 c7f0f3b1 Anthony Liguori
        len = strtoul(words[2], NULL, 0);
307 c7f0f3b1 Anthony Liguori
308 c7f0f3b1 Anthony Liguori
        data_len = strlen(words[3]);
309 c7f0f3b1 Anthony Liguori
        if (data_len < 3) {
310 c7f0f3b1 Anthony Liguori
            qtest_send(chr, "ERR invalid argument size\n");
311 c7f0f3b1 Anthony Liguori
            return;
312 c7f0f3b1 Anthony Liguori
        }
313 c7f0f3b1 Anthony Liguori
314 c7f0f3b1 Anthony Liguori
        data = g_malloc(len);
315 c7f0f3b1 Anthony Liguori
        for (i = 0; i < len; i++) {
316 c7f0f3b1 Anthony Liguori
            if ((i * 2 + 4) <= data_len) {
317 c7f0f3b1 Anthony Liguori
                data[i] = hex2nib(words[3][i * 2 + 2]) << 4;
318 c7f0f3b1 Anthony Liguori
                data[i] |= hex2nib(words[3][i * 2 + 3]);
319 c7f0f3b1 Anthony Liguori
            } else {
320 c7f0f3b1 Anthony Liguori
                data[i] = 0;
321 c7f0f3b1 Anthony Liguori
            }
322 c7f0f3b1 Anthony Liguori
        }
323 c7f0f3b1 Anthony Liguori
        cpu_physical_memory_write(addr, data, len);
324 c7f0f3b1 Anthony Liguori
        g_free(data);
325 c7f0f3b1 Anthony Liguori
326 c7f0f3b1 Anthony Liguori
        qtest_send_prefix(chr);
327 c7f0f3b1 Anthony Liguori
        qtest_send(chr, "OK\n");
328 8156be56 Paolo Bonzini
    } else if (strcmp(words[0], "clock_step") == 0) {
329 8156be56 Paolo Bonzini
        int64_t ns;
330 8156be56 Paolo Bonzini
331 8156be56 Paolo Bonzini
        if (words[1]) {
332 8156be56 Paolo Bonzini
            ns = strtoll(words[1], NULL, 0);
333 8156be56 Paolo Bonzini
        } else {
334 8156be56 Paolo Bonzini
            ns = qemu_clock_deadline(vm_clock);
335 8156be56 Paolo Bonzini
        }
336 8156be56 Paolo Bonzini
        qtest_clock_warp(qemu_get_clock_ns(vm_clock) + ns);
337 8156be56 Paolo Bonzini
        qtest_send_prefix(chr);
338 8156be56 Paolo Bonzini
        qtest_send(chr, "OK %"PRIi64"\n", (int64_t)qemu_get_clock_ns(vm_clock));
339 8156be56 Paolo Bonzini
    } else if (strcmp(words[0], "clock_set") == 0) {
340 8156be56 Paolo Bonzini
        int64_t ns;
341 8156be56 Paolo Bonzini
342 8156be56 Paolo Bonzini
        g_assert(words[1]);
343 8156be56 Paolo Bonzini
        ns = strtoll(words[1], NULL, 0);
344 8156be56 Paolo Bonzini
        qtest_clock_warp(ns);
345 8156be56 Paolo Bonzini
        qtest_send_prefix(chr);
346 8156be56 Paolo Bonzini
        qtest_send(chr, "OK %"PRIi64"\n", (int64_t)qemu_get_clock_ns(vm_clock));
347 c7f0f3b1 Anthony Liguori
    } else {
348 c7f0f3b1 Anthony Liguori
        qtest_send_prefix(chr);
349 c7f0f3b1 Anthony Liguori
        qtest_send(chr, "FAIL Unknown command `%s'\n", words[0]);
350 c7f0f3b1 Anthony Liguori
    }
351 c7f0f3b1 Anthony Liguori
}
352 c7f0f3b1 Anthony Liguori
353 c7f0f3b1 Anthony Liguori
static void qtest_process_inbuf(CharDriverState *chr, GString *inbuf)
354 c7f0f3b1 Anthony Liguori
{
355 c7f0f3b1 Anthony Liguori
    char *end;
356 c7f0f3b1 Anthony Liguori
357 c7f0f3b1 Anthony Liguori
    while ((end = strchr(inbuf->str, '\n')) != NULL) {
358 c7f0f3b1 Anthony Liguori
        size_t offset;
359 c7f0f3b1 Anthony Liguori
        GString *cmd;
360 c7f0f3b1 Anthony Liguori
        gchar **words;
361 c7f0f3b1 Anthony Liguori
362 c7f0f3b1 Anthony Liguori
        offset = end - inbuf->str;
363 c7f0f3b1 Anthony Liguori
364 c7f0f3b1 Anthony Liguori
        cmd = g_string_new_len(inbuf->str, offset);
365 c7f0f3b1 Anthony Liguori
        g_string_erase(inbuf, 0, offset + 1);
366 c7f0f3b1 Anthony Liguori
367 c7f0f3b1 Anthony Liguori
        words = g_strsplit(cmd->str, " ", 0);
368 c7f0f3b1 Anthony Liguori
        qtest_process_command(chr, words);
369 c7f0f3b1 Anthony Liguori
        g_strfreev(words);
370 c7f0f3b1 Anthony Liguori
371 c7f0f3b1 Anthony Liguori
        g_string_free(cmd, TRUE);
372 c7f0f3b1 Anthony Liguori
    }
373 c7f0f3b1 Anthony Liguori
}
374 c7f0f3b1 Anthony Liguori
375 c7f0f3b1 Anthony Liguori
static void qtest_read(void *opaque, const uint8_t *buf, int size)
376 c7f0f3b1 Anthony Liguori
{
377 c7f0f3b1 Anthony Liguori
    CharDriverState *chr = opaque;
378 c7f0f3b1 Anthony Liguori
379 c7f0f3b1 Anthony Liguori
    g_string_append_len(inbuf, (const gchar *)buf, size);
380 c7f0f3b1 Anthony Liguori
    qtest_process_inbuf(chr, inbuf);
381 c7f0f3b1 Anthony Liguori
}
382 c7f0f3b1 Anthony Liguori
383 c7f0f3b1 Anthony Liguori
static int qtest_can_read(void *opaque)
384 c7f0f3b1 Anthony Liguori
{
385 c7f0f3b1 Anthony Liguori
    return 1024;
386 c7f0f3b1 Anthony Liguori
}
387 c7f0f3b1 Anthony Liguori
388 c7f0f3b1 Anthony Liguori
static void qtest_event(void *opaque, int event)
389 c7f0f3b1 Anthony Liguori
{
390 c7f0f3b1 Anthony Liguori
    int i;
391 c7f0f3b1 Anthony Liguori
392 c7f0f3b1 Anthony Liguori
    switch (event) {
393 c7f0f3b1 Anthony Liguori
    case CHR_EVENT_OPENED:
394 c7f0f3b1 Anthony Liguori
        qemu_system_reset(false);
395 c7f0f3b1 Anthony Liguori
        for (i = 0; i < ARRAY_SIZE(irq_levels); i++) {
396 c7f0f3b1 Anthony Liguori
            irq_levels[i] = 0;
397 c7f0f3b1 Anthony Liguori
        }
398 6e92466a Anthony Liguori
        qemu_gettimeofday(&start_time);
399 c7f0f3b1 Anthony Liguori
        qtest_opened = true;
400 c7f0f3b1 Anthony Liguori
        if (qtest_log_fp) {
401 c7f0f3b1 Anthony Liguori
            fprintf(qtest_log_fp, "[I " FMT_timeval "] OPENED\n",
402 7f3bf92f Richard Henderson
                    start_time.tv_sec, (long) start_time.tv_usec);
403 c7f0f3b1 Anthony Liguori
        }
404 c7f0f3b1 Anthony Liguori
        break;
405 c7f0f3b1 Anthony Liguori
    case CHR_EVENT_CLOSED:
406 c7f0f3b1 Anthony Liguori
        qtest_opened = false;
407 c7f0f3b1 Anthony Liguori
        if (qtest_log_fp) {
408 6e92466a Anthony Liguori
            qemu_timeval tv;
409 c7f0f3b1 Anthony Liguori
            qtest_get_time(&tv);
410 c7f0f3b1 Anthony Liguori
            fprintf(qtest_log_fp, "[I +" FMT_timeval "] CLOSED\n",
411 7f3bf92f Richard Henderson
                    tv.tv_sec, (long) tv.tv_usec);
412 c7f0f3b1 Anthony Liguori
        }
413 c7f0f3b1 Anthony Liguori
        break;
414 c7f0f3b1 Anthony Liguori
    default:
415 c7f0f3b1 Anthony Liguori
        break;
416 c7f0f3b1 Anthony Liguori
    }
417 c7f0f3b1 Anthony Liguori
}
418 c7f0f3b1 Anthony Liguori
419 c7f0f3b1 Anthony Liguori
int qtest_init(void)
420 c7f0f3b1 Anthony Liguori
{
421 c7f0f3b1 Anthony Liguori
    CharDriverState *chr;
422 c7f0f3b1 Anthony Liguori
423 c7f0f3b1 Anthony Liguori
    g_assert(qtest_chrdev != NULL);
424 c7f0f3b1 Anthony Liguori
425 8156be56 Paolo Bonzini
    configure_icount("0");
426 c7f0f3b1 Anthony Liguori
    chr = qemu_chr_new("qtest", qtest_chrdev, NULL);
427 c7f0f3b1 Anthony Liguori
428 c7f0f3b1 Anthony Liguori
    qemu_chr_add_handlers(chr, qtest_can_read, qtest_read, qtest_event, chr);
429 c7f0f3b1 Anthony Liguori
    qemu_chr_fe_set_echo(chr, true);
430 c7f0f3b1 Anthony Liguori
431 c7f0f3b1 Anthony Liguori
    inbuf = g_string_new("");
432 c7f0f3b1 Anthony Liguori
433 c7f0f3b1 Anthony Liguori
    if (qtest_log) {
434 c7f0f3b1 Anthony Liguori
        if (strcmp(qtest_log, "none") != 0) {
435 c7f0f3b1 Anthony Liguori
            qtest_log_fp = fopen(qtest_log, "w+");
436 c7f0f3b1 Anthony Liguori
        }
437 c7f0f3b1 Anthony Liguori
    } else {
438 c7f0f3b1 Anthony Liguori
        qtest_log_fp = stderr;
439 c7f0f3b1 Anthony Liguori
    }
440 c7f0f3b1 Anthony Liguori
441 c7f0f3b1 Anthony Liguori
    qtest_chr = chr;
442 c7f0f3b1 Anthony Liguori
443 c7f0f3b1 Anthony Liguori
    return 0;
444 c7f0f3b1 Anthony Liguori
}