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 "cpu.h"
17#include "sysemu/qtest.h"
18#include "hw/qdev.h"
19#include "chardev/char-fe.h"
20#include "exec/ioport.h"
21#include "exec/memory.h"
22#include "hw/irq.h"
23#include "sysemu/accel.h"
24#include "sysemu/sysemu.h"
25#include "sysemu/cpus.h"
26#include "qemu/config-file.h"
27#include "qemu/option.h"
28#include "qemu/error-report.h"
29#include "qemu/module.h"
30#include "qemu/cutils.h"
31#ifdef TARGET_PPC64
32#include "hw/ppc/spapr_rtas.h"
33#endif
34
35#define MAX_IRQ 256
36
37bool qtest_allowed;
38
39static DeviceState *irq_intercept_dev;
40static FILE *qtest_log_fp;
41static CharBackend qtest_chr;
42static GString *inbuf;
43static int irq_levels[MAX_IRQ];
44static qemu_timeval start_time;
45static bool qtest_opened;
46
47#define FMT_timeval "%ld.%06ld"
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
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180static int hex2nib(char ch)
181{
182 if (ch >= '0' && ch <= '9') {
183 return ch - '0';
184 } else if (ch >= 'a' && ch <= 'f') {
185 return 10 + (ch - 'a');
186 } else if (ch >= 'A' && ch <= 'F') {
187 return 10 + (ch - 'A');
188 } else {
189 return -1;
190 }
191}
192
193static void qtest_get_time(qemu_timeval *tv)
194{
195 qemu_gettimeofday(tv);
196 tv->tv_sec -= start_time.tv_sec;
197 tv->tv_usec -= start_time.tv_usec;
198 if (tv->tv_usec < 0) {
199 tv->tv_usec += 1000000;
200 tv->tv_sec -= 1;
201 }
202}
203
204static void qtest_send_prefix(CharBackend *chr)
205{
206 qemu_timeval tv;
207
208 if (!qtest_log_fp || !qtest_opened) {
209 return;
210 }
211
212 qtest_get_time(&tv);
213 fprintf(qtest_log_fp, "[S +" FMT_timeval "] ",
214 (long) tv.tv_sec, (long) tv.tv_usec);
215}
216
217static void GCC_FMT_ATTR(1, 2) qtest_log_send(const char *fmt, ...)
218{
219 va_list ap;
220
221 if (!qtest_log_fp || !qtest_opened) {
222 return;
223 }
224
225 qtest_send_prefix(NULL);
226
227 va_start(ap, fmt);
228 vfprintf(qtest_log_fp, fmt, ap);
229 va_end(ap);
230}
231
232static void do_qtest_send(CharBackend *chr, const char *str, size_t len)
233{
234 qemu_chr_fe_write_all(chr, (uint8_t *)str, len);
235 if (qtest_log_fp && qtest_opened) {
236 fprintf(qtest_log_fp, "%s", str);
237 }
238}
239
240static void qtest_send(CharBackend *chr, const char *str)
241{
242 do_qtest_send(chr, str, strlen(str));
243}
244
245static void GCC_FMT_ATTR(2, 3) qtest_sendf(CharBackend *chr,
246 const char *fmt, ...)
247{
248 va_list ap;
249 gchar *buffer;
250
251 va_start(ap, fmt);
252 buffer = g_strdup_vprintf(fmt, ap);
253 qtest_send(chr, buffer);
254 g_free(buffer);
255 va_end(ap);
256}
257
258static void qtest_irq_handler(void *opaque, int n, int level)
259{
260 qemu_irq old_irq = *(qemu_irq *)opaque;
261 qemu_set_irq(old_irq, level);
262
263 if (irq_levels[n] != level) {
264 CharBackend *chr = &qtest_chr;
265 irq_levels[n] = level;
266 qtest_send_prefix(chr);
267 qtest_sendf(chr, "IRQ %s %d\n",
268 level ? "raise" : "lower", n);
269 }
270}
271
272static void qtest_process_command(CharBackend *chr, gchar **words)
273{
274 const gchar *command;
275
276 g_assert(words);
277
278 command = words[0];
279
280 if (qtest_log_fp) {
281 qemu_timeval tv;
282 int i;
283
284 qtest_get_time(&tv);
285 fprintf(qtest_log_fp, "[R +" FMT_timeval "]",
286 (long) tv.tv_sec, (long) tv.tv_usec);
287 for (i = 0; words[i]; i++) {
288 fprintf(qtest_log_fp, " %s", words[i]);
289 }
290 fprintf(qtest_log_fp, "\n");
291 }
292
293 g_assert(command);
294 if (strcmp(words[0], "irq_intercept_out") == 0
295 || strcmp(words[0], "irq_intercept_in") == 0) {
296 DeviceState *dev;
297 NamedGPIOList *ngl;
298
299 g_assert(words[1]);
300 dev = DEVICE(object_resolve_path(words[1], NULL));
301 if (!dev) {
302 qtest_send_prefix(chr);
303 qtest_send(chr, "FAIL Unknown device\n");
304 return;
305 }
306
307 if (irq_intercept_dev) {
308 qtest_send_prefix(chr);
309 if (irq_intercept_dev != dev) {
310 qtest_send(chr, "FAIL IRQ intercept already enabled\n");
311 } else {
312 qtest_send(chr, "OK\n");
313 }
314 return;
315 }
316
317 QLIST_FOREACH(ngl, &dev->gpios, node) {
318
319 if (ngl->name) {
320 continue;
321 }
322 if (words[0][14] == 'o') {
323 int i;
324 for (i = 0; i < ngl->num_out; ++i) {
325 qemu_irq *disconnected = g_new0(qemu_irq, 1);
326 qemu_irq icpt = qemu_allocate_irq(qtest_irq_handler,
327 disconnected, i);
328
329 *disconnected = qdev_intercept_gpio_out(dev, icpt,
330 ngl->name, i);
331 }
332 } else {
333 qemu_irq_intercept_in(ngl->in, qtest_irq_handler,
334 ngl->num_in);
335 }
336 }
337 irq_intercept_dev = dev;
338 qtest_send_prefix(chr);
339 qtest_send(chr, "OK\n");
340 } else if (strcmp(words[0], "set_irq_in") == 0) {
341 DeviceState *dev;
342 qemu_irq irq;
343 char *name;
344 int ret;
345 int num;
346 int level;
347
348 g_assert(words[1] && words[2] && words[3] && words[4]);
349
350 dev = DEVICE(object_resolve_path(words[1], NULL));
351 if (!dev) {
352 qtest_send_prefix(chr);
353 qtest_send(chr, "FAIL Unknown device\n");
354 return;
355 }
356
357 if (strcmp(words[2], "unnamed-gpio-in") == 0) {
358 name = NULL;
359 } else {
360 name = words[2];
361 }
362
363 ret = qemu_strtoi(words[3], NULL, 0, &num);
364 g_assert(!ret);
365 ret = qemu_strtoi(words[4], NULL, 0, &level);
366 g_assert(!ret);
367
368 irq = qdev_get_gpio_in_named(dev, name, num);
369
370 qemu_set_irq(irq, level);
371 qtest_send_prefix(chr);
372 qtest_send(chr, "OK\n");
373 } else if (strcmp(words[0], "outb") == 0 ||
374 strcmp(words[0], "outw") == 0 ||
375 strcmp(words[0], "outl") == 0) {
376 unsigned long addr;
377 unsigned long value;
378 int ret;
379
380 g_assert(words[1] && words[2]);
381 ret = qemu_strtoul(words[1], NULL, 0, &addr);
382 g_assert(ret == 0);
383 ret = qemu_strtoul(words[2], NULL, 0, &value);
384 g_assert(ret == 0);
385 g_assert(addr <= 0xffff);
386
387 if (words[0][3] == 'b') {
388 cpu_outb(addr, value);
389 } else if (words[0][3] == 'w') {
390 cpu_outw(addr, value);
391 } else if (words[0][3] == 'l') {
392 cpu_outl(addr, value);
393 }
394 qtest_send_prefix(chr);
395 qtest_send(chr, "OK\n");
396 } else if (strcmp(words[0], "inb") == 0 ||
397 strcmp(words[0], "inw") == 0 ||
398 strcmp(words[0], "inl") == 0) {
399 unsigned long addr;
400 uint32_t value = -1U;
401 int ret;
402
403 g_assert(words[1]);
404 ret = qemu_strtoul(words[1], NULL, 0, &addr);
405 g_assert(ret == 0);
406 g_assert(addr <= 0xffff);
407
408 if (words[0][2] == 'b') {
409 value = cpu_inb(addr);
410 } else if (words[0][2] == 'w') {
411 value = cpu_inw(addr);
412 } else if (words[0][2] == 'l') {
413 value = cpu_inl(addr);
414 }
415 qtest_send_prefix(chr);
416 qtest_sendf(chr, "OK 0x%04x\n", value);
417 } else if (strcmp(words[0], "writeb") == 0 ||
418 strcmp(words[0], "writew") == 0 ||
419 strcmp(words[0], "writel") == 0 ||
420 strcmp(words[0], "writeq") == 0) {
421 uint64_t addr;
422 uint64_t value;
423 int ret;
424
425 g_assert(words[1] && words[2]);
426 ret = qemu_strtou64(words[1], NULL, 0, &addr);
427 g_assert(ret == 0);
428 ret = qemu_strtou64(words[2], NULL, 0, &value);
429 g_assert(ret == 0);
430
431 if (words[0][5] == 'b') {
432 uint8_t data = value;
433 address_space_rw(first_cpu->as, addr, MEMTXATTRS_UNSPECIFIED,
434 &data, 1, true);
435 } else if (words[0][5] == 'w') {
436 uint16_t data = value;
437 tswap16s(&data);
438 address_space_rw(first_cpu->as, addr, MEMTXATTRS_UNSPECIFIED,
439 (uint8_t *) &data, 2, true);
440 } else if (words[0][5] == 'l') {
441 uint32_t data = value;
442 tswap32s(&data);
443 address_space_rw(first_cpu->as, addr, MEMTXATTRS_UNSPECIFIED,
444 (uint8_t *) &data, 4, true);
445 } else if (words[0][5] == 'q') {
446 uint64_t data = value;
447 tswap64s(&data);
448 address_space_rw(first_cpu->as, addr, MEMTXATTRS_UNSPECIFIED,
449 (uint8_t *) &data, 8, true);
450 }
451 qtest_send_prefix(chr);
452 qtest_send(chr, "OK\n");
453 } else if (strcmp(words[0], "readb") == 0 ||
454 strcmp(words[0], "readw") == 0 ||
455 strcmp(words[0], "readl") == 0 ||
456 strcmp(words[0], "readq") == 0) {
457 uint64_t addr;
458 uint64_t value = UINT64_C(-1);
459 int ret;
460
461 g_assert(words[1]);
462 ret = qemu_strtou64(words[1], NULL, 0, &addr);
463 g_assert(ret == 0);
464
465 if (words[0][4] == 'b') {
466 uint8_t data;
467 address_space_rw(first_cpu->as, addr, MEMTXATTRS_UNSPECIFIED,
468 &data, 1, false);
469 value = data;
470 } else if (words[0][4] == 'w') {
471 uint16_t data;
472 address_space_rw(first_cpu->as, addr, MEMTXATTRS_UNSPECIFIED,
473 (uint8_t *) &data, 2, false);
474 value = tswap16(data);
475 } else if (words[0][4] == 'l') {
476 uint32_t data;
477 address_space_rw(first_cpu->as, addr, MEMTXATTRS_UNSPECIFIED,
478 (uint8_t *) &data, 4, false);
479 value = tswap32(data);
480 } else if (words[0][4] == 'q') {
481 address_space_rw(first_cpu->as, addr, MEMTXATTRS_UNSPECIFIED,
482 (uint8_t *) &value, 8, false);
483 tswap64s(&value);
484 }
485 qtest_send_prefix(chr);
486 qtest_sendf(chr, "OK 0x%016" PRIx64 "\n", value);
487 } else if (strcmp(words[0], "read") == 0) {
488 uint64_t addr, len, i;
489 uint8_t *data;
490 char *enc;
491 int ret;
492
493 g_assert(words[1] && words[2]);
494 ret = qemu_strtou64(words[1], NULL, 0, &addr);
495 g_assert(ret == 0);
496 ret = qemu_strtou64(words[2], NULL, 0, &len);
497 g_assert(ret == 0);
498
499 g_assert(len);
500
501 data = g_malloc(len);
502 address_space_rw(first_cpu->as, addr, MEMTXATTRS_UNSPECIFIED,
503 data, len, false);
504
505 enc = g_malloc(2 * len + 1);
506 for (i = 0; i < len; i++) {
507 sprintf(&enc[i * 2], "%02x", data[i]);
508 }
509
510 qtest_send_prefix(chr);
511 qtest_sendf(chr, "OK 0x%s\n", enc);
512
513 g_free(data);
514 g_free(enc);
515 } else if (strcmp(words[0], "b64read") == 0) {
516 uint64_t addr, len;
517 uint8_t *data;
518 gchar *b64_data;
519 int ret;
520
521 g_assert(words[1] && words[2]);
522 ret = qemu_strtou64(words[1], NULL, 0, &addr);
523 g_assert(ret == 0);
524 ret = qemu_strtou64(words[2], NULL, 0, &len);
525 g_assert(ret == 0);
526
527 data = g_malloc(len);
528 address_space_rw(first_cpu->as, addr, MEMTXATTRS_UNSPECIFIED,
529 data, len, false);
530 b64_data = g_base64_encode(data, len);
531 qtest_send_prefix(chr);
532 qtest_sendf(chr, "OK %s\n", b64_data);
533
534 g_free(data);
535 g_free(b64_data);
536 } else if (strcmp(words[0], "write") == 0) {
537 uint64_t addr, len, i;
538 uint8_t *data;
539 size_t data_len;
540 int ret;
541
542 g_assert(words[1] && words[2] && words[3]);
543 ret = qemu_strtou64(words[1], NULL, 0, &addr);
544 g_assert(ret == 0);
545 ret = qemu_strtou64(words[2], NULL, 0, &len);
546 g_assert(ret == 0);
547
548 data_len = strlen(words[3]);
549 if (data_len < 3) {
550 qtest_send(chr, "ERR invalid argument size\n");
551 return;
552 }
553
554 data = g_malloc(len);
555 for (i = 0; i < len; i++) {
556 if ((i * 2 + 4) <= data_len) {
557 data[i] = hex2nib(words[3][i * 2 + 2]) << 4;
558 data[i] |= hex2nib(words[3][i * 2 + 3]);
559 } else {
560 data[i] = 0;
561 }
562 }
563 address_space_rw(first_cpu->as, addr, MEMTXATTRS_UNSPECIFIED,
564 data, len, true);
565 g_free(data);
566
567 qtest_send_prefix(chr);
568 qtest_send(chr, "OK\n");
569 } else if (strcmp(words[0], "memset") == 0) {
570 uint64_t addr, len;
571 uint8_t *data;
572 unsigned long pattern;
573 int ret;
574
575 g_assert(words[1] && words[2] && words[3]);
576 ret = qemu_strtou64(words[1], NULL, 0, &addr);
577 g_assert(ret == 0);
578 ret = qemu_strtou64(words[2], NULL, 0, &len);
579 g_assert(ret == 0);
580 ret = qemu_strtoul(words[3], NULL, 0, &pattern);
581 g_assert(ret == 0);
582
583 if (len) {
584 data = g_malloc(len);
585 memset(data, pattern, len);
586 address_space_rw(first_cpu->as, addr, MEMTXATTRS_UNSPECIFIED,
587 data, len, true);
588 g_free(data);
589 }
590
591 qtest_send_prefix(chr);
592 qtest_send(chr, "OK\n");
593 } else if (strcmp(words[0], "b64write") == 0) {
594 uint64_t addr, len;
595 uint8_t *data;
596 size_t data_len;
597 gsize out_len;
598 int ret;
599
600 g_assert(words[1] && words[2] && words[3]);
601 ret = qemu_strtou64(words[1], NULL, 0, &addr);
602 g_assert(ret == 0);
603 ret = qemu_strtou64(words[2], NULL, 0, &len);
604 g_assert(ret == 0);
605
606 data_len = strlen(words[3]);
607 if (data_len < 3) {
608 qtest_send(chr, "ERR invalid argument size\n");
609 return;
610 }
611
612 data = g_base64_decode_inplace(words[3], &out_len);
613 if (out_len != len) {
614 qtest_log_send("b64write: data length mismatch (told %"PRIu64", "
615 "found %zu)\n",
616 len, out_len);
617 out_len = MIN(out_len, len);
618 }
619
620 address_space_rw(first_cpu->as, addr, MEMTXATTRS_UNSPECIFIED,
621 data, len, true);
622
623 qtest_send_prefix(chr);
624 qtest_send(chr, "OK\n");
625 } else if (strcmp(words[0], "endianness") == 0) {
626 qtest_send_prefix(chr);
627#if defined(TARGET_WORDS_BIGENDIAN)
628 qtest_sendf(chr, "OK big\n");
629#else
630 qtest_sendf(chr, "OK little\n");
631#endif
632#ifdef TARGET_PPC64
633 } else if (strcmp(words[0], "rtas") == 0) {
634 uint64_t res, args, ret;
635 unsigned long nargs, nret;
636 int rc;
637
638 rc = qemu_strtoul(words[2], NULL, 0, &nargs);
639 g_assert(rc == 0);
640 rc = qemu_strtou64(words[3], NULL, 0, &args);
641 g_assert(rc == 0);
642 rc = qemu_strtoul(words[4], NULL, 0, &nret);
643 g_assert(rc == 0);
644 rc = qemu_strtou64(words[5], NULL, 0, &ret);
645 g_assert(rc == 0);
646 res = qtest_rtas_call(words[1], nargs, args, nret, ret);
647
648 qtest_send_prefix(chr);
649 qtest_sendf(chr, "OK %"PRIu64"\n", res);
650#endif
651 } else if (qtest_enabled() && strcmp(words[0], "clock_step") == 0) {
652 int64_t ns;
653
654 if (words[1]) {
655 int ret = qemu_strtoi64(words[1], NULL, 0, &ns);
656 g_assert(ret == 0);
657 } else {
658 ns = qemu_clock_deadline_ns_all(QEMU_CLOCK_VIRTUAL);
659 }
660 qtest_clock_warp(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + ns);
661 qtest_send_prefix(chr);
662 qtest_sendf(chr, "OK %"PRIi64"\n",
663 (int64_t)qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL));
664 } else if (qtest_enabled() && strcmp(words[0], "clock_set") == 0) {
665 int64_t ns;
666 int ret;
667
668 g_assert(words[1]);
669 ret = qemu_strtoi64(words[1], NULL, 0, &ns);
670 g_assert(ret == 0);
671 qtest_clock_warp(ns);
672 qtest_send_prefix(chr);
673 qtest_sendf(chr, "OK %"PRIi64"\n",
674 (int64_t)qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL));
675 } else {
676 qtest_send_prefix(chr);
677 qtest_sendf(chr, "FAIL Unknown command '%s'\n", words[0]);
678 }
679}
680
681static void qtest_process_inbuf(CharBackend *chr, GString *inbuf)
682{
683 char *end;
684
685 while ((end = strchr(inbuf->str, '\n')) != NULL) {
686 size_t offset;
687 GString *cmd;
688 gchar **words;
689
690 offset = end - inbuf->str;
691
692 cmd = g_string_new_len(inbuf->str, offset);
693 g_string_erase(inbuf, 0, offset + 1);
694
695 words = g_strsplit(cmd->str, " ", 0);
696 qtest_process_command(chr, words);
697 g_strfreev(words);
698
699 g_string_free(cmd, TRUE);
700 }
701}
702
703static void qtest_read(void *opaque, const uint8_t *buf, int size)
704{
705 CharBackend *chr = opaque;
706
707 g_string_append_len(inbuf, (const gchar *)buf, size);
708 qtest_process_inbuf(chr, inbuf);
709}
710
711static int qtest_can_read(void *opaque)
712{
713 return 1024;
714}
715
716static void qtest_event(void *opaque, int event)
717{
718 int i;
719
720 switch (event) {
721 case CHR_EVENT_OPENED:
722
723
724
725
726
727
728 for (i = 0; i < ARRAY_SIZE(irq_levels); i++) {
729 irq_levels[i] = 0;
730 }
731 qemu_gettimeofday(&start_time);
732 qtest_opened = true;
733 if (qtest_log_fp) {
734 fprintf(qtest_log_fp, "[I " FMT_timeval "] OPENED\n",
735 (long) start_time.tv_sec, (long) start_time.tv_usec);
736 }
737 break;
738 case CHR_EVENT_CLOSED:
739 qtest_opened = false;
740 if (qtest_log_fp) {
741 qemu_timeval tv;
742 qtest_get_time(&tv);
743 fprintf(qtest_log_fp, "[I +" FMT_timeval "] CLOSED\n",
744 (long) tv.tv_sec, (long) tv.tv_usec);
745 }
746 break;
747 default:
748 break;
749 }
750}
751
752void qtest_init(const char *qtest_chrdev, const char *qtest_log, Error **errp)
753{
754 Chardev *chr;
755
756 chr = qemu_chr_new("qtest", qtest_chrdev, NULL);
757
758 if (chr == NULL) {
759 error_setg(errp, "Failed to initialize device for qtest: \"%s\"",
760 qtest_chrdev);
761 return;
762 }
763
764 if (qtest_log) {
765 if (strcmp(qtest_log, "none") != 0) {
766 qtest_log_fp = fopen(qtest_log, "w+");
767 }
768 } else {
769 qtest_log_fp = stderr;
770 }
771
772 qemu_chr_fe_init(&qtest_chr, chr, errp);
773 qemu_chr_fe_set_handlers(&qtest_chr, qtest_can_read, qtest_read,
774 qtest_event, NULL, &qtest_chr, NULL, true);
775 qemu_chr_fe_set_echo(&qtest_chr, true);
776
777 inbuf = g_string_new("");
778}
779
780bool qtest_driver(void)
781{
782 return qtest_chr.chr != NULL;
783}
784