From b40310616d2bd550279dd22b05483c3c613a00ff Mon Sep 17 00:00:00 2001 From: Mahmoud Mandour Date: Fri, 6 Aug 2021 15:10:12 +0100 Subject: [PATCH 01/22] plugins/execlog: removed unintended "s" at the end of log lines. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Mahmoud Mandour Signed-off-by: Alex Bennée Message-Id: <20210803151428.125323-1-ma.mandourr@gmail.com> Message-Id: <20210806141015.2487502-2-alex.bennee@linaro.org> Cc: qemu-stable@nongnu.org --- contrib/plugins/execlog.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/plugins/execlog.c b/contrib/plugins/execlog.c index 2de9f0d7d4..a5275dcc15 100644 --- a/contrib/plugins/execlog.c +++ b/contrib/plugins/execlog.c @@ -67,7 +67,7 @@ static void vcpu_insn_exec(unsigned int cpu_index, void *udata) /* Print previous instruction in cache */ if (s->len) { qemu_plugin_outs(s->str); - qemu_plugin_outs("s\n"); + qemu_plugin_outs("\n"); } /* Store new instruction in cache */ From 8d316275ade2aa8ed9ede7c4518d3244ca941cb8 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Fri, 6 Aug 2021 15:10:13 +0100 Subject: [PATCH 02/22] gitlab-ci: Merge "build-disabled" with "build-without-default-features" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Both jobs are testing more or less the same thing (building QEMU with features disabled), so we are wasting precious CI cycles here by doing this twice. Merge the jobs by using --without-default-features by default and just adding some additional --disable-... switches which are not covered by the generic switch (yet). And while we're at it, also test compilation with "--disable-fdt" (which forces us to change the list of targets in this job, though, since some targets do not work without fdt). Signed-off-by: Thomas Huth Reviewed-by: Willian Rampazzo Message-Id: <20210730143809.717079-2-thuth@redhat.com> Signed-off-by: Alex Bennée Message-Id: <20210806141015.2487502-3-alex.bennee@linaro.org> --- .gitlab-ci.d/buildtest.yml | 97 +++++--------------------------------- 1 file changed, 13 insertions(+), 84 deletions(-) diff --git a/.gitlab-ci.d/buildtest.yml b/.gitlab-ci.d/buildtest.yml index 903ee65f32..f390f98044 100644 --- a/.gitlab-ci.d/buildtest.yml +++ b/.gitlab-ci.d/buildtest.yml @@ -202,85 +202,6 @@ acceptance-system-opensuse: MAKE_CHECK_ARGS: check-acceptance -build-disabled: - extends: .native_build_job_template - needs: - job: amd64-fedora-container - variables: - IMAGE: fedora - CONFIGURE_ARGS: - --disable-attr - --disable-auth-pam - --disable-avx2 - --disable-bochs - --disable-brlapi - --disable-bzip2 - --disable-cap-ng - --disable-capstone - --disable-cloop - --disable-coroutine-pool - --disable-curl - --disable-curses - --disable-dmg - --disable-docs - --disable-gcrypt - --disable-glusterfs - --disable-gnutls - --disable-gtk - --disable-guest-agent - --disable-iconv - --disable-keyring - --disable-kvm - --disable-libiscsi - --disable-libpmem - --disable-libssh - --disable-libudev - --disable-libusb - --disable-libxml2 - --disable-linux-aio - --disable-live-block-migration - --disable-lzo - --disable-malloc-trim - --disable-mpath - --disable-nettle - --disable-numa - --disable-opengl - --disable-parallels - --disable-pie - --disable-qcow1 - --disable-qed - --disable-qom-cast-debug - --disable-rbd - --disable-rdma - --disable-replication - --disable-sdl - --disable-seccomp - --disable-slirp - --disable-smartcard - --disable-snappy - --disable-sparse - --disable-spice - --disable-strip - --disable-tpm - --disable-usb-redir - --disable-vdi - --disable-vhost-crypto - --disable-vhost-net - --disable-vhost-scsi - --disable-vhost-kernel - --disable-vhost-user - --disable-vhost-vdpa - --disable-vhost-vsock - --disable-virglrenderer - --disable-vnc - --disable-vte - --disable-vvfat - --disable-xen - --disable-zstd - TARGETS: arm-softmmu i386-softmmu ppc64-softmmu mips64-softmmu - s390x-softmmu i386-linux-user - MAKE_CHECK_ARGS: check-qtest SPEED=slow - # This jobs explicitly disable TCG (--disable-tcg), KVM is detected by # the configure script. The container doesn't contain Xen headers so # Xen accelerator is not detected / selected. As result it build the @@ -649,12 +570,20 @@ build-without-default-devices: build-without-default-features: extends: .native_build_job_template needs: - job: amd64-debian-container + job: amd64-fedora-container variables: - IMAGE: debian-amd64 - CONFIGURE_ARGS: --without-default-features --disable-user - --target-list-exclude=arm-softmmu,i386-softmmu,mipsel-softmmu,mips64-softmmu,ppc-softmmu - MAKE_CHECK_ARGS: check-unit + IMAGE: fedora + CONFIGURE_ARGS: + --without-default-features + --disable-capstone + --disable-fdt + --disable-pie + --disable-qom-cast-debug + --disable-slirp + --disable-strip + TARGETS: avr-softmmu i386-softmmu mips64-softmmu s390x-softmmu sh4-softmmu + sparc64-softmmu hexagon-linux-user i386-linux-user s390x-linux-user + MAKE_CHECK_ARGS: check-unit check-qtest SPEED=slow build-libvhost-user: stage: build From d3ac658fbeb568ced3b4623f2ce4a8ee5ee5fa68 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Fri, 6 Aug 2021 15:10:14 +0100 Subject: [PATCH 03/22] gitlab-ci: Remove superfluous "dnf install" statement MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The container already features meson and ninja, so there is no need to try to install it with dnf again. Signed-off-by: Thomas Huth Reviewed-by: Willian Rampazzo Message-Id: <20210730143809.717079-3-thuth@redhat.com> Signed-off-by: Alex Bennée Message-Id: <20210806141015.2487502-4-alex.bennee@linaro.org> --- .gitlab-ci.d/buildtest.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.gitlab-ci.d/buildtest.yml b/.gitlab-ci.d/buildtest.yml index f390f98044..38f08452f1 100644 --- a/.gitlab-ci.d/buildtest.yml +++ b/.gitlab-ci.d/buildtest.yml @@ -590,8 +590,6 @@ build-libvhost-user: image: $CI_REGISTRY_IMAGE/qemu/fedora:latest needs: job: amd64-fedora-container - before_script: - - dnf install -y meson ninja-build script: - mkdir subprojects/libvhost-user/build - cd subprojects/libvhost-user/build From 40e916b4bc414c730df48c7d4405e66c8691756f Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Fri, 6 Aug 2021 15:10:15 +0100 Subject: [PATCH 04/22] gitlab-ci: Fix ..._RUNNER_AVAILABLE variables and document them MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The patch that recently introduced the S390X_RUNNER_AVAILABLE variable in custom-runners.yml missed that the bottom half of the file is rather about aarch64 than s390x. Thus rename the S390X_RUNNER_AVAILABLE to AARCH64_RUNNER_AVAILABLE in those jobs. Finally mention both variables in our CI documentation, too. Fixes: c5dd0f0342 ("Improve rules for the staging branch") Signed-off-by: Thomas Huth Reviewed-by: Willian Rampazzo Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20210730143809.717079-4-thuth@redhat.com> [AJB: moved due to docu changes] Signed-off-by: Alex Bennée Message-Id: <20210806141015.2487502-5-alex.bennee@linaro.org> --- .gitlab-ci.d/custom-runners.yml | 12 ++++++------ docs/devel/ci-jobs.rst | 11 +++++++++++ 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/.gitlab-ci.d/custom-runners.yml b/.gitlab-ci.d/custom-runners.yml index 564b94565d..0d3e4a7b4b 100644 --- a/.gitlab-ci.d/custom-runners.yml +++ b/.gitlab-ci.d/custom-runners.yml @@ -137,7 +137,7 @@ ubuntu-20.04-aarch64-all-linux-static: - aarch64 rules: - if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH =~ /^staging/' - - if: "$S390X_RUNNER_AVAILABLE" + - if: "$AARCH64_RUNNER_AVAILABLE" script: # --disable-libssh is needed because of https://bugs.launchpad.net/qemu/+bug/1838763 # --disable-glusterfs is needed because there's no static version of those libs in distro supplied packages @@ -157,7 +157,7 @@ ubuntu-20.04-aarch64-all: - aarch64 rules: - if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH =~ /^staging/' - - if: "$S390X_RUNNER_AVAILABLE" + - if: "$AARCH64_RUNNER_AVAILABLE" script: - mkdir build - cd build @@ -174,7 +174,7 @@ ubuntu-20.04-aarch64-alldbg: - aarch64 rules: - if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH =~ /^staging/' - - if: "$S390X_RUNNER_AVAILABLE" + - if: "$AARCH64_RUNNER_AVAILABLE" script: - mkdir build - cd build @@ -193,7 +193,7 @@ ubuntu-20.04-aarch64-clang: rules: - if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH =~ /^staging/' when: manual - - if: "$S390X_RUNNER_AVAILABLE" + - if: "$AARCH64_RUNNER_AVAILABLE" when: manual script: - mkdir build @@ -211,7 +211,7 @@ ubuntu-20.04-aarch64-tci: - aarch64 rules: - if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH =~ /^staging/' - - if: "$S390X_RUNNER_AVAILABLE" + - if: "$AARCH64_RUNNER_AVAILABLE" script: - mkdir build - cd build @@ -228,7 +228,7 @@ ubuntu-20.04-aarch64-notcg: rules: - if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH =~ /^staging/' when: manual - - if: "$S390X_RUNNER_AVAILABLE" + - if: "$AARCH64_RUNNER_AVAILABLE" when: manual script: - mkdir build diff --git a/docs/devel/ci-jobs.rst b/docs/devel/ci-jobs.rst index 9cd9819786..277975e4ad 100644 --- a/docs/devel/ci-jobs.rst +++ b/docs/devel/ci-jobs.rst @@ -38,3 +38,14 @@ these artifacts are not already cached, downloading them make the jobs reach the timeout limit). Set this variable to have the tests using the Avocado framework run automatically. +AARCH64_RUNNER_AVAILABLE +~~~~~~~~~~~~~~~~~~~~~~~~ +If you've got access to an aarch64 host that can be used as a gitlab-CI +runner, you can set this variable to enable the tests that require this +kind of host. The runner should be tagged with "aarch64". + +S390X_RUNNER_AVAILABLE +~~~~~~~~~~~~~~~~~~~~~~ +If you've got access to an IBM Z host that can be used as a gitlab-CI +runner, you can set this variable to enable the tests that require this +kind of host. The runner should be tagged with "s390x". From b906acace2d4f68b6ff8de73739a773cc4851436 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 11 Aug 2021 12:05:50 +0200 Subject: [PATCH 05/22] plugins: do not limit exported symbols if modules are active MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On Mac --enable-modules and --enable-plugins are currently incompatible, because the Apple -Wl,-exported_symbols_list command line options prevents the export of any symbols needed by the modules. On x86 -Wl,--dynamic-list does not have this effect, but only because the -Wl,--export-dynamic option provided by gmodule-2.0.pc overrides it. On Apple there is no -Wl,--export-dynamic, because it is the default, and thus no override. Either way, when modules are active there is no reason to include the plugin_ldflags. While at it, avoid the useless -Wl,--export-dynamic when --enable-plugins is specified but --enable-modules is not; this way, the GNU and Apple configurations are more similar. Resolves: https://gitlab.com/qemu-project/qemu/-/issues/516 Signed-off-by: Paolo Bonzini [AJB: fix noexport to no-export] Signed-off-by: Alex Bennée Message-Id: <20210811100550.54714-1-pbonzini@redhat.com> Cc: qemu-stable@nongnu.org --- configure | 5 ++--- plugins/meson.build | 14 ++++++++------ 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/configure b/configure index 9a79a004d7..7659870810 100755 --- a/configure +++ b/configure @@ -3187,9 +3187,8 @@ glib_req_ver=2.56 glib_modules=gthread-2.0 if test "$modules" = yes; then glib_modules="$glib_modules gmodule-export-2.0" -fi -if test "$plugins" = "yes"; then - glib_modules="$glib_modules gmodule-2.0" +elif test "$plugins" = "yes"; then + glib_modules="$glib_modules gmodule-no-export-2.0" fi for i in $glib_modules; do diff --git a/plugins/meson.build b/plugins/meson.build index e77723010e..bfd5c9822a 100644 --- a/plugins/meson.build +++ b/plugins/meson.build @@ -1,9 +1,11 @@ -if 'CONFIG_HAS_LD_DYNAMIC_LIST' in config_host - plugin_ldflags = ['-Wl,--dynamic-list=' + (meson.build_root() / 'qemu-plugins-ld.symbols')] -elif 'CONFIG_HAS_LD_EXPORTED_SYMBOLS_LIST' in config_host - plugin_ldflags = ['-Wl,-exported_symbols_list,' + (meson.build_root() / 'qemu-plugins-ld64.symbols')] -else - plugin_ldflags = [] +plugin_ldflags = [] +# Modules need more symbols than just those in plugins/qemu-plugins.symbols +if not enable_modules + if 'CONFIG_HAS_LD_DYNAMIC_LIST' in config_host + plugin_ldflags = ['-Wl,--dynamic-list=' + (meson.build_root() / 'qemu-plugins-ld.symbols')] + elif 'CONFIG_HAS_LD_EXPORTED_SYMBOLS_LIST' in config_host + plugin_ldflags = ['-Wl,-exported_symbols_list,' + (meson.build_root() / 'qemu-plugins-ld64.symbols')] + endif endif specific_ss.add(when: 'CONFIG_PLUGIN', if_true: [files( From c79a2116af6ad5a923e1bf127a78e8089e315021 Mon Sep 17 00:00:00 2001 From: Mahmoud Mandour Date: Tue, 3 Aug 2021 17:13:00 +0200 Subject: [PATCH 06/22] plugins/cache: supported multicore cache modelling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Multicore L1 cache modelling is introduced and is supported for both full system emulation and linux-user. For full-system emulation, L1 icache and dcache are maintained for each available core, since this information is exposed to the plugin through `qemu_plugin_n_vcpus()`. For linux-user, a static number of cores is assumed (default 1 core, and can be provided as a plugin argument `cores=N`). Every memory access goes through one of these caches, this approach is taken as it's somewhat akin to what happens on real setup, where a program that dispatches more threads than the available cores, they'll thrash each other Signed-off-by: Mahmoud Mandour Message-Id: <20210803151301.123581-2-ma.mandourr@gmail.com> Signed-off-by: Alex Bennée --- contrib/plugins/cache.c | 174 ++++++++++++++++++++++++++++++---------- 1 file changed, 131 insertions(+), 43 deletions(-) diff --git a/contrib/plugins/cache.c b/contrib/plugins/cache.c index 066ea6d8ec..a1e03ca882 100644 --- a/contrib/plugins/cache.c +++ b/contrib/plugins/cache.c @@ -17,18 +17,12 @@ static enum qemu_plugin_mem_rw rw = QEMU_PLUGIN_MEM_RW; static GHashTable *miss_ht; -static GMutex mtx; +static GMutex hashtable_lock; static GRand *rng; static int limit; static bool sys; -static uint64_t dmem_accesses; -static uint64_t dmisses; - -static uint64_t imem_accesses; -static uint64_t imisses; - enum EvictionPolicy { LRU, FIFO, @@ -80,6 +74,8 @@ typedef struct { int blksize_shift; uint64_t set_mask; uint64_t tag_mask; + uint64_t accesses; + uint64_t misses; } Cache; typedef struct { @@ -96,7 +92,16 @@ void (*update_miss)(Cache *cache, int set, int blk); void (*metadata_init)(Cache *cache); void (*metadata_destroy)(Cache *cache); -Cache *dcache, *icache; +static int cores; +static Cache **dcaches, **icaches; + +static GMutex *dcache_locks; +static GMutex *icache_locks; + +static uint64_t all_dmem_accesses; +static uint64_t all_imem_accesses; +static uint64_t all_imisses; +static uint64_t all_dmisses; static int pow_of_two(int num) { @@ -233,20 +238,24 @@ static bool bad_cache_params(int blksize, int assoc, int cachesize) static Cache *cache_init(int blksize, int assoc, int cachesize) { - if (bad_cache_params(blksize, assoc, cachesize)) { - return NULL; - } - Cache *cache; int i; uint64_t blk_mask; + /* + * This function shall not be called directly, and hence expects suitable + * parameters. + */ + g_assert(!bad_cache_params(blksize, assoc, cachesize)); + cache = g_new(Cache, 1); cache->assoc = assoc; cache->cachesize = cachesize; cache->num_sets = cachesize / (blksize * assoc); cache->sets = g_new(CacheSet, cache->num_sets); cache->blksize_shift = pow_of_two(blksize); + cache->accesses = 0; + cache->misses = 0; for (i = 0; i < cache->num_sets; i++) { cache->sets[i].blocks = g_new0(CacheBlock, assoc); @@ -263,6 +272,24 @@ static Cache *cache_init(int blksize, int assoc, int cachesize) return cache; } +static Cache **caches_init(int blksize, int assoc, int cachesize) +{ + Cache **caches; + int i; + + if (bad_cache_params(blksize, assoc, cachesize)) { + return NULL; + } + + caches = g_new(Cache *, cores); + + for (i = 0; i < cores; i++) { + caches[i] = cache_init(blksize, assoc, cachesize); + } + + return caches; +} + static int get_invalid_block(Cache *cache, uint64_t set) { int i; @@ -353,6 +380,7 @@ static void vcpu_mem_access(unsigned int vcpu_index, qemu_plugin_meminfo_t info, { uint64_t effective_addr; struct qemu_plugin_hwaddr *hwaddr; + int cache_idx; InsnData *insn; hwaddr = qemu_plugin_get_hwaddr(info, vaddr); @@ -361,32 +389,35 @@ static void vcpu_mem_access(unsigned int vcpu_index, qemu_plugin_meminfo_t info, } effective_addr = hwaddr ? qemu_plugin_hwaddr_phys_addr(hwaddr) : vaddr; + cache_idx = vcpu_index % cores; - g_mutex_lock(&mtx); - if (!access_cache(dcache, effective_addr)) { + g_mutex_lock(&dcache_locks[cache_idx]); + if (!access_cache(dcaches[cache_idx], effective_addr)) { insn = (InsnData *) userdata; - insn->dmisses++; - dmisses++; + __atomic_fetch_add(&insn->dmisses, 1, __ATOMIC_SEQ_CST); + dcaches[cache_idx]->misses++; } - dmem_accesses++; - g_mutex_unlock(&mtx); + dcaches[cache_idx]->accesses++; + g_mutex_unlock(&dcache_locks[cache_idx]); } static void vcpu_insn_exec(unsigned int vcpu_index, void *userdata) { uint64_t insn_addr; InsnData *insn; + int cache_idx; - g_mutex_lock(&mtx); insn_addr = ((InsnData *) userdata)->addr; - if (!access_cache(icache, insn_addr)) { + cache_idx = vcpu_index % cores; + g_mutex_lock(&icache_locks[cache_idx]); + if (!access_cache(icaches[cache_idx], insn_addr)) { insn = (InsnData *) userdata; - insn->imisses++; - imisses++; + __atomic_fetch_add(&insn->imisses, 1, __ATOMIC_SEQ_CST); + icaches[cache_idx]->misses++; } - imem_accesses++; - g_mutex_unlock(&mtx); + icaches[cache_idx]->accesses++; + g_mutex_unlock(&icache_locks[cache_idx]); } static void vcpu_tb_trans(qemu_plugin_id_t id, struct qemu_plugin_tb *tb) @@ -411,7 +442,7 @@ static void vcpu_tb_trans(qemu_plugin_id_t id, struct qemu_plugin_tb *tb) * new entries for those instructions. Instead, we fetch the same * entry from the hash table and register it for the callback again. */ - g_mutex_lock(&mtx); + g_mutex_lock(&hashtable_lock); data = g_hash_table_lookup(miss_ht, GUINT_TO_POINTER(effective_addr)); if (data == NULL) { data = g_new0(InsnData, 1); @@ -421,7 +452,7 @@ static void vcpu_tb_trans(qemu_plugin_id_t id, struct qemu_plugin_tb *tb) g_hash_table_insert(miss_ht, GUINT_TO_POINTER(effective_addr), (gpointer) data); } - g_mutex_unlock(&mtx); + g_mutex_unlock(&hashtable_lock); qemu_plugin_register_vcpu_mem_cb(insn, vcpu_mem_access, QEMU_PLUGIN_CB_NO_REGS, @@ -453,6 +484,15 @@ static void cache_free(Cache *cache) g_free(cache); } +static void caches_free(Cache **caches) +{ + int i; + + for (i = 0; i < cores; i++) { + cache_free(caches[i]); + } +} + static int dcmp(gconstpointer a, gconstpointer b) { InsnData *insn_a = (InsnData *) a; @@ -461,6 +501,37 @@ static int dcmp(gconstpointer a, gconstpointer b) return insn_a->dmisses < insn_b->dmisses ? 1 : -1; } +static void append_stats_line(GString *line, uint64_t daccess, uint64_t dmisses, + uint64_t iaccess, uint64_t imisses) +{ + double dmiss_rate, imiss_rate; + + dmiss_rate = ((double) dmisses) / (daccess) * 100.0; + imiss_rate = ((double) imisses) / (iaccess) * 100.0; + + g_string_append_printf(line, "%-14lu %-12lu %9.4lf%% %-14lu %-12lu" + " %9.4lf%%\n", + daccess, + dmisses, + daccess ? dmiss_rate : 0.0, + iaccess, + imisses, + iaccess ? imiss_rate : 0.0); +} + +static void sum_stats(void) +{ + int i; + + g_assert(cores > 1); + for (i = 0; i < cores; i++) { + all_imisses += icaches[i]->misses; + all_dmisses += dcaches[i]->misses; + all_imem_accesses += icaches[i]->accesses; + all_dmem_accesses += dcaches[i]->accesses; + } +} + static int icmp(gconstpointer a, gconstpointer b) { InsnData *insn_a = (InsnData *) a; @@ -471,19 +542,29 @@ static int icmp(gconstpointer a, gconstpointer b) static void log_stats(void) { - g_autoptr(GString) rep = g_string_new(""); - g_string_append_printf(rep, - "Data accesses: %lu, Misses: %lu\nMiss rate: %lf%%\n\n", - dmem_accesses, - dmisses, - ((double) dmisses / (double) dmem_accesses) * 100.0); + int i; + Cache *icache, *dcache; - g_string_append_printf(rep, - "Instruction accesses: %lu, Misses: %lu\nMiss rate: %lf%%\n\n", - imem_accesses, - imisses, - ((double) imisses / (double) imem_accesses) * 100.0); + g_autoptr(GString) rep = g_string_new("core #, data accesses, data misses," + " dmiss rate, insn accesses," + " insn misses, imiss rate\n"); + for (i = 0; i < cores; i++) { + g_string_append_printf(rep, "%-8d", i); + dcache = dcaches[i]; + icache = icaches[i]; + append_stats_line(rep, dcache->accesses, dcache->misses, + icache->accesses, icache->misses); + } + + if (cores > 1) { + sum_stats(); + g_string_append_printf(rep, "%-8s", "sum"); + append_stats_line(rep, all_dmem_accesses, all_dmisses, + all_imem_accesses, all_imisses); + } + + g_string_append(rep, "\n"); qemu_plugin_outs(rep->str); } @@ -530,8 +611,8 @@ static void plugin_exit(qemu_plugin_id_t id, void *p) log_stats(); log_top_insns(); - cache_free(dcache); - cache_free(icache); + caches_free(dcaches); + caches_free(icaches); g_hash_table_destroy(miss_ht); } @@ -579,6 +660,8 @@ int qemu_plugin_install(qemu_plugin_id_t id, const qemu_info_t *info, policy = LRU; + cores = sys ? qemu_plugin_n_vcpus() : 1; + for (i = 0; i < argc; i++) { char *opt = argv[i]; if (g_str_has_prefix(opt, "iblksize=")) { @@ -595,6 +678,8 @@ int qemu_plugin_install(qemu_plugin_id_t id, const qemu_info_t *info, dcachesize = g_ascii_strtoll(opt + 11, NULL, 10); } else if (g_str_has_prefix(opt, "limit=")) { limit = g_ascii_strtoll(opt + 6, NULL, 10); + } else if (g_str_has_prefix(opt, "cores=")) { + cores = g_ascii_strtoll(opt + 6, NULL, 10); } else if (g_str_has_prefix(opt, "evict=")) { gchar *p = opt + 6; if (g_strcmp0(p, "rand") == 0) { @@ -615,22 +700,25 @@ int qemu_plugin_install(qemu_plugin_id_t id, const qemu_info_t *info, policy_init(); - dcache = cache_init(dblksize, dassoc, dcachesize); - if (!dcache) { + dcaches = caches_init(dblksize, dassoc, dcachesize); + if (!dcaches) { const char *err = cache_config_error(dblksize, dassoc, dcachesize); fprintf(stderr, "dcache cannot be constructed from given parameters\n"); fprintf(stderr, "%s\n", err); return -1; } - icache = cache_init(iblksize, iassoc, icachesize); - if (!icache) { + icaches = caches_init(iblksize, iassoc, icachesize); + if (!icaches) { const char *err = cache_config_error(iblksize, iassoc, icachesize); fprintf(stderr, "icache cannot be constructed from given parameters\n"); fprintf(stderr, "%s\n", err); return -1; } + dcache_locks = g_new0(GMutex, cores); + icache_locks = g_new0(GMutex, cores); + qemu_plugin_register_vcpu_tb_trans_cb(id, vcpu_tb_trans); qemu_plugin_register_atexit_cb(id, plugin_exit, NULL); From 1156a03372e114df8da219ebbe483ece9c31eb54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Wed, 1 Sep 2021 13:38:14 +0100 Subject: [PATCH 07/22] plugins: sort exported symbol list MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This will make it easier to add new exported functions. Signed-off-by: Alex Bennée --- plugins/qemu-plugins.symbols | 48 ++++++++++++++++++------------------ 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/plugins/qemu-plugins.symbols b/plugins/qemu-plugins.symbols index 40b4ff3821..dee7610387 100644 --- a/plugins/qemu-plugins.symbols +++ b/plugins/qemu-plugins.symbols @@ -1,37 +1,37 @@ { - qemu_plugin_uninstall; - qemu_plugin_reset; - qemu_plugin_register_vcpu_init_cb; + qemu_plugin_get_hwaddr; + qemu_plugin_hwaddr_is_io; + qemu_plugin_insn_data; + qemu_plugin_insn_disas; + qemu_plugin_insn_haddr; + qemu_plugin_insn_size; + qemu_plugin_insn_vaddr; + qemu_plugin_mem_is_big_endian; + qemu_plugin_mem_is_sign_extended; + qemu_plugin_mem_is_store; + qemu_plugin_mem_size_shift; + qemu_plugin_n_max_vcpus; + qemu_plugin_n_vcpus; + qemu_plugin_outs; + qemu_plugin_register_atexit_cb; + qemu_plugin_register_flush_cb; qemu_plugin_register_vcpu_exit_cb; qemu_plugin_register_vcpu_idle_cb; - qemu_plugin_register_vcpu_resume_cb; + qemu_plugin_register_vcpu_init_cb; qemu_plugin_register_vcpu_insn_exec_cb; qemu_plugin_register_vcpu_insn_exec_inline; qemu_plugin_register_vcpu_mem_cb; qemu_plugin_register_vcpu_mem_inline; - qemu_plugin_register_vcpu_tb_trans_cb; - qemu_plugin_register_vcpu_tb_exec_cb; - qemu_plugin_register_vcpu_tb_exec_inline; - qemu_plugin_register_flush_cb; + qemu_plugin_register_vcpu_resume_cb; qemu_plugin_register_vcpu_syscall_cb; qemu_plugin_register_vcpu_syscall_ret_cb; - qemu_plugin_register_atexit_cb; - qemu_plugin_tb_n_insns; + qemu_plugin_register_vcpu_tb_exec_cb; + qemu_plugin_register_vcpu_tb_exec_inline; + qemu_plugin_register_vcpu_tb_trans_cb; + qemu_plugin_reset; qemu_plugin_tb_get_insn; + qemu_plugin_tb_n_insns; qemu_plugin_tb_vaddr; - qemu_plugin_insn_data; - qemu_plugin_insn_size; - qemu_plugin_insn_vaddr; - qemu_plugin_insn_haddr; - qemu_plugin_insn_disas; - qemu_plugin_mem_size_shift; - qemu_plugin_mem_is_sign_extended; - qemu_plugin_mem_is_big_endian; - qemu_plugin_mem_is_store; - qemu_plugin_get_hwaddr; - qemu_plugin_hwaddr_is_io; + qemu_plugin_uninstall; qemu_plugin_vcpu_for_each; - qemu_plugin_n_vcpus; - qemu_plugin_n_max_vcpus; - qemu_plugin_outs; }; From 5397acb8a6435f2f07cacfd2adbc2606710876b4 Mon Sep 17 00:00:00 2001 From: Mahmoud Mandour Date: Tue, 3 Aug 2021 17:13:01 +0200 Subject: [PATCH 08/22] docs/devel/tcg-plugins: added cores arg to cache plugin MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Mahmoud Mandour Message-Id: <20210803151301.123581-3-ma.mandourr@gmail.com> Signed-off-by: Alex Bennée --- docs/devel/tcg-plugins.rst | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/docs/devel/tcg-plugins.rst b/docs/devel/tcg-plugins.rst index 047bf4ada7..2d29a8972b 100644 --- a/docs/devel/tcg-plugins.rst +++ b/docs/devel/tcg-plugins.rst @@ -355,11 +355,8 @@ configuration when a given working set is run:: will report the following:: - Data accesses: 996479, Misses: 507 - Miss rate: 0.050879% - - Instruction accesses: 2641737, Misses: 18617 - Miss rate: 0.704726% + core #, data accesses, data misses, dmiss rate, insn accesses, insn misses, imiss rate + 0 996695 508 0.0510% 2642799 18617 0.7044% address, data misses, instruction 0x424f1e (_int_malloc), 109, movq %rax, 8(%rcx) @@ -403,3 +400,9 @@ The plugin has a number of arguments, all of them are optional: Sets the eviction policy to POLICY. Available policies are: :code:`lru`, :code:`fifo`, and :code:`rand`. The plugin will use the specified policy for both instruction and data caches. (default: POLICY = :code:`lru`) + + * arg="cores=N" + + Sets the number of cores for which we maintain separate icache and dcache. + (default: for linux-user, N = 1, for full system emulation: N = cores + available to guest) From 3a445acb491131c27636363eff607cf2344e1cf3 Mon Sep 17 00:00:00 2001 From: Mahmoud Mandour Date: Fri, 30 Jul 2021 15:58:05 +0200 Subject: [PATCH 09/22] plugins: allow plugin arguments to be passed directly MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Passing arguments to plugins had to be done through "arg=". This is redundant and introduces confusion especially when the argument has a name and value (e.g. `-plugin plugin_name,arg="argname=argvalue"`). This allows passing plugin arguments directly e.g: `-plugin plugin_name,argname=argvalue` For now, passing arguments through "arg=" is still supports but outputs a deprecation warning. Also, this commit makes boolean arguments passed to plugins in the `argname=on|off` form instead of the deprecated short-boolean form. Signed-off-by: Mahmoud Mandour Tested-by: Alex Bennée Reviewed-by: Alex Bennée Signed-off-by: Alex Bennée Message-Id: <20210730135817.17816-2-ma.mandourr@gmail.com> --- linux-user/main.c | 2 +- plugins/loader.c | 24 ++++++++++++++++++++---- qemu-options.hx | 9 ++++----- 3 files changed, 25 insertions(+), 10 deletions(-) diff --git a/linux-user/main.c b/linux-user/main.c index 37ed50d98e..a6094563b6 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -463,7 +463,7 @@ static const struct qemu_argument arg_table[] = { "", "[[enable=]][,events=][,file=]"}, #ifdef CONFIG_PLUGIN {"plugin", "QEMU_PLUGIN", true, handle_arg_plugin, - "", "[file=][,arg=]"}, + "", "[file=][,=]"}, #endif {"version", "QEMU_VERSION", false, handle_arg_version, "", "display version information and exit"}, diff --git a/plugins/loader.c b/plugins/loader.c index 05df40398d..a4ec281692 100644 --- a/plugins/loader.c +++ b/plugins/loader.c @@ -94,6 +94,8 @@ static int plugin_add(void *opaque, const char *name, const char *value, { struct qemu_plugin_parse_arg *arg = opaque; struct qemu_plugin_desc *p; + bool is_on; + char *fullarg; if (strcmp(name, "file") == 0) { if (strcmp(value, "") == 0) { @@ -107,18 +109,32 @@ static int plugin_add(void *opaque, const char *name, const char *value, QTAILQ_INSERT_TAIL(arg->head, p, entry); } arg->curr = p; - } else if (strcmp(name, "arg") == 0) { + } else { if (arg->curr == NULL) { error_setg(errp, "missing earlier '-plugin file=' option"); return 1; } + + if (g_strcmp0(name, "arg") == 0 && + !qapi_bool_parse(name, value, &is_on, NULL)) { + if (strchr(value, '=') == NULL) { + /* Will treat arg="argname" as "argname=on" */ + fullarg = g_strdup_printf("%s=%s", value, "on"); + } else { + fullarg = g_strdup_printf("%s", value); + } + warn_report("using 'arg=%s' is deprecated", value); + error_printf("Please use '%s' directly\n", fullarg); + } else { + fullarg = g_strdup_printf("%s=%s", name, value); + } + p = arg->curr; p->argc++; p->argv = g_realloc_n(p->argv, p->argc, sizeof(char *)); - p->argv[p->argc - 1] = g_strdup(value); - } else { - error_setg(errp, "-plugin: unexpected parameter '%s'; ignored", name); + p->argv[p->argc - 1] = fullarg; } + return 0; } diff --git a/qemu-options.hx b/qemu-options.hx index 83aa59a920..4a9ee722c9 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -4532,19 +4532,18 @@ SRST ERST DEF("plugin", HAS_ARG, QEMU_OPTION_plugin, - "-plugin [file=][,arg=]\n" + "-plugin [file=][,=]\n" " load a plugin\n", QEMU_ARCH_ALL) SRST -``-plugin file=file[,arg=string]`` +``-plugin file=file[,argname=argvalue]`` Load a plugin. ``file=file`` Load the given plugin from a shared library file. - ``arg=string`` - Argument string passed to the plugin. (Can be given multiple - times.) + ``argname=argvalue`` + Argument passed to the plugin. (Can be given multiple times.) ERST HXCOMM Internal use From 6a9e8a086d7c3d836bcc4772b3ab60072648f9aa Mon Sep 17 00:00:00 2001 From: Mahmoud Mandour Date: Fri, 30 Jul 2021 15:58:06 +0200 Subject: [PATCH 10/22] plugins/api: added a boolean parsing plugin api MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This call will help boolean argument parsing since arguments are now passed to plugins as a name and value. Signed-off-by: Mahmoud Mandour Reviewed-by: Alex Bennée Message-Id: <20210730135817.17816-3-ma.mandourr@gmail.com> [AJB: add to symbols] Signed-off-by: Alex Bennée --- include/qemu/qemu-plugin.h | 13 +++++++++++++ plugins/api.c | 5 +++++ plugins/qemu-plugins.symbols | 1 + 3 files changed, 19 insertions(+) diff --git a/include/qemu/qemu-plugin.h b/include/qemu/qemu-plugin.h index e6e815abc5..5f1017201f 100644 --- a/include/qemu/qemu-plugin.h +++ b/include/qemu/qemu-plugin.h @@ -577,4 +577,17 @@ int qemu_plugin_n_max_vcpus(void); */ void qemu_plugin_outs(const char *string); +/** + * qemu_plugin_bool_parse() - parses a boolean argument in the form of + * "=[on|yes|true|off|no|false]" + * + * @name: argument name, the part before the equals sign + * @val: argument value, what's after the equals sign + * @ret: output return value + * + * returns true if the combination @name=@val parses correctly to a boolean + * argument, and false otherwise + */ +bool qemu_plugin_bool_parse(const char *name, const char *val, bool *ret); + #endif /* QEMU_PLUGIN_API_H */ diff --git a/plugins/api.c b/plugins/api.c index 2d521e6ba8..acff9ce8ac 100644 --- a/plugins/api.c +++ b/plugins/api.c @@ -383,3 +383,8 @@ void qemu_plugin_outs(const char *string) { qemu_log_mask(CPU_LOG_PLUGIN, "%s", string); } + +bool qemu_plugin_bool_parse(const char *name, const char *value, bool *ret) +{ + return name && value && qapi_bool_parse(name, value, ret, NULL); +} diff --git a/plugins/qemu-plugins.symbols b/plugins/qemu-plugins.symbols index dee7610387..67b309ea2a 100644 --- a/plugins/qemu-plugins.symbols +++ b/plugins/qemu-plugins.symbols @@ -1,4 +1,5 @@ { + qemu_plugin_bool_parse; qemu_plugin_get_hwaddr; qemu_plugin_hwaddr_is_io; qemu_plugin_insn_data; From f698d5ef1cc401805b3eea92908e57be71a3ac05 Mon Sep 17 00:00:00 2001 From: Mahmoud Mandour Date: Fri, 30 Jul 2021 15:58:07 +0200 Subject: [PATCH 11/22] plugins/hotpages: introduce sortby arg and parsed bool args correctly MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since plugin arguments now expect boolean arguments, a plugin argument name "sortby" now expects a value of "read", "write", or "address". "io" arg is now expected to be passed as a full-form boolean parameter, i.e. "io=on|true|yes|off|false|no" Signed-off-by: Mahmoud Mandour Reviewed-by: Alex Bennée Signed-off-by: Alex Bennée Message-Id: <20210730135817.17816-4-ma.mandourr@gmail.com> --- contrib/plugins/hotpages.c | 30 ++++++++++++++++++++---------- docs/devel/tcg-plugins.rst | 15 +++++++++++++++ 2 files changed, 35 insertions(+), 10 deletions(-) diff --git a/contrib/plugins/hotpages.c b/contrib/plugins/hotpages.c index bf53267532..0d12910af6 100644 --- a/contrib/plugins/hotpages.c +++ b/contrib/plugins/hotpages.c @@ -169,16 +169,26 @@ int qemu_plugin_install(qemu_plugin_id_t id, const qemu_info_t *info, 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); + g_autofree char **tokens = g_strsplit(opt, "=", -1); + + if (g_strcmp0(tokens[0], "sortby") == 0) { + if (g_strcmp0(tokens[1], "reads") == 0) { + sort_by = SORT_R; + } else if (g_strcmp0(tokens[1], "writes") == 0) { + sort_by = SORT_W; + } else if (g_strcmp0(tokens[1], "address") == 0) { + sort_by = SORT_A; + } else { + fprintf(stderr, "invalid value to sortby: %s\n", tokens[1]); + return -1; + } + } else if (g_strcmp0(tokens[0], "io") == 0) { + if (!qemu_plugin_bool_parse(tokens[0], tokens[1], &track_io)) { + fprintf(stderr, "boolean argument parsing failed: %s\n", opt); + return -1; + } + } else if (g_strcmp0(tokens[0], "pagesize") == 0) { + page_size = g_ascii_strtoull(tokens[1], NULL, 10); } else { fprintf(stderr, "option parsing failed: %s\n", opt); return -1; diff --git a/docs/devel/tcg-plugins.rst b/docs/devel/tcg-plugins.rst index 2d29a8972b..aa75b390b1 100644 --- a/docs/devel/tcg-plugins.rst +++ b/docs/devel/tcg-plugins.rst @@ -193,6 +193,21 @@ Similar to hotblocks but this time tracks memory accesses:: 0x0000000048b000, 0x0001, 130594, 0x0001, 355 0x0000000048a000, 0x0001, 1826, 0x0001, 11 +The hotpages plugin can be configured using the following arguments: + + * sortby=reads|writes|address + + Log the data sorted by either the number of reads, the number of writes, or + memory address. (Default: entries are sorted by the sum of reads and writes) + + * io=on + + Track IO addresses. Only relevant to full system emulation. (Default: off) + + * pagesize=N + + The page size used. (Default: N = 4096) + - contrib/plugins/howvec.c This is an instruction classifier so can be used to count different From 8a3eab66e62993228887588d753eefacc918184b Mon Sep 17 00:00:00 2001 From: Mahmoud Mandour Date: Fri, 30 Jul 2021 15:58:08 +0200 Subject: [PATCH 12/22] plugins/hotblocks: Added correct boolean argument parsing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Mahmoud Mandour Reviewed-by: Alex Bennée Signed-off-by: Alex Bennée Message-Id: <20210730135817.17816-5-ma.mandourr@gmail.com> --- contrib/plugins/hotblocks.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/contrib/plugins/hotblocks.c b/contrib/plugins/hotblocks.c index 4b08340143..062200a7a4 100644 --- a/contrib/plugins/hotblocks.c +++ b/contrib/plugins/hotblocks.c @@ -133,8 +133,18 @@ QEMU_PLUGIN_EXPORT int qemu_plugin_install(qemu_plugin_id_t id, const qemu_info_t *info, int argc, char **argv) { - if (argc && strcmp(argv[0], "inline") == 0) { - do_inline = true; + for (int i = 0; i < argc; i++) { + char *opt = argv[i]; + g_autofree char **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 { + fprintf(stderr, "option parsing failed: %s\n", opt); + return -1; + } } plugin_init(); From b18a0cad812c6b3afc158bb050b0a2232f9776b7 Mon Sep 17 00:00:00 2001 From: Mahmoud Mandour Date: Fri, 30 Jul 2021 15:58:09 +0200 Subject: [PATCH 13/22] plugins/lockstep: make socket path not positional & parse bool arg MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Mahmoud Mandour Reviewed-by: Alex Bennée Signed-off-by: Alex Bennée Message-Id: <20210730135817.17816-6-ma.mandourr@gmail.com> --- contrib/plugins/lockstep.c | 31 ++++++++++++++++++++++--------- docs/devel/tcg-plugins.rst | 2 +- 2 files changed, 23 insertions(+), 10 deletions(-) diff --git a/contrib/plugins/lockstep.c b/contrib/plugins/lockstep.c index 7fd35eb669..a41ffe83fa 100644 --- a/contrib/plugins/lockstep.c +++ b/contrib/plugins/lockstep.c @@ -319,22 +319,35 @@ QEMU_PLUGIN_EXPORT int qemu_plugin_install(qemu_plugin_id_t id, int argc, char **argv) { int i; - - if (!argc || !argv[0]) { - qemu_plugin_outs("Need a socket path to talk to other instance."); - return -1; - } + g_autofree char *sock_path = NULL; for (i = 0; i < argc; i++) { char *p = argv[i]; - if (strcmp(p, "verbose") == 0) { - verbose = true; - } else if (!setup_unix_socket(argv[0])) { - qemu_plugin_outs("Failed to setup socket for communications."); + g_autofree char **tokens = g_strsplit(p, "=", 2); + + if (g_strcmp0(tokens[0], "verbose") == 0) { + if (!qemu_plugin_bool_parse(tokens[0], tokens[1], &verbose)) { + fprintf(stderr, "boolean argument parsing failed: %s\n", p); + return -1; + } + } else if (g_strcmp0(tokens[0], "sockpath") == 0) { + sock_path = tokens[1]; + } else { + fprintf(stderr, "option parsing failed: %s\n", p); return -1; } } + if (sock_path == NULL) { + fprintf(stderr, "Need a socket path to talk to other instance.\n"); + return -1; + } + + if (!setup_unix_socket(sock_path)) { + fprintf(stderr, "Failed to setup socket for communications.\n"); + return -1; + } + our_id = id; qemu_plugin_register_vcpu_tb_trans_cb(id, vcpu_tb_trans); diff --git a/docs/devel/tcg-plugins.rst b/docs/devel/tcg-plugins.rst index aa75b390b1..5cddf31c70 100644 --- a/docs/devel/tcg-plugins.rst +++ b/docs/devel/tcg-plugins.rst @@ -286,7 +286,7 @@ communicate over:: ./sparc-softmmu/qemu-system-sparc -monitor none -parallel none \ -net none -M SS-20 -m 256 -kernel day11/zImage.elf \ - -plugin ./contrib/plugins/liblockstep.so,arg=lockstep-sparc.sock \ + -plugin ./contrib/plugins/liblockstep.so,sockpath=lockstep-sparc.sock \ -d plugin,nochain which will eventually report:: From 60753843f6f6c3933f6ac10667eef8a4327279e2 Mon Sep 17 00:00:00 2001 From: Mahmoud Mandour Date: Fri, 30 Jul 2021 15:58:10 +0200 Subject: [PATCH 14/22] plugins/hwprofile: adapt to the new plugin arguments scheme MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Parsing boolean arguments correctly (e.g. pattern=on or source=false). Introduced a new "track" argument that takes a [read|write] value. This substitutes passing read or write to "arg=" that is deprecated. Also, matches are now taken one by one through the "match" argument. Signed-off-by: Mahmoud Mandour Reviewed-by: Alex Bennée Tested-by: Alex Bennée Signed-off-by: Alex Bennée Message-Id: <20210730135817.17816-7-ma.mandourr@gmail.com> --- contrib/plugins/hwprofile.c | 39 +++++++++++++++++++++++++------------ docs/devel/tcg-plugins.rst | 8 ++++---- 2 files changed, 31 insertions(+), 16 deletions(-) diff --git a/contrib/plugins/hwprofile.c b/contrib/plugins/hwprofile.c index faf216ac00..691d4edb0c 100644 --- a/contrib/plugins/hwprofile.c +++ b/contrib/plugins/hwprofile.c @@ -259,27 +259,42 @@ int qemu_plugin_install(qemu_plugin_id_t id, const qemu_info_t *info, int argc, char **argv) { int i; + g_autoptr(GString) matches_raw = g_string_new(""); for (i = 0; i < argc; i++) { char *opt = argv[i]; - if (g_strcmp0(opt, "read") == 0) { - rw = QEMU_PLUGIN_MEM_R; - } else if (g_strcmp0(opt, "write") == 0) { - rw = QEMU_PLUGIN_MEM_W; - } else if (g_strcmp0(opt, "pattern") == 0) { - pattern = true; - } else if (g_strcmp0(opt, "source") == 0) { - source = true; - } else if (g_str_has_prefix(opt, "match")) { - gchar **parts = g_strsplit(opt, "=", 2); + g_autofree char **tokens = g_strsplit(opt, "=", 2); + + if (g_strcmp0(tokens[0], "track") == 0) { + if (g_strcmp0(tokens[1], "read") == 0) { + rw = QEMU_PLUGIN_MEM_R; + } else if (g_strcmp0(tokens[1], "write") == 0) { + rw = QEMU_PLUGIN_MEM_W; + } else { + fprintf(stderr, "invalid value for track: %s\n", tokens[1]); + return -1; + } + } else if (g_strcmp0(tokens[0], "pattern") == 0) { + if (!qemu_plugin_bool_parse(tokens[0], tokens[1], &pattern)) { + fprintf(stderr, "boolean argument parsing failed: %s\n", opt); + return -1; + } + } else if (g_strcmp0(tokens[0], "source") == 0) { + if (!qemu_plugin_bool_parse(tokens[0], tokens[1], &source)) { + fprintf(stderr, "boolean argument parsing failed: %s\n", opt); + return -1; + } + } else if (g_strcmp0(tokens[0], "match") == 0) { check_match = true; - matches = g_strsplit(parts[1], ",", -1); - g_strfreev(parts); + g_string_append_printf(matches_raw, "%s,", tokens[1]); } else { fprintf(stderr, "option parsing failed: %s\n", opt); return -1; } } + if (check_match) { + matches = g_strsplit(matches_raw->str, ",", -1); + } if (source && pattern) { fprintf(stderr, "can only currently track either source or pattern.\n"); diff --git a/docs/devel/tcg-plugins.rst b/docs/devel/tcg-plugins.rst index 5cddf31c70..e1f9eff587 100644 --- a/docs/devel/tcg-plugins.rst +++ b/docs/devel/tcg-plugins.rst @@ -306,22 +306,22 @@ which will eventually report:: The hwprofile tool can only be used with system emulation and allows the user to see what hardware is accessed how often. It has a number of options: - * arg=read or arg=write + * track=read or track=write By default the plugin tracks both reads and writes. You can use one of these options to limit the tracking to just one class of accesses. - * arg=source + * source Will include a detailed break down of what the guest PC that made the - access was. Not compatible with arg=pattern. Example output:: + access was. Not compatible with the pattern option. Example output:: cirrus-low-memory @ 0xfffffd00000a0000 pc:fffffc0000005cdc, 1, 256 pc:fffffc0000005ce8, 1, 256 pc:fffffc0000005cec, 1, 256 - * arg=pattern + * pattern Instead break down the accesses based on the offset into the HW region. This can be useful for seeing the most used registers of a From d8525358592a830c219401a1e83490470dfd28d1 Mon Sep 17 00:00:00 2001 From: Mahmoud Mandour Date: Fri, 30 Jul 2021 15:58:11 +0200 Subject: [PATCH 15/22] plugins/howvec: adapting to the new argument passing scheme MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Correctly parsing plugin argument since they now must be provided as full-form boolean parameters, e.g.: -plugin ./contrib/plugins/libhowvec.so,verbose=on,inline=on Also, introduced the argument "count" that accepts one opt to count individually at a time. Signed-off-by: Mahmoud Mandour Reviewed-by: Alex Bennée Tested-by: Alex Bennée Signed-off-by: Alex Bennée Message-Id: <20210730135817.17816-8-ma.mandourr@gmail.com> --- contrib/plugins/howvec.c | 27 +++++++++++++++++++-------- docs/devel/tcg-plugins.rst | 10 +++++----- 2 files changed, 24 insertions(+), 13 deletions(-) diff --git a/contrib/plugins/howvec.c b/contrib/plugins/howvec.c index 600f7facc1..4a5ec3d936 100644 --- a/contrib/plugins/howvec.c +++ b/contrib/plugins/howvec.c @@ -333,23 +333,34 @@ QEMU_PLUGIN_EXPORT int qemu_plugin_install(qemu_plugin_id_t id, for (i = 0; i < argc; i++) { char *p = argv[i]; - if (strcmp(p, "inline") == 0) { - do_inline = true; - } else if (strcmp(p, "verbose") == 0) { - verbose = true; - } else { + g_autofree char **tokens = g_strsplit(p, "=", -1); + 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", p); + return -1; + } + } else if (g_strcmp0(tokens[0], "verbose") == 0) { + if (!qemu_plugin_bool_parse(tokens[0], tokens[1], &verbose)) { + fprintf(stderr, "boolean argument parsing failed: %s\n", p); + return -1; + } + } else if (g_strcmp0(tokens[0], "count") == 0) { + char *value = tokens[1]; int j; CountType type = COUNT_INDIVIDUAL; - if (*p == '!') { + if (*value == '!') { type = COUNT_NONE; - p++; + value++; } for (j = 0; j < class_table_sz; j++) { - if (strcmp(p, class_table[j].opt) == 0) { + if (strcmp(value, class_table[j].opt) == 0) { class_table[j].what = type; break; } } + } else { + fprintf(stderr, "option parsing failed: %s\n", p); + return -1; } } diff --git a/docs/devel/tcg-plugins.rst b/docs/devel/tcg-plugins.rst index e1f9eff587..7b1dece024 100644 --- a/docs/devel/tcg-plugins.rst +++ b/docs/devel/tcg-plugins.rst @@ -80,7 +80,7 @@ Once built a program can be run with multiple plugins loaded each with their own arguments:: $QEMU $OTHER_QEMU_ARGS \ - -plugin tests/plugin/libhowvec.so,arg=inline,arg=hint \ + -plugin tests/plugin/libhowvec.so,inline=on,count=hint \ -plugin tests/plugin/libhotblocks.so Arguments are plugin specific and can be used to modify their @@ -212,13 +212,13 @@ The hotpages plugin can be configured using the following arguments: This is an instruction classifier so can be used to count different types of instructions. It has a number of options to refine which get -counted. You can give an argument for a class of instructions to break -it down fully, so for example to see all the system registers -accesses:: +counted. You can give a value to the `count` argument for a class of +instructions to break it down fully, so for example to see all the system +registers accesses:: ./aarch64-softmmu/qemu-system-aarch64 $(QEMU_ARGS) \ -append "root=/dev/sda2 systemd.unit=benchmark.service" \ - -smp 4 -plugin ./contrib/plugins/libhowvec.so,arg=sreg -d plugin + -smp 4 -plugin ./contrib/plugins/libhowvec.so,count=sreg -d plugin which will lead to a sorted list after the class breakdown:: From 2dd3fef8a66d7667c82a3add39754077071a66f7 Mon Sep 17 00:00:00 2001 From: Mahmoud Mandour Date: Fri, 30 Jul 2021 15:58:12 +0200 Subject: [PATCH 16/22] docs/tcg-plugins: new passing parameters scheme for cache docs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Mahmoud Mandour Reviewed-by: Alex Bennée Signed-off-by: Alex Bennée Message-Id: <20210730135817.17816-9-ma.mandourr@gmail.com> --- docs/devel/tcg-plugins.rst | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/docs/devel/tcg-plugins.rst b/docs/devel/tcg-plugins.rst index 7b1dece024..fcc460bf7b 100644 --- a/docs/devel/tcg-plugins.rst +++ b/docs/devel/tcg-plugins.rst @@ -389,34 +389,34 @@ will report the following:: The plugin has a number of arguments, all of them are optional: - * arg="limit=N" + * limit=N Print top N icache and dcache thrashing instructions along with their address, number of misses, and its disassembly. (default: 32) - * arg="icachesize=N" - * arg="iblksize=B" - * arg="iassoc=A" + * icachesize=N + * iblksize=B + * iassoc=A Instruction cache configuration arguments. They specify the cache size, block size, and associativity of the instruction cache, respectively. (default: N = 16384, B = 64, A = 8) - * arg="dcachesize=N" - * arg="dblksize=B" - * arg="dassoc=A" + * dcachesize=N + * dblksize=B + * dassoc=A Data cache configuration arguments. They specify the cache size, block size, and associativity of the data cache, respectively. (default: N = 16384, B = 64, A = 8) - * arg="evict=POLICY" + * evict=POLICY Sets the eviction policy to POLICY. Available policies are: :code:`lru`, :code:`fifo`, and :code:`rand`. The plugin will use the specified policy for both instruction and data caches. (default: POLICY = :code:`lru`) - * arg="cores=N" + * cores=N Sets the number of cores for which we maintain separate icache and dcache. (default: for linux-user, N = 1, for full system emulation: N = cores From 30b95b44523dbe0f0a0ad2cd23232dbb0c1c6a69 Mon Sep 17 00:00:00 2001 From: Mahmoud Mandour Date: Fri, 30 Jul 2021 15:58:13 +0200 Subject: [PATCH 17/22] tests/plugins/bb: adapt to the new arg passing scheme MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Mahmoud Mandour Reviewed-by: Alex Bennée Signed-off-by: Alex Bennée Message-Id: <20210730135817.17816-10-ma.mandourr@gmail.com> --- tests/plugin/bb.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/tests/plugin/bb.c b/tests/plugin/bb.c index de09bdde4e..7d470a1011 100644 --- a/tests/plugin/bb.c +++ b/tests/plugin/bb.c @@ -104,10 +104,17 @@ QEMU_PLUGIN_EXPORT int qemu_plugin_install(qemu_plugin_id_t id, for (i = 0; i < argc; i++) { char *opt = argv[i]; - if (g_strcmp0(opt, "inline") == 0) { - do_inline = true; - } else if (g_strcmp0(opt, "idle") == 0) { - idle_report = true; + g_autofree char **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; From 0163ce31794b5debcf2527b8156a78dabc45b802 Mon Sep 17 00:00:00 2001 From: Mahmoud Mandour Date: Fri, 30 Jul 2021 15:58:14 +0200 Subject: [PATCH 18/22] tests/plugins/insn: made arg inline not positional and parse it as bool MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Made argument "inline" not positional, this has two benefits. First is that we adhere to how QEMU passes args generally, by taking the last value of an argument and drop the others. And the second is that this sets up a framework for potentially adding new args easily. Signed-off-by: Mahmoud Mandour Reviewed-by: Alex Bennée Message-Id: <20210730135817.17816-11-ma.mandourr@gmail.com> [AJB: fix check-tcg tests calling arg=inline] Signed-off-by: Alex Bennée --- tests/plugin/insn.c | 14 ++++++++++++-- tests/tcg/i386/Makefile.softmmu-target | 2 +- tests/tcg/i386/Makefile.target | 2 +- tests/tcg/x86_64/Makefile.softmmu-target | 2 +- 4 files changed, 15 insertions(+), 5 deletions(-) diff --git a/tests/plugin/insn.c b/tests/plugin/insn.c index c253980ec8..0f6a1938c1 100644 --- a/tests/plugin/insn.c +++ b/tests/plugin/insn.c @@ -62,8 +62,18 @@ QEMU_PLUGIN_EXPORT int qemu_plugin_install(qemu_plugin_id_t id, const qemu_info_t *info, int argc, char **argv) { - if (argc && !strcmp(argv[0], "inline")) { - do_inline = true; + for (int i = 0; i < argc; i++) { + char *opt = argv[i]; + g_autofree char **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 { + fprintf(stderr, "option parsing failed: %s\n", opt); + return -1; + } } qemu_plugin_register_vcpu_tb_trans_cb(id, vcpu_tb_trans); diff --git a/tests/tcg/i386/Makefile.softmmu-target b/tests/tcg/i386/Makefile.softmmu-target index fa9b1b9f90..9b9038d0be 100644 --- a/tests/tcg/i386/Makefile.softmmu-target +++ b/tests/tcg/i386/Makefile.softmmu-target @@ -38,7 +38,7 @@ run-plugin-%-with-libinsn.so: $(call run-test, $@, \ $(QEMU) -monitor none -display none \ -chardev file$(COMMA)path=$@.out$(COMMA)id=output \ - -plugin ../../plugin/libinsn.so$(COMMA)arg=inline \ + -plugin ../../plugin/libinsn.so$(COMMA)inline=on \ -d plugin -D $*-with-libinsn.so.pout \ $(QEMU_OPTS) $*, \ "$* on $(TARGET_NAME)") diff --git a/tests/tcg/i386/Makefile.target b/tests/tcg/i386/Makefile.target index b0a2128980..a053ca3f15 100644 --- a/tests/tcg/i386/Makefile.target +++ b/tests/tcg/i386/Makefile.target @@ -61,7 +61,7 @@ endif # non-inline runs will trigger the duplicate instruction heuristics in libinsn.so run-plugin-%-with-libinsn.so: $(call run-test, $@, $(QEMU) $(QEMU_OPTS) \ - -plugin ../../plugin/libinsn.so$(COMMA)arg=inline \ + -plugin ../../plugin/libinsn.so$(COMMA)inline=on \ -d plugin -D $*-with-libinsn.so.pout $*, \ "$* (inline) on $(TARGET_NAME)") diff --git a/tests/tcg/x86_64/Makefile.softmmu-target b/tests/tcg/x86_64/Makefile.softmmu-target index 9896319f0e..2afa3298bf 100644 --- a/tests/tcg/x86_64/Makefile.softmmu-target +++ b/tests/tcg/x86_64/Makefile.softmmu-target @@ -38,7 +38,7 @@ run-plugin-%-with-libinsn.so: $(call run-test, $@, \ $(QEMU) -monitor none -display none \ -chardev file$(COMMA)path=$@.out$(COMMA)id=output \ - -plugin ../../plugin/libinsn.so$(COMMA)arg=inline \ + -plugin ../../plugin/libinsn.so$(COMMA)inline=on \ -d plugin -D $*-with-libinsn.so.pout \ $(QEMU_OPTS) $*, \ "$* on $(TARGET_NAME)") From 5ae589faad33708c1db0024bb818a2421bd8444c Mon Sep 17 00:00:00 2001 From: Mahmoud Mandour Date: Fri, 30 Jul 2021 15:58:15 +0200 Subject: [PATCH 19/22] tests/plugins/mem: introduce "track" arg and make args not positional MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit makes the plugin adhere to the new plugins arg-passing scheme by expecting full-form boolean args instead of short-form booleans. This necessitates that we introduce a new argument, here "track", to accept "r", "w", or "rw". Also, it makes arguments not positional and we only care about the last value specified for a certain argument. callback/inline args are now supplied separately as bool arguments so that both can be enabled individually. Signed-off-by: Mahmoud Mandour Reviewed-by: Alex Bennée Signed-off-by: Alex Bennée Message-Id: <20210730135817.17816-12-ma.mandourr@gmail.com> --- tests/plugin/mem.c | 51 ++++++++++++++++++++++++++++------------------ 1 file changed, 31 insertions(+), 20 deletions(-) diff --git a/tests/plugin/mem.c b/tests/plugin/mem.c index afd1d27e5c..4570f7d815 100644 --- a/tests/plugin/mem.c +++ b/tests/plugin/mem.c @@ -80,29 +80,40 @@ QEMU_PLUGIN_EXPORT int qemu_plugin_install(qemu_plugin_id_t id, const qemu_info_t *info, int argc, char **argv) { - if (argc) { - if (argc >= 3) { - if (!strcmp(argv[2], "haddr")) { - do_haddr = true; - } - } - if (argc >= 2) { - const char *str = argv[1]; - if (!strcmp(str, "r")) { - rw = QEMU_PLUGIN_MEM_R; - } else if (!strcmp(str, "w")) { - rw = QEMU_PLUGIN_MEM_W; + for (int i = 0; i < argc; i++) { + char *opt = argv[i]; + g_autofree char **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, "invaild 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; } - } - if (!strcmp(argv[0], "inline")) { - do_inline = true; - do_callback = false; - } else if (!strcmp(argv[0], "both")) { - do_inline = true; - do_callback = true; } else { - do_callback = true; + fprintf(stderr, "option parsing failed: %s\n", opt); + return -1; } } From a694d739bbf87e9de4ab1b76e03722e7eca32a4d Mon Sep 17 00:00:00 2001 From: Mahmoud Mandour Date: Fri, 30 Jul 2021 15:58:16 +0200 Subject: [PATCH 20/22] tests/plugins/syscalls: adhere to new arg-passing scheme MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Mahmoud Mandour Reviewed-by: Alex Bennée Signed-off-by: Alex Bennée Message-Id: <20210730135817.17816-13-ma.mandourr@gmail.com> --- tests/plugin/syscall.c | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/tests/plugin/syscall.c b/tests/plugin/syscall.c index 6dd71092e1..484b48de49 100644 --- a/tests/plugin/syscall.c +++ b/tests/plugin/syscall.c @@ -119,17 +119,26 @@ QEMU_PLUGIN_EXPORT int qemu_plugin_install(qemu_plugin_id_t id, const qemu_info_t *info, int argc, char **argv) { - if (argc == 0) { - statistics = g_hash_table_new_full(NULL, g_direct_equal, NULL, g_free); - } else { - for (int i = 0; i < argc; i++) { - if (g_strcmp0(argv[i], "print") != 0) { - fprintf(stderr, "unsupported argument: %s\n", argv[i]); - return -1; + bool do_print = false; + + for (int i = 0; i < argc; i++) { + char *opt = argv[i]; + g_autofree char **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); From 67f145745fc2187f0c5b5df72794e9efcfd0533d Mon Sep 17 00:00:00 2001 From: Mahmoud Mandour Date: Mon, 2 Aug 2021 15:44:14 +0200 Subject: [PATCH 21/22] docs/deprecated: deprecate passing plugin args through `arg=` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Mahmoud Mandour Message-Id: <20210802134414.52037-1-ma.mandourr@gmail.com> Reviewed-by: Alex Bennée [AJB: fixed up move of deprecated.rst] Signed-off-by: Alex Bennée --- docs/about/deprecated.rst | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/docs/about/deprecated.rst b/docs/about/deprecated.rst index 1e1a5e96ad..6e88a84bba 100644 --- a/docs/about/deprecated.rst +++ b/docs/about/deprecated.rst @@ -139,6 +139,18 @@ The ``-no-quit`` is a synonym for ``-display ...,window-close=off`` which should be used instead. +Plugin argument passing through ``arg=`` (since 6.1) +'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' + +Passing TCG plugins arguments through ``arg=`` is redundant is makes the +command-line less readable, especially when the argument itself consist of a +name and a value, e.g. ``-plugin plugin_name,arg="arg_name=arg_value"``. +Therefore, the usage of ``arg`` is redundant. Single-word arguments are treated +as short-form boolean values, and passed to plugins as ``arg_name=on``. +However, short-form booleans are deprecated and full explicit ``arg_name=on`` +form is preferred. + + QEMU Machine Protocol (QMP) commands ------------------------------------ From a35af836d103f781d2fea437129732c16ba64b25 Mon Sep 17 00:00:00 2001 From: Mahmoud Mandour Date: Mon, 30 Aug 2021 14:15:34 +0200 Subject: [PATCH 22/22] docs/devel: be consistent about example plugin names MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some plugins were prefixed with `.c`, some were not. Since the name is essentially the full-name of the plugin file, it's logical to include the extension. Signed-off-by: Mahmoud Mandour Message-Id: <20210830121534.656559-1-ma.mandourr@gmail.com> Reviewed-by: Alex Bennée Signed-off-by: Alex Bennée --- docs/devel/tcg-plugins.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/devel/tcg-plugins.rst b/docs/devel/tcg-plugins.rst index fcc460bf7b..dac5101a3c 100644 --- a/docs/devel/tcg-plugins.rst +++ b/docs/devel/tcg-plugins.rst @@ -301,7 +301,7 @@ which will eventually report:: previously @ 0x000000ffd08098/5 (809900593 insns) previously @ 0x000000ffd080c0/1 (809900588 insns) -- contrib/plugins/hwprofile +- contrib/plugins/hwprofile.c The hwprofile tool can only be used with system emulation and allows the user to see what hardware is accessed how often. It has a number of options: @@ -360,7 +360,7 @@ which will output an execution trace following this structure:: 0, 0xd34, 0xf9c8f000, "bl #0x10c8" 0, 0x10c8, 0xfff96c43, "ldr r3, [r0, #0x44]", load, 0x200000e4, RAM -- contrib/plugins/cache +- contrib/plugins/cache.c Cache modelling plugin that measures the performance of a given cache configuration when a given working set is run::