summaryrefslogtreecommitdiffstats
path: root/debug/risc-v-gsp-rm-vm/qemu/greeneye_trace.c
diff options
context:
space:
mode:
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.c128
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;
+}