diff options
Diffstat (limited to 'debug/risc-v-gsp-rm-vm/qemu/greeneye_trace.c')
| -rw-r--r-- | debug/risc-v-gsp-rm-vm/qemu/greeneye_trace.c | 128 |
1 files changed, 128 insertions, 0 deletions
diff --git a/debug/risc-v-gsp-rm-vm/qemu/greeneye_trace.c b/debug/risc-v-gsp-rm-vm/qemu/greeneye_trace.c new file mode 100644 index 0000000..a20748a --- /dev/null +++ b/debug/risc-v-gsp-rm-vm/qemu/greeneye_trace.c @@ -0,0 +1,128 @@ +/* + * green-eye TCG trace plugin - full instruction/memory activity recording. + * + * This is the "complete map" upgrade from stop-based observation: QEMU calls + * the plugin for every translated instruction and every memory access. Output + * is JSONL (one object per line), ready to be folded into a green-eye session: + * + * {"t":"exec","vcpu":0,"pc":"0x80000194"} + * {"t":"write","vcpu":0,"addr":"0x80000850","size":8} + * {"t":"read","vcpu":0,"addr":"0x10000005","size":1} + * {"t":"summary","insns":12345,"mem":678} + * + * Arguments (all optional): + * path=FILE output file (default greeneye-trace.jsonl) + * exec=on|off record instruction execution (default off; heavy) + * start=0xADDR only instrument PCs >= start + * end=0xADDR only instrument PCs <= end + * + * Build: make -C qemu (needs qemu-plugin.h, vendored here) + * Run: qemu-system-riscv64 ... \ + * -plugin qemu/greeneye-trace.so,path=/tmp/ge-trace.jsonl,exec=on + * + * License: GPL-2.0-or-later (matches QEMU's plugin API header). + */ +#include <inttypes.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <qemu-plugin.h> + +QEMU_PLUGIN_EXPORT int qemu_plugin_version = QEMU_PLUGIN_VERSION; + +static FILE *trace_fp; +static bool trace_exec; +static uint64_t start_pc; +static uint64_t end_pc; +static uint64_t insn_count; +static uint64_t mem_count; + +static void vcpu_insn_exec(unsigned int vcpu_index, void *userdata) +{ + uint64_t pc = (uint64_t)(uintptr_t)userdata; + insn_count++; + fprintf(trace_fp, "{\"t\":\"exec\",\"vcpu\":%u,\"pc\":\"0x%" PRIx64 "\"}\n", + vcpu_index, pc); +} + +static void vcpu_mem(unsigned int vcpu_index, qemu_plugin_meminfo_t info, + uint64_t vaddr, void *userdata) +{ + bool is_store = qemu_plugin_mem_is_store(info); + unsigned int shift = qemu_plugin_mem_size_shift(info); + (void)userdata; + mem_count++; + fprintf(trace_fp, + "{\"t\":\"%s\",\"vcpu\":%u,\"addr\":\"0x%" PRIx64 "\",\"size\":%u}\n", + is_store ? "write" : "read", vcpu_index, vaddr, 1u << shift); +} + +static void vcpu_tb_trans(qemu_plugin_id_t id, struct qemu_plugin_tb *tb) +{ + size_t n = qemu_plugin_tb_n_insns(tb); + (void)id; + for (size_t i = 0; i < n; i++) { + struct qemu_plugin_insn *insn = qemu_plugin_tb_get_insn(tb, i); + uint64_t pc = qemu_plugin_insn_vaddr(insn); + if (start_pc && pc < start_pc) { + continue; + } + if (end_pc && pc > end_pc) { + continue; + } + if (trace_exec) { + qemu_plugin_register_vcpu_insn_exec_cb( + insn, vcpu_insn_exec, QEMU_PLUGIN_CB_NO_REGS, + (void *)(uintptr_t)pc); + } + qemu_plugin_register_vcpu_mem_cb(insn, vcpu_mem, QEMU_PLUGIN_CB_NO_REGS, + QEMU_PLUGIN_MEM_RW, NULL); + } +} + +static void plugin_exit(qemu_plugin_id_t id, void *userdata) +{ + (void)id; + (void)userdata; + if (trace_fp) { + fprintf(trace_fp, + "{\"t\":\"summary\",\"insns\":%" PRIu64 ",\"mem\":%" PRIu64 "}\n", + insn_count, mem_count); + fclose(trace_fp); + trace_fp = NULL; + } + qemu_plugin_outs("green-eye trace complete\n"); +} + +QEMU_PLUGIN_EXPORT int qemu_plugin_install(qemu_plugin_id_t id, + const qemu_info_t *info, int argc, + char **argv) +{ + const char *path = "greeneye-trace.jsonl"; + (void)info; + + for (int i = 0; i < argc; i++) { + if (strncmp(argv[i], "path=", 5) == 0) { + path = argv[i] + 5; + } else if (strncmp(argv[i], "exec=", 5) == 0) { + trace_exec = strcmp(argv[i] + 5, "on") == 0 + || strcmp(argv[i] + 5, "true") == 0; + } else if (strncmp(argv[i], "start=", 6) == 0) { + start_pc = strtoull(argv[i] + 6, NULL, 0); + } else if (strncmp(argv[i], "end=", 4) == 0) { + end_pc = strtoull(argv[i] + 4, NULL, 0); + } + } + + trace_fp = fopen(path, "w"); + if (!trace_fp) { + qemu_plugin_outs("green-eye: cannot open trace output\n"); + return -1; + } + qemu_plugin_register_vcpu_tb_trans_cb(id, vcpu_tb_trans); + qemu_plugin_register_atexit_cb(id, plugin_exit, NULL); + qemu_plugin_outs("green-eye trace plugin armed\n"); + return 0; +} |
