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