1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20#include "qemu/osdep.h"
21
22#include <unistd.h>
23#ifndef _WIN32
24#include <sys/socket.h>
25#include <qemu/sockets.h>
26#include <sys/un.h>
27#endif
28
29#include "qemu-common.h"
30#include "qemu/etrace.h"
31#include "qemu/timer.h"
32#include "exec/memory.h"
33#include "exec/address-spaces.h"
34#include "cpu.h"
35#include "exec/exec-all.h"
36
37
38#define ETRACE_VERSION_MAJOR 0
39#define ETRACE_VERSION_MINOR 0
40
41enum {
42 TYPE_EXEC = 1,
43 TYPE_TB = 2,
44 TYPE_NOTE = 3,
45 TYPE_MEM = 4,
46 TYPE_ARCH = 5,
47 TYPE_BARRIER = 6,
48 TYPE_OLD_EVENT_U64 = 7,
49 TYPE_EVENT_U64 = 8,
50 TYPE_INFO = 0x4554,
51};
52
53struct etrace_hdr {
54 uint16_t type;
55 uint16_t unit_id;
56 uint32_t len;
57} QEMU_PACKED;
58
59enum etrace_info_flags {
60 ETRACE_INFO_F_TB_CHAINING = (1 << 0),
61};
62
63struct etrace_info_data {
64 uint64_t attr;
65 struct {
66 uint16_t major;
67 uint16_t minor;
68 } version;
69} QEMU_PACKED;
70
71struct etrace_arch {
72 struct {
73 uint32_t arch_id;
74 uint8_t arch_bits;
75 uint8_t big_endian;
76 } guest, host;
77} QEMU_PACKED;
78
79struct etrace_exec {
80 uint64_t start_time;
81} QEMU_PACKED;
82
83struct etrace_note {
84 uint64_t time;
85} QEMU_PACKED;
86
87struct etrace_mem {
88 uint64_t time;
89 uint64_t vaddr;
90 uint64_t paddr;
91 uint64_t value;
92 uint32_t attr;
93 uint8_t size;
94 uint8_t padd[3];
95} QEMU_PACKED;
96
97struct etrace_tb {
98 uint64_t vaddr;
99 uint64_t paddr;
100 uint64_t host_addr;
101 uint32_t guest_code_len;
102 uint32_t host_code_len;
103} QEMU_PACKED;
104
105struct etrace_event_u64 {
106 uint32_t flags;
107 uint16_t unit_id;
108 uint16_t __reserved;
109 uint64_t time;
110 uint64_t val;
111 uint64_t prev_val;
112 uint16_t dev_name_len;
113 uint16_t event_name_len;
114} QEMU_PACKED;
115
116const char *qemu_arg_etrace;
117const char *qemu_arg_etrace_flags;
118struct etracer qemu_etracer = {0};
119bool qemu_etrace_enabled;
120
121void qemu_etrace_cleanup(void)
122{
123 etrace_close(&qemu_etracer);
124}
125
126struct {
127 const char *name;
128 enum qemu_etrace_flag flags;
129} qemu_etrace_flagmap[] = {
130 { "none", ETRACE_F_NONE },
131 { "exec", ETRACE_F_EXEC },
132 { "disas", ETRACE_F_TRANSLATION },
133 { "mem", ETRACE_F_MEM },
134 { "cpu", ETRACE_F_CPU },
135 { "gpio", ETRACE_F_GPIO },
136 { "all", ~0 },
137 { NULL, 0 },
138};
139
140static uint64_t qemu_etrace_str2flags(const char *str, size_t len)
141{
142 uint64_t flags = 0;
143 unsigned int pos = 0;
144
145 while (qemu_etrace_flagmap[pos].name) {
146 if (len != strlen(qemu_etrace_flagmap[pos].name)) {
147 pos++;
148 continue;
149 }
150
151 if (!memcmp(qemu_etrace_flagmap[pos].name, str, len)) {
152 flags |= qemu_etrace_flagmap[pos].flags;
153 break;
154 }
155 pos++;
156 }
157 if (!flags) {
158 fprintf(stderr, "Invalid etrace flag %s\n", str);
159 exit(EXIT_FAILURE);
160 }
161 return flags;
162}
163
164static uint64_t qemu_etrace_opts2flags(const char *opts)
165{
166 uint64_t flags = 0;
167 const char *prev = opts, *end = opts;
168
169 while (prev && *prev) {
170 while (*end != ',' && *end != 0) {
171 end++;
172 }
173 flags |= qemu_etrace_str2flags(prev, end - prev);
174 while (*end == ',') {
175 end++;
176 }
177 prev = end;
178 }
179 return flags;
180}
181
182static void etrace_write(struct etracer *t, const void *buf, size_t len)
183{
184 size_t r;
185
186 r = fwrite(buf, 1, len, t->fp);
187 if (feof(t->fp) || ferror(t->fp)) {
188 fprintf(stderr, "Etrace peer EOF/disconnected!\n");
189
190 fclose(t->fp);
191 t->fp = NULL;
192 exit(1);
193 }
194
195 assert(r == len);
196}
197
198static void etrace_write_header(struct etracer *t, uint16_t type,
199 uint16_t unit_id, uint32_t len)
200{
201 struct etrace_hdr hdr = {
202 .type = type,
203 .unit_id = unit_id,
204 .len = len
205 };
206 etrace_write(t, &hdr, sizeof hdr);
207}
208
209#define UNIX_PREFIX "unix:"
210
211static int sk_unix_client(const char *descr)
212{
213#ifndef _WIN32
214 struct sockaddr_un addr;
215 int fd, nfd;
216
217 fd = socket(AF_UNIX, SOCK_STREAM, 0);
218 printf("connect to %s\n", descr + strlen(UNIX_PREFIX));
219
220 memset(&addr, 0, sizeof addr);
221 addr.sun_family = AF_UNIX;
222 strncpy(addr.sun_path, descr + strlen(UNIX_PREFIX),
223 sizeof addr.sun_path);
224 if (connect(fd, (struct sockaddr *)&addr, sizeof(addr)) >= 0) {
225 return fd;
226 }
227
228 printf("Failed to connect to %s, attempt to listen\n", addr.sun_path);
229 unlink(addr.sun_path);
230
231 if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
232 goto fail;
233 }
234
235 listen(fd, 5);
236 nfd = accept(fd, NULL, NULL);
237 close(fd);
238 return nfd;
239fail:
240 close(fd);
241#endif
242 return -1;
243}
244
245static FILE *etrace_open(const char *descr)
246{
247 FILE *fp = NULL;
248 int fd = -1;
249
250 if (descr == NULL) {
251 return NULL;
252 }
253
254 if (memcmp(UNIX_PREFIX, descr, strlen(UNIX_PREFIX)) == 0) {
255
256 fd = sk_unix_client(descr);
257 fp = fdopen(fd, "w");
258 } else {
259 fp = fopen(descr, "w");
260 }
261 return fp;
262}
263
264
265
266
267
268
269bool etrace_init(struct etracer *t, const char *filename,
270 const char *opts,
271 unsigned int arch_id, unsigned int arch_bits)
272{
273 struct etrace_info_data id;
274 struct etrace_arch arch;
275
276 memset(t, 0, sizeof *t);
277 t->fp = etrace_open(filename);
278 if (!t->fp) {
279 return false;
280 }
281
282 memset(&id, 0, sizeof id);
283 id.version.major = ETRACE_VERSION_MAJOR;
284 id.version.minor = ETRACE_VERSION_MINOR;
285 id.attr = 0;
286 if (tcg_tb_chain) {
287 id.attr |= ETRACE_INFO_F_TB_CHAINING;
288 }
289 etrace_write_header(t, TYPE_INFO, 0, sizeof id);
290 etrace_write(t, &id, sizeof id);
291
292
293
294 arch.guest.arch_id = arch_id;
295 t->arch_bits = arch.guest.arch_bits = arch_bits;
296#ifdef TARGET_WORDS_BIGENDIAN
297 arch.guest.big_endian = 1;
298#endif
299 etrace_write_header(t, TYPE_ARCH, 0, sizeof arch);
300 etrace_write(t, &arch, sizeof arch);
301
302 t->flags = qemu_etrace_opts2flags(opts);
303 return true;
304}
305
306static void etrace_flush_exec_cache(struct etracer *t)
307{
308 size_t size64 = t->exec_cache.pos * sizeof t->exec_cache.t64[0];
309 size_t size32 = t->exec_cache.pos * sizeof t->exec_cache.t32[0];
310 size_t size = t->arch_bits == 32 ? size32 : size64;
311 struct etrace_exec ex;
312
313 if (!size) {
314 return;
315 }
316
317 ex.start_time = t->exec_cache.start_time;
318
319 etrace_write_header(t, TYPE_EXEC, t->exec_cache.unit_id, size + sizeof ex);
320 etrace_write(t, &ex, sizeof ex);
321 etrace_write(t, &t->exec_cache.t64[0], size);
322 t->exec_cache.pos = 0;
323 memset(&t->exec_cache.t64[0], 0, sizeof t->exec_cache.t64);
324
325
326
327 etrace_write_header(t, TYPE_BARRIER, t->exec_cache.unit_id, 0);
328}
329
330#define PROXIMITY_MASK (~0xfff)
331
332
333
334static bool address_near(uint64_t a, uint64_t b)
335{
336 a &= PROXIMITY_MASK;
337 b &= PROXIMITY_MASK;
338 return a == b;
339}
340
341static bool qualify_merge(uint64_t start, uint64_t end,
342 uint64_t new_start, uint64_t new_end)
343{
344 if (end != new_start) {
345 return false;
346 }
347
348 if (start == end || new_start == new_end) {
349 return false;
350 }
351
352 if (!address_near(start, end)) {
353 return false;
354 }
355 if (!address_near(new_start, new_end)) {
356 return false;
357 }
358
359 return true;
360}
361
362
363#define XC_ACCESSOR(field) \
364static inline void execache_set_ ## field(struct etracer *t, \
365 unsigned int pos, uint64_t v) \
366{ \
367 if (t->arch_bits == 32) { \
368 t->exec_cache.t32[pos].field = v; \
369 } else { \
370 t->exec_cache.t64[pos].field = v; \
371 } \
372} \
373static inline uint64_t execache_get_ ## field(struct etracer *t, \
374 unsigned int pos) \
375{ \
376 if (t->arch_bits == 32) { \
377 return t->exec_cache.t32[pos].field; \
378 } else { \
379 return t->exec_cache.t64[pos].field; \
380 } \
381}
382
383XC_ACCESSOR(start)
384XC_ACCESSOR(end)
385XC_ACCESSOR(duration)
386
387
388
389
390
391
392
393void etrace_dump_exec(struct etracer *t, unsigned int unit_id,
394 uint64_t start, uint64_t end,
395 uint64_t start_time, uint32_t duration)
396{
397 unsigned int pos;
398
399 if (unit_id != t->exec_cache.unit_id) {
400 etrace_flush_exec_cache(t);
401 t->exec_cache.unit_id = unit_id;
402 }
403
404 pos = t->exec_cache.pos;
405 if (pos == 0) {
406 t->exec_cache.start_time = start_time;
407 }
408
409 assert(t->arch_bits == 32 || t->arch_bits == 64);
410 if (pos &&
411 qualify_merge(execache_get_start(t, pos), execache_get_end(t, pos),
412 start, end)) {
413
414 pos -= 1;
415 execache_set_duration(t, pos, execache_get_duration(t, pos) + duration);
416 } else {
417
418 t->exec_cache.pos += 1;
419 execache_set_start(t, pos, start);
420 execache_set_duration(t, pos, duration);
421 }
422
423 execache_set_end(t, pos, end);
424 if (!tcg_tb_chain) {
425 assert(execache_get_start(t, pos) <= execache_get_end(t, pos));
426 }
427
428 if (t->exec_cache.pos == EXEC_CACHE_SIZE) {
429 etrace_flush_exec_cache(t);
430 }
431}
432
433static void etrace_dump_guestmem(struct etracer *t, AddressSpace *as,
434 uint64_t guest_vaddr, uint64_t guest_paddr,
435 size_t guest_len)
436{
437#if defined(CONFIG_USER_ONLY)
438
439 etrace_write(t, (void *) (uintptr_t) guest_vaddr, guest_len);
440#else
441 unsigned char buf[8 * 1024];
442
443
444
445 if (as == NULL) {
446 as = &address_space_memory;
447 }
448
449
450
451 while (guest_len) {
452 unsigned int copylen = guest_len > sizeof buf ? sizeof buf : guest_len;
453
454 address_space_rw(as, guest_paddr, MEMTXATTRS_UNSPECIFIED, buf, copylen, 0);
455 etrace_write(t, buf, copylen);
456 guest_len -= copylen;
457 }
458#endif
459}
460
461
462
463
464
465
466
467
468
469
470void etrace_dump_tb(struct etracer *t, AddressSpace *as, uint16_t unit_id,
471 uint64_t guest_vaddr, uint64_t guest_paddr,
472 size_t guest_len,
473 void *host_buf, size_t host_len)
474{
475 struct etrace_tb tb;
476 size_t size;
477
478 tb.vaddr = guest_vaddr;
479 tb.paddr = guest_paddr;
480 tb.host_addr = (intptr_t) host_buf;
481 tb.guest_code_len = guest_len;
482 tb.host_code_len = host_len;
483
484 size = sizeof tb + guest_len + host_len;
485
486 etrace_write_header(t, TYPE_TB, unit_id, size);
487 etrace_write(t, &tb, sizeof tb);
488
489 etrace_dump_guestmem(t, as, guest_vaddr, guest_paddr, guest_len);
490
491 etrace_write(t, host_buf, host_len);
492}
493
494static uint64_t etrace_time(void)
495{
496#if defined(CONFIG_USER_ONLY)
497 return 0;
498#else
499 uint64_t t;
500 CPUState *cpu = current_cpu;
501
502 if (cpu) {
503 void *tb = cpu->current_tb;
504
505
506
507 cpu->current_tb = NULL;
508 t = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
509 cpu->current_tb = tb;
510 } else {
511 t = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
512 }
513 return t;
514#endif
515}
516
517void etrace_mem_access(struct etracer *t, uint16_t unit_id,
518 uint64_t guest_vaddr, uint64_t guest_paddr,
519 size_t size, uint64_t attr, uint64_t val)
520{
521 struct etrace_mem mem;
522
523 etrace_flush_exec_cache(t);
524 mem.time = etrace_time();
525 mem.vaddr = guest_vaddr;
526 mem.paddr = guest_paddr;
527 mem.attr = attr;
528 mem.size = size;
529 mem.value = val;
530
531
532 etrace_write_header(t, TYPE_MEM, unit_id, sizeof mem);
533 etrace_write(t, &mem, sizeof mem);
534}
535
536void etrace_dump_exec_start(struct etracer *t,
537 unsigned int unit_id,
538 uint64_t start)
539{
540 assert(!t->exec_start_valid);
541 t->exec_start = start;
542 t->exec_start_time = etrace_time();
543 t->exec_start_valid = true;
544}
545
546void etrace_dump_exec_end(struct etracer *t,
547 unsigned int unit_id,
548 uint64_t end)
549{
550 int64_t tdiff;
551 if (!t->exec_start_valid) {
552 printf("exec_start not valid! %" PRIx64 " %" PRIx64 "\n", t->exec_start, end);
553 }
554 tdiff = etrace_time() - t->exec_start_time;
555 if (tdiff < 0) {
556 printf("tdiff=%" PRId64 "\n", tdiff);
557 fflush(NULL);
558 }
559 assert(tdiff >= 0);
560 assert(t->exec_start_valid);
561 t->exec_start_valid = false;
562 etrace_dump_exec(t, unit_id, t->exec_start, end, t->exec_start_time, tdiff);
563}
564
565void etrace_note_write(struct etracer *t, unsigned int unit_id,
566 void *buf, size_t len)
567{
568 struct etrace_note nt;
569
570 etrace_flush_exec_cache(t);
571
572 nt.time = etrace_time();
573 etrace_write_header(t, TYPE_NOTE, unit_id, sizeof nt + len);
574 etrace_write(t, &nt, sizeof nt);
575 etrace_write(t, buf, len);
576}
577
578int etrace_note_fprintf(FILE *fp,
579 const char *fmt, ...)
580{
581 struct etracer *t = (void *) fp;
582 va_list ap;
583 char *s;
584 int r;
585
586 va_start(ap, fmt);
587 r = vasprintf(&s, fmt, ap);
588 if (r > 0) {
589 etrace_note_write(t, t->current_unit_id, s, r);
590 }
591 va_end(ap);
592 return r;
593}
594
595void etrace_event_u64(struct etracer *t, uint16_t unit_id,
596 uint32_t flags,
597 const char *dev_name,
598 const char *event_name,
599 uint64_t val, uint64_t prev_val)
600{
601 struct etrace_event_u64 event;
602 size_t dev_len, event_len;
603
604 etrace_flush_exec_cache(t);
605
606 dev_len = strlen(dev_name) + 1;
607 event_len = strlen(event_name) + 1;
608
609 event.time = etrace_time();
610 event.flags = flags;
611 event.unit_id = unit_id;
612 event.dev_name_len = dev_len;
613 event.event_name_len = event_len;
614 event.val = val;
615 event.prev_val = prev_val;
616 etrace_write_header(t, TYPE_EVENT_U64, unit_id,
617 sizeof event + dev_len + event_len);
618 etrace_write(t, &event, sizeof event);
619 etrace_write(t, dev_name, dev_len);
620 etrace_write(t, event_name, event_len);
621}
622
623void etrace_close(struct etracer *t)
624{
625 if (t->fp) {
626 etrace_flush_exec_cache(t);
627 fclose(t->fp);
628 }
629}
630