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