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 cpu_physical_memory_write(addr, &data, 1);
391 } else if (words[0][5] == 'w') {
392 uint16_t data = value;
393 tswap16s(&data);
394 cpu_physical_memory_write(addr, &data, 2);
395 } else if (words[0][5] == 'l') {
396 uint32_t data = value;
397 tswap32s(&data);
398 cpu_physical_memory_write(addr, &data, 4);
399 } else if (words[0][5] == 'q') {
400 uint64_t data = value;
401 tswap64s(&data);
402 cpu_physical_memory_write(addr, &data, 8);
403 }
404 qtest_send_prefix(chr);
405 qtest_send(chr, "OK\n");
406 } else if (strcmp(words[0], "readb") == 0 ||
407 strcmp(words[0], "readw") == 0 ||
408 strcmp(words[0], "readl") == 0 ||
409 strcmp(words[0], "readq") == 0) {
410 uint64_t addr;
411 uint64_t value = UINT64_C(-1);
412 int ret;
413
414 g_assert(words[1]);
415 ret = qemu_strtou64(words[1], NULL, 0, &addr);
416 g_assert(ret == 0);
417
418 if (words[0][4] == 'b') {
419 uint8_t data;
420 cpu_physical_memory_read(addr, &data, 1);
421 value = data;
422 } else if (words[0][4] == 'w') {
423 uint16_t data;
424 cpu_physical_memory_read(addr, &data, 2);
425 value = tswap16(data);
426 } else if (words[0][4] == 'l') {
427 uint32_t data;
428 cpu_physical_memory_read(addr, &data, 4);
429 value = tswap32(data);
430 } else if (words[0][4] == 'q') {
431 cpu_physical_memory_read(addr, &value, 8);
432 tswap64s(&value);
433 }
434 qtest_send_prefix(chr);
435 qtest_sendf(chr, "OK 0x%016" PRIx64 "\n", value);
436 } else if (strcmp(words[0], "read") == 0) {
437 uint64_t addr, len, i;
438 uint8_t *data;
439 char *enc;
440 int ret;
441
442 g_assert(words[1] && words[2]);
443 ret = qemu_strtou64(words[1], NULL, 0, &addr);
444 g_assert(ret == 0);
445 ret = qemu_strtou64(words[2], NULL, 0, &len);
446 g_assert(ret == 0);
447
448 g_assert(len);
449
450 data = g_malloc(len);
451 cpu_physical_memory_read(addr, data, len);
452
453 enc = g_malloc(2 * len + 1);
454 for (i = 0; i < len; i++) {
455 sprintf(&enc[i * 2], "%02x", data[i]);
456 }
457
458 qtest_send_prefix(chr);
459 qtest_sendf(chr, "OK 0x%s\n", enc);
460
461 g_free(data);
462 g_free(enc);
463 } else if (strcmp(words[0], "b64read") == 0) {
464 uint64_t addr, len;
465 uint8_t *data;
466 gchar *b64_data;
467 int ret;
468
469 g_assert(words[1] && words[2]);
470 ret = qemu_strtou64(words[1], NULL, 0, &addr);
471 g_assert(ret == 0);
472 ret = qemu_strtou64(words[2], NULL, 0, &len);
473 g_assert(ret == 0);
474
475 data = g_malloc(len);
476 cpu_physical_memory_read(addr, data, len);
477 b64_data = g_base64_encode(data, len);
478 qtest_send_prefix(chr);
479 qtest_sendf(chr, "OK %s\n", b64_data);
480
481 g_free(data);
482 g_free(b64_data);
483 } else if (strcmp(words[0], "write") == 0) {
484 uint64_t addr, len, i;
485 uint8_t *data;
486 size_t data_len;
487 int ret;
488
489 g_assert(words[1] && words[2] && words[3]);
490 ret = qemu_strtou64(words[1], NULL, 0, &addr);
491 g_assert(ret == 0);
492 ret = qemu_strtou64(words[2], NULL, 0, &len);
493 g_assert(ret == 0);
494
495 data_len = strlen(words[3]);
496 if (data_len < 3) {
497 qtest_send(chr, "ERR invalid argument size\n");
498 return;
499 }
500
501 data = g_malloc(len);
502 for (i = 0; i < len; i++) {
503 if ((i * 2 + 4) <= data_len) {
504 data[i] = hex2nib(words[3][i * 2 + 2]) << 4;
505 data[i] |= hex2nib(words[3][i * 2 + 3]);
506 } else {
507 data[i] = 0;
508 }
509 }
510 cpu_physical_memory_write(addr, data, len);
511 g_free(data);
512
513 qtest_send_prefix(chr);
514 qtest_send(chr, "OK\n");
515 } else if (strcmp(words[0], "memset") == 0) {
516 uint64_t addr, len;
517 uint8_t *data;
518 unsigned long pattern;
519 int ret;
520
521 g_assert(words[1] && words[2] && words[3]);
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 ret = qemu_strtoul(words[3], NULL, 0, &pattern);
527 g_assert(ret == 0);
528
529 if (len) {
530 data = g_malloc(len);
531 memset(data, pattern, len);
532 cpu_physical_memory_write(addr, data, len);
533 g_free(data);
534 }
535
536 qtest_send_prefix(chr);
537 qtest_send(chr, "OK\n");
538 } else if (strcmp(words[0], "b64write") == 0) {
539 uint64_t addr, len;
540 uint8_t *data;
541 size_t data_len;
542 gsize out_len;
543 int ret;
544
545 g_assert(words[1] && words[2] && words[3]);
546 ret = qemu_strtou64(words[1], NULL, 0, &addr);
547 g_assert(ret == 0);
548 ret = qemu_strtou64(words[2], NULL, 0, &len);
549 g_assert(ret == 0);
550
551 data_len = strlen(words[3]);
552 if (data_len < 3) {
553 qtest_send(chr, "ERR invalid argument size\n");
554 return;
555 }
556
557 data = g_base64_decode_inplace(words[3], &out_len);
558 if (out_len != len) {
559 qtest_log_send("b64write: data length mismatch (told %"PRIu64", "
560 "found %zu)\n",
561 len, out_len);
562 out_len = MIN(out_len, len);
563 }
564
565 cpu_physical_memory_write(addr, data, out_len);
566
567 qtest_send_prefix(chr);
568 qtest_send(chr, "OK\n");
569 } else if (strcmp(words[0], "endianness") == 0) {
570 qtest_send_prefix(chr);
571#if defined(TARGET_WORDS_BIGENDIAN)
572 qtest_sendf(chr, "OK big\n");
573#else
574 qtest_sendf(chr, "OK little\n");
575#endif
576#ifdef TARGET_PPC64
577 } else if (strcmp(words[0], "rtas") == 0) {
578 uint64_t res, args, ret;
579 unsigned long nargs, nret;
580 int rc;
581
582 rc = qemu_strtoul(words[2], NULL, 0, &nargs);
583 g_assert(rc == 0);
584 rc = qemu_strtou64(words[3], NULL, 0, &args);
585 g_assert(rc == 0);
586 rc = qemu_strtoul(words[4], NULL, 0, &nret);
587 g_assert(rc == 0);
588 rc = qemu_strtou64(words[5], NULL, 0, &ret);
589 g_assert(rc == 0);
590 res = qtest_rtas_call(words[1], nargs, args, nret, ret);
591
592 qtest_send_prefix(chr);
593 qtest_sendf(chr, "OK %"PRIu64"\n", res);
594#endif
595 } else if (qtest_enabled() && strcmp(words[0], "clock_step") == 0) {
596 int64_t ns;
597
598 if (words[1]) {
599 int ret = qemu_strtoi64(words[1], NULL, 0, &ns);
600 g_assert(ret == 0);
601 } else {
602 ns = qemu_clock_deadline_ns_all(QEMU_CLOCK_VIRTUAL);
603 }
604 qtest_clock_warp(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + ns);
605 qtest_send_prefix(chr);
606 qtest_sendf(chr, "OK %"PRIi64"\n",
607 (int64_t)qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL));
608 } else if (qtest_enabled() && strcmp(words[0], "clock_set") == 0) {
609 int64_t ns;
610 int ret;
611
612 g_assert(words[1]);
613 ret = qemu_strtoi64(words[1], NULL, 0, &ns);
614 g_assert(ret == 0);
615 qtest_clock_warp(ns);
616 qtest_send_prefix(chr);
617 qtest_sendf(chr, "OK %"PRIi64"\n",
618 (int64_t)qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL));
619 } else {
620 qtest_send_prefix(chr);
621 qtest_sendf(chr, "FAIL Unknown command '%s'\n", words[0]);
622 }
623}
624
625static void qtest_process_inbuf(CharBackend *chr, GString *inbuf)
626{
627 char *end;
628
629 while ((end = strchr(inbuf->str, '\n')) != NULL) {
630 size_t offset;
631 GString *cmd;
632 gchar **words;
633
634 offset = end - inbuf->str;
635
636 cmd = g_string_new_len(inbuf->str, offset);
637 g_string_erase(inbuf, 0, offset + 1);
638
639 words = g_strsplit(cmd->str, " ", 0);
640 qtest_process_command(chr, words);
641 g_strfreev(words);
642
643 g_string_free(cmd, TRUE);
644 }
645}
646
647static void qtest_read(void *opaque, const uint8_t *buf, int size)
648{
649 CharBackend *chr = opaque;
650
651 g_string_append_len(inbuf, (const gchar *)buf, size);
652 qtest_process_inbuf(chr, inbuf);
653}
654
655static int qtest_can_read(void *opaque)
656{
657 return 1024;
658}
659
660static void qtest_event(void *opaque, int event)
661{
662 int i;
663
664 switch (event) {
665 case CHR_EVENT_OPENED:
666
667
668
669
670
671
672 for (i = 0; i < ARRAY_SIZE(irq_levels); i++) {
673 irq_levels[i] = 0;
674 }
675 qemu_gettimeofday(&start_time);
676 qtest_opened = true;
677 if (qtest_log_fp) {
678 fprintf(qtest_log_fp, "[I " FMT_timeval "] OPENED\n",
679 (long) start_time.tv_sec, (long) start_time.tv_usec);
680 }
681 break;
682 case CHR_EVENT_CLOSED:
683 qtest_opened = false;
684 if (qtest_log_fp) {
685 qemu_timeval tv;
686 qtest_get_time(&tv);
687 fprintf(qtest_log_fp, "[I +" FMT_timeval "] CLOSED\n",
688 (long) tv.tv_sec, (long) tv.tv_usec);
689 }
690 break;
691 default:
692 break;
693 }
694}
695
696static int qtest_init_accel(MachineState *ms)
697{
698 QemuOpts *opts = qemu_opts_create(qemu_find_opts("icount"), NULL, 0,
699 &error_abort);
700 qemu_opt_set(opts, "shift", "0", &error_abort);
701 configure_icount(opts, &error_abort);
702 qemu_opts_del(opts);
703 return 0;
704}
705
706void qtest_init(const char *qtest_chrdev, const char *qtest_log, Error **errp)
707{
708 Chardev *chr;
709
710 chr = qemu_chr_new("qtest", qtest_chrdev);
711
712 if (chr == NULL) {
713 error_setg(errp, "Failed to initialize device for qtest: \"%s\"",
714 qtest_chrdev);
715 return;
716 }
717
718 if (qtest_log) {
719 if (strcmp(qtest_log, "none") != 0) {
720 qtest_log_fp = fopen(qtest_log, "w+");
721 }
722 } else {
723 qtest_log_fp = stderr;
724 }
725
726 qemu_chr_fe_init(&qtest_chr, chr, errp);
727 qemu_chr_fe_set_handlers(&qtest_chr, qtest_can_read, qtest_read,
728 qtest_event, NULL, &qtest_chr, NULL, true);
729 qemu_chr_fe_set_echo(&qtest_chr, true);
730
731 inbuf = g_string_new("");
732}
733
734bool qtest_driver(void)
735{
736 return qtest_chr.chr != NULL;
737}
738
739static void qtest_accel_class_init(ObjectClass *oc, void *data)
740{
741 AccelClass *ac = ACCEL_CLASS(oc);
742 ac->name = "QTest";
743 ac->available = qtest_available;
744 ac->init_machine = qtest_init_accel;
745 ac->allowed = &qtest_allowed;
746}
747
748#define TYPE_QTEST_ACCEL ACCEL_CLASS_NAME("qtest")
749
750static const TypeInfo qtest_accel_type = {
751 .name = TYPE_QTEST_ACCEL,
752 .parent = TYPE_ACCEL,
753 .class_init = qtest_accel_class_init,
754};
755
756static void qtest_type_init(void)
757{
758 type_register_static(&qtest_accel_type);
759}
760
761type_init(qtest_type_init);
762