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