1 /* 2 * Copyright (C) 2018, Emilio G. Cota <cota@braap.org> 3 * 4 * License: GNU GPL, version 2 or later. 5 * See the COPYING file in the top-level directory. 6 */ 7 #include <inttypes.h> 8 #include <assert.h> 9 #include <stdlib.h> 10 #include <string.h> 11 #include <unistd.h> 12 #include <stdio.h> 13 #include <glib.h> 14 15 #include <qemu-plugin.h> 16 17 QEMU_PLUGIN_EXPORT int qemu_plugin_version = QEMU_PLUGIN_VERSION; 18 19 static uint64_t mem_count; 20 static uint64_t io_count; 21 static bool do_inline; 22 static bool do_haddr; 23 static enum qemu_plugin_mem_rw rw = QEMU_PLUGIN_MEM_RW; 24 25 static void plugin_exit(qemu_plugin_id_t id, void *p) 26 { 27 g_autoptr(GString) out = g_string_new(""); 28 29 g_string_printf(out, "mem accesses: %" PRIu64 "\n", mem_count); 30 if (do_haddr) { 31 g_string_append_printf(out, "io accesses: %" PRIu64 "\n", io_count); 32 } 33 qemu_plugin_outs(out->str); 34 } 35 36 static void vcpu_mem(unsigned int cpu_index, qemu_plugin_meminfo_t meminfo, 37 uint64_t vaddr, void *udata) 38 { 39 if (do_haddr) { 40 struct qemu_plugin_hwaddr *hwaddr; 41 hwaddr = qemu_plugin_get_hwaddr(meminfo, vaddr); 42 if (qemu_plugin_hwaddr_is_io(hwaddr)) { 43 io_count++; 44 } else { 45 mem_count++; 46 } 47 } else { 48 mem_count++; 49 } 50 } 51 52 static void vcpu_tb_trans(qemu_plugin_id_t id, struct qemu_plugin_tb *tb) 53 { 54 size_t n = qemu_plugin_tb_n_insns(tb); 55 size_t i; 56 57 for (i = 0; i < n; i++) { 58 struct qemu_plugin_insn *insn = qemu_plugin_tb_get_insn(tb, i); 59 60 if (do_inline) { 61 qemu_plugin_register_vcpu_mem_inline(insn, rw, 62 QEMU_PLUGIN_INLINE_ADD_U64, 63 &mem_count, 1); 64 } else { 65 qemu_plugin_register_vcpu_mem_cb(insn, vcpu_mem, 66 QEMU_PLUGIN_CB_NO_REGS, 67 rw, NULL); 68 } 69 } 70 } 71 72 QEMU_PLUGIN_EXPORT int qemu_plugin_install(qemu_plugin_id_t id, 73 const qemu_info_t *info, 74 int argc, char **argv) 75 { 76 if (argc) { 77 if (argc >= 3) { 78 if (!strcmp(argv[2], "haddr")) { 79 do_haddr = true; 80 } 81 } 82 if (argc >= 2) { 83 const char *str = argv[1]; 84 85 if (!strcmp(str, "r")) { 86 rw = QEMU_PLUGIN_MEM_R; 87 } else if (!strcmp(str, "w")) { 88 rw = QEMU_PLUGIN_MEM_W; 89 } 90 } 91 if (!strcmp(argv[0], "inline")) { 92 do_inline = true; 93 } 94 } 95 96 qemu_plugin_register_vcpu_tb_trans_cb(id, vcpu_tb_trans); 97 qemu_plugin_register_atexit_cb(id, plugin_exit, NULL); 98 return 0; 99 } 100