diff options
Diffstat (limited to 'tests/plugin')
-rw-r--r-- | tests/plugin/bb.c | 133 | ||||
-rw-r--r-- | tests/plugin/empty.c | 32 | ||||
-rw-r--r-- | tests/plugin/inline.c | 302 | ||||
-rw-r--r-- | tests/plugin/insn.c | 233 | ||||
-rw-r--r-- | tests/plugin/mem.c | 139 | ||||
-rw-r--r-- | tests/plugin/meson.build | 22 | ||||
-rw-r--r-- | tests/plugin/syscall.c | 144 |
7 files changed, 0 insertions, 1005 deletions
diff --git a/tests/plugin/bb.c b/tests/plugin/bb.c deleted file mode 100644 index 36776de..0000000 --- a/tests/plugin/bb.c +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Copyright (C) 2018, Emilio G. Cota <cota@braap.org> - * - * License: GNU GPL, version 2 or later. - * See the COPYING file in the top-level directory. - */ -#include <inttypes.h> -#include <assert.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <stdio.h> -#include <glib.h> - -#include <qemu-plugin.h> - -QEMU_PLUGIN_EXPORT int qemu_plugin_version = QEMU_PLUGIN_VERSION; - -typedef struct { - uint64_t bb_count; - uint64_t insn_count; -} CPUCount; - -static struct qemu_plugin_scoreboard *counts; -static qemu_plugin_u64 bb_count; -static qemu_plugin_u64 insn_count; - -static bool do_inline; -/* Dump running CPU total on idle? */ -static bool idle_report; - -static void gen_one_cpu_report(CPUCount *count, GString *report, - unsigned int cpu_index) -{ - if (count->bb_count) { - g_string_append_printf(report, "CPU%d: " - "bb's: %" PRIu64", insns: %" PRIu64 "\n", - cpu_index, - count->bb_count, count->insn_count); - } -} - -static void plugin_exit(qemu_plugin_id_t id, void *p) -{ - g_autoptr(GString) report = g_string_new(""); - - for (int i = 0; i < qemu_plugin_num_vcpus(); ++i) { - CPUCount *count = qemu_plugin_scoreboard_find(counts, i); - gen_one_cpu_report(count, report, i); - } - g_string_append_printf(report, "Total: " - "bb's: %" PRIu64", insns: %" PRIu64 "\n", - qemu_plugin_u64_sum(bb_count), - qemu_plugin_u64_sum(insn_count)); - qemu_plugin_outs(report->str); - qemu_plugin_scoreboard_free(counts); -} - -static void vcpu_idle(qemu_plugin_id_t id, unsigned int cpu_index) -{ - CPUCount *count = qemu_plugin_scoreboard_find(counts, cpu_index); - g_autoptr(GString) report = g_string_new(""); - gen_one_cpu_report(count, report, cpu_index); - - if (report->len > 0) { - g_string_prepend(report, "Idling "); - qemu_plugin_outs(report->str); - } -} - -static void vcpu_tb_exec(unsigned int cpu_index, void *udata) -{ - CPUCount *count = qemu_plugin_scoreboard_find(counts, cpu_index); - - uintptr_t n_insns = (uintptr_t)udata; - count->insn_count += n_insns; - count->bb_count++; -} - -static void vcpu_tb_trans(qemu_plugin_id_t id, struct qemu_plugin_tb *tb) -{ - size_t n_insns = qemu_plugin_tb_n_insns(tb); - - if (do_inline) { - qemu_plugin_register_vcpu_tb_exec_inline_per_vcpu( - tb, QEMU_PLUGIN_INLINE_ADD_U64, bb_count, 1); - qemu_plugin_register_vcpu_tb_exec_inline_per_vcpu( - tb, QEMU_PLUGIN_INLINE_ADD_U64, insn_count, n_insns); - } else { - qemu_plugin_register_vcpu_tb_exec_cb(tb, vcpu_tb_exec, - QEMU_PLUGIN_CB_NO_REGS, - (void *)n_insns); - } -} - -QEMU_PLUGIN_EXPORT int qemu_plugin_install(qemu_plugin_id_t id, - const qemu_info_t *info, - int argc, char **argv) -{ - int i; - - for (i = 0; i < argc; i++) { - char *opt = argv[i]; - g_auto(GStrv) tokens = g_strsplit(opt, "=", 2); - if (g_strcmp0(tokens[0], "inline") == 0) { - if (!qemu_plugin_bool_parse(tokens[0], tokens[1], &do_inline)) { - fprintf(stderr, "boolean argument parsing failed: %s\n", opt); - return -1; - } - } else if (g_strcmp0(tokens[0], "idle") == 0) { - if (!qemu_plugin_bool_parse(tokens[0], tokens[1], &idle_report)) { - fprintf(stderr, "boolean argument parsing failed: %s\n", opt); - return -1; - } - } else { - fprintf(stderr, "option parsing failed: %s\n", opt); - return -1; - } - } - - counts = qemu_plugin_scoreboard_new(sizeof(CPUCount)); - bb_count = qemu_plugin_scoreboard_u64_in_struct(counts, CPUCount, bb_count); - insn_count = qemu_plugin_scoreboard_u64_in_struct( - counts, CPUCount, insn_count); - - if (idle_report) { - qemu_plugin_register_vcpu_idle_cb(id, vcpu_idle); - } - - qemu_plugin_register_vcpu_tb_trans_cb(id, vcpu_tb_trans); - qemu_plugin_register_atexit_cb(id, plugin_exit, NULL); - return 0; -} diff --git a/tests/plugin/empty.c b/tests/plugin/empty.c deleted file mode 100644 index 8fa6bac..0000000 --- a/tests/plugin/empty.c +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (C) 2018, Emilio G. Cota <cota@braap.org> - * - * License: GNU GPL, version 2 or later. - * See the COPYING file in the top-level directory. - */ -#include <inttypes.h> -#include <assert.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <stdio.h> - -#include <qemu-plugin.h> - -QEMU_PLUGIN_EXPORT int qemu_plugin_version = QEMU_PLUGIN_VERSION; - -/* - * Empty TB translation callback. - * This allows us to measure the overhead of injecting and then - * removing empty instrumentation. - */ -static void vcpu_tb_trans(qemu_plugin_id_t id, struct qemu_plugin_tb *tb) -{ } - -QEMU_PLUGIN_EXPORT int qemu_plugin_install(qemu_plugin_id_t id, - const qemu_info_t *info, - int argc, char **argv) -{ - qemu_plugin_register_vcpu_tb_trans_cb(id, vcpu_tb_trans); - return 0; -} diff --git a/tests/plugin/inline.c b/tests/plugin/inline.c deleted file mode 100644 index cd63827..0000000 --- a/tests/plugin/inline.c +++ /dev/null @@ -1,302 +0,0 @@ -/* - * Copyright (C) 2023, Pierrick Bouvier <pierrick.bouvier@linaro.org> - * - * Demonstrates and tests usage of inline ops. - * - * License: GNU GPL, version 2 or later. - * See the COPYING file in the top-level directory. - */ - -#include <glib.h> -#include <stdint.h> -#include <stdio.h> - -#include <qemu-plugin.h> - -typedef struct { - uint64_t count_tb; - uint64_t count_tb_inline; - uint64_t count_insn; - uint64_t count_insn_inline; - uint64_t count_mem; - uint64_t count_mem_inline; - uint64_t tb_cond_num_trigger; - uint64_t tb_cond_track_count; - uint64_t insn_cond_num_trigger; - uint64_t insn_cond_track_count; -} CPUCount; - -static const uint64_t cond_trigger_limit = 100; - -typedef struct { - uint64_t data_insn; - uint64_t data_tb; - uint64_t data_mem; -} CPUData; - -static struct qemu_plugin_scoreboard *counts; -static qemu_plugin_u64 count_tb; -static qemu_plugin_u64 count_tb_inline; -static qemu_plugin_u64 count_insn; -static qemu_plugin_u64 count_insn_inline; -static qemu_plugin_u64 count_mem; -static qemu_plugin_u64 count_mem_inline; -static qemu_plugin_u64 tb_cond_num_trigger; -static qemu_plugin_u64 tb_cond_track_count; -static qemu_plugin_u64 insn_cond_num_trigger; -static qemu_plugin_u64 insn_cond_track_count; -static struct qemu_plugin_scoreboard *data; -static qemu_plugin_u64 data_insn; -static qemu_plugin_u64 data_tb; -static qemu_plugin_u64 data_mem; - -static uint64_t global_count_tb; -static uint64_t global_count_insn; -static uint64_t global_count_mem; -static unsigned int max_cpu_index; -static GMutex tb_lock; -static GMutex insn_lock; -static GMutex mem_lock; - -QEMU_PLUGIN_EXPORT int qemu_plugin_version = QEMU_PLUGIN_VERSION; - -static void stats_insn(void) -{ - const uint64_t expected = global_count_insn; - const uint64_t per_vcpu = qemu_plugin_u64_sum(count_insn); - const uint64_t inl_per_vcpu = - qemu_plugin_u64_sum(count_insn_inline); - const uint64_t cond_num_trigger = - qemu_plugin_u64_sum(insn_cond_num_trigger); - const uint64_t cond_track_left = qemu_plugin_u64_sum(insn_cond_track_count); - const uint64_t conditional = - cond_num_trigger * cond_trigger_limit + cond_track_left; - printf("insn: %" PRIu64 "\n", expected); - printf("insn: %" PRIu64 " (per vcpu)\n", per_vcpu); - printf("insn: %" PRIu64 " (per vcpu inline)\n", inl_per_vcpu); - printf("insn: %" PRIu64 " (cond cb)\n", conditional); - g_assert(expected > 0); - g_assert(per_vcpu == expected); - g_assert(inl_per_vcpu == expected); - g_assert(conditional == expected); -} - -static void stats_tb(void) -{ - const uint64_t expected = global_count_tb; - const uint64_t per_vcpu = qemu_plugin_u64_sum(count_tb); - const uint64_t inl_per_vcpu = - qemu_plugin_u64_sum(count_tb_inline); - const uint64_t cond_num_trigger = qemu_plugin_u64_sum(tb_cond_num_trigger); - const uint64_t cond_track_left = qemu_plugin_u64_sum(tb_cond_track_count); - const uint64_t conditional = - cond_num_trigger * cond_trigger_limit + cond_track_left; - printf("tb: %" PRIu64 "\n", expected); - printf("tb: %" PRIu64 " (per vcpu)\n", per_vcpu); - printf("tb: %" PRIu64 " (per vcpu inline)\n", inl_per_vcpu); - printf("tb: %" PRIu64 " (conditional cb)\n", conditional); - g_assert(expected > 0); - g_assert(per_vcpu == expected); - g_assert(inl_per_vcpu == expected); - g_assert(conditional == expected); -} - -static void stats_mem(void) -{ - const uint64_t expected = global_count_mem; - const uint64_t per_vcpu = qemu_plugin_u64_sum(count_mem); - const uint64_t inl_per_vcpu = - qemu_plugin_u64_sum(count_mem_inline); - printf("mem: %" PRIu64 "\n", expected); - printf("mem: %" PRIu64 " (per vcpu)\n", per_vcpu); - printf("mem: %" PRIu64 " (per vcpu inline)\n", inl_per_vcpu); - g_assert(expected > 0); - g_assert(per_vcpu == expected); - g_assert(inl_per_vcpu == expected); -} - -static void plugin_exit(qemu_plugin_id_t id, void *udata) -{ - const unsigned int num_cpus = qemu_plugin_num_vcpus(); - g_assert(num_cpus == max_cpu_index + 1); - - for (int i = 0; i < num_cpus ; ++i) { - const uint64_t tb = qemu_plugin_u64_get(count_tb, i); - const uint64_t tb_inline = qemu_plugin_u64_get(count_tb_inline, i); - const uint64_t insn = qemu_plugin_u64_get(count_insn, i); - const uint64_t insn_inline = qemu_plugin_u64_get(count_insn_inline, i); - const uint64_t mem = qemu_plugin_u64_get(count_mem, i); - const uint64_t mem_inline = qemu_plugin_u64_get(count_mem_inline, i); - const uint64_t tb_cond_trigger = - qemu_plugin_u64_get(tb_cond_num_trigger, i); - const uint64_t tb_cond_left = - qemu_plugin_u64_get(tb_cond_track_count, i); - const uint64_t insn_cond_trigger = - qemu_plugin_u64_get(insn_cond_num_trigger, i); - const uint64_t insn_cond_left = - qemu_plugin_u64_get(insn_cond_track_count, i); - printf("cpu %d: tb (%" PRIu64 ", %" PRIu64 - ", %" PRIu64 " * %" PRIu64 " + %" PRIu64 - ") | " - "insn (%" PRIu64 ", %" PRIu64 - ", %" PRIu64 " * %" PRIu64 " + %" PRIu64 - ") | " - "mem (%" PRIu64 ", %" PRIu64 ")" - "\n", - i, - tb, tb_inline, - tb_cond_trigger, cond_trigger_limit, tb_cond_left, - insn, insn_inline, - insn_cond_trigger, cond_trigger_limit, insn_cond_left, - mem, mem_inline); - g_assert(tb == tb_inline); - g_assert(insn == insn_inline); - g_assert(mem == mem_inline); - g_assert(tb_cond_trigger == tb / cond_trigger_limit); - g_assert(tb_cond_left == tb % cond_trigger_limit); - g_assert(insn_cond_trigger == insn / cond_trigger_limit); - g_assert(insn_cond_left == insn % cond_trigger_limit); - } - - stats_tb(); - stats_insn(); - stats_mem(); - - qemu_plugin_scoreboard_free(counts); - qemu_plugin_scoreboard_free(data); -} - -static void vcpu_tb_exec(unsigned int cpu_index, void *udata) -{ - qemu_plugin_u64_add(count_tb, cpu_index, 1); - g_assert(qemu_plugin_u64_get(data_tb, cpu_index) == (uintptr_t) udata); - g_mutex_lock(&tb_lock); - max_cpu_index = MAX(max_cpu_index, cpu_index); - global_count_tb++; - g_mutex_unlock(&tb_lock); -} - -static void vcpu_tb_cond_exec(unsigned int cpu_index, void *udata) -{ - g_assert(qemu_plugin_u64_get(tb_cond_track_count, cpu_index) == - cond_trigger_limit); - g_assert(qemu_plugin_u64_get(data_tb, cpu_index) == (uintptr_t) udata); - qemu_plugin_u64_set(tb_cond_track_count, cpu_index, 0); - qemu_plugin_u64_add(tb_cond_num_trigger, cpu_index, 1); -} - -static void vcpu_insn_cond_exec(unsigned int cpu_index, void *udata) -{ - g_assert(qemu_plugin_u64_get(insn_cond_track_count, cpu_index) == - cond_trigger_limit); - g_assert(qemu_plugin_u64_get(data_insn, cpu_index) == (uintptr_t) udata); - qemu_plugin_u64_set(insn_cond_track_count, cpu_index, 0); - qemu_plugin_u64_add(insn_cond_num_trigger, cpu_index, 1); -} - -static void vcpu_insn_exec(unsigned int cpu_index, void *udata) -{ - qemu_plugin_u64_add(count_insn, cpu_index, 1); - g_assert(qemu_plugin_u64_get(data_insn, cpu_index) == (uintptr_t) udata); - g_mutex_lock(&insn_lock); - global_count_insn++; - g_mutex_unlock(&insn_lock); -} - -static void vcpu_mem_access(unsigned int cpu_index, - qemu_plugin_meminfo_t info, - uint64_t vaddr, - void *udata) -{ - qemu_plugin_u64_add(count_mem, cpu_index, 1); - g_assert(qemu_plugin_u64_get(data_mem, cpu_index) == (uintptr_t) udata); - g_mutex_lock(&mem_lock); - global_count_mem++; - g_mutex_unlock(&mem_lock); -} - -static void vcpu_tb_trans(qemu_plugin_id_t id, struct qemu_plugin_tb *tb) -{ - void *tb_store = tb; - qemu_plugin_register_vcpu_tb_exec_inline_per_vcpu( - tb, QEMU_PLUGIN_INLINE_STORE_U64, data_tb, (uintptr_t) tb_store); - qemu_plugin_register_vcpu_tb_exec_cb( - tb, vcpu_tb_exec, QEMU_PLUGIN_CB_NO_REGS, tb_store); - qemu_plugin_register_vcpu_tb_exec_inline_per_vcpu( - tb, QEMU_PLUGIN_INLINE_ADD_U64, count_tb_inline, 1); - - qemu_plugin_register_vcpu_tb_exec_inline_per_vcpu( - tb, QEMU_PLUGIN_INLINE_ADD_U64, tb_cond_track_count, 1); - qemu_plugin_register_vcpu_tb_exec_cond_cb( - tb, vcpu_tb_cond_exec, QEMU_PLUGIN_CB_NO_REGS, - QEMU_PLUGIN_COND_EQ, tb_cond_track_count, cond_trigger_limit, tb_store); - - for (int idx = 0; idx < qemu_plugin_tb_n_insns(tb); ++idx) { - struct qemu_plugin_insn *insn = qemu_plugin_tb_get_insn(tb, idx); - void *insn_store = insn; - void *mem_store = (char *)insn_store + 0xff; - - qemu_plugin_register_vcpu_insn_exec_inline_per_vcpu( - insn, QEMU_PLUGIN_INLINE_STORE_U64, data_insn, - (uintptr_t) insn_store); - qemu_plugin_register_vcpu_insn_exec_cb( - insn, vcpu_insn_exec, QEMU_PLUGIN_CB_NO_REGS, insn_store); - qemu_plugin_register_vcpu_insn_exec_inline_per_vcpu( - insn, QEMU_PLUGIN_INLINE_ADD_U64, count_insn_inline, 1); - - qemu_plugin_register_vcpu_insn_exec_inline_per_vcpu( - insn, QEMU_PLUGIN_INLINE_ADD_U64, insn_cond_track_count, 1); - qemu_plugin_register_vcpu_insn_exec_cond_cb( - insn, vcpu_insn_cond_exec, QEMU_PLUGIN_CB_NO_REGS, - QEMU_PLUGIN_COND_EQ, insn_cond_track_count, cond_trigger_limit, - insn_store); - - qemu_plugin_register_vcpu_mem_inline_per_vcpu( - insn, QEMU_PLUGIN_MEM_RW, - QEMU_PLUGIN_INLINE_STORE_U64, - data_mem, (uintptr_t) mem_store); - qemu_plugin_register_vcpu_mem_cb(insn, &vcpu_mem_access, - QEMU_PLUGIN_CB_NO_REGS, - QEMU_PLUGIN_MEM_RW, mem_store); - qemu_plugin_register_vcpu_mem_inline_per_vcpu( - insn, QEMU_PLUGIN_MEM_RW, - QEMU_PLUGIN_INLINE_ADD_U64, - count_mem_inline, 1); - } -} - -QEMU_PLUGIN_EXPORT -int qemu_plugin_install(qemu_plugin_id_t id, const qemu_info_t *info, - int argc, char **argv) -{ - counts = qemu_plugin_scoreboard_new(sizeof(CPUCount)); - count_tb = qemu_plugin_scoreboard_u64_in_struct( - counts, CPUCount, count_tb); - count_insn = qemu_plugin_scoreboard_u64_in_struct( - counts, CPUCount, count_insn); - count_mem = qemu_plugin_scoreboard_u64_in_struct( - counts, CPUCount, count_mem); - count_tb_inline = qemu_plugin_scoreboard_u64_in_struct( - counts, CPUCount, count_tb_inline); - count_insn_inline = qemu_plugin_scoreboard_u64_in_struct( - counts, CPUCount, count_insn_inline); - count_mem_inline = qemu_plugin_scoreboard_u64_in_struct( - counts, CPUCount, count_mem_inline); - tb_cond_num_trigger = qemu_plugin_scoreboard_u64_in_struct( - counts, CPUCount, tb_cond_num_trigger); - tb_cond_track_count = qemu_plugin_scoreboard_u64_in_struct( - counts, CPUCount, tb_cond_track_count); - insn_cond_num_trigger = qemu_plugin_scoreboard_u64_in_struct( - counts, CPUCount, insn_cond_num_trigger); - insn_cond_track_count = qemu_plugin_scoreboard_u64_in_struct( - counts, CPUCount, insn_cond_track_count); - data = qemu_plugin_scoreboard_new(sizeof(CPUData)); - data_insn = qemu_plugin_scoreboard_u64_in_struct(data, CPUData, data_insn); - data_tb = qemu_plugin_scoreboard_u64_in_struct(data, CPUData, data_tb); - data_mem = qemu_plugin_scoreboard_u64_in_struct(data, CPUData, data_mem); - - qemu_plugin_register_vcpu_tb_trans_cb(id, vcpu_tb_trans); - qemu_plugin_register_atexit_cb(id, plugin_exit, NULL); - - return 0; -} diff --git a/tests/plugin/insn.c b/tests/plugin/insn.c deleted file mode 100644 index 5e0aa03..0000000 --- a/tests/plugin/insn.c +++ /dev/null @@ -1,233 +0,0 @@ -/* - * Copyright (C) 2018, Emilio G. Cota <cota@braap.org> - * - * License: GNU GPL, version 2 or later. - * See the COPYING file in the top-level directory. - */ -#include <inttypes.h> -#include <assert.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <stdio.h> -#include <glib.h> - -#include <qemu-plugin.h> - -QEMU_PLUGIN_EXPORT int qemu_plugin_version = QEMU_PLUGIN_VERSION; - -static qemu_plugin_u64 insn_count; - -static bool do_inline; -static bool do_size; -static GArray *sizes; - -typedef struct { - uint64_t hits; - uint64_t last_hit; - uint64_t total_delta; -} MatchCount; - -typedef struct { - char *match_string; - struct qemu_plugin_scoreboard *counts; /* MatchCount */ -} Match; - -static GArray *matches; - -typedef struct { - Match *match; - uint64_t vaddr; - uint64_t hits; - char *disas; -} Instruction; - -/* - * Initialise a new vcpu with reading the register list - */ -static void vcpu_init(qemu_plugin_id_t id, unsigned int vcpu_index) -{ - g_autoptr(GArray) reg_list = qemu_plugin_get_registers(); - g_autoptr(GByteArray) reg_value = g_byte_array_new(); - - if (reg_list) { - for (int i = 0; i < reg_list->len; i++) { - qemu_plugin_reg_descriptor *rd = &g_array_index( - reg_list, qemu_plugin_reg_descriptor, i); - int count = qemu_plugin_read_register(rd->handle, reg_value); - g_assert(count > 0); - } - } -} - - -static void vcpu_insn_exec_before(unsigned int cpu_index, void *udata) -{ - qemu_plugin_u64_add(insn_count, cpu_index, 1); -} - -static void vcpu_insn_matched_exec_before(unsigned int cpu_index, void *udata) -{ - Instruction *insn = (Instruction *) udata; - Match *insn_match = insn->match; - MatchCount *match = qemu_plugin_scoreboard_find(insn_match->counts, - cpu_index); - - g_autoptr(GString) ts = g_string_new(""); - - insn->hits++; - g_string_append_printf(ts, "0x%" PRIx64 ", '%s', %"PRId64 " hits", - insn->vaddr, insn->disas, insn->hits); - - uint64_t icount = qemu_plugin_u64_get(insn_count, cpu_index); - uint64_t delta = icount - match->last_hit; - - match->hits++; - match->total_delta += delta; - - g_string_append_printf(ts, - " , cpu %u," - " %"PRId64" match hits," - " Δ+%"PRId64 " since last match," - " %"PRId64 " avg insns/match\n", - cpu_index, - match->hits, delta, - match->total_delta / match->hits); - - match->last_hit = icount; - - qemu_plugin_outs(ts->str); -} - -static void vcpu_tb_trans(qemu_plugin_id_t id, struct qemu_plugin_tb *tb) -{ - size_t n = qemu_plugin_tb_n_insns(tb); - size_t i; - - for (i = 0; i < n; i++) { - struct qemu_plugin_insn *insn = qemu_plugin_tb_get_insn(tb, i); - - if (do_inline) { - qemu_plugin_register_vcpu_insn_exec_inline_per_vcpu( - insn, QEMU_PLUGIN_INLINE_ADD_U64, insn_count, 1); - } else { - uint64_t vaddr = qemu_plugin_insn_vaddr(insn); - qemu_plugin_register_vcpu_insn_exec_cb( - insn, vcpu_insn_exec_before, QEMU_PLUGIN_CB_NO_REGS, - GUINT_TO_POINTER(vaddr)); - } - - if (do_size) { - size_t sz = qemu_plugin_insn_size(insn); - if (sz > sizes->len) { - g_array_set_size(sizes, sz); - } - unsigned long *cnt = &g_array_index(sizes, unsigned long, sz); - (*cnt)++; - } - - /* - * If we are tracking certain instructions we will need more - * information about the instruction which we also need to - * save if there is a hit. - */ - if (matches->len) { - char *insn_disas = qemu_plugin_insn_disas(insn); - for (int j = 0; j < matches->len; j++) { - Match *m = &g_array_index(matches, Match, j); - if (g_str_has_prefix(insn_disas, m->match_string)) { - Instruction *rec = g_new0(Instruction, 1); - rec->disas = g_strdup(insn_disas); - rec->vaddr = qemu_plugin_insn_vaddr(insn); - rec->match = m; - qemu_plugin_register_vcpu_insn_exec_cb( - insn, vcpu_insn_matched_exec_before, - QEMU_PLUGIN_CB_NO_REGS, rec); - } - } - g_free(insn_disas); - } - } -} - -static void plugin_exit(qemu_plugin_id_t id, void *p) -{ - g_autoptr(GString) out = g_string_new(NULL); - int i; - - if (do_size) { - for (i = 0; i <= sizes->len; i++) { - unsigned long *cnt = &g_array_index(sizes, unsigned long, i); - if (*cnt) { - g_string_append_printf(out, - "len %d bytes: %ld insns\n", i, *cnt); - } - } - } else { - for (i = 0; i < qemu_plugin_num_vcpus(); i++) { - g_string_append_printf(out, "cpu %d insns: %" PRIu64 "\n", - i, qemu_plugin_u64_get(insn_count, i)); - } - g_string_append_printf(out, "total insns: %" PRIu64 "\n", - qemu_plugin_u64_sum(insn_count)); - } - qemu_plugin_outs(out->str); - - qemu_plugin_scoreboard_free(insn_count.score); - for (i = 0; i < matches->len; ++i) { - Match *m = &g_array_index(matches, Match, i); - g_free(m->match_string); - qemu_plugin_scoreboard_free(m->counts); - } - g_array_free(matches, TRUE); - g_array_free(sizes, TRUE); -} - - -/* Add a match to the array of matches */ -static void parse_match(char *match) -{ - Match new_match = { - .match_string = g_strdup(match), - .counts = qemu_plugin_scoreboard_new(sizeof(MatchCount)) }; - g_array_append_val(matches, new_match); -} - -QEMU_PLUGIN_EXPORT int qemu_plugin_install(qemu_plugin_id_t id, - const qemu_info_t *info, - int argc, char **argv) -{ - matches = g_array_new(false, true, sizeof(Match)); - /* null terminated so 0 is not a special case */ - sizes = g_array_new(true, true, sizeof(unsigned long)); - - for (int i = 0; i < argc; i++) { - char *opt = argv[i]; - g_auto(GStrv) tokens = g_strsplit(opt, "=", 2); - if (g_strcmp0(tokens[0], "inline") == 0) { - if (!qemu_plugin_bool_parse(tokens[0], tokens[1], &do_inline)) { - fprintf(stderr, "boolean argument parsing failed: %s\n", opt); - return -1; - } - } else if (g_strcmp0(tokens[0], "sizes") == 0) { - if (!qemu_plugin_bool_parse(tokens[0], tokens[1], &do_size)) { - fprintf(stderr, "boolean argument parsing failed: %s\n", opt); - return -1; - } - } else if (g_strcmp0(tokens[0], "match") == 0) { - parse_match(tokens[1]); - } else { - fprintf(stderr, "option parsing failed: %s\n", opt); - return -1; - } - } - - insn_count = qemu_plugin_scoreboard_u64( - qemu_plugin_scoreboard_new(sizeof(uint64_t))); - - /* Register init, translation block and exit callbacks */ - qemu_plugin_register_vcpu_init_cb(id, vcpu_init); - qemu_plugin_register_vcpu_tb_trans_cb(id, vcpu_tb_trans); - qemu_plugin_register_atexit_cb(id, plugin_exit, NULL); - return 0; -} diff --git a/tests/plugin/mem.c b/tests/plugin/mem.c deleted file mode 100644 index b650ddd..0000000 --- a/tests/plugin/mem.c +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright (C) 2018, Emilio G. Cota <cota@braap.org> - * - * License: GNU GPL, version 2 or later. - * See the COPYING file in the top-level directory. - */ -#include <inttypes.h> -#include <assert.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <stdio.h> -#include <glib.h> - -#include <qemu-plugin.h> - -QEMU_PLUGIN_EXPORT int qemu_plugin_version = QEMU_PLUGIN_VERSION; - -typedef struct { - uint64_t mem_count; - uint64_t io_count; -} CPUCount; - -static struct qemu_plugin_scoreboard *counts; -static qemu_plugin_u64 mem_count; -static qemu_plugin_u64 io_count; -static bool do_inline, do_callback; -static bool do_haddr; -static enum qemu_plugin_mem_rw rw = QEMU_PLUGIN_MEM_RW; - -static void plugin_exit(qemu_plugin_id_t id, void *p) -{ - g_autoptr(GString) out = g_string_new(""); - - if (do_inline || do_callback) { - g_string_printf(out, "mem accesses: %" PRIu64 "\n", - qemu_plugin_u64_sum(mem_count)); - } - if (do_haddr) { - g_string_append_printf(out, "io accesses: %" PRIu64 "\n", - qemu_plugin_u64_sum(io_count)); - } - qemu_plugin_outs(out->str); - qemu_plugin_scoreboard_free(counts); -} - -static void vcpu_mem(unsigned int cpu_index, qemu_plugin_meminfo_t meminfo, - uint64_t vaddr, void *udata) -{ - if (do_haddr) { - struct qemu_plugin_hwaddr *hwaddr; - hwaddr = qemu_plugin_get_hwaddr(meminfo, vaddr); - if (qemu_plugin_hwaddr_is_io(hwaddr)) { - qemu_plugin_u64_add(io_count, cpu_index, 1); - } else { - qemu_plugin_u64_add(mem_count, cpu_index, 1); - } - } else { - qemu_plugin_u64_add(mem_count, cpu_index, 1); - } -} - -static void vcpu_tb_trans(qemu_plugin_id_t id, struct qemu_plugin_tb *tb) -{ - size_t n = qemu_plugin_tb_n_insns(tb); - size_t i; - - for (i = 0; i < n; i++) { - struct qemu_plugin_insn *insn = qemu_plugin_tb_get_insn(tb, i); - - if (do_inline) { - qemu_plugin_register_vcpu_mem_inline_per_vcpu( - insn, rw, - QEMU_PLUGIN_INLINE_ADD_U64, - mem_count, 1); - } - if (do_callback) { - qemu_plugin_register_vcpu_mem_cb(insn, vcpu_mem, - QEMU_PLUGIN_CB_NO_REGS, - rw, NULL); - } - } -} - -QEMU_PLUGIN_EXPORT int qemu_plugin_install(qemu_plugin_id_t id, - const qemu_info_t *info, - int argc, char **argv) -{ - - for (int i = 0; i < argc; i++) { - char *opt = argv[i]; - g_auto(GStrv) tokens = g_strsplit(opt, "=", 2); - - if (g_strcmp0(tokens[0], "haddr") == 0) { - if (!qemu_plugin_bool_parse(tokens[0], tokens[1], &do_haddr)) { - fprintf(stderr, "boolean argument parsing failed: %s\n", opt); - return -1; - } - } else if (g_strcmp0(tokens[0], "track") == 0) { - if (g_strcmp0(tokens[1], "r") == 0) { - rw = QEMU_PLUGIN_MEM_R; - } else if (g_strcmp0(tokens[1], "w") == 0) { - rw = QEMU_PLUGIN_MEM_W; - } else if (g_strcmp0(tokens[1], "rw") == 0) { - rw = QEMU_PLUGIN_MEM_RW; - } else { - fprintf(stderr, "invalid value for argument track: %s\n", opt); - return -1; - } - } else if (g_strcmp0(tokens[0], "inline") == 0) { - if (!qemu_plugin_bool_parse(tokens[0], tokens[1], &do_inline)) { - fprintf(stderr, "boolean argument parsing failed: %s\n", opt); - return -1; - } - } else if (g_strcmp0(tokens[0], "callback") == 0) { - if (!qemu_plugin_bool_parse(tokens[0], tokens[1], &do_callback)) { - fprintf(stderr, "boolean argument parsing failed: %s\n", opt); - return -1; - } - } else { - fprintf(stderr, "option parsing failed: %s\n", opt); - return -1; - } - } - - if (do_inline && do_callback) { - fprintf(stderr, - "can't enable inline and callback counting at the same time\n"); - return -1; - } - - counts = qemu_plugin_scoreboard_new(sizeof(CPUCount)); - mem_count = qemu_plugin_scoreboard_u64_in_struct( - counts, CPUCount, mem_count); - io_count = qemu_plugin_scoreboard_u64_in_struct(counts, CPUCount, io_count); - qemu_plugin_register_vcpu_tb_trans_cb(id, vcpu_tb_trans); - qemu_plugin_register_atexit_cb(id, plugin_exit, NULL); - return 0; -} diff --git a/tests/plugin/meson.build b/tests/plugin/meson.build deleted file mode 100644 index 9eece5b..0000000 --- a/tests/plugin/meson.build +++ /dev/null @@ -1,22 +0,0 @@ -t = [] -if get_option('plugins') - foreach i : ['bb', 'empty', 'inline', 'insn', 'mem', 'syscall'] - if host_os == 'windows' - t += shared_module(i, files(i + '.c') + '../../contrib/plugins/win32_linker.c', - include_directories: '../../include/qemu', - link_depends: [win32_qemu_plugin_api_lib], - link_args: ['-Lplugins', '-lqemu_plugin_api'], - dependencies: glib) - - else - t += shared_module(i, files(i + '.c'), - include_directories: '../../include/qemu', - dependencies: glib) - endif - endforeach -endif -if t.length() > 0 - alias_target('test-plugins', t) -else - run_target('test-plugins', command: find_program('true')) -endif diff --git a/tests/plugin/syscall.c b/tests/plugin/syscall.c deleted file mode 100644 index 72e1a5b..0000000 --- a/tests/plugin/syscall.c +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright (C) 2020, Matthias Weckbecker <matthias@weckbecker.name> - * - * License: GNU GPL, version 2 or later. - * See the COPYING file in the top-level directory. - */ -#include <inttypes.h> -#include <assert.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <stdio.h> -#include <glib.h> - -#include <qemu-plugin.h> - -QEMU_PLUGIN_EXPORT int qemu_plugin_version = QEMU_PLUGIN_VERSION; - -typedef struct { - int64_t num; - int64_t calls; - int64_t errors; -} SyscallStats; - -static GMutex lock; -static GHashTable *statistics; - -static SyscallStats *get_or_create_entry(int64_t num) -{ - SyscallStats *entry = - (SyscallStats *) g_hash_table_lookup(statistics, GINT_TO_POINTER(num)); - - if (!entry) { - entry = g_new0(SyscallStats, 1); - entry->num = num; - g_hash_table_insert(statistics, GINT_TO_POINTER(num), (gpointer) entry); - } - - return entry; -} - -static void vcpu_syscall(qemu_plugin_id_t id, unsigned int vcpu_index, - int64_t num, uint64_t a1, uint64_t a2, - uint64_t a3, uint64_t a4, uint64_t a5, - uint64_t a6, uint64_t a7, uint64_t a8) -{ - if (statistics) { - SyscallStats *entry; - g_mutex_lock(&lock); - entry = get_or_create_entry(num); - entry->calls++; - g_mutex_unlock(&lock); - } else { - g_autofree gchar *out = g_strdup_printf("syscall #%" PRIi64 "\n", num); - qemu_plugin_outs(out); - } -} - -static void vcpu_syscall_ret(qemu_plugin_id_t id, unsigned int vcpu_idx, - int64_t num, int64_t ret) -{ - if (statistics) { - SyscallStats *entry; - - g_mutex_lock(&lock); - /* Should always return an existent entry. */ - entry = get_or_create_entry(num); - if (ret < 0) { - entry->errors++; - } - g_mutex_unlock(&lock); - } else { - g_autofree gchar *out = g_strdup_printf( - "syscall #%" PRIi64 " returned -> %" PRIi64 "\n", num, ret); - qemu_plugin_outs(out); - } -} - -static void print_entry(gpointer val, gpointer user_data) -{ - SyscallStats *entry = (SyscallStats *) val; - int64_t syscall_num = entry->num; - g_autofree gchar *out = g_strdup_printf( - "%-13" PRIi64 "%-6" PRIi64 " %" PRIi64 "\n", - syscall_num, entry->calls, entry->errors); - qemu_plugin_outs(out); -} - -static gint comp_func(gconstpointer ea, gconstpointer eb) -{ - SyscallStats *ent_a = (SyscallStats *) ea; - SyscallStats *ent_b = (SyscallStats *) eb; - - return ent_a->calls > ent_b->calls ? -1 : 1; -} - -/* ************************************************************************* */ -static void plugin_exit(qemu_plugin_id_t id, void *p) -{ - if (!statistics) { - return; - } - - g_mutex_lock(&lock); - GList *entries = g_hash_table_get_values(statistics); - entries = g_list_sort(entries, comp_func); - qemu_plugin_outs("syscall no. calls errors\n"); - - g_list_foreach(entries, print_entry, NULL); - - g_list_free(entries); - g_hash_table_destroy(statistics); - g_mutex_unlock(&lock); -} - -QEMU_PLUGIN_EXPORT int qemu_plugin_install(qemu_plugin_id_t id, - const qemu_info_t *info, - int argc, char **argv) -{ - bool do_print = false; - - for (int i = 0; i < argc; i++) { - char *opt = argv[i]; - g_auto(GStrv) tokens = g_strsplit(opt, "=", 2); - - if (g_strcmp0(tokens[0], "print") == 0) { - if (!qemu_plugin_bool_parse(tokens[0], tokens[1], &do_print)) { - fprintf(stderr, "boolean argument parsing failed: %s\n", opt); - } - } else { - fprintf(stderr, "unsupported argument: %s\n", argv[i]); - return -1; - } - } - - if (!do_print) { - statistics = g_hash_table_new_full(NULL, g_direct_equal, NULL, g_free); - } - - qemu_plugin_register_vcpu_syscall_cb(id, vcpu_syscall); - qemu_plugin_register_vcpu_syscall_ret_cb(id, vcpu_syscall_ret); - qemu_plugin_register_atexit_cb(id, plugin_exit, NULL); - return 0; -} |