qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

mem.c (4038B)


      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 inline_mem_count;
     20 static uint64_t cb_mem_count;
     21 static uint64_t io_count;
     22 static bool do_inline, do_callback;
     23 static bool do_haddr;
     24 static enum qemu_plugin_mem_rw rw = QEMU_PLUGIN_MEM_RW;
     25 
     26 static void plugin_exit(qemu_plugin_id_t id, void *p)
     27 {
     28     g_autoptr(GString) out = g_string_new("");
     29 
     30     if (do_inline) {
     31         g_string_printf(out, "inline mem accesses: %" PRIu64 "\n", inline_mem_count);
     32     }
     33     if (do_callback) {
     34         g_string_append_printf(out, "callback mem accesses: %" PRIu64 "\n", cb_mem_count);
     35     }
     36     if (do_haddr) {
     37         g_string_append_printf(out, "io accesses: %" PRIu64 "\n", io_count);
     38     }
     39     qemu_plugin_outs(out->str);
     40 }
     41 
     42 static void vcpu_mem(unsigned int cpu_index, qemu_plugin_meminfo_t meminfo,
     43                      uint64_t vaddr, void *udata)
     44 {
     45     if (do_haddr) {
     46         struct qemu_plugin_hwaddr *hwaddr;
     47         hwaddr = qemu_plugin_get_hwaddr(meminfo, vaddr);
     48         if (qemu_plugin_hwaddr_is_io(hwaddr)) {
     49             io_count++;
     50         } else {
     51             cb_mem_count++;
     52         }
     53     } else {
     54         cb_mem_count++;
     55     }
     56 }
     57 
     58 static void vcpu_tb_trans(qemu_plugin_id_t id, struct qemu_plugin_tb *tb)
     59 {
     60     size_t n = qemu_plugin_tb_n_insns(tb);
     61     size_t i;
     62 
     63     for (i = 0; i < n; i++) {
     64         struct qemu_plugin_insn *insn = qemu_plugin_tb_get_insn(tb, i);
     65 
     66         if (do_inline) {
     67             qemu_plugin_register_vcpu_mem_inline(insn, rw,
     68                                                  QEMU_PLUGIN_INLINE_ADD_U64,
     69                                                  &inline_mem_count, 1);
     70         }
     71         if (do_callback) {
     72             qemu_plugin_register_vcpu_mem_cb(insn, vcpu_mem,
     73                                              QEMU_PLUGIN_CB_NO_REGS,
     74                                              rw, NULL);
     75         }
     76     }
     77 }
     78 
     79 QEMU_PLUGIN_EXPORT int qemu_plugin_install(qemu_plugin_id_t id,
     80                                            const qemu_info_t *info,
     81                                            int argc, char **argv)
     82 {
     83 
     84     for (int i = 0; i < argc; i++) {
     85         char *opt = argv[i];
     86         g_autofree char **tokens = g_strsplit(opt, "=", 2);
     87 
     88         if (g_strcmp0(tokens[0], "haddr") == 0) {
     89             if (!qemu_plugin_bool_parse(tokens[0], tokens[1], &do_haddr)) {
     90                 fprintf(stderr, "boolean argument parsing failed: %s\n", opt);
     91                 return -1;
     92             }
     93         } else if (g_strcmp0(tokens[0], "track") == 0) {
     94             if (g_strcmp0(tokens[1], "r") == 0) {
     95                 rw = QEMU_PLUGIN_MEM_R;
     96             } else if (g_strcmp0(tokens[1], "w") == 0) {
     97                 rw = QEMU_PLUGIN_MEM_W;
     98             } else if (g_strcmp0(tokens[1], "rw") == 0) {
     99                 rw = QEMU_PLUGIN_MEM_RW;
    100             } else {
    101                 fprintf(stderr, "invaild value for argument track: %s\n", opt);
    102                 return -1;
    103             }
    104         } else if (g_strcmp0(tokens[0], "inline") == 0) {
    105             if (!qemu_plugin_bool_parse(tokens[0], tokens[1], &do_inline)) {
    106                 fprintf(stderr, "boolean argument parsing failed: %s\n", opt);
    107                 return -1;
    108             }
    109         } else if (g_strcmp0(tokens[0], "callback") == 0) {
    110             if (!qemu_plugin_bool_parse(tokens[0], tokens[1], &do_callback)) {
    111                 fprintf(stderr, "boolean argument parsing failed: %s\n", opt);
    112                 return -1;
    113             }
    114         } else {
    115             fprintf(stderr, "option parsing failed: %s\n", opt);
    116             return -1;
    117         }
    118     }
    119 
    120     qemu_plugin_register_vcpu_tb_trans_cb(id, vcpu_tb_trans);
    121     qemu_plugin_register_atexit_cb(id, plugin_exit, NULL);
    122     return 0;
    123 }