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 "cpu.h"
17#include "sysemu/qtest.h"
18#include "sysemu/runstate.h"
19#include "chardev/char-fe.h"
20#include "exec/ioport.h"
21#include "exec/memory.h"
22#include "hw/qdev-core.h"
23#include "hw/irq.h"
24#include "qemu/accel.h"
25#include "sysemu/cpu-timers.h"
26#include "qemu/config-file.h"
27#include "qemu/option.h"
28#include "qemu/error-report.h"
29#include "qemu/module.h"
30#include "qemu/cutils.h"
31#include "qapi/qmp/qerror.h"
32#include "qom/object_interfaces.h"
33#include CONFIG_DEVICES
34#ifdef CONFIG_PSERIES
35#include "hw/ppc/spapr_rtas.h"
36#endif
37
38#define MAX_IRQ 256
39
40#define TYPE_QTEST "qtest"
41
42OBJECT_DECLARE_SIMPLE_TYPE(QTest, QTEST)
43
44struct QTest {
45 Object parent;
46
47 bool has_machine_link;
48 char *chr_name;
49 Chardev *chr;
50 CharBackend qtest_chr;
51 char *log;
52};
53
54bool qtest_allowed;
55
56static DeviceState *irq_intercept_dev;
57static FILE *qtest_log_fp;
58static QTest *qtest;
59static GString *inbuf;
60static int irq_levels[MAX_IRQ];
61static GTimer *timer;
62static bool qtest_opened;
63static void (*qtest_server_send)(void*, const char*);
64static void *qtest_server_send_opaque;
65
66#define FMT_timeval "%.06f"
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
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254static int hex2nib(char ch)
255{
256 if (ch >= '0' && ch <= '9') {
257 return ch - '0';
258 } else if (ch >= 'a' && ch <= 'f') {
259 return 10 + (ch - 'a');
260 } else if (ch >= 'A' && ch <= 'F') {
261 return 10 + (ch - 'A');
262 } else {
263 return -1;
264 }
265}
266
267static void qtest_send_prefix(CharBackend *chr)
268{
269 if (!qtest_log_fp || !qtest_opened) {
270 return;
271 }
272
273 fprintf(qtest_log_fp, "[S +" FMT_timeval "] ", g_timer_elapsed(timer, NULL));
274}
275
276static void G_GNUC_PRINTF(1, 2) qtest_log_send(const char *fmt, ...)
277{
278 va_list ap;
279
280 if (!qtest_log_fp || !qtest_opened) {
281 return;
282 }
283
284 qtest_send_prefix(NULL);
285
286 va_start(ap, fmt);
287 vfprintf(qtest_log_fp, fmt, ap);
288 va_end(ap);
289}
290
291static void qtest_server_char_be_send(void *opaque, const char *str)
292{
293 size_t len = strlen(str);
294 CharBackend* chr = (CharBackend *)opaque;
295 qemu_chr_fe_write_all(chr, (uint8_t *)str, len);
296 if (qtest_log_fp && qtest_opened) {
297 fprintf(qtest_log_fp, "%s", str);
298 }
299}
300
301static void qtest_send(CharBackend *chr, const char *str)
302{
303 qtest_server_send(qtest_server_send_opaque, str);
304}
305
306static void G_GNUC_PRINTF(2, 3) qtest_sendf(CharBackend *chr,
307 const char *fmt, ...)
308{
309 va_list ap;
310 gchar *buffer;
311
312 va_start(ap, fmt);
313 buffer = g_strdup_vprintf(fmt, ap);
314 qtest_send(chr, buffer);
315 g_free(buffer);
316 va_end(ap);
317}
318
319static void qtest_irq_handler(void *opaque, int n, int level)
320{
321 qemu_irq old_irq = *(qemu_irq *)opaque;
322 qemu_set_irq(old_irq, level);
323
324 if (irq_levels[n] != level) {
325 CharBackend *chr = &qtest->qtest_chr;
326 irq_levels[n] = level;
327 qtest_send_prefix(chr);
328 qtest_sendf(chr, "IRQ %s %d\n",
329 level ? "raise" : "lower", n);
330 }
331}
332
333static int64_t qtest_clock_counter;
334
335int64_t qtest_get_virtual_clock(void)
336{
337 return qatomic_read_i64(&qtest_clock_counter);
338}
339
340static void qtest_set_virtual_clock(int64_t count)
341{
342 qatomic_set_i64(&qtest_clock_counter, count);
343}
344
345static void qtest_clock_warp(int64_t dest)
346{
347 int64_t clock = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
348 AioContext *aio_context;
349 assert(qtest_enabled());
350 aio_context = qemu_get_aio_context();
351 while (clock < dest) {
352 int64_t deadline = qemu_clock_deadline_ns_all(QEMU_CLOCK_VIRTUAL,
353 QEMU_TIMER_ATTR_ALL);
354 int64_t warp = qemu_soonest_timeout(dest - clock, deadline);
355
356 qtest_set_virtual_clock(qtest_get_virtual_clock() + warp);
357
358 qemu_clock_run_timers(QEMU_CLOCK_VIRTUAL);
359 timerlist_run_timers(aio_context->tlg.tl[QEMU_CLOCK_VIRTUAL]);
360 clock = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
361 }
362 qemu_clock_notify(QEMU_CLOCK_VIRTUAL);
363}
364
365static void qtest_process_command(CharBackend *chr, gchar **words)
366{
367 const gchar *command;
368
369 g_assert(words);
370
371 command = words[0];
372
373 if (qtest_log_fp) {
374 int i;
375
376 fprintf(qtest_log_fp, "[R +" FMT_timeval "]", g_timer_elapsed(timer, NULL));
377 for (i = 0; words[i]; i++) {
378 fprintf(qtest_log_fp, " %s", words[i]);
379 }
380 fprintf(qtest_log_fp, "\n");
381 }
382
383 g_assert(command);
384 if (strcmp(words[0], "irq_intercept_out") == 0
385 || strcmp(words[0], "irq_intercept_in") == 0) {
386 DeviceState *dev;
387 NamedGPIOList *ngl;
388
389 g_assert(words[1]);
390 dev = DEVICE(object_resolve_path(words[1], NULL));
391 if (!dev) {
392 qtest_send_prefix(chr);
393 qtest_send(chr, "FAIL Unknown device\n");
394 return;
395 }
396
397 if (irq_intercept_dev) {
398 qtest_send_prefix(chr);
399 if (irq_intercept_dev != dev) {
400 qtest_send(chr, "FAIL IRQ intercept already enabled\n");
401 } else {
402 qtest_send(chr, "OK\n");
403 }
404 return;
405 }
406
407 QLIST_FOREACH(ngl, &dev->gpios, node) {
408
409 if (ngl->name) {
410 continue;
411 }
412 if (words[0][14] == 'o') {
413 int i;
414 for (i = 0; i < ngl->num_out; ++i) {
415 qemu_irq *disconnected = g_new0(qemu_irq, 1);
416 qemu_irq icpt = qemu_allocate_irq(qtest_irq_handler,
417 disconnected, i);
418
419 *disconnected = qdev_intercept_gpio_out(dev, icpt,
420 ngl->name, i);
421 }
422 } else {
423 qemu_irq_intercept_in(ngl->in, qtest_irq_handler,
424 ngl->num_in);
425 }
426 }
427 irq_intercept_dev = dev;
428 qtest_send_prefix(chr);
429 qtest_send(chr, "OK\n");
430 } else if (strcmp(words[0], "set_irq_in") == 0) {
431 DeviceState *dev;
432 qemu_irq irq;
433 char *name;
434 int ret;
435 int num;
436 int level;
437
438 g_assert(words[1] && words[2] && words[3] && words[4]);
439
440 dev = DEVICE(object_resolve_path(words[1], NULL));
441 if (!dev) {
442 qtest_send_prefix(chr);
443 qtest_send(chr, "FAIL Unknown device\n");
444 return;
445 }
446
447 if (strcmp(words[2], "unnamed-gpio-in") == 0) {
448 name = NULL;
449 } else {
450 name = words[2];
451 }
452
453 ret = qemu_strtoi(words[3], NULL, 0, &num);
454 g_assert(!ret);
455 ret = qemu_strtoi(words[4], NULL, 0, &level);
456 g_assert(!ret);
457
458 irq = qdev_get_gpio_in_named(dev, name, num);
459
460 qemu_set_irq(irq, level);
461 qtest_send_prefix(chr);
462 qtest_send(chr, "OK\n");
463 } else if (strcmp(words[0], "outb") == 0 ||
464 strcmp(words[0], "outw") == 0 ||
465 strcmp(words[0], "outl") == 0) {
466 unsigned long addr;
467 unsigned long value;
468 int ret;
469
470 g_assert(words[1] && words[2]);
471 ret = qemu_strtoul(words[1], NULL, 0, &addr);
472 g_assert(ret == 0);
473 ret = qemu_strtoul(words[2], NULL, 0, &value);
474 g_assert(ret == 0);
475 g_assert(addr <= 0xffff);
476
477 if (words[0][3] == 'b') {
478 cpu_outb(addr, value);
479 } else if (words[0][3] == 'w') {
480 cpu_outw(addr, value);
481 } else if (words[0][3] == 'l') {
482 cpu_outl(addr, value);
483 }
484 qtest_send_prefix(chr);
485 qtest_send(chr, "OK\n");
486 } else if (strcmp(words[0], "inb") == 0 ||
487 strcmp(words[0], "inw") == 0 ||
488 strcmp(words[0], "inl") == 0) {
489 unsigned long addr;
490 uint32_t value = -1U;
491 int ret;
492
493 g_assert(words[1]);
494 ret = qemu_strtoul(words[1], NULL, 0, &addr);
495 g_assert(ret == 0);
496 g_assert(addr <= 0xffff);
497
498 if (words[0][2] == 'b') {
499 value = cpu_inb(addr);
500 } else if (words[0][2] == 'w') {
501 value = cpu_inw(addr);
502 } else if (words[0][2] == 'l') {
503 value = cpu_inl(addr);
504 }
505 qtest_send_prefix(chr);
506 qtest_sendf(chr, "OK 0x%04x\n", value);
507 } else if (strcmp(words[0], "writeb") == 0 ||
508 strcmp(words[0], "writew") == 0 ||
509 strcmp(words[0], "writel") == 0 ||
510 strcmp(words[0], "writeq") == 0) {
511 uint64_t addr;
512 uint64_t value;
513 int ret;
514
515 g_assert(words[1] && words[2]);
516 ret = qemu_strtou64(words[1], NULL, 0, &addr);
517 g_assert(ret == 0);
518 ret = qemu_strtou64(words[2], NULL, 0, &value);
519 g_assert(ret == 0);
520
521 if (words[0][5] == 'b') {
522 uint8_t data = value;
523 address_space_write(first_cpu->as, addr, MEMTXATTRS_UNSPECIFIED,
524 &data, 1);
525 } else if (words[0][5] == 'w') {
526 uint16_t data = value;
527 tswap16s(&data);
528 address_space_write(first_cpu->as, addr, MEMTXATTRS_UNSPECIFIED,
529 &data, 2);
530 } else if (words[0][5] == 'l') {
531 uint32_t data = value;
532 tswap32s(&data);
533 address_space_write(first_cpu->as, addr, MEMTXATTRS_UNSPECIFIED,
534 &data, 4);
535 } else if (words[0][5] == 'q') {
536 uint64_t data = value;
537 tswap64s(&data);
538 address_space_write(first_cpu->as, addr, MEMTXATTRS_UNSPECIFIED,
539 &data, 8);
540 }
541 qtest_send_prefix(chr);
542 qtest_send(chr, "OK\n");
543 } else if (strcmp(words[0], "readb") == 0 ||
544 strcmp(words[0], "readw") == 0 ||
545 strcmp(words[0], "readl") == 0 ||
546 strcmp(words[0], "readq") == 0) {
547 uint64_t addr;
548 uint64_t value = UINT64_C(-1);
549 int ret;
550
551 g_assert(words[1]);
552 ret = qemu_strtou64(words[1], NULL, 0, &addr);
553 g_assert(ret == 0);
554
555 if (words[0][4] == 'b') {
556 uint8_t data;
557 address_space_read(first_cpu->as, addr, MEMTXATTRS_UNSPECIFIED,
558 &data, 1);
559 value = data;
560 } else if (words[0][4] == 'w') {
561 uint16_t data;
562 address_space_read(first_cpu->as, addr, MEMTXATTRS_UNSPECIFIED,
563 &data, 2);
564 value = tswap16(data);
565 } else if (words[0][4] == 'l') {
566 uint32_t data;
567 address_space_read(first_cpu->as, addr, MEMTXATTRS_UNSPECIFIED,
568 &data, 4);
569 value = tswap32(data);
570 } else if (words[0][4] == 'q') {
571 address_space_read(first_cpu->as, addr, MEMTXATTRS_UNSPECIFIED,
572 &value, 8);
573 tswap64s(&value);
574 }
575 qtest_send_prefix(chr);
576 qtest_sendf(chr, "OK 0x%016" PRIx64 "\n", value);
577 } else if (strcmp(words[0], "read") == 0) {
578 uint64_t addr, len, i;
579 uint8_t *data;
580 char *enc;
581 int ret;
582
583 g_assert(words[1] && words[2]);
584 ret = qemu_strtou64(words[1], NULL, 0, &addr);
585 g_assert(ret == 0);
586 ret = qemu_strtou64(words[2], NULL, 0, &len);
587 g_assert(ret == 0);
588
589 g_assert(len);
590
591 data = g_malloc(len);
592 address_space_read(first_cpu->as, addr, MEMTXATTRS_UNSPECIFIED, data,
593 len);
594
595 enc = g_malloc(2 * len + 1);
596 for (i = 0; i < len; i++) {
597 sprintf(&enc[i * 2], "%02x", data[i]);
598 }
599
600 qtest_send_prefix(chr);
601 qtest_sendf(chr, "OK 0x%s\n", enc);
602
603 g_free(data);
604 g_free(enc);
605 } else if (strcmp(words[0], "b64read") == 0) {
606 uint64_t addr, len;
607 uint8_t *data;
608 gchar *b64_data;
609 int ret;
610
611 g_assert(words[1] && words[2]);
612 ret = qemu_strtou64(words[1], NULL, 0, &addr);
613 g_assert(ret == 0);
614 ret = qemu_strtou64(words[2], NULL, 0, &len);
615 g_assert(ret == 0);
616
617 data = g_malloc(len);
618 address_space_read(first_cpu->as, addr, MEMTXATTRS_UNSPECIFIED, data,
619 len);
620 b64_data = g_base64_encode(data, len);
621 qtest_send_prefix(chr);
622 qtest_sendf(chr, "OK %s\n", b64_data);
623
624 g_free(data);
625 g_free(b64_data);
626 } else if (strcmp(words[0], "write") == 0) {
627 uint64_t addr, len, i;
628 uint8_t *data;
629 size_t data_len;
630 int ret;
631
632 g_assert(words[1] && words[2] && words[3]);
633 ret = qemu_strtou64(words[1], NULL, 0, &addr);
634 g_assert(ret == 0);
635 ret = qemu_strtou64(words[2], NULL, 0, &len);
636 g_assert(ret == 0);
637
638 data_len = strlen(words[3]);
639 if (data_len < 3) {
640 qtest_send(chr, "ERR invalid argument size\n");
641 return;
642 }
643
644 data = g_malloc(len);
645 for (i = 0; i < len; i++) {
646 if ((i * 2 + 4) <= data_len) {
647 data[i] = hex2nib(words[3][i * 2 + 2]) << 4;
648 data[i] |= hex2nib(words[3][i * 2 + 3]);
649 } else {
650 data[i] = 0;
651 }
652 }
653 address_space_write(first_cpu->as, addr, MEMTXATTRS_UNSPECIFIED, data,
654 len);
655 g_free(data);
656
657 qtest_send_prefix(chr);
658 qtest_send(chr, "OK\n");
659 } else if (strcmp(words[0], "memset") == 0) {
660 uint64_t addr, len;
661 uint8_t *data;
662 unsigned long pattern;
663 int ret;
664
665 g_assert(words[1] && words[2] && words[3]);
666 ret = qemu_strtou64(words[1], NULL, 0, &addr);
667 g_assert(ret == 0);
668 ret = qemu_strtou64(words[2], NULL, 0, &len);
669 g_assert(ret == 0);
670 ret = qemu_strtoul(words[3], NULL, 0, &pattern);
671 g_assert(ret == 0);
672
673 if (len) {
674 data = g_malloc(len);
675 memset(data, pattern, len);
676 address_space_write(first_cpu->as, addr, MEMTXATTRS_UNSPECIFIED,
677 data, len);
678 g_free(data);
679 }
680
681 qtest_send_prefix(chr);
682 qtest_send(chr, "OK\n");
683 } else if (strcmp(words[0], "b64write") == 0) {
684 uint64_t addr, len;
685 uint8_t *data;
686 size_t data_len;
687 gsize out_len;
688 int ret;
689
690 g_assert(words[1] && words[2] && words[3]);
691 ret = qemu_strtou64(words[1], NULL, 0, &addr);
692 g_assert(ret == 0);
693 ret = qemu_strtou64(words[2], NULL, 0, &len);
694 g_assert(ret == 0);
695
696 data_len = strlen(words[3]);
697 if (data_len < 3) {
698 qtest_send(chr, "ERR invalid argument size\n");
699 return;
700 }
701
702 data = g_base64_decode_inplace(words[3], &out_len);
703 if (out_len != len) {
704 qtest_log_send("b64write: data length mismatch (told %"PRIu64", "
705 "found %zu)\n",
706 len, out_len);
707 out_len = MIN(out_len, len);
708 }
709
710 address_space_write(first_cpu->as, addr, MEMTXATTRS_UNSPECIFIED, data,
711 len);
712
713 qtest_send_prefix(chr);
714 qtest_send(chr, "OK\n");
715 } else if (strcmp(words[0], "endianness") == 0) {
716 qtest_send_prefix(chr);
717#if TARGET_BIG_ENDIAN
718 qtest_sendf(chr, "OK big\n");
719#else
720 qtest_sendf(chr, "OK little\n");
721#endif
722#ifdef CONFIG_PSERIES
723 } else if (strcmp(words[0], "rtas") == 0) {
724 uint64_t res, args, ret;
725 unsigned long nargs, nret;
726 int rc;
727
728 rc = qemu_strtoul(words[2], NULL, 0, &nargs);
729 g_assert(rc == 0);
730 rc = qemu_strtou64(words[3], NULL, 0, &args);
731 g_assert(rc == 0);
732 rc = qemu_strtoul(words[4], NULL, 0, &nret);
733 g_assert(rc == 0);
734 rc = qemu_strtou64(words[5], NULL, 0, &ret);
735 g_assert(rc == 0);
736 res = qtest_rtas_call(words[1], nargs, args, nret, ret);
737
738 qtest_send_prefix(chr);
739 qtest_sendf(chr, "OK %"PRIu64"\n", res);
740#endif
741 } else if (qtest_enabled() && strcmp(words[0], "clock_step") == 0) {
742 int64_t ns;
743
744 if (words[1]) {
745 int ret = qemu_strtoi64(words[1], NULL, 0, &ns);
746 g_assert(ret == 0);
747 } else {
748 ns = qemu_clock_deadline_ns_all(QEMU_CLOCK_VIRTUAL,
749 QEMU_TIMER_ATTR_ALL);
750 }
751 qtest_clock_warp(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + ns);
752 qtest_send_prefix(chr);
753 qtest_sendf(chr, "OK %"PRIi64"\n",
754 (int64_t)qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL));
755 } else if (strcmp(words[0], "module_load") == 0) {
756 g_assert(words[1] && words[2]);
757
758 qtest_send_prefix(chr);
759 if (module_load_one(words[1], words[2], false)) {
760 qtest_sendf(chr, "OK\n");
761 } else {
762 qtest_sendf(chr, "FAIL\n");
763 }
764 } else if (qtest_enabled() && strcmp(words[0], "clock_set") == 0) {
765 int64_t ns;
766 int ret;
767
768 g_assert(words[1]);
769 ret = qemu_strtoi64(words[1], NULL, 0, &ns);
770 g_assert(ret == 0);
771 qtest_clock_warp(ns);
772 qtest_send_prefix(chr);
773 qtest_sendf(chr, "OK %"PRIi64"\n",
774 (int64_t)qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL));
775 } else {
776 qtest_send_prefix(chr);
777 qtest_sendf(chr, "FAIL Unknown command '%s'\n", words[0]);
778 }
779}
780
781static void qtest_process_inbuf(CharBackend *chr, GString *inbuf)
782{
783 char *end;
784
785 while ((end = strchr(inbuf->str, '\n')) != NULL) {
786 size_t offset;
787 GString *cmd;
788 gchar **words;
789
790 offset = end - inbuf->str;
791
792 cmd = g_string_new_len(inbuf->str, offset);
793 g_string_erase(inbuf, 0, offset + 1);
794
795 words = g_strsplit(cmd->str, " ", 0);
796 qtest_process_command(chr, words);
797 g_strfreev(words);
798
799 g_string_free(cmd, TRUE);
800 }
801}
802
803static void qtest_read(void *opaque, const uint8_t *buf, int size)
804{
805 CharBackend *chr = opaque;
806
807 g_string_append_len(inbuf, (const gchar *)buf, size);
808 qtest_process_inbuf(chr, inbuf);
809}
810
811static int qtest_can_read(void *opaque)
812{
813 return 1024;
814}
815
816static void qtest_event(void *opaque, QEMUChrEvent event)
817{
818 int i;
819
820 switch (event) {
821 case CHR_EVENT_OPENED:
822
823
824
825
826
827
828 for (i = 0; i < ARRAY_SIZE(irq_levels); i++) {
829 irq_levels[i] = 0;
830 }
831
832 g_clear_pointer(&timer, g_timer_destroy);
833 timer = g_timer_new();
834 qtest_opened = true;
835 if (qtest_log_fp) {
836 fprintf(qtest_log_fp, "[I " FMT_timeval "] OPENED\n", g_timer_elapsed(timer, NULL));
837 }
838 break;
839 case CHR_EVENT_CLOSED:
840 qtest_opened = false;
841 if (qtest_log_fp) {
842 fprintf(qtest_log_fp, "[I +" FMT_timeval "] CLOSED\n", g_timer_elapsed(timer, NULL));
843 }
844 g_clear_pointer(&timer, g_timer_destroy);
845 break;
846 default:
847 break;
848 }
849}
850
851void qtest_server_init(const char *qtest_chrdev, const char *qtest_log, Error **errp)
852{
853 ERRP_GUARD();
854 Chardev *chr;
855 Object *qtest;
856
857 chr = qemu_chr_new("qtest", qtest_chrdev, NULL);
858 if (chr == NULL) {
859 error_setg(errp, "Failed to initialize device for qtest: \"%s\"",
860 qtest_chrdev);
861 return;
862 }
863
864 qtest = object_new(TYPE_QTEST);
865 object_property_set_str(qtest, "chardev", "qtest", &error_abort);
866 if (qtest_log) {
867 object_property_set_str(qtest, "log", qtest_log, &error_abort);
868 }
869 object_property_add_child(qdev_get_machine(), "qtest", qtest);
870 user_creatable_complete(USER_CREATABLE(qtest), errp);
871 if (*errp) {
872 object_unparent(qtest);
873 }
874 object_unref(OBJECT(chr));
875 object_unref(qtest);
876}
877
878static bool qtest_server_start(QTest *q, Error **errp)
879{
880 Chardev *chr = q->chr;
881 const char *qtest_log = q->log;
882
883 if (qtest_log) {
884 if (strcmp(qtest_log, "none") != 0) {
885 qtest_log_fp = fopen(qtest_log, "w+");
886 }
887 } else {
888 qtest_log_fp = stderr;
889 }
890
891 if (!qemu_chr_fe_init(&q->qtest_chr, chr, errp)) {
892 return false;
893 }
894 qemu_chr_fe_set_handlers(&q->qtest_chr, qtest_can_read, qtest_read,
895 qtest_event, NULL, &q->qtest_chr, NULL, true);
896 qemu_chr_fe_set_echo(&q->qtest_chr, true);
897
898 inbuf = g_string_new("");
899
900 if (!qtest_server_send) {
901 qtest_server_set_send_handler(qtest_server_char_be_send, &q->qtest_chr);
902 }
903 qtest = q;
904 return true;
905}
906
907void qtest_server_set_send_handler(void (*send)(void*, const char*),
908 void *opaque)
909{
910 qtest_server_send = send;
911 qtest_server_send_opaque = opaque;
912}
913
914bool qtest_driver(void)
915{
916 return qtest && qtest->qtest_chr.chr != NULL;
917}
918
919void qtest_server_inproc_recv(void *dummy, const char *buf)
920{
921 static GString *gstr;
922 if (!gstr) {
923 gstr = g_string_new(NULL);
924 }
925 g_string_append(gstr, buf);
926 if (gstr->str[gstr->len - 1] == '\n') {
927 qtest_process_inbuf(NULL, gstr);
928 g_string_truncate(gstr, 0);
929 }
930}
931
932static void qtest_complete(UserCreatable *uc, Error **errp)
933{
934 QTest *q = QTEST(uc);
935 if (qtest) {
936 error_setg(errp, "Only one instance of qtest can be created");
937 return;
938 }
939 if (!q->chr_name) {
940 error_setg(errp, "No backend specified");
941 return;
942 }
943
944 if (OBJECT(uc)->parent != qdev_get_machine()) {
945 q->has_machine_link = true;
946 object_property_add_const_link(qdev_get_machine(), "qtest", OBJECT(uc));
947 } else {
948
949 }
950
951 qtest_server_start(q, errp);
952}
953
954static void qtest_unparent(Object *obj)
955{
956 QTest *q = QTEST(obj);
957
958 if (qtest == q) {
959 qemu_chr_fe_disconnect(&q->qtest_chr);
960 assert(!qtest_opened);
961 qemu_chr_fe_deinit(&q->qtest_chr, false);
962 if (qtest_log_fp) {
963 fclose(qtest_log_fp);
964 qtest_log_fp = NULL;
965 }
966 qtest = NULL;
967 }
968
969 if (q->has_machine_link) {
970 object_property_del(qdev_get_machine(), "qtest");
971 q->has_machine_link = false;
972 }
973}
974
975static void qtest_set_log(Object *obj, const char *value, Error **errp)
976{
977 QTest *q = QTEST(obj);
978
979 if (qtest == q) {
980 error_setg(errp, QERR_PERMISSION_DENIED);
981 } else {
982 g_free(q->log);
983 q->log = g_strdup(value);
984 }
985}
986
987static char *qtest_get_log(Object *obj, Error **errp)
988{
989 QTest *q = QTEST(obj);
990
991 return g_strdup(q->log);
992}
993
994static void qtest_set_chardev(Object *obj, const char *value, Error **errp)
995{
996 QTest *q = QTEST(obj);
997 Chardev *chr;
998
999 if (qtest == q) {
1000 error_setg(errp, QERR_PERMISSION_DENIED);
1001 return;
1002 }
1003
1004 chr = qemu_chr_find(value);
1005 if (!chr) {
1006 error_setg(errp, "Cannot find character device '%s'", value);
1007 return;
1008 }
1009
1010 g_free(q->chr_name);
1011 q->chr_name = g_strdup(value);
1012
1013 if (q->chr) {
1014 object_unref(q->chr);
1015 }
1016 q->chr = chr;
1017 object_ref(chr);
1018}
1019
1020static char *qtest_get_chardev(Object *obj, Error **errp)
1021{
1022 QTest *q = QTEST(obj);
1023
1024 return g_strdup(q->chr_name);
1025}
1026
1027static void qtest_class_init(ObjectClass *oc, void *data)
1028{
1029 UserCreatableClass *ucc = USER_CREATABLE_CLASS(oc);
1030
1031 oc->unparent = qtest_unparent;
1032 ucc->complete = qtest_complete;
1033
1034 object_class_property_add_str(oc, "chardev",
1035 qtest_get_chardev, qtest_set_chardev);
1036 object_class_property_add_str(oc, "log",
1037 qtest_get_log, qtest_set_log);
1038}
1039
1040static const TypeInfo qtest_info = {
1041 .name = TYPE_QTEST,
1042 .parent = TYPE_OBJECT,
1043 .class_init = qtest_class_init,
1044 .instance_size = sizeof(QTest),
1045 .interfaces = (InterfaceInfo[]) {
1046 { TYPE_USER_CREATABLE },
1047 { }
1048 }
1049};
1050
1051static void register_types(void)
1052{
1053 type_register_static(&qtest_info);
1054}
1055
1056type_init(register_types);
1057