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