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