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
148static int hex2nib(char ch)
149{
150 if (ch >= '0' && ch <= '9') {
151 return ch - '0';
152 } else if (ch >= 'a' && ch <= 'f') {
153 return 10 + (ch - 'a');
154 } else if (ch >= 'A' && ch <= 'F') {
155 return 10 + (ch - 'A');
156 } else {
157 return -1;
158 }
159}
160
161static void qtest_get_time(qemu_timeval *tv)
162{
163 qemu_gettimeofday(tv);
164 tv->tv_sec -= start_time.tv_sec;
165 tv->tv_usec -= start_time.tv_usec;
166 if (tv->tv_usec < 0) {
167 tv->tv_usec += 1000000;
168 tv->tv_sec -= 1;
169 }
170}
171
172static void qtest_send_prefix(CharDriverState *chr)
173{
174 qemu_timeval tv;
175
176 if (!qtest_log_fp || !qtest_opened) {
177 return;
178 }
179
180 qtest_get_time(&tv);
181 fprintf(qtest_log_fp, "[S +" FMT_timeval "] ",
182 (long) tv.tv_sec, (long) tv.tv_usec);
183}
184
185static void GCC_FMT_ATTR(2, 3) qtest_send(CharDriverState *chr,
186 const char *fmt, ...)
187{
188 va_list ap;
189 char buffer[1024];
190 size_t len;
191
192 va_start(ap, fmt);
193 len = vsnprintf(buffer, sizeof(buffer), fmt, ap);
194 va_end(ap);
195
196 qemu_chr_fe_write_all(chr, (uint8_t *)buffer, len);
197 if (qtest_log_fp && qtest_opened) {
198 fprintf(qtest_log_fp, "%s", buffer);
199 }
200}
201
202static void qtest_irq_handler(void *opaque, int n, int level)
203{
204 qemu_irq old_irq = *(qemu_irq *)opaque;
205 qemu_set_irq(old_irq, level);
206
207 if (irq_levels[n] != level) {
208 CharDriverState *chr = qtest_chr;
209 irq_levels[n] = level;
210 qtest_send_prefix(chr);
211 qtest_send(chr, "IRQ %s %d\n",
212 level ? "raise" : "lower", n);
213 }
214}
215
216static void qtest_process_command(CharDriverState *chr, gchar **words)
217{
218 const gchar *command;
219
220 g_assert(words);
221
222 command = words[0];
223
224 if (qtest_log_fp) {
225 qemu_timeval tv;
226 int i;
227
228 qtest_get_time(&tv);
229 fprintf(qtest_log_fp, "[R +" FMT_timeval "]",
230 (long) tv.tv_sec, (long) tv.tv_usec);
231 for (i = 0; words[i]; i++) {
232 fprintf(qtest_log_fp, " %s", words[i]);
233 }
234 fprintf(qtest_log_fp, "\n");
235 }
236
237 g_assert(command);
238 if (strcmp(words[0], "irq_intercept_out") == 0
239 || strcmp(words[0], "irq_intercept_in") == 0) {
240 DeviceState *dev;
241 NamedGPIOList *ngl;
242
243 g_assert(words[1]);
244 dev = DEVICE(object_resolve_path(words[1], NULL));
245 if (!dev) {
246 qtest_send_prefix(chr);
247 qtest_send(chr, "FAIL Unknown device\n");
248 return;
249 }
250
251 if (irq_intercept_dev) {
252 qtest_send_prefix(chr);
253 if (irq_intercept_dev != dev) {
254 qtest_send(chr, "FAIL IRQ intercept already enabled\n");
255 } else {
256 qtest_send(chr, "OK\n");
257 }
258 return;
259 }
260
261 QLIST_FOREACH(ngl, &dev->gpios, node) {
262
263 if (ngl->name) {
264 continue;
265 }
266 if (words[0][14] == 'o') {
267 int i;
268 for (i = 0; i < ngl->num_out; ++i) {
269 qemu_irq *disconnected = g_new0(qemu_irq, 1);
270 qemu_irq icpt = qemu_allocate_irq(qtest_irq_handler,
271 disconnected, i);
272
273 *disconnected = qdev_intercept_gpio_out(dev, icpt,
274 ngl->name, i);
275 }
276 } else {
277 qemu_irq_intercept_in(ngl->in, qtest_irq_handler,
278 ngl->num_in);
279 }
280 }
281 irq_intercept_dev = dev;
282 qtest_send_prefix(chr);
283 qtest_send(chr, "OK\n");
284
285 } else if (strcmp(words[0], "outb") == 0 ||
286 strcmp(words[0], "outw") == 0 ||
287 strcmp(words[0], "outl") == 0) {
288 uint16_t addr;
289 uint32_t value;
290
291 g_assert(words[1] && words[2]);
292 addr = strtoul(words[1], NULL, 0);
293 value = strtoul(words[2], NULL, 0);
294
295 if (words[0][3] == 'b') {
296 cpu_outb(addr, value);
297 } else if (words[0][3] == 'w') {
298 cpu_outw(addr, value);
299 } else if (words[0][3] == 'l') {
300 cpu_outl(addr, value);
301 }
302 qtest_send_prefix(chr);
303 qtest_send(chr, "OK\n");
304 } else if (strcmp(words[0], "inb") == 0 ||
305 strcmp(words[0], "inw") == 0 ||
306 strcmp(words[0], "inl") == 0) {
307 uint16_t addr;
308 uint32_t value = -1U;
309
310 g_assert(words[1]);
311 addr = strtoul(words[1], NULL, 0);
312
313 if (words[0][2] == 'b') {
314 value = cpu_inb(addr);
315 } else if (words[0][2] == 'w') {
316 value = cpu_inw(addr);
317 } else if (words[0][2] == 'l') {
318 value = cpu_inl(addr);
319 }
320 qtest_send_prefix(chr);
321 qtest_send(chr, "OK 0x%04x\n", value);
322 } else if (strcmp(words[0], "writeb") == 0 ||
323 strcmp(words[0], "writew") == 0 ||
324 strcmp(words[0], "writel") == 0 ||
325 strcmp(words[0], "writeq") == 0) {
326 uint64_t addr;
327 uint64_t value;
328
329 g_assert(words[1] && words[2]);
330 addr = strtoull(words[1], NULL, 0);
331 value = strtoull(words[2], NULL, 0);
332
333 if (words[0][5] == 'b') {
334 uint8_t data = value;
335 cpu_physical_memory_write(addr, &data, 1);
336 } else if (words[0][5] == 'w') {
337 uint16_t data = value;
338 tswap16s(&data);
339 cpu_physical_memory_write(addr, &data, 2);
340 } else if (words[0][5] == 'l') {
341 uint32_t data = value;
342 tswap32s(&data);
343 cpu_physical_memory_write(addr, &data, 4);
344 } else if (words[0][5] == 'q') {
345 uint64_t data = value;
346 tswap64s(&data);
347 cpu_physical_memory_write(addr, &data, 8);
348 }
349 qtest_send_prefix(chr);
350 qtest_send(chr, "OK\n");
351 } else if (strcmp(words[0], "readb") == 0 ||
352 strcmp(words[0], "readw") == 0 ||
353 strcmp(words[0], "readl") == 0 ||
354 strcmp(words[0], "readq") == 0) {
355 uint64_t addr;
356 uint64_t value = UINT64_C(-1);
357
358 g_assert(words[1]);
359 addr = strtoull(words[1], NULL, 0);
360
361 if (words[0][4] == 'b') {
362 uint8_t data;
363 cpu_physical_memory_read(addr, &data, 1);
364 value = data;
365 } else if (words[0][4] == 'w') {
366 uint16_t data;
367 cpu_physical_memory_read(addr, &data, 2);
368 value = tswap16(data);
369 } else if (words[0][4] == 'l') {
370 uint32_t data;
371 cpu_physical_memory_read(addr, &data, 4);
372 value = tswap32(data);
373 } else if (words[0][4] == 'q') {
374 cpu_physical_memory_read(addr, &value, 8);
375 tswap64s(&value);
376 }
377 qtest_send_prefix(chr);
378 qtest_send(chr, "OK 0x%016" PRIx64 "\n", value);
379 } else if (strcmp(words[0], "read") == 0) {
380 uint64_t addr, len, i;
381 uint8_t *data;
382
383 g_assert(words[1] && words[2]);
384 addr = strtoull(words[1], NULL, 0);
385 len = strtoull(words[2], NULL, 0);
386
387 data = g_malloc(len);
388 cpu_physical_memory_read(addr, data, len);
389
390 qtest_send_prefix(chr);
391 qtest_send(chr, "OK 0x");
392 for (i = 0; i < len; i++) {
393 qtest_send(chr, "%02x", data[i]);
394 }
395 qtest_send(chr, "\n");
396
397 g_free(data);
398 } else if (strcmp(words[0], "write") == 0) {
399 uint64_t addr, len, i;
400 uint8_t *data;
401 size_t data_len;
402
403 g_assert(words[1] && words[2] && words[3]);
404 addr = strtoull(words[1], NULL, 0);
405 len = strtoull(words[2], NULL, 0);
406
407 data_len = strlen(words[3]);
408 if (data_len < 3) {
409 qtest_send(chr, "ERR invalid argument size\n");
410 return;
411 }
412
413 data = g_malloc(len);
414 for (i = 0; i < len; i++) {
415 if ((i * 2 + 4) <= data_len) {
416 data[i] = hex2nib(words[3][i * 2 + 2]) << 4;
417 data[i] |= hex2nib(words[3][i * 2 + 3]);
418 } else {
419 data[i] = 0;
420 }
421 }
422 cpu_physical_memory_write(addr, data, len);
423 g_free(data);
424
425 qtest_send_prefix(chr);
426 qtest_send(chr, "OK\n");
427 } else if (qtest_enabled() && strcmp(words[0], "clock_step") == 0) {
428 int64_t ns;
429
430 if (words[1]) {
431 ns = strtoll(words[1], NULL, 0);
432 } else {
433 ns = qemu_clock_deadline_ns_all(QEMU_CLOCK_VIRTUAL);
434 }
435 qtest_clock_warp(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + ns);
436 qtest_send_prefix(chr);
437 qtest_send(chr, "OK %"PRIi64"\n", (int64_t)qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL));
438 } else if (qtest_enabled() && strcmp(words[0], "clock_set") == 0) {
439 int64_t ns;
440
441 g_assert(words[1]);
442 ns = strtoll(words[1], NULL, 0);
443 qtest_clock_warp(ns);
444 qtest_send_prefix(chr);
445 qtest_send(chr, "OK %"PRIi64"\n", (int64_t)qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL));
446 } else {
447 qtest_send_prefix(chr);
448 qtest_send(chr, "FAIL Unknown command `%s'\n", words[0]);
449 }
450}
451
452static void qtest_process_inbuf(CharDriverState *chr, GString *inbuf)
453{
454 char *end;
455
456 while ((end = strchr(inbuf->str, '\n')) != NULL) {
457 size_t offset;
458 GString *cmd;
459 gchar **words;
460
461 offset = end - inbuf->str;
462
463 cmd = g_string_new_len(inbuf->str, offset);
464 g_string_erase(inbuf, 0, offset + 1);
465
466 words = g_strsplit(cmd->str, " ", 0);
467 qtest_process_command(chr, words);
468 g_strfreev(words);
469
470 g_string_free(cmd, TRUE);
471 }
472}
473
474static void qtest_read(void *opaque, const uint8_t *buf, int size)
475{
476 CharDriverState *chr = opaque;
477
478 g_string_append_len(inbuf, (const gchar *)buf, size);
479 qtest_process_inbuf(chr, inbuf);
480}
481
482static int qtest_can_read(void *opaque)
483{
484 return 1024;
485}
486
487static void qtest_event(void *opaque, int event)
488{
489 int i;
490
491 switch (event) {
492 case CHR_EVENT_OPENED:
493
494
495
496
497
498
499 for (i = 0; i < ARRAY_SIZE(irq_levels); i++) {
500 irq_levels[i] = 0;
501 }
502 qemu_gettimeofday(&start_time);
503 qtest_opened = true;
504 if (qtest_log_fp) {
505 fprintf(qtest_log_fp, "[I " FMT_timeval "] OPENED\n",
506 (long) start_time.tv_sec, (long) start_time.tv_usec);
507 }
508 break;
509 case CHR_EVENT_CLOSED:
510 qtest_opened = false;
511 if (qtest_log_fp) {
512 qemu_timeval tv;
513 qtest_get_time(&tv);
514 fprintf(qtest_log_fp, "[I +" FMT_timeval "] CLOSED\n",
515 (long) tv.tv_sec, (long) tv.tv_usec);
516 }
517 break;
518 default:
519 break;
520 }
521}
522
523static void configure_qtest_icount(const char *options)
524{
525 QemuOpts *opts = qemu_opts_parse(qemu_find_opts("icount"), options, 1);
526 configure_icount(opts, &error_abort);
527 qemu_opts_del(opts);
528}
529
530static int qtest_init_accel(MachineState *ms)
531{
532 configure_qtest_icount("0");
533 return 0;
534}
535
536void qtest_init(const char *qtest_chrdev, const char *qtest_log, Error **errp)
537{
538 CharDriverState *chr;
539
540 chr = qemu_chr_new("qtest", qtest_chrdev, NULL);
541
542 if (chr == NULL) {
543 error_setg(errp, "Failed to initialize device for qtest: \"%s\"",
544 qtest_chrdev);
545 return;
546 }
547
548 if (qtest_log) {
549 if (strcmp(qtest_log, "none") != 0) {
550 qtest_log_fp = fopen(qtest_log, "w+");
551 }
552 } else {
553 qtest_log_fp = stderr;
554 }
555
556 qemu_chr_add_handlers(chr, qtest_can_read, qtest_read, qtest_event, chr);
557 qemu_chr_fe_set_echo(chr, true);
558
559 inbuf = g_string_new("");
560 qtest_chr = chr;
561}
562
563bool qtest_driver(void)
564{
565 return qtest_chr;
566}
567
568static void qtest_accel_class_init(ObjectClass *oc, void *data)
569{
570 AccelClass *ac = ACCEL_CLASS(oc);
571 ac->name = "QTest";
572 ac->available = qtest_available;
573 ac->init_machine = qtest_init_accel;
574 ac->allowed = &qtest_allowed;
575}
576
577#define TYPE_QTEST_ACCEL ACCEL_CLASS_NAME("qtest")
578
579static const TypeInfo qtest_accel_type = {
580 .name = TYPE_QTEST_ACCEL,
581 .parent = TYPE_ACCEL,
582 .class_init = qtest_accel_class_init,
583};
584
585static void qtest_type_init(void)
586{
587 type_register_static(&qtest_accel_type);
588}
589
590type_init(qtest_type_init);
591