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