diff options
| author | Peter Maydell | 2022-02-11 14:11:49 +0100 |
|---|---|---|
| committer | Peter Maydell | 2022-02-11 14:11:49 +0100 |
| commit | da36afa2d8dc9c778292ff172083caba9558b4fa (patch) | |
| tree | 73a39175a68ecbf7404c785050d24261c9e08d3e /tests/plugin | |
| parent | Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20220208'... (diff) | |
| parent | include/exec: fix softmmu version of TARGET_ABI_FMT_lx (diff) | |
| download | qemu-da36afa2d8dc9c778292ff172083caba9558b4fa.tar.gz qemu-da36afa2d8dc9c778292ff172083caba9558b4fa.tar.xz qemu-da36afa2d8dc9c778292ff172083caba9558b4fa.zip | |
Merge remote-tracking branch 'remotes/stsquad/tags/pull-testing-and-plugins-090222-1' into staging
Testing and plugin updates:
- include vhost tests in qtest
- clean-up gcov ephemera in clean/.gitignore
- lcitool and docker updates
- mention .editorconfig in devel notes
- switch Centos8 to Centos Stream 8
- remove TCG tracing support
- add coverage plugin using drcov format
- expand abilities of libinsn.so plugin
- use correct logging for i386 int cases
- move reset of plugin data to start of block
- deprecate ppc6432abi
- fix TARGET_ABI_FMT_ptr for softmmu builds
# gpg: Signature made Wed 09 Feb 2022 14:13:14 GMT
# gpg: using RSA key 6685AE99E75167BCAFC8DF35FBD0DB095A9E2A44
# gpg: Good signature from "Alex Bennée (Master Work Key) <alex.bennee@linaro.org>" [full]
# Primary key fingerprint: 6685 AE99 E751 67BC AFC8 DF35 FBD0 DB09 5A9E 2A44
* remotes/stsquad/tags/pull-testing-and-plugins-090222-1: (28 commits)
include/exec: fix softmmu version of TARGET_ABI_FMT_lx
linux-user: Remove the deprecated ppc64abi32 target
plugins: move reset of plugin data to tb_start
target/i386: use CPU_LOG_INT for IRQ servicing
tests/plugins: add instruction matching to libinsn.so
tests/plugin: allow libinsn.so per-CPU counts
contrib/plugins: add a drcov plugin
plugins: add helper functions for coverage plugins
tracing: excise the tcg related from tracetool
tracing: remove the trace-tcg includes from the build
tracing: remove TCG memory access tracing
docs: remove references to TCG tracing
tests/tcg/sh4: disable another unreliable test
tests: Update CentOS 8 container to CentOS Stream 8
tests/lcitool: Allow lcitool-refresh in out-of-tree builds, too
gitlab: fall back to commit hash in qemu-setup filename
docs/devel: mention our .editorconfig
tests/lcitool: Install libibumad to cover RDMA on Debian based distros
tests: Manually remove libxml2 on MSYS2 runners
tests/lcitool: Refresh submodule and remove libxml2
...
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'tests/plugin')
| -rw-r--r-- | tests/plugin/insn.c | 126 |
1 files changed, 118 insertions, 8 deletions
diff --git a/tests/plugin/insn.c b/tests/plugin/insn.c index d229fdc001..cd5ea5d4ae 100644 --- a/tests/plugin/insn.c +++ b/tests/plugin/insn.c @@ -16,22 +16,80 @@ QEMU_PLUGIN_EXPORT int qemu_plugin_version = QEMU_PLUGIN_VERSION; -static uint64_t insn_count; +#define MAX_CPUS 8 /* lets not go nuts */ + +typedef struct { + uint64_t last_pc; + uint64_t insn_count; +} InstructionCount; + +static InstructionCount counts[MAX_CPUS]; +static uint64_t inline_insn_count; + static bool do_inline; static bool do_size; static GArray *sizes; +typedef struct { + char *match_string; + uint64_t hits[MAX_CPUS]; + uint64_t last_hit[MAX_CPUS]; + uint64_t total_delta[MAX_CPUS]; + GPtrArray *history[MAX_CPUS]; +} Match; + +static GArray *matches; + +typedef struct { + Match *match; + uint64_t vaddr; + uint64_t hits; + char *disas; +} Instruction; + static void vcpu_insn_exec_before(unsigned int cpu_index, void *udata) { - static uint64_t last_pc; + unsigned int i = cpu_index % MAX_CPUS; + InstructionCount *c = &counts[i]; uint64_t this_pc = GPOINTER_TO_UINT(udata); - if (this_pc == last_pc) { + if (this_pc == c->last_pc) { g_autofree gchar *out = g_strdup_printf("detected repeat execution @ 0x%" PRIx64 "\n", this_pc); qemu_plugin_outs(out); } - last_pc = this_pc; - insn_count++; + c->last_pc = this_pc; + c->insn_count++; +} + +static void vcpu_insn_matched_exec_before(unsigned int cpu_index, void *udata) +{ + unsigned int i = cpu_index % MAX_CPUS; + Instruction *insn = (Instruction *) udata; + Match *match = insn->match; + 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 = counts[i].insn_count; + uint64_t delta = icount - match->last_hit[i]; + + match->hits[i]++; + match->total_delta[i] += delta; + + g_string_append_printf(ts, + ", %"PRId64" match hits, " + "Δ+%"PRId64 " since last match," + " %"PRId64 " avg insns/match\n", + match->hits[i], delta, + match->total_delta[i] / match->hits[i]); + + match->last_hit[i] = icount; + + qemu_plugin_outs(ts->str); + + g_ptr_array_add(match->history[i], insn); } static void vcpu_tb_trans(qemu_plugin_id_t id, struct qemu_plugin_tb *tb) @@ -44,7 +102,7 @@ static void vcpu_tb_trans(qemu_plugin_id_t id, struct qemu_plugin_tb *tb) if (do_inline) { qemu_plugin_register_vcpu_insn_exec_inline( - insn, QEMU_PLUGIN_INLINE_ADD_U64, &insn_count, 1); + insn, QEMU_PLUGIN_INLINE_ADD_U64, &inline_insn_count, 1); } else { uint64_t vaddr = qemu_plugin_insn_vaddr(insn); qemu_plugin_register_vcpu_insn_exec_cb( @@ -60,15 +118,38 @@ static void vcpu_tb_trans(qemu_plugin_id_t id, struct qemu_plugin_tb *tb) 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) { + char *insn_disas = qemu_plugin_insn_disas(insn); + int j; + for (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) { - int i; for (i = 0; i <= sizes->len; i++) { unsigned long *cnt = &g_array_index(sizes, unsigned long, i); if (*cnt) { @@ -76,12 +157,39 @@ static void plugin_exit(qemu_plugin_id_t id, void *p) "len %d bytes: %ld insns\n", i, *cnt); } } + } else if (do_inline) { + g_string_append_printf(out, "insns: %" PRIu64 "\n", inline_insn_count); } else { - g_string_append_printf(out, "insns: %" PRIu64 "\n", insn_count); + uint64_t total_insns = 0; + for (i = 0; i < MAX_CPUS; i++) { + InstructionCount *c = &counts[i]; + if (c->insn_count) { + g_string_append_printf(out, "cpu %d insns: %" PRIu64 "\n", + i, c->insn_count); + total_insns += c->insn_count; + } + } + g_string_append_printf(out, "total insns: %" PRIu64 "\n", + total_insns); } qemu_plugin_outs(out->str); } + +/* Add a match to the array of matches */ +static void parse_match(char *match) +{ + Match new_match = { .match_string = match }; + int i; + for (i = 0; i < MAX_CPUS; i++) { + new_match.history[i] = g_ptr_array_new(); + } + if (!matches) { + matches = g_array_new(false, true, sizeof(Match)); + } + 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) @@ -99,6 +207,8 @@ QEMU_PLUGIN_EXPORT int qemu_plugin_install(qemu_plugin_id_t id, 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; |
