From: "Alex Bennée" <alex.bennee@linaro.org>
To: peter.maydell@linaro.org
Cc: "Richard Henderson" <richard.henderson@linaro.org>,
"Alex Bennée" <alex.bennee@linaro.org>,
qemu-devel@nongnu.org
Subject: [PULL v2 67/73] tests/plugin: add hotpages to analyse memory access patterns
Date: Fri, 25 Oct 2019 07:37:07 +0100 [thread overview]
Message-ID: <20191025063713.23374-68-alex.bennee@linaro.org> (raw)
In-Reply-To: <20191025063713.23374-1-alex.bennee@linaro.org>
This plugin gives a summary of access patterns grouped by "pages" and
showing read/write patterns by vCPUS.
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
diff --git a/tests/plugin/Makefile b/tests/plugin/Makefile
index 3656429d46b..75467b6db85 100644
--- a/tests/plugin/Makefile
+++ b/tests/plugin/Makefile
@@ -12,6 +12,7 @@ NAMES += insn
NAMES += mem
NAMES += hotblocks
NAMES += howvec
+NAMES += hotpages
SONAMES := $(addsuffix .so,$(addprefix lib,$(NAMES)))
diff --git a/tests/plugin/hotpages.c b/tests/plugin/hotpages.c
new file mode 100644
index 00000000000..77df07a3ccf
--- /dev/null
+++ b/tests/plugin/hotpages.c
@@ -0,0 +1,191 @@
+/*
+ * Copyright (C) 2019, Alex Bennée <alex.bennee@linaro.org>
+ *
+ * Hot Pages - show which pages saw the most memory accesses.
+ *
+ * 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 <inttypes.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <glib.h>
+
+#include <qemu-plugin.h>
+
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+
+static uint64_t page_size = 4096;
+static uint64_t page_mask;
+static int limit = 50;
+static enum qemu_plugin_mem_rw rw = QEMU_PLUGIN_MEM_RW;
+static bool track_io;
+
+enum sort_type {
+ SORT_RW = 0,
+ SORT_R,
+ SORT_W,
+ SORT_A
+};
+
+static int sort_by = SORT_RW;
+
+typedef struct {
+ uint64_t page_address;
+ int cpu_read;
+ int cpu_write;
+ uint64_t reads;
+ uint64_t writes;
+} PageCounters;
+
+static GMutex lock;
+static GHashTable *pages;
+
+static gint cmp_access_count(gconstpointer a, gconstpointer b)
+{
+ PageCounters *ea = (PageCounters *) a;
+ PageCounters *eb = (PageCounters *) b;
+ int r;
+ switch (sort_by) {
+ case SORT_RW:
+ r = (ea->reads + ea->writes) > (eb->reads + eb->writes) ? -1 : 1;
+ break;
+ case SORT_R:
+ r = ea->reads > eb->reads ? -1 : 1;
+ break;
+ case SORT_W:
+ r = ea->writes > eb->writes ? -1 : 1;
+ break;
+ case SORT_A:
+ r = ea->page_address > eb->page_address ? -1 : 1;
+ break;
+ default:
+ g_assert_not_reached();
+ }
+ return r;
+}
+
+
+static void plugin_exit(qemu_plugin_id_t id, void *p)
+{
+ g_autoptr(GString) report = g_string_new("Addr, RCPUs, Reads, WCPUs, Writes\n");
+ int i;
+ GList *counts;
+
+ counts = g_hash_table_get_values(pages);
+ if (counts && g_list_next(counts)) {
+ GList *it;
+
+ it = g_list_sort(counts, cmp_access_count);
+
+ for (i = 0; i < limit && it->next; i++, it = it->next) {
+ PageCounters *rec = (PageCounters *) it->data;
+ g_string_append_printf(report,
+ "%#016"PRIx64", 0x%04x, %"PRId64
+ ", 0x%04x, %"PRId64"\n",
+ rec->page_address,
+ rec->cpu_read, rec->reads,
+ rec->cpu_write, rec->writes);
+ }
+ g_list_free(it);
+ }
+
+ qemu_plugin_outs(report->str);
+}
+
+static void plugin_init(void)
+{
+ page_mask = (page_size - 1);
+ pages = g_hash_table_new(NULL, g_direct_equal);
+}
+
+static void vcpu_haddr(unsigned int cpu_index, qemu_plugin_meminfo_t meminfo,
+ uint64_t vaddr, void *udata)
+{
+ struct qemu_plugin_hwaddr *hwaddr = qemu_plugin_get_hwaddr(meminfo, vaddr);
+ uint64_t page;
+ PageCounters *count;
+
+ /* We only get a hwaddr for system emulation */
+ if (track_io) {
+ if (hwaddr && qemu_plugin_hwaddr_is_io(hwaddr)) {
+ page = vaddr;
+ } else {
+ return;
+ }
+ } else {
+ if (hwaddr && !qemu_plugin_hwaddr_is_io(hwaddr)) {
+ page = (uint64_t) qemu_plugin_hwaddr_device_offset(hwaddr);
+ } else {
+ page = vaddr;
+ }
+ }
+ page &= ~page_mask;
+
+ g_mutex_lock(&lock);
+ count = (PageCounters *) g_hash_table_lookup(pages, GUINT_TO_POINTER(page));
+
+ if (!count) {
+ count = g_new0(PageCounters, 1);
+ count->page_address = page;
+ g_hash_table_insert(pages, GUINT_TO_POINTER(page), (gpointer) count);
+ }
+ if (qemu_plugin_mem_is_store(meminfo)) {
+ count->writes++;
+ count->cpu_write |= (1 << cpu_index);
+ } else {
+ count->reads++;
+ count->cpu_read |= (1 << cpu_index);
+ }
+
+ g_mutex_unlock(&lock);
+}
+
+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);
+ qemu_plugin_register_vcpu_mem_cb(insn, vcpu_haddr,
+ 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)
+{
+ int i;
+
+ for (i = 0; i < argc; i++) {
+ char *opt = argv[i];
+ if (g_strcmp0(opt, "reads") == 0) {
+ sort_by = SORT_R;
+ } else if (g_strcmp0(opt, "writes") == 0) {
+ sort_by = SORT_W;
+ } else if (g_strcmp0(opt, "address") == 0) {
+ sort_by = SORT_A;
+ } else if (g_strcmp0(opt, "io") == 0) {
+ track_io = true;
+ } else if (g_str_has_prefix(opt, "pagesize=")) {
+ page_size = g_ascii_strtoull(opt + 9, NULL, 10);
+ } else {
+ fprintf(stderr, "option parsing failed: %s\n", opt);
+ return -1;
+ }
+ }
+
+ plugin_init();
+
+ qemu_plugin_register_vcpu_tb_trans_cb(id, vcpu_tb_trans);
+ qemu_plugin_register_atexit_cb(id, plugin_exit, NULL);
+ return 0;
+}
--
2.20.1
next prev parent reply other threads:[~2019-10-25 7:36 UTC|newest]
Thread overview: 84+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-10-25 6:36 [PULL v2 00/73] tcg plugins and testing updates Alex Bennée
2019-10-25 6:36 ` [PULL v2 01/73] travis.yml: reduce scope of the --enable-debug build Alex Bennée
2019-10-25 6:36 ` [PULL v2 02/73] travis.yml: Add libvdeplug-dev to compile-test net/vde.c Alex Bennée
2019-10-25 6:36 ` [PULL v2 03/73] travis.yml: Use libsdl2 instead of libsdl1.2, and install libsdl2-image Alex Bennée
2019-10-25 6:36 ` [PULL v2 04/73] travis.yml: Use newer version of libgnutls and libpng Alex Bennée
2019-10-25 6:36 ` [PULL v2 05/73] travis.yml: Fix the ccache lines Alex Bennée
2019-10-25 6:36 ` [PULL v2 06/73] travis.yml: Test the release tarball Alex Bennée
2019-10-25 6:36 ` [PULL v2 07/73] travis.yml: bump Xcode 10 to latest dot release Alex Bennée
2019-10-25 6:36 ` [PULL v2 08/73] cirrus.yml: add latest Xcode build target Alex Bennée
2019-10-25 6:36 ` [PULL v2 09/73] tests/vm: netbsd autoinstall, using serial console Alex Bennée
2019-10-25 6:36 ` [PULL v2 10/73] tests/vm: Let subclasses disable IPv6 Alex Bennée
2019-10-25 6:36 ` [PULL v2 11/73] tests/vm/netbsd: Disable IPv6 Alex Bennée
2019-10-25 6:36 ` [PULL v2 12/73] travis.yml: cache the clang sanitizer build Alex Bennée
2019-10-25 6:36 ` [PULL v2 13/73] gitlab-ci.yml: Use libvdeplug-dev to compile-test the VDE network backend Alex Bennée
2019-10-25 6:36 ` [PULL v2 14/73] travis.yml: --enable-debug-tcg to check-tcg Alex Bennée
2019-10-25 6:36 ` [PULL v2 15/73] tests/docker: set HOST_ARCH if we don't have ARCH Alex Bennée
2019-10-25 6:36 ` [PULL v2 16/73] tests/docker: update Travis image to a more current version Alex Bennée
2019-10-25 6:36 ` [PULL v2 17/73] trace: expand mem_info:size_shift to 4 bits Alex Bennée
2019-10-25 6:36 ` [PULL v2 18/73] trace: add mmu_index to mem_info Alex Bennée
2019-10-25 6:36 ` [PULL v2 19/73] cpu: introduce cpu_in_exclusive_context() Alex Bennée
2019-10-25 6:36 ` [PULL v2 20/73] translate-all: use cpu_in_exclusive_work_context() in tb_flush Alex Bennée
2019-10-25 6:36 ` [PULL v2 21/73] docs/devel: add plugins.rst design document Alex Bennée
2019-10-25 6:36 ` [PULL v2 22/73] plugin: add user-facing API Alex Bennée
2019-10-25 6:36 ` [PULL v2 23/73] plugin: add core code Alex Bennée
2019-10-25 6:36 ` [PULL v2 24/73] plugin: add implementation of the api Alex Bennée
2019-10-25 6:36 ` [PULL v2 25/73] queue: add QTAILQ_REMOVE_SEVERAL Alex Bennée
2019-10-25 6:36 ` [PULL v2 26/73] cputlb: document get_page_addr_code Alex Bennée
2019-10-25 6:36 ` [PULL v2 27/73] cputlb: introduce get_page_addr_code_hostp Alex Bennée
2019-10-25 6:36 ` [PULL v2 28/73] tcg: add tcg_gen_st_ptr Alex Bennée
2019-10-25 6:36 ` [PULL v2 29/73] plugin-gen: add module for TCG-related code Alex Bennée
2019-10-25 6:36 ` [PULL v2 30/73] atomic_template: add inline trace/plugin helpers Alex Bennée
2019-10-25 6:36 ` [PULL v2 31/73] tcg: let plugins instrument virtual memory accesses Alex Bennée
2019-10-25 6:36 ` [PULL v2 32/73] plugins: implement helpers for resolving hwaddr Alex Bennée
2019-10-25 6:36 ` [PULL v2 33/73] translate-all: notify plugin code of tb_flush Alex Bennée
2019-10-25 6:36 ` [PULL v2 34/73] *-user: notify plugin of exit Alex Bennée
2019-10-25 6:36 ` [PULL v2 35/73] *-user: plugin syscalls Alex Bennée
2019-10-25 6:36 ` [PULL v2 36/73] cpu: hook plugin vcpu events Alex Bennée
2019-10-25 6:36 ` [PULL v2 37/73] plugin-gen: add plugin_insn_append Alex Bennée
2019-10-25 6:36 ` [PULL v2 38/73] cputlb: ensure _cmmu helper functions follow the naming standard Alex Bennée
2019-10-25 6:36 ` [PULL v2 39/73] translator: add translator_ld{ub,sw,uw,l,q} Alex Bennée
2019-10-25 6:36 ` [PULL v2 40/73] target/arm: fetch code with translator_ld Alex Bennée
2019-10-25 6:36 ` [PULL v2 41/73] target/ppc: " Alex Bennée
2019-10-25 6:36 ` [PULL v2 42/73] target/sh4: " Alex Bennée
2019-10-25 6:36 ` [PULL v2 43/73] target/i386: " Alex Bennée
2019-10-25 6:36 ` [PULL v2 44/73] target/hppa: " Alex Bennée
2019-10-25 6:36 ` [PULL v2 45/73] target/m68k: " Alex Bennée
2019-10-25 6:36 ` [PULL v2 46/73] target/alpha: " Alex Bennée
2019-10-25 7:40 ` USB-audio sound issues with qemu-system-ppc in Linux and Windows Howard Spoelstra
2019-10-25 6:36 ` [PULL v2 47/73] target/riscv: fetch code with translator_ld Alex Bennée
2019-10-25 6:36 ` [PULL v2 48/73] target/sparc: " Alex Bennée
2019-10-25 6:36 ` [PULL v2 49/73] target/xtensa: " Alex Bennée
2019-10-25 6:36 ` [PULL v2 50/73] target/openrisc: " Alex Bennée
2019-10-25 6:36 ` [PULL v2 51/73] translator: inject instrumentation from plugins Alex Bennée
2019-10-25 6:36 ` [PULL v2 52/73] configure: add --enable-plugins Alex Bennée
2019-10-25 6:36 ` [PULL v2 53/73] plugin: add API symbols to qemu-plugins.symbols Alex Bennée
2019-10-25 6:36 ` [PULL v2 54/73] plugin: expand the plugin_init function to include an info block Alex Bennée
2019-10-25 6:36 ` [PULL v2 55/73] plugin: add qemu_plugin_insn_disas helper Alex Bennée
2019-10-25 6:36 ` [PULL v2 56/73] plugin: add qemu_plugin_outs helper Alex Bennée
2019-10-25 6:36 ` [PULL v2 57/73] vl: support -plugin option Alex Bennée
2019-10-25 6:36 ` [PULL v2 58/73] linux-user: " Alex Bennée
2019-10-25 6:36 ` [PULL v2 59/73] tests/plugin: add sample plugins Alex Bennée
2019-10-25 6:37 ` [PULL v2 60/73] tests/tcg/Makefile.target: fix path to config-host.mak Alex Bennée
2019-10-25 6:37 ` [PULL v2 61/73] tests/tcg: set QEMU_OPTS for all cris runs Alex Bennée
2019-10-25 6:37 ` [PULL v2 62/73] tests/tcg: move "virtual" tests to EXTRA_TESTS Alex Bennée
2019-10-25 6:37 ` [PULL v2 63/73] tests/tcg: drop test-i386-fprem from TESTS when not SLOW Alex Bennée
2019-10-25 6:37 ` [PULL v2 64/73] tests/tcg: enable plugin testing Alex Bennée
2019-10-25 6:37 ` [PULL v2 65/73] tests/plugin: add a hotblocks plugin Alex Bennée
2019-10-25 6:37 ` [PULL v2 66/73] tests/plugin: add instruction execution breakdown Alex Bennée
2019-10-25 6:37 ` Alex Bennée [this message]
2019-10-25 6:37 ` [PULL v2 68/73] accel/stubs: reduce headers from tcg-stub Alex Bennée
2019-10-25 6:37 ` [PULL v2 69/73] include/exec: wrap cpu_ldst.h in CONFIG_TCG Alex Bennée
2019-10-25 6:37 ` [PULL v2 70/73] .travis.yml: add --enable-plugins tests Alex Bennée
2019-10-25 6:37 ` [PULL v2 71/73] scripts/checkpatch.pl: don't complain about (foo, /* empty */) Alex Bennée
2019-10-25 6:37 ` [PULL v2 72/73] MAINTAINERS: add me for the TCG plugins code Alex Bennée
2019-10-25 6:37 ` [PULL v2 73/73] travis.yml: enable linux-gcc-debug-tcg cache Alex Bennée
2019-10-25 12:59 ` [PULL v2 00/73] tcg plugins and testing updates Markus Armbruster
2019-10-25 15:04 ` Alex Bennée
2019-10-25 20:23 ` Markus Armbruster
2019-10-27 19:44 ` Peter Maydell
2019-10-28 9:07 ` Alex Bennée
2019-11-06 12:42 ` Markus Armbruster
2019-11-08 17:23 ` Peter Maydell
2019-10-25 16:53 ` Peter Maydell
2019-10-25 19:38 ` Alex Bennée
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20191025063713.23374-68-alex.bennee@linaro.org \
--to=alex.bennee@linaro.org \
--cc=peter.maydell@linaro.org \
--cc=qemu-devel@nongnu.org \
--cc=richard.henderson@linaro.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).