From patchwork Wed Jun 28 12:04:22 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: "Wu, Fei" X-Patchwork-Id: 13295646 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 52A8CEB64D7 for ; Wed, 28 Jun 2023 12:03:03 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1qETsY-0007T5-Ny; Wed, 28 Jun 2023 08:02:34 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qETsV-0007RI-EI for qemu-devel@nongnu.org; Wed, 28 Jun 2023 08:02:31 -0400 Received: from mga01.intel.com ([192.55.52.88]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qETsL-0006gJ-IU for qemu-devel@nongnu.org; Wed, 28 Jun 2023 08:02:24 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1687953741; x=1719489741; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=aaJLbVtXWOrEQkF11Ofk/Wyc6O9RkGgE5iisLJpkf50=; b=nk/g2nshWLuaLAyrsUpJCn1u+62kAFv5vFwTPT/uajqBI1/QELM586+y DdtkVL1zKftXAOxEd3LFujhBGSf1atKpBouLcbLZUkkxzFA1gJnGzMCPp 3lKYc+3upEImeXlYQwqlfP4KHuvXZtOd9hPDbd/j+WOQeuH+N7YlxFe30 fPZZk9DfP5OOjgyq7WVF9fVXG4IXQDATW5lCERMRfdmlBHGeA+fccqOHk DHqP4mTQDjhyGDWv2EtcXM1X9SLFwXzb45txLEclGDNblSqa81ZKDBccM R+7jXsudEAxsSdFMRNSdRMrMCcdOWkDpXHXP7YpGGRz4HK38RBublgzTQ A==; X-IronPort-AV: E=McAfee;i="6600,9927,10754"; a="392547248" X-IronPort-AV: E=Sophos;i="6.01,165,1684825200"; d="scan'208";a="392547248" Received: from orsmga004.jf.intel.com ([10.7.209.38]) by fmsmga101.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 28 Jun 2023 05:02:13 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10754"; a="841047471" X-IronPort-AV: E=Sophos;i="6.01,165,1684825200"; d="scan'208";a="841047471" Received: from wufei-optiplex-7090.sh.intel.com ([10.238.200.247]) by orsmga004.jf.intel.com with ESMTP; 28 Jun 2023 05:02:10 -0700 From: Fei Wu To: richard.henderson@linaro.org, alex.bennee@linaro.org, qemu-devel@nongnu.org Cc: "Vanderson M. do Rosario" , Fei Wu , Paolo Bonzini Subject: [PATCH v16 1/9] accel/tcg: introduce TBStatistics structure Date: Wed, 28 Jun 2023 20:04:22 +0800 Message-Id: <20230628120430.73777-2-fei2.wu@intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230628120430.73777-1-fei2.wu@intel.com> References: <20230628120430.73777-1-fei2.wu@intel.com> MIME-Version: 1.0 Received-SPF: pass client-ip=192.55.52.88; envelope-from=fei2.wu@intel.com; helo=mga01.intel.com X-Spam_score_int: -43 X-Spam_score: -4.4 X-Spam_bar: ---- X-Spam_report: (-4.4 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_MED=-2.3, RCVD_IN_MSPIKE_H3=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org From: "Vanderson M. do Rosario" To store statistics for each TB, we created a TBStatistics structure which is linked with the TBs. TBStatistics can stay alive after tb_flush and be relinked to a regenerated TB. So the statistics can be accumulated even through flushes. The goal is to have all present and future qemu/tcg statistics and meta-data stored in this new structure. Reviewed-by: Alex Bennée Signed-off-by: Vanderson M. do Rosario Message-Id: <20190829173437.5926-2-vandersonmr2@gmail.com> [AJB: fix git author, review comments] Signed-off-by: Alex Bennée Signed-off-by: Fei Wu --- MAINTAINERS | 1 + accel/tcg/meson.build | 1 + accel/tcg/tb-context.h | 1 + accel/tcg/tb-hash.h | 7 ++++ accel/tcg/tb-maint.c | 19 +++++++++++ accel/tcg/tb-stats.c | 46 ++++++++++++++++++++++++++ accel/tcg/translate-all.c | 44 +++++++++++++++++++++++++ include/exec/tb-stats-flags.h | 19 +++++++++++ include/exec/tb-stats.h | 56 ++++++++++++++++++++++++++++++++ include/exec/translation-block.h | 3 ++ 10 files changed, 197 insertions(+) create mode 100644 accel/tcg/tb-stats.c create mode 100644 include/exec/tb-stats-flags.h create mode 100644 include/exec/tb-stats.h diff --git a/MAINTAINERS b/MAINTAINERS index e07746ac7d..f11c58f371 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -153,6 +153,7 @@ F: include/exec/cpu*.h F: include/exec/exec-all.h F: include/exec/tb-flush.h F: include/exec/target_long.h +F: include/exec/tb-stats*.h F: include/exec/helper*.h F: include/exec/helper*.h.inc F: include/exec/helper-info.c.inc diff --git a/accel/tcg/meson.build b/accel/tcg/meson.build index 166bef173b..239120c933 100644 --- a/accel/tcg/meson.build +++ b/accel/tcg/meson.build @@ -4,6 +4,7 @@ tcg_ss.add(files( 'cpu-exec-common.c', 'cpu-exec.c', 'tb-maint.c', + 'tb-stats.c', 'tcg-runtime-gvec.c', 'tcg-runtime.c', 'translate-all.c', diff --git a/accel/tcg/tb-context.h b/accel/tcg/tb-context.h index cac62d9749..d7910d586b 100644 --- a/accel/tcg/tb-context.h +++ b/accel/tcg/tb-context.h @@ -35,6 +35,7 @@ struct TBContext { /* statistics */ unsigned tb_flush_count; unsigned tb_phys_invalidate_count; + struct qht tb_stats; }; extern TBContext tb_ctx; diff --git a/accel/tcg/tb-hash.h b/accel/tcg/tb-hash.h index a0c61f25cd..638fe58270 100644 --- a/accel/tcg/tb-hash.h +++ b/accel/tcg/tb-hash.h @@ -67,4 +67,11 @@ uint32_t tb_hash_func(tb_page_addr_t phys_pc, vaddr pc, return qemu_xxhash8(phys_pc, pc, flags2, flags, cf_mask); } +static inline +uint32_t tb_stats_hash_func(tb_page_addr_t phys_pc, target_ulong pc, + uint32_t flags) +{ + return qemu_xxhash5(phys_pc, pc, flags); +} + #endif diff --git a/accel/tcg/tb-maint.c b/accel/tcg/tb-maint.c index 3541419845..264bdd84b3 100644 --- a/accel/tcg/tb-maint.c +++ b/accel/tcg/tb-maint.c @@ -24,6 +24,7 @@ #include "exec/log.h" #include "exec/exec-all.h" #include "exec/tb-flush.h" +#include "exec/tb-stats.h" #include "exec/translate-all.h" #include "sysemu/tcg.h" #include "tcg/tcg.h" @@ -41,6 +42,23 @@ #define TB_FOR_EACH_JMP(head_tb, tb, n) \ TB_FOR_EACH_TAGGED((head_tb)->jmp_list_head, tb, n, jmp_list_next) +/* + * This is the more or less the same compare as tb_cmp(), but the + * data persists over tb_flush. We also aggregate the various + * variations of cflags under one record and ignore the details of + * page overlap (although we can count it). + */ +bool tb_stats_cmp(const void *ap, const void *bp) +{ + const TBStatistics *a = ap; + const TBStatistics *b = bp; + + return a->phys_pc == b->phys_pc && + a->pc == b->pc && + a->cs_base == b->cs_base && + a->flags == b->flags; +} + static bool tb_cmp(const void *ap, const void *bp) { const TranslationBlock *a = ap; @@ -59,6 +77,7 @@ void tb_htable_init(void) unsigned int mode = QHT_MODE_AUTO_RESIZE; qht_init(&tb_ctx.htable, tb_cmp, CODE_GEN_HTABLE_SIZE, mode); + init_tb_stats_htable(); } typedef struct PageDesc PageDesc; diff --git a/accel/tcg/tb-stats.c b/accel/tcg/tb-stats.c new file mode 100644 index 0000000000..2b6be943ef --- /dev/null +++ b/accel/tcg/tb-stats.c @@ -0,0 +1,46 @@ +/* + * QEMU System Emulator, Code Quality Monitor System + * + * Copyright (c) 2019 Vanderson M. do Rosario + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "qemu/osdep.h" + +#include "disas/disas.h" + +#include "exec/tb-stats.h" +#include "tb-context.h" + +/* TBStatistic collection controls */ +enum TBStatsStatus { + TB_STATS_STOPPED = 0, + TB_STATS_RUNNING +}; + +static enum TBStatsStatus tcg_collect_tb_stats; + +void init_tb_stats_htable(void) +{ + if (!tb_ctx.tb_stats.map && tb_stats_collection_enabled()) { + qht_init(&tb_ctx.tb_stats, tb_stats_cmp, + CODE_GEN_HTABLE_SIZE, QHT_MODE_AUTO_RESIZE); + } +} + +void enable_collect_tb_stats(void) +{ + tcg_collect_tb_stats = TB_STATS_RUNNING; + init_tb_stats_htable(); +} + +void disable_collect_tb_stats(void) +{ + tcg_collect_tb_stats = TB_STATS_STOPPED; +} + +bool tb_stats_collection_enabled(void) +{ + return tcg_collect_tb_stats == TB_STATS_RUNNING; +} diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c index d3d4fbc1a4..5f47b862d8 100644 --- a/accel/tcg/translate-all.c +++ b/accel/tcg/translate-all.c @@ -53,6 +53,7 @@ #include "qemu/cacheinfo.h" #include "qemu/timer.h" #include "exec/log.h" +#include "exec/tb-stats.h" #include "sysemu/cpus.h" #include "sysemu/cpu-timers.h" #include "sysemu/tcg.h" @@ -283,6 +284,37 @@ static int setjmp_gen_code(CPUArchState *env, TranslationBlock *tb, return tcg_gen_code(tcg_ctx, tb, pc); } +static TBStatistics *tb_get_stats(tb_page_addr_t phys_pc, target_ulong pc, + target_ulong cs_base, uint32_t flags) +{ + TBStatistics *new_stats = g_new0(TBStatistics, 1); + uint32_t hash = tb_stats_hash_func(phys_pc, pc, flags); + void *existing_stats = NULL; + new_stats->phys_pc = phys_pc; + new_stats->pc = pc; + new_stats->cs_base = cs_base; + new_stats->flags = flags; + + /* + * All initialisation must be complete before we insert into qht + * table otherwise another thread might get a partially created + * structure. + */ + qht_insert(&tb_ctx.tb_stats, new_stats, hash, &existing_stats); + + if (unlikely(existing_stats)) { + /* + * If there is already a TBStatistic for this TB from a previous flush + * then just make the new TB point to the older TBStatistic + */ + g_free(new_stats); + return existing_stats; + } else { + return new_stats; + } +} + + /* Called with mmap_lock held for user mode emulation. */ TranslationBlock *tb_gen_code(CPUState *cpu, vaddr pc, uint64_t cs_base, @@ -353,6 +385,18 @@ TranslationBlock *tb_gen_code(CPUState *cpu, trace_translate_block(tb, pc, tb->tc.ptr); + /* + * We want to fetch the stats structure before we start code + * generation so we can count interesting things about this + * generation. + */ + if (tb_stats_collection_enabled()) { + tb->tb_stats = tb_get_stats(phys_pc, cflags & CF_PCREL ? 0 : pc, + cs_base, flags); + } else { + tb->tb_stats = NULL; + } + gen_code_size = setjmp_gen_code(env, tb, pc, host_pc, &max_insns, &ti); if (unlikely(gen_code_size < 0)) { switch (gen_code_size) { diff --git a/include/exec/tb-stats-flags.h b/include/exec/tb-stats-flags.h new file mode 100644 index 0000000000..c994cf3b9d --- /dev/null +++ b/include/exec/tb-stats-flags.h @@ -0,0 +1,19 @@ +/* + * QEMU System Emulator, Code Quality Monitor System + * + * We define the flags and control bits here to avoid complications of + * including TCG/CPU information in common code. + * + * Copyright (c) 2019 Vanderson M. do Rosario + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ +#ifndef TB_STATS_FLAGS +#define TB_STATS_FLAGS + +/* TBStatistic collection controls */ +void enable_collect_tb_stats(void); +void disable_collect_tb_stats(void); +bool tb_stats_collection_enabled(void); + +#endif diff --git a/include/exec/tb-stats.h b/include/exec/tb-stats.h new file mode 100644 index 0000000000..8feb50e87d --- /dev/null +++ b/include/exec/tb-stats.h @@ -0,0 +1,56 @@ +/* + * QEMU System Emulator, Code Quality Monitor System + * + * Copyright (c) 2019 Vanderson M. do Rosario + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef TB_STATS_H + +#define TB_STATS_H + +#include "exec/cpu-common.h" +#include "exec/translation-block.h" +#include "exec/tb-stats-flags.h" +#include "tcg/tcg.h" + +typedef struct TBStatistics TBStatistics; + +/* + * This struct stores statistics such as execution count of the + * TranslationBlocks. Each sets of TBs for a given phys_pc/pc/flags + * has its own TBStatistics which will persist over tb_flush. + * + * We include additional counters to track number of translations as + * well as variants for compile flags. + */ +struct TBStatistics { + tb_page_addr_t phys_pc; + vaddr pc; + uint32_t flags; + /* cs_base isn't included in the hash but we do check for matches */ + uint64_t cs_base; +}; + +bool tb_stats_cmp(const void *ap, const void *bp); + +void init_tb_stats_htable(void); + +#endif diff --git a/include/exec/translation-block.h b/include/exec/translation-block.h index 5119924927..6fd8c8bc48 100644 --- a/include/exec/translation-block.h +++ b/include/exec/translation-block.h @@ -141,6 +141,9 @@ struct TranslationBlock { uintptr_t jmp_list_head; uintptr_t jmp_list_next[2]; uintptr_t jmp_dest[2]; + + /* Pointer to a struct where statistics from the TB is stored */ + struct TBStatistics *tb_stats; }; /* The alignment given to TranslationBlock during allocation. */ From patchwork Wed Jun 28 12:04:23 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: "Wu, Fei" X-Patchwork-Id: 13295652 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 64FABEB64D7 for ; Wed, 28 Jun 2023 12:04:08 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1qETsh-0007Uv-1c; Wed, 28 Jun 2023 08:02:43 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qETsV-0007RJ-E9 for qemu-devel@nongnu.org; Wed, 28 Jun 2023 08:02:31 -0400 Received: from mga01.intel.com ([192.55.52.88]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qETsN-0006hC-50 for qemu-devel@nongnu.org; Wed, 28 Jun 2023 08:02:25 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1687953743; x=1719489743; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=LzRwM6iUAnwAGkBm1Wss6OjnmIf7taC0KbSVByqzQqk=; b=QYeD+8ByW838OKNHB+Zx97KNIA5tF6HX6cHSQZj/IMsGUA1xWvoRe4YB b6lvEkMHYtyfueHaV8bgEWGLjq6g9/5z9BQHpf9NezMgiysMazDbdiWg7 vaoOWlum5nBNbWm7xd3cNnUhS82V16dhkkIWDYxCrMVV4L9SWDksVcnMP giUHjKKBmOEfUvOpLxIRbiNiLaImTtdfGPvfZiyK9JtcpWwGHFmbKv2LD J6QHi8EN7c1E6+P2cpXnwX0WdjoSM/YXcFrerwUW8hSQ0qWpmXqLYbfgW 9SywOx8A1XKo8hAN0vbfeNxqetptwU05KD5tKMkPGjnXMTtT+WcoBY1J3 g==; X-IronPort-AV: E=McAfee;i="6600,9927,10754"; a="392547271" X-IronPort-AV: E=Sophos;i="6.01,165,1684825200"; d="scan'208";a="392547271" Received: from orsmga004.jf.intel.com ([10.7.209.38]) by fmsmga101.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 28 Jun 2023 05:02:15 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10754"; a="841047478" X-IronPort-AV: E=Sophos;i="6.01,165,1684825200"; d="scan'208";a="841047478" Received: from wufei-optiplex-7090.sh.intel.com ([10.238.200.247]) by orsmga004.jf.intel.com with ESMTP; 28 Jun 2023 05:02:13 -0700 From: Fei Wu To: richard.henderson@linaro.org, alex.bennee@linaro.org, qemu-devel@nongnu.org Cc: "Vanderson M. do Rosario" , Fei Wu , Paolo Bonzini Subject: [PATCH v16 2/9] accel: collecting TB execution count Date: Wed, 28 Jun 2023 20:04:23 +0800 Message-Id: <20230628120430.73777-3-fei2.wu@intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230628120430.73777-1-fei2.wu@intel.com> References: <20230628120430.73777-1-fei2.wu@intel.com> MIME-Version: 1.0 Received-SPF: pass client-ip=192.55.52.88; envelope-from=fei2.wu@intel.com; helo=mga01.intel.com X-Spam_score_int: -43 X-Spam_score: -4.4 X-Spam_bar: ---- X-Spam_report: (-4.4 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_MED=-2.3, RCVD_IN_MSPIKE_H3=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org From: "Vanderson M. do Rosario" If a TB has a TBS (TBStatistics) with the TB_EXEC_STATS enabled, then we instrument the start code of this TB to atomically count the number of times it is executed. We count both the number of "normal" executions and atomic executions of a TB. The execution count of the TB is stored in its respective TBS. All TBStatistics are created by default with the flags from default_tbstats_flag. [Richard Henderson created the inline gen_tb_exec_count] Signed-off-by: Vanderson M. do Rosario Message-Id: <20190829173437.5926-3-vandersonmr2@gmail.com> [AJB: Fix author] Signed-off-by: Alex Bennée Signed-off-by: Fei Wu --- accel/tcg/cpu-exec.c | 6 ++++++ accel/tcg/tb-stats.c | 18 ++++++++++++++++++ accel/tcg/tcg-runtime.c | 1 + accel/tcg/translate-all.c | 6 ++++-- accel/tcg/translator.c | 26 ++++++++++++++++++++++++++ include/exec/tb-stats-flags.h | 6 ++++++ include/exec/tb-stats.h | 7 +++++++ include/tcg/tcg-temp-internal.h | 2 ++ 8 files changed, 70 insertions(+), 2 deletions(-) diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c index ba1890a373..ba8ac61069 100644 --- a/accel/tcg/cpu-exec.c +++ b/accel/tcg/cpu-exec.c @@ -25,6 +25,7 @@ #include "trace.h" #include "disas/disas.h" #include "exec/exec-all.h" +#include "exec/tb-stats.h" #include "tcg/tcg.h" #include "qemu/atomic.h" #include "qemu/rcu.h" @@ -562,7 +563,12 @@ void cpu_exec_step_atomic(CPUState *cpu) mmap_unlock(); } + if (tb_stats_enabled(tb, TB_EXEC_STATS)) { + tb->tb_stats->executions.atomic++; + } + cpu_exec_enter(cpu); + /* execute the generated code */ trace_exec_tb(tb, pc); cpu_tb_exec(cpu, tb, &tb_exit); diff --git a/accel/tcg/tb-stats.c b/accel/tcg/tb-stats.c index 2b6be943ef..2b7321b548 100644 --- a/accel/tcg/tb-stats.c +++ b/accel/tcg/tb-stats.c @@ -20,6 +20,7 @@ enum TBStatsStatus { }; static enum TBStatsStatus tcg_collect_tb_stats; +static uint32_t tbstats_flag; void init_tb_stats_htable(void) { @@ -44,3 +45,20 @@ bool tb_stats_collection_enabled(void) { return tcg_collect_tb_stats == TB_STATS_RUNNING; } + +uint32_t get_tbstats_flag(void) +{ + return tbstats_flag; +} + +void set_tbstats_flag(uint32_t flag) +{ + tbstats_flag = flag; +} + +bool tb_stats_enabled(TranslationBlock *tb, uint32_t flag) +{ + return tb_stats_collection_enabled() && + tb->tb_stats && + (tbstats_flag & flag); +} diff --git a/accel/tcg/tcg-runtime.c b/accel/tcg/tcg-runtime.c index 9fa539ad3d..14d684c2ee 100644 --- a/accel/tcg/tcg-runtime.c +++ b/accel/tcg/tcg-runtime.c @@ -27,6 +27,7 @@ #include "exec/helper-proto-common.h" #include "exec/cpu_ldst.h" #include "exec/exec-all.h" +#include "exec/tb-stats.h" #include "disas/disas.h" #include "exec/log.h" #include "tcg/tcg.h" diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c index 5f47b862d8..d7a35e0ea5 100644 --- a/accel/tcg/translate-all.c +++ b/accel/tcg/translate-all.c @@ -388,9 +388,11 @@ TranslationBlock *tb_gen_code(CPUState *cpu, /* * We want to fetch the stats structure before we start code * generation so we can count interesting things about this - * generation. + * generation. If dfilter is in effect we will only collect stats + * for the specified range. */ - if (tb_stats_collection_enabled()) { + if (tb_stats_collection_enabled() && + qemu_log_in_addr_range(tb->pc)) { tb->tb_stats = tb_get_stats(phys_pc, cflags & CF_PCREL ? 0 : pc, cs_base, flags); } else { diff --git a/accel/tcg/translator.c b/accel/tcg/translator.c index 0fd9efceba..4743fa7d01 100644 --- a/accel/tcg/translator.c +++ b/accel/tcg/translator.c @@ -10,10 +10,12 @@ #include "qemu/osdep.h" #include "qemu/log.h" #include "qemu/error-report.h" +#include "tcg/tcg-temp-internal.h" #include "exec/exec-all.h" #include "exec/translator.h" #include "exec/translate-all.h" #include "exec/plugin-gen.h" +#include "exec/tb-stats.h" #include "tcg/tcg-op-common.h" static void gen_io_start(void) @@ -117,6 +119,29 @@ static void gen_tb_end(const TranslationBlock *tb, uint32_t cflags, } } +static void gen_tb_exec_count(TranslationBlock *tb) +{ + if (tb_stats_enabled(tb, TB_EXEC_STATS)) { + TCGv_ptr ptr = tcg_temp_ebb_new_ptr(); + + tcg_gen_movi_ptr(ptr, (intptr_t)&tb->tb_stats->executions.normal); + if (sizeof(tb->tb_stats->executions.normal) == 4) { + TCGv_i32 t = tcg_temp_ebb_new_i32(); + tcg_gen_ld_i32(t, ptr, 0); + tcg_gen_addi_i32(t, t, 1); + tcg_gen_st_i32(t, ptr, 0); + tcg_temp_free_i32(t); + } else { + TCGv_i64 t = tcg_temp_ebb_new_i64(); + tcg_gen_ld_i64(t, ptr, 0); + tcg_gen_addi_i64(t, t, 1); + tcg_gen_st_i64(t, ptr, 0); + tcg_temp_free_i64(t); + } + tcg_temp_free_ptr(ptr); + } +} + bool translator_use_goto_tb(DisasContextBase *db, vaddr dest) { /* Suppress goto_tb if requested. */ @@ -156,6 +181,7 @@ void translator_loop(CPUState *cpu, TranslationBlock *tb, int *max_insns, /* Start translating. */ icount_start_insn = gen_tb_start(cflags); + gen_tb_exec_count(tb); ops->tb_start(db, cpu); tcg_debug_assert(db->is_jmp == DISAS_NEXT); /* no early exit */ diff --git a/include/exec/tb-stats-flags.h b/include/exec/tb-stats-flags.h index c994cf3b9d..c0e63408e2 100644 --- a/include/exec/tb-stats-flags.h +++ b/include/exec/tb-stats-flags.h @@ -11,9 +11,15 @@ #ifndef TB_STATS_FLAGS #define TB_STATS_FLAGS +#define TB_NONE_STATS (0) /* no stats */ +#define TB_EXEC_STATS (1 << 0) + /* TBStatistic collection controls */ void enable_collect_tb_stats(void); void disable_collect_tb_stats(void); bool tb_stats_collection_enabled(void); +uint32_t get_tbstats_flag(void); +void set_tbstats_flag(uint32_t flag); + #endif diff --git a/include/exec/tb-stats.h b/include/exec/tb-stats.h index 8feb50e87d..a8abab269c 100644 --- a/include/exec/tb-stats.h +++ b/include/exec/tb-stats.h @@ -47,10 +47,17 @@ struct TBStatistics { uint32_t flags; /* cs_base isn't included in the hash but we do check for matches */ uint64_t cs_base; + + /* Execution stats */ + struct { + unsigned long normal; + unsigned long atomic; + } executions; }; bool tb_stats_cmp(const void *ap, const void *bp); void init_tb_stats_htable(void); +bool tb_stats_enabled(TranslationBlock *tb, uint32_t flag); #endif diff --git a/include/tcg/tcg-temp-internal.h b/include/tcg/tcg-temp-internal.h index dded2917e5..61ef055b92 100644 --- a/include/tcg/tcg-temp-internal.h +++ b/include/tcg/tcg-temp-internal.h @@ -25,6 +25,8 @@ #ifndef TCG_TEMP_INTERNAL_H #define TCG_TEMP_INTERNAL_H +#include "tcg.h" + /* * Allocation and freeing of EBB temps is reserved to TCG internals */ From patchwork Wed Jun 28 12:04:24 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: "Wu, Fei" X-Patchwork-Id: 13295656 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id CCE41EB64D7 for ; Wed, 28 Jun 2023 12:06:16 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1qETsi-0007WF-9J; Wed, 28 Jun 2023 08:02:44 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qETsZ-0007Tm-Ax for qemu-devel@nongnu.org; Wed, 28 Jun 2023 08:02:35 -0400 Received: from mga01.intel.com ([192.55.52.88]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qETsO-0006fL-7z for qemu-devel@nongnu.org; Wed, 28 Jun 2023 08:02:31 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1687953744; x=1719489744; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=UITAbsHPAO3cWSt8CcG4QwPpQLcHTwuhR8EaY218itU=; b=gS6BZ3xWMOPOpJ9Aem46gJPmrLlGPkkSkXc5g9LtnRh/6/Zi3q1ig0XM Xbege16Hb+7pLSbop7/EbLVGmepbNc+cK3mQpSWOtGxDhwsmoar5UMWxz /sJc3QT7Cnl8ayxmiVUC/YEizujeumhc+2d+Vo25N3EZC1EGbvTRslQjM pKjav7sXvVYDde5ALyoe+NTFs8GLk8vpwbOhq8uiy4y0+IrZO9xXNwTMh xRKCy331EAlyswyNQVgaFlqeXyJWRNukTBzmWDWaz16x3fzqjnoh91Og4 PsR5gvHKZtVUDmP6fDR2lPYyPQ8vaDvmNkDSv4NhpQEX6jy4/LldWLASr A==; X-IronPort-AV: E=McAfee;i="6600,9927,10754"; a="392547283" X-IronPort-AV: E=Sophos;i="6.01,165,1684825200"; d="scan'208";a="392547283" Received: from orsmga004.jf.intel.com ([10.7.209.38]) by fmsmga101.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 28 Jun 2023 05:02:18 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10754"; a="841047486" X-IronPort-AV: E=Sophos;i="6.01,165,1684825200"; d="scan'208";a="841047486" Received: from wufei-optiplex-7090.sh.intel.com ([10.238.200.247]) by orsmga004.jf.intel.com with ESMTP; 28 Jun 2023 05:02:15 -0700 From: Fei Wu To: richard.henderson@linaro.org, alex.bennee@linaro.org, qemu-devel@nongnu.org Cc: Fei Wu , "Vanderson M . do Rosario" , Paolo Bonzini Subject: [PATCH v16 3/9] accel/tcg: add jit stats to TBStatistics Date: Wed, 28 Jun 2023 20:04:24 +0800 Message-Id: <20230628120430.73777-4-fei2.wu@intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230628120430.73777-1-fei2.wu@intel.com> References: <20230628120430.73777-1-fei2.wu@intel.com> MIME-Version: 1.0 Received-SPF: pass client-ip=192.55.52.88; envelope-from=fei2.wu@intel.com; helo=mga01.intel.com X-Spam_score_int: -43 X-Spam_score: -4.4 X-Spam_bar: ---- X-Spam_report: (-4.4 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_MED=-2.3, RCVD_IN_MSPIKE_H3=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org This collects all the statistics for TBStatistics, not only for the whole emulation but for each TB. Signed-off-by: Vanderson M. do Rosario Signed-off-by: Alex Bennée Signed-off-by: Fei Wu --- accel/tcg/monitor.c | 6 +++ accel/tcg/tb-stats.c | 69 +++++++++++++++++++++++++++++++++++ accel/tcg/translate-all.c | 31 ++++++++++++++-- accel/tcg/translator.c | 5 +++ include/exec/tb-stats-flags.h | 1 + include/exec/tb-stats.h | 30 +++++++++++++++ include/tcg/tcg.h | 10 +++++ tcg/tcg.c | 47 ++++++++++++++++++++++-- 8 files changed, 193 insertions(+), 6 deletions(-) diff --git a/accel/tcg/monitor.c b/accel/tcg/monitor.c index d48de23999..567950a7ed 100644 --- a/accel/tcg/monitor.c +++ b/accel/tcg/monitor.c @@ -16,6 +16,7 @@ #include "sysemu/cpu-timers.h" #include "sysemu/tcg.h" #include "tcg/tcg.h" +#include "exec/tb-stats.h" #include "internal.h" @@ -70,6 +71,11 @@ HumanReadableText *qmp_x_query_opcount(Error **errp) { g_autoptr(GString) buf = g_string_new(""); + if (!tb_stats_collection_enabled()) { + error_setg(errp, "TB information not being recorded"); + return NULL; + } + if (!tcg_enabled()) { error_setg(errp, "Opcode count information is only available with accel=tcg"); diff --git a/accel/tcg/tb-stats.c b/accel/tcg/tb-stats.c index 2b7321b548..11322359c7 100644 --- a/accel/tcg/tb-stats.c +++ b/accel/tcg/tb-stats.c @@ -9,6 +9,10 @@ #include "qemu/osdep.h" #include "disas/disas.h" +#include "exec/exec-all.h" +#include "tcg/tcg.h" + +#include "qemu/qemu-print.h" #include "exec/tb-stats.h" #include "tb-context.h" @@ -22,6 +26,71 @@ enum TBStatsStatus { static enum TBStatsStatus tcg_collect_tb_stats; static uint32_t tbstats_flag; +struct jit_profile_info { + uint64_t translations; + uint64_t aborted; + uint64_t ops; + unsigned ops_max; + uint64_t del_ops; + uint64_t temps; + unsigned temps_max; + uint64_t host; + uint64_t guest; + uint64_t search_data; +}; + +#define stat_per_translation(stat, name) \ + (stat->translations.total ? stat->name / stat->translations.total : 0) + +/* accumulate the statistics from all TBs */ +static void collect_jit_profile_info(void *p, uint32_t hash, void *userp) +{ + struct jit_profile_info *jpi = userp; + TBStatistics *tbs = p; + + jpi->translations += tbs->translations.total; + jpi->ops += tbs->code.num_tcg_ops; + if (stat_per_translation(tbs, code.num_tcg_ops) > jpi->ops_max) { + jpi->ops_max = stat_per_translation(tbs, code.num_tcg_ops); + } + jpi->del_ops += tbs->code.deleted_ops; + jpi->temps += tbs->code.temps; + if (stat_per_translation(tbs, code.temps) > jpi->temps_max) { + jpi->temps_max = stat_per_translation(tbs, code.temps); + } + jpi->host += tbs->code.out_len; + jpi->guest += tbs->code.in_len; + jpi->search_data += tbs->code.search_out_len; +} + +/* dump JIT statistics using TBStats */ +void dump_jit_profile_info(GString *buf) +{ + if (!tb_stats_collection_enabled()) { + return; + } + + struct jit_profile_info *jpi = g_new0(struct jit_profile_info, 1); + + qht_iter(&tb_ctx.tb_stats, collect_jit_profile_info, jpi); + + if (jpi->translations) { + g_string_append_printf(buf, "translated TBs %" PRId64 "\n", + jpi->translations); + g_string_append_printf(buf, "avg ops/TB %0.1f max=%d\n", + jpi->ops / (double) jpi->translations, jpi->ops_max); + g_string_append_printf(buf, "deleted ops/TB %0.2f\n", + jpi->del_ops / (double) jpi->translations); + g_string_append_printf(buf, "avg temps/TB %0.2f max=%d\n", + jpi->temps / (double) jpi->translations, jpi->temps_max); + g_string_append_printf(buf, "avg host code/TB %0.1f\n", + jpi->host / (double) jpi->translations); + g_string_append_printf(buf, "avg search data/TB %0.1f\n", + jpi->search_data / (double) jpi->translations); + } + g_free(jpi); +} + void init_tb_stats_htable(void) { if (!tb_ctx.tb_stats.map && tb_stats_collection_enabled()) { diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c index d7a35e0ea5..4f1d3b4612 100644 --- a/accel/tcg/translate-all.c +++ b/accel/tcg/translate-all.c @@ -266,7 +266,7 @@ void page_init(void) */ static int setjmp_gen_code(CPUArchState *env, TranslationBlock *tb, vaddr pc, void *host_pc, - int *max_insns, int64_t *ti) + int *max_insns) { int ret = sigsetjmp(tcg_ctx->jmp_trans, 0); if (unlikely(ret != 0)) { @@ -294,6 +294,8 @@ static TBStatistics *tb_get_stats(tb_page_addr_t phys_pc, target_ulong pc, new_stats->pc = pc; new_stats->cs_base = cs_base; new_stats->flags = flags; + new_stats->tbs = g_ptr_array_new(); + qemu_mutex_init(&new_stats->jit_stats_lock); /* * All initialisation must be complete before we insert into qht @@ -307,6 +309,7 @@ static TBStatistics *tb_get_stats(tb_page_addr_t phys_pc, target_ulong pc, * If there is already a TBStatistic for this TB from a previous flush * then just make the new TB point to the older TBStatistic */ + g_ptr_array_free(new_stats->tbs, true); g_free(new_stats); return existing_stats; } else { @@ -325,7 +328,6 @@ TranslationBlock *tb_gen_code(CPUState *cpu, tb_page_addr_t phys_pc; tcg_insn_unit *gen_code_buf; int gen_code_size, search_size, max_insns; - int64_t ti; void *host_pc; assert_memory_lock(); @@ -399,7 +401,7 @@ TranslationBlock *tb_gen_code(CPUState *cpu, tb->tb_stats = NULL; } - gen_code_size = setjmp_gen_code(env, tb, pc, host_pc, &max_insns, &ti); + gen_code_size = setjmp_gen_code(env, tb, pc, host_pc, &max_insns); if (unlikely(gen_code_size < 0)) { switch (gen_code_size) { case -1: @@ -553,6 +555,29 @@ TranslationBlock *tb_gen_code(CPUState *cpu, return tb; } + /* + * Collect JIT stats when enabled. We batch them all up here to + * avoid spamming the cache with atomic accesses + */ + if (tb_stats_enabled(tb, TB_JIT_STATS)) { + TBStatistics *ts = tb->tb_stats; + qemu_mutex_lock(&ts->jit_stats_lock); + + ts->code.num_tcg_ops_opt += tcg_ctx->nb_ops; + ts->code.in_len += tb->size; + ts->code.out_len += tb->tc.size; + ts->code.search_out_len += search_size; + + ts->translations.total++; + if (tb_page_addr1(tb) != -1) { + ts->translations.spanning++; + } + + g_ptr_array_add(ts->tbs, tb); + + qemu_mutex_unlock(&ts->jit_stats_lock); + } + /* * Insert TB into the corresponding region tree before publishing it * through QHT. Otherwise rewinding happened in the TB might fail to diff --git a/accel/tcg/translator.c b/accel/tcg/translator.c index 4743fa7d01..3995d45a66 100644 --- a/accel/tcg/translator.c +++ b/accel/tcg/translator.c @@ -248,6 +248,11 @@ void translator_loop(CPUState *cpu, TranslationBlock *tb, int *max_insns, tb->size = db->pc_next - db->pc_first; tb->icount = db->num_insns; + /* Save number of guest instructions for TB_JIT_STATS */ + if (tb_stats_enabled(tb, TB_JIT_STATS)) { + tb->tb_stats->code.num_guest_inst += db->num_insns; + } + if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM) && qemu_log_in_addr_range(db->pc_first)) { FILE *logfile = qemu_log_trylock(); diff --git a/include/exec/tb-stats-flags.h b/include/exec/tb-stats-flags.h index c0e63408e2..286ca93bcc 100644 --- a/include/exec/tb-stats-flags.h +++ b/include/exec/tb-stats-flags.h @@ -13,6 +13,7 @@ #define TB_NONE_STATS (0) /* no stats */ #define TB_EXEC_STATS (1 << 0) +#define TB_JIT_STATS (1 << 1) /* TBStatistic collection controls */ void enable_collect_tb_stats(void); diff --git a/include/exec/tb-stats.h b/include/exec/tb-stats.h index a8abab269c..7c445856c9 100644 --- a/include/exec/tb-stats.h +++ b/include/exec/tb-stats.h @@ -53,6 +53,34 @@ struct TBStatistics { unsigned long normal; unsigned long atomic; } executions; + + /* JIT Stats - protected by lock */ + QemuMutex jit_stats_lock; + + /* Sum of all operations for all translations */ + struct { + unsigned num_guest_inst; + unsigned num_tcg_ops; + unsigned num_tcg_ops_opt; + unsigned spills; + + unsigned temps; + unsigned deleted_ops; + unsigned in_len; + unsigned out_len; + unsigned search_out_len; + } code; + + struct { + unsigned long total; + unsigned long spanning; + } translations; + + /* + * All persistent (cached) TranslationBlocks using + * this TBStats structure. Has to be reset on a tb_flush. + */ + GPtrArray *tbs; }; bool tb_stats_cmp(const void *ap, const void *bp); @@ -60,4 +88,6 @@ bool tb_stats_cmp(const void *ap, const void *bp); void init_tb_stats_htable(void); bool tb_stats_enabled(TranslationBlock *tb, uint32_t flag); +void dump_jit_profile_info(GString *buf); + #endif diff --git a/include/tcg/tcg.h b/include/tcg/tcg.h index 95541e9474..8c0857fe12 100644 --- a/include/tcg/tcg.h +++ b/include/tcg/tcg.h @@ -478,6 +478,14 @@ static inline TCGRegSet output_pref(const TCGOp *op, unsigned i) return i < ARRAY_SIZE(op->output_pref) ? op->output_pref[i] : 0; } +/* + * The TCGProfile structure holds data for the lifetime of the translator. + */ +typedef struct TCGProfile { + /* Lifetime count of TCGOps per TCGContext when tb_stats enabled */ + size_t table_op_count[NB_OPS]; +} TCGProfile; + struct TCGContext { uint8_t *pool_cur, *pool_end; TCGPool *pool_first, *pool_current, *pool_first_large; @@ -507,6 +515,8 @@ struct TCGContext { tcg_insn_unit *code_buf; /* pointer for start of tb */ tcg_insn_unit *code_ptr; /* pointer for running end of tb */ + TCGProfile prof; + #ifdef CONFIG_DEBUG_TCG int goto_tb_issue_mask; const TCGOpcode *vecop_list; diff --git a/tcg/tcg.c b/tcg/tcg.c index a0628fe424..1318220a77 100644 --- a/tcg/tcg.c +++ b/tcg/tcg.c @@ -36,6 +36,7 @@ #include "qemu/timer.h" #include "exec/translation-block.h" #include "exec/tlb-common.h" +#include "exec/tb-stats.h" #include "tcg/tcg-op-common.h" #if UINTPTR_MAX == UINT32_MAX @@ -3033,6 +3034,9 @@ void tcg_op_remove(TCGContext *s, TCGOp *op) QTAILQ_REMOVE(&s->ops, op, link); QTAILQ_INSERT_TAIL(&s->free_ops, op, link); s->nb_ops--; + if (tb_stats_enabled(s->gen_tb, TB_JIT_STATS)) { + s->gen_tb->tb_stats->code.deleted_ops++; + } } void tcg_remove_ops_after(TCGOp *op) @@ -4198,6 +4202,10 @@ static TCGReg tcg_reg_alloc(TCGContext *s, TCGRegSet required_regs, } /* We must spill something. */ + if (tb_stats_enabled(s->gen_tb, TB_JIT_STATS)) { + s->gen_tb->tb_stats->code.spills++; + } + for (j = f; j < 2; j++) { TCGRegSet set = reg_ct[j]; @@ -5902,9 +5910,17 @@ static void tcg_out_st_helper_args(TCGContext *s, const TCGLabelQemuLdst *ldst, tcg_out_helper_load_common_args(s, ldst, parm, info, next_arg); } -void tcg_dump_op_count(GString *buf) +static void collect_tcg_profiler(TCGProfile *prof) { - g_string_append_printf(buf, "[TCG profiler not compiled]\n"); + unsigned int n_ctxs = qatomic_read(&tcg_cur_ctxs); + unsigned int i; + + for (i = 0; i < n_ctxs; i++) { + TCGContext *s = qatomic_read(&tcg_ctxs[i]); + for (i = 0; i < NB_OPS; i++) { + prof->table_op_count[i] += s->prof.table_op_count[i]; + } + } } int tcg_gen_code(TCGContext *s, TranslationBlock *tb, uint64_t pc_start) @@ -5912,6 +5928,12 @@ int tcg_gen_code(TCGContext *s, TranslationBlock *tb, uint64_t pc_start) int i, start_words, num_insns; TCGOp *op; + /* save pre-optimisation op count */ + if (tb_stats_enabled(tb, TB_JIT_STATS)) { + tb->tb_stats->code.num_tcg_ops += s->nb_ops; + tb->tb_stats->code.temps += s->nb_temps; + } + if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP) && qemu_log_in_addr_range(pc_start))) { FILE *logfile = qemu_log_trylock(); @@ -6003,6 +6025,13 @@ int tcg_gen_code(TCGContext *s, TranslationBlock *tb, uint64_t pc_start) s->gen_insn_data = tcg_malloc(sizeof(uint64_t) * s->gen_tb->icount * start_words); + if (tb_stats_collection_enabled()) { + QTAILQ_FOREACH(op, &s->ops, link) { + TCGOpcode opc = op->opc; + s->prof.table_op_count[opc]++; + } + } + num_insns = -1; QTAILQ_FOREACH(op, &s->ops, link) { TCGOpcode opc = op->opc; @@ -6101,9 +6130,21 @@ int tcg_gen_code(TCGContext *s, TranslationBlock *tb, uint64_t pc_start) return tcg_current_code_size(s); } +void tcg_dump_op_count(GString *buf) +{ + TCGProfile prof = {}; + int i; + + collect_tcg_profiler(&prof); + for (i = 0; i < NB_OPS; i++) { + g_string_append_printf(buf, "%s %" PRId64 "\n", + tcg_op_defs[i].name, prof.table_op_count[i]); + } +} + void tcg_dump_info(GString *buf) { - g_string_append_printf(buf, "[TCG profiler not compiled]\n"); + dump_jit_profile_info(buf); } #ifdef ELF_HOST_MACHINE From patchwork Wed Jun 28 12:04:25 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: "Wu, Fei" X-Patchwork-Id: 13295650 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 647D5EB64D7 for ; Wed, 28 Jun 2023 12:03:51 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1qETsi-0007WZ-OA; Wed, 28 Jun 2023 08:02:44 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qETsb-0007UN-8l for qemu-devel@nongnu.org; Wed, 28 Jun 2023 08:02:42 -0400 Received: from mga01.intel.com ([192.55.52.88]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qETsX-0006gJ-5K for qemu-devel@nongnu.org; Wed, 28 Jun 2023 08:02:36 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1687953753; x=1719489753; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=rdyvIQY1vMsq7QenLkKjezYRM2l/kzmqU/Pzp2JhkJA=; b=IoFhhf0k0LPP6+u2TUb+Vr41aXxpN8reDKMIpgnA31VDmcvU98wKKER3 zUeVxQW7ni2DBBbB0AmN9v1a5n1seobbfH5+gVkcn0ye4O75H0y580jMV 05/8PvBIWPyK0UeneGjJuEDz14ak2YyDyB2LGZ61yWXsLIPZsaeBOfz2v LdUQfMD/qs5wsH5BywQqClISFu6a4SXNu5dpNJAKTb86p74C+IPoIoePh NhAJ9i1Voq/aLG/yIs9C3pPerObAMHa7G4/Lhj+NPTsia9c5x74s62EXb QRTueVop6Ff8vvjOQ/LRVpDtpDt1Z8X4VKS0eN8VLORpkA5utndMAtUCB Q==; X-IronPort-AV: E=McAfee;i="6600,9927,10754"; a="392547299" X-IronPort-AV: E=Sophos;i="6.01,165,1684825200"; d="scan'208";a="392547299" Received: from orsmga004.jf.intel.com ([10.7.209.38]) by fmsmga101.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 28 Jun 2023 05:02:21 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10754"; a="841047489" X-IronPort-AV: E=Sophos;i="6.01,165,1684825200"; d="scan'208";a="841047489" Received: from wufei-optiplex-7090.sh.intel.com ([10.238.200.247]) by orsmga004.jf.intel.com with ESMTP; 28 Jun 2023 05:02:18 -0700 From: Fei Wu To: richard.henderson@linaro.org, alex.bennee@linaro.org, qemu-devel@nongnu.org Cc: "Vanderson M. do Rosario" , "Dr . David Alan Gilbert" , Fei Wu , Paolo Bonzini , "Dr. David Alan Gilbert" Subject: [PATCH v16 4/9] monitor: adding tb_stats hmp command Date: Wed, 28 Jun 2023 20:04:25 +0800 Message-Id: <20230628120430.73777-5-fei2.wu@intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230628120430.73777-1-fei2.wu@intel.com> References: <20230628120430.73777-1-fei2.wu@intel.com> MIME-Version: 1.0 Received-SPF: pass client-ip=192.55.52.88; envelope-from=fei2.wu@intel.com; helo=mga01.intel.com X-Spam_score_int: -43 X-Spam_score: -4.4 X-Spam_bar: ---- X-Spam_report: (-4.4 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_MED=-2.3, RCVD_IN_MSPIKE_H3=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org From: "Vanderson M. do Rosario" Adding tb_stats [start|stop|status] command to hmp. This allows controlling the collection of statistics. It is also possible to set the flag of collection: all, jit, or exec. The goal of this command is to allow the dynamic exploration of the TCG behavior and quality. Therefore, for now, a corresponding QMP command is not worthwhile. Acked-by: Dr. David Alan Gilbert Signed-off-by: Vanderson M. do Rosario Message-Id: <20190829173437.5926-8-vandersonmr2@gmail.com> Message-Id: <20190829173437.5926-9-vandersonmr2@gmail.com> [AJB: fix authorship] Signed-off-by: Alex Bennée Signed-off-by: Fei Wu --- accel/tcg/monitor.c | 98 +++++++++++++++++++++++++++++++++++ accel/tcg/tb-stats.c | 17 ++++++ hmp-commands.hx | 16 ++++++ include/exec/tb-stats-flags.h | 1 + include/exec/tb-stats.h | 4 ++ include/monitor/hmp.h | 1 + 6 files changed, 137 insertions(+) diff --git a/accel/tcg/monitor.c b/accel/tcg/monitor.c index 567950a7ed..60b66f16ff 100644 --- a/accel/tcg/monitor.c +++ b/accel/tcg/monitor.c @@ -11,14 +11,19 @@ #include "qapi/error.h" #include "qapi/type-helpers.h" #include "qapi/qapi-commands-machine.h" +#include "qapi/qmp/qdict.h" #include "monitor/monitor.h" +#include "monitor/hmp.h" #include "sysemu/cpus.h" #include "sysemu/cpu-timers.h" #include "sysemu/tcg.h" #include "tcg/tcg.h" #include "exec/tb-stats.h" +#include "exec/tb-flush.h" #include "internal.h" +#include "tb-context.h" +enum TbstatsCmd { TBS_CMD_START, TBS_CMD_STOP, TBS_CMD_STATUS }; static void dump_drift_info(GString *buf) { @@ -87,6 +92,99 @@ HumanReadableText *qmp_x_query_opcount(Error **errp) return human_readable_text_from_str(buf); } +struct TbstatsCommand { + enum TbstatsCmd cmd; + uint32_t flag; + Monitor *mon; +}; + +static void do_hmp_tbstats_safe(CPUState *cpu, run_on_cpu_data icmd) +{ + struct TbstatsCommand *cmdinfo = icmd.host_ptr; + int cmd = cmdinfo->cmd; + uint32_t flag = cmdinfo->flag; + Monitor *mon = cmdinfo->mon; + + switch (cmd) { + case TBS_CMD_START: + if (tb_stats_collection_enabled()) { + monitor_printf(mon, "TB information already being recorded\n"); + break; + } + + set_tbstats_flag(flag); + enable_collect_tb_stats(); + tb_flush(cpu); + break; + case TBS_CMD_STOP: + if (tb_stats_collection_disabled()) { + monitor_printf(mon, "TB information not being recorded\n"); + break; + } + + /* Dissalloc all TBStatistics structures and stop creating new ones */ + disable_collect_tb_stats(); + clean_tbstats(); + tb_flush(cpu); + break; + case TBS_CMD_STATUS: + if (tb_stats_collection_enabled()) { + uint32_t flag = get_tbstats_flag(); + monitor_printf(mon, "tb_stats is enabled with flag:\n"); + monitor_printf(mon, " EXEC: %d\n", !!(flag & TB_EXEC_STATS)); + monitor_printf(mon, " JIT: %d\n", !!(flag & TB_JIT_STATS)); + } else { + monitor_printf(mon, "tb_stats is disabled\n"); + } + break; + default: /* INVALID */ + g_assert_not_reached(); + break; + } + + g_free(cmdinfo); +} + +void hmp_tbstats(Monitor *mon, const QDict *qdict) +{ + if (!tcg_enabled()) { + monitor_printf(mon, "Only available with accel=tcg\n"); + return; + } + + char *cmd = (char *) qdict_get_try_str(qdict, "command"); + enum TbstatsCmd icmd = -1; + + if (strcmp(cmd, "start") == 0) { + icmd = TBS_CMD_START; + } else if (strcmp(cmd, "stop") == 0) { + icmd = TBS_CMD_STOP; + } else if (strcmp(cmd, "status") == 0) { + icmd = TBS_CMD_STATUS; + } else { + monitor_printf(mon, "Invalid command\n"); + return; + } + + char *sflag = (char *) qdict_get_try_str(qdict, "flag"); + uint32_t flag = TB_EXEC_STATS | TB_JIT_STATS; + if (sflag) { + if (strcmp(sflag, "jit") == 0) { + flag = TB_JIT_STATS; + } else if (strcmp(sflag, "exec") == 0) { + flag = TB_EXEC_STATS; + } + } + + struct TbstatsCommand *tbscommand = g_new0(struct TbstatsCommand, 1); + tbscommand->cmd = icmd; + tbscommand->flag = flag; + tbscommand->mon = mon; + async_safe_run_on_cpu(first_cpu, do_hmp_tbstats_safe, + RUN_ON_CPU_HOST_PTR(tbscommand)); + +} + static void hmp_tcg_register(void) { monitor_register_hmp_info_hrt("jit", qmp_x_query_jit); diff --git a/accel/tcg/tb-stats.c b/accel/tcg/tb-stats.c index 11322359c7..c90dde37d0 100644 --- a/accel/tcg/tb-stats.c +++ b/accel/tcg/tb-stats.c @@ -91,6 +91,18 @@ void dump_jit_profile_info(GString *buf) g_free(jpi); } +static void free_tbstats(void *p, uint32_t hash, void *userp) +{ + g_free(p); +} + +void clean_tbstats(void) +{ + /* remove all tb_stats */ + qht_iter(&tb_ctx.tb_stats, free_tbstats, NULL); + qht_destroy(&tb_ctx.tb_stats); +} + void init_tb_stats_htable(void) { if (!tb_ctx.tb_stats.map && tb_stats_collection_enabled()) { @@ -115,6 +127,11 @@ bool tb_stats_collection_enabled(void) return tcg_collect_tb_stats == TB_STATS_RUNNING; } +bool tb_stats_collection_disabled(void) +{ + return tcg_collect_tb_stats == TB_STATS_STOPPED; +} + uint32_t get_tbstats_flag(void) { return tbstats_flag; diff --git a/hmp-commands.hx b/hmp-commands.hx index 2cbd0f77a0..639e9d9e53 100644 --- a/hmp-commands.hx +++ b/hmp-commands.hx @@ -1670,6 +1670,22 @@ SRST Executes a qemu-io command on the given block device. ERST +#if defined(CONFIG_TCG) + { + .name = "tb_stats", + .args_type = "command:s,flag:s?", + .params = "command [flag]", + .help = "Control tb statistics collection:" + "tb_stats (start|stop|status) [all|jit|exec]", + .cmd = hmp_tbstats, + }, +#endif + +SRST +``tb_stats`` *command* *flag* + Control recording tb statistics +ERST + { .name = "qom-list", .args_type = "path:s?", diff --git a/include/exec/tb-stats-flags.h b/include/exec/tb-stats-flags.h index 286ca93bcc..d8b844be99 100644 --- a/include/exec/tb-stats-flags.h +++ b/include/exec/tb-stats-flags.h @@ -19,6 +19,7 @@ void enable_collect_tb_stats(void); void disable_collect_tb_stats(void); bool tb_stats_collection_enabled(void); +bool tb_stats_collection_disabled(void); uint32_t get_tbstats_flag(void); void set_tbstats_flag(uint32_t flag); diff --git a/include/exec/tb-stats.h b/include/exec/tb-stats.h index 7c445856c9..ef6e8b6388 100644 --- a/include/exec/tb-stats.h +++ b/include/exec/tb-stats.h @@ -31,6 +31,8 @@ #include "exec/tb-stats-flags.h" #include "tcg/tcg.h" +enum SortBy { SORT_BY_HOTNESS, SORT_BY_HG /* Host/Guest */, SORT_BY_SPILLS }; + typedef struct TBStatistics TBStatistics; /* @@ -90,4 +92,6 @@ bool tb_stats_enabled(TranslationBlock *tb, uint32_t flag); void dump_jit_profile_info(GString *buf); +void clean_tbstats(void); + #endif diff --git a/include/monitor/hmp.h b/include/monitor/hmp.h index 13f9a2dedb..2e7f141754 100644 --- a/include/monitor/hmp.h +++ b/include/monitor/hmp.h @@ -181,5 +181,6 @@ void hmp_ioport_write(Monitor *mon, const QDict *qdict); void hmp_boot_set(Monitor *mon, const QDict *qdict); void hmp_info_mtree(Monitor *mon, const QDict *qdict); void hmp_info_cryptodev(Monitor *mon, const QDict *qdict); +void hmp_tbstats(Monitor *mon, const QDict *qdict); #endif From patchwork Wed Jun 28 12:04:26 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: "Wu, Fei" X-Patchwork-Id: 13295655 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 09BE7EB64DA for ; Wed, 28 Jun 2023 12:06:07 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1qETsk-0007at-Em; Wed, 28 Jun 2023 08:02:46 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qETsd-0007UR-7k for qemu-devel@nongnu.org; Wed, 28 Jun 2023 08:02:42 -0400 Received: from mga01.intel.com ([192.55.52.88]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qETsX-0006hC-TT for qemu-devel@nongnu.org; Wed, 28 Jun 2023 08:02:37 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1687953753; x=1719489753; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=iXdZiM9wHrHsHxOasbNIOEuEt1z288cTyQQ7G+fWjmI=; b=iTtwfSYGBIhtzag/LhFMXYK0Pbnqi8sRXKh6WL8oJO0Xekap4EsyxGDy lGMivJ9/6Lornf5Oih7GprWONmUFPG3AY6uvPkNfwEzp2tXWeCfBP45XT /Aqh7aLnjDxtTwI4PfIDVw1OyBpUKGzeJZBw0rhTCvjeTwz7oWW0Ne29+ E/yYk7kbXasmof7MebpIZStW9sXt9rtLM+o8Bo7706eaBG+3TD7C24ouc 5p2gH5WFH54BmkHIFmMTQqfdhQ4IVhSYUWEEMD7OW2T4hiQKycgLf9Cig KnsM4D2G8lNegXk696DBbQJyXQAhZB/cB7HZ1hvwiOXjfkMC5q4A6lapd w==; X-IronPort-AV: E=McAfee;i="6600,9927,10754"; a="392547314" X-IronPort-AV: E=Sophos;i="6.01,165,1684825200"; d="scan'208";a="392547314" Received: from orsmga004.jf.intel.com ([10.7.209.38]) by fmsmga101.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 28 Jun 2023 05:02:23 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10754"; a="841047493" X-IronPort-AV: E=Sophos;i="6.01,165,1684825200"; d="scan'208";a="841047493" Received: from wufei-optiplex-7090.sh.intel.com ([10.238.200.247]) by orsmga004.jf.intel.com with ESMTP; 28 Jun 2023 05:02:21 -0700 From: Fei Wu To: richard.henderson@linaro.org, alex.bennee@linaro.org, qemu-devel@nongnu.org Cc: Fei Wu , Paolo Bonzini Subject: [PATCH v16 5/9] tb-stats: reset the tracked TBs on a tb_flush Date: Wed, 28 Jun 2023 20:04:26 +0800 Message-Id: <20230628120430.73777-6-fei2.wu@intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230628120430.73777-1-fei2.wu@intel.com> References: <20230628120430.73777-1-fei2.wu@intel.com> MIME-Version: 1.0 Received-SPF: pass client-ip=192.55.52.88; envelope-from=fei2.wu@intel.com; helo=mga01.intel.com X-Spam_score_int: -43 X-Spam_score: -4.4 X-Spam_bar: ---- X-Spam_report: (-4.4 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_MED=-2.3, RCVD_IN_MSPIKE_H3=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org From: Alex Bennée We keep track of translations but can only do so up until the translation cache is flushed. At that point we really have no idea if we can re-create a translation because all the active tracking information has been reset. Signed-off-by: Alex Bennée Reviewed-by: Richard Henderson Signed-off-by: Fei Wu --- accel/tcg/tb-maint.c | 1 + accel/tcg/tb-stats.c | 18 ++++++++++++++++++ include/exec/tb-stats.h | 8 ++++++++ 3 files changed, 27 insertions(+) diff --git a/accel/tcg/tb-maint.c b/accel/tcg/tb-maint.c index 264bdd84b3..1ebe6fc60e 100644 --- a/accel/tcg/tb-maint.c +++ b/accel/tcg/tb-maint.c @@ -762,6 +762,7 @@ static void do_tb_flush(CPUState *cpu, run_on_cpu_data tb_flush_count) qht_reset_size(&tb_ctx.htable, CODE_GEN_HTABLE_SIZE); tb_remove_all(); + tbstats_reset_tbs(); tcg_region_reset_all(); /* XXX: flush processor icache at this point if cache flush is expensive */ qatomic_inc(&tb_ctx.tb_flush_count); diff --git a/accel/tcg/tb-stats.c b/accel/tcg/tb-stats.c index c90dde37d0..7c7f700c89 100644 --- a/accel/tcg/tb-stats.c +++ b/accel/tcg/tb-stats.c @@ -103,6 +103,24 @@ void clean_tbstats(void) qht_destroy(&tb_ctx.tb_stats); } +/* + * We have to reset the tbs array on a tb_flush as those + * TranslationBlocks no longer exist. + */ + +static void reset_tbs_array(void *p, uint32_t hash, void *userp) +{ + TBStatistics *tbs = p; + g_ptr_array_set_size(tbs->tbs, 0); +} + +void tbstats_reset_tbs(void) +{ + if (tb_ctx.tb_stats.map) { + qht_iter(&tb_ctx.tb_stats, reset_tbs_array, NULL); + } +} + void init_tb_stats_htable(void) { if (!tb_ctx.tb_stats.map && tb_stats_collection_enabled()) { diff --git a/include/exec/tb-stats.h b/include/exec/tb-stats.h index ef6e8b6388..cef177bc69 100644 --- a/include/exec/tb-stats.h +++ b/include/exec/tb-stats.h @@ -94,4 +94,12 @@ void dump_jit_profile_info(GString *buf); void clean_tbstats(void); +/** + * tbstats_reset_tbs: reset the linked array of TBs + * + * Reset the list of tbs for a given array. Should be called from + * safe work during tb_flush. + */ +void tbstats_reset_tbs(void); + #endif From patchwork Wed Jun 28 12:04:27 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: "Wu, Fei" X-Patchwork-Id: 13295647 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 05B05EB64DC for ; Wed, 28 Jun 2023 12:03:03 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1qETsm-0007eL-9M; Wed, 28 Jun 2023 08:02:48 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qETsh-0007V9-3n for qemu-devel@nongnu.org; Wed, 28 Jun 2023 08:02:43 -0400 Received: from mga01.intel.com ([192.55.52.88]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qETsb-0006fL-2n for qemu-devel@nongnu.org; Wed, 28 Jun 2023 08:02:41 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1687953757; x=1719489757; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=L4Zd6iiRNdH2iLCY1pXJfPM8xvt/tnGJDZIWGSL+Bx4=; b=CLV+5eK7zJ/wZp/ZyYpdN3ekWsswtcME8sGwlMYghQnZ6SEGYexIc//1 P5PZe7/Xr0itlnAPCevYcaoSKV/qf1mHN9WfgSCmMc4R9khp1N0J3lNLj jucNQrzgoB5IbI3aPl2CzX2zAult7GhylhlFMjT/sa/r3nzy62Lv3Ma8R MapPW5/tL5gWdX9bLStPr0VCpPaXY892WEawCG58nVJ5vLxaf4Ont4MWL 6+BQL5i7Dg7+u/QzgBY6apG3K/5ayhM3ZcodSeYdnVg8WA1hqe5LzMQsB 0qQlOeOy5XvZCiX/5/+ZmHed9CNSB+dv3KG5iDj78g7TxyNGf8q8vkoBC Q==; X-IronPort-AV: E=McAfee;i="6600,9927,10754"; a="392547330" X-IronPort-AV: E=Sophos;i="6.01,165,1684825200"; d="scan'208";a="392547330" Received: from orsmga004.jf.intel.com ([10.7.209.38]) by fmsmga101.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 28 Jun 2023 05:02:26 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10754"; a="841047496" X-IronPort-AV: E=Sophos;i="6.01,165,1684825200"; d="scan'208";a="841047496" Received: from wufei-optiplex-7090.sh.intel.com ([10.238.200.247]) by orsmga004.jf.intel.com with ESMTP; 28 Jun 2023 05:02:23 -0700 From: Fei Wu To: richard.henderson@linaro.org, alex.bennee@linaro.org, qemu-devel@nongnu.org Cc: "Vanderson M. do Rosario" , "Dr . David Alan Gilbert" , Fei Wu , Paolo Bonzini , "Dr. David Alan Gilbert" Subject: [PATCH v16 6/9] tb-stats: Adding info [tb-list|tb] commands to HMP Date: Wed, 28 Jun 2023 20:04:27 +0800 Message-Id: <20230628120430.73777-7-fei2.wu@intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230628120430.73777-1-fei2.wu@intel.com> References: <20230628120430.73777-1-fei2.wu@intel.com> MIME-Version: 1.0 Received-SPF: pass client-ip=192.55.52.88; envelope-from=fei2.wu@intel.com; helo=mga01.intel.com X-Spam_score_int: -43 X-Spam_score: -4.4 X-Spam_bar: ---- X-Spam_report: (-4.4 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_MED=-2.3, RCVD_IN_MSPIKE_H3=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_PDS_OTHER_BAD_TLD=0.01, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org From: "Vanderson M. do Rosario" These commands allow the exploration of TBs generated by the TCG. Understand which one hotter, with more guest/host instructions... and examine their guest code. The goal of this command is to allow the dynamic exploration of TCG behavior and code quality. Therefore, for now, a corresponding QMP command is not worthwhile. Example of output: ------------------------------ TB id:0 | phys:0xa21f562e virt:0x0000000000000000 flags:0x00028010 0 inv/1 | exec:6171503732/0 guest inst cov:94.77% | trans:1 ints: g:8 op:28 op_opt:24 spills:0 | h/g (host bytes / guest insts): 37.000000 0xa21f562e: 00002797 auipc a5,8192 # 0xa21f762e 0xa21f5632: a2278793 addi a5,a5,-1502 0xa21f5636: 639c ld a5,0(a5) 0xa21f5638: 00178713 addi a4,a5,1 0xa21f563c: 00002797 auipc a5,8192 # 0xa21f763c 0xa21f5640: a1478793 addi a5,a5,-1516 0xa21f5644: e398 sd a4,0(a5) 0xa21f5646: b7e5 j -24 # 0xa21f562e ------------------------------ Acked-by: Dr. David Alan Gilbert Signed-off-by: Vanderson M. do Rosario Message-Id: <20190829173437.5926-10-vandersonmr2@gmail.com> [AJB: fix authorship, dropped coverset] Signed-off-by: Alex Bennée Signed-off-by: Fei Wu --- accel/tcg/monitor.c | 112 ++++++++++++++++++++++++ accel/tcg/tb-stats.c | 177 ++++++++++++++++++++++++++++++++++++++ disas/disas-mon.c | 15 +++- disas/disas.c | 2 + hmp-commands-info.hx | 16 ++++ include/disas/disas.h | 8 +- include/exec/tb-stats.h | 25 ++++++ include/monitor/hmp.h | 2 + monitor/hmp-cmds-target.c | 3 +- 9 files changed, 356 insertions(+), 4 deletions(-) diff --git a/accel/tcg/monitor.c b/accel/tcg/monitor.c index 60b66f16ff..0ce5a1cb45 100644 --- a/accel/tcg/monitor.c +++ b/accel/tcg/monitor.c @@ -8,18 +8,22 @@ #include "qemu/osdep.h" #include "qemu/accel.h" +#include "qemu/log.h" #include "qapi/error.h" #include "qapi/type-helpers.h" #include "qapi/qapi-commands-machine.h" #include "qapi/qmp/qdict.h" #include "monitor/monitor.h" #include "monitor/hmp.h" +#include "monitor/hmp-target.h" #include "sysemu/cpus.h" #include "sysemu/cpu-timers.h" #include "sysemu/tcg.h" #include "tcg/tcg.h" #include "exec/tb-stats.h" #include "exec/tb-flush.h" +#include "disas/disas.h" +#include "tb-context.h" #include "internal.h" #include "tb-context.h" @@ -185,6 +189,114 @@ void hmp_tbstats(Monitor *mon, const QDict *qdict) } +struct tblist_dump_info { + int count; + int sortedby; + Monitor *mon; +}; + +static void do_dump_tblist_info_safe(CPUState *cpu, run_on_cpu_data info) +{ + struct tblist_dump_info *tbdi = info.host_ptr; + g_autoptr(GString) buf = g_string_new(""); + + dump_tblist_info(buf, tbdi->count, tbdi->sortedby); + monitor_printf(tbdi->mon, "%s", buf->str); + + g_free(tbdi); +} + +void hmp_info_tblist(Monitor *mon, const QDict *qdict) +{ + int number_int; + const char *sortedby_str = NULL; + + if (!tcg_enabled()) { + monitor_printf(mon, "Only available with accel=tcg\n"); + return; + } + if (!tb_ctx.tb_stats.map) { + monitor_printf(mon, "no TB information recorded\n"); + return; + } + + number_int = qdict_get_try_int(qdict, "number", 10); + sortedby_str = qdict_get_try_str(qdict, "sortedby"); + + int sortedby = SORT_BY_HOTNESS; + if (sortedby_str == NULL || strcmp(sortedby_str, "hotness") == 0) { + sortedby = SORT_BY_HOTNESS; + } else if (strcmp(sortedby_str, "hg") == 0) { + sortedby = SORT_BY_HG; + } else if (strcmp(sortedby_str, "spills") == 0) { + sortedby = SORT_BY_SPILLS; + } else { + monitor_printf(mon, "valid sort options are: hotness hg spills\n"); + return; + } + + struct tblist_dump_info *tbdi = g_new(struct tblist_dump_info, 1); + tbdi->count = number_int; + tbdi->sortedby = sortedby; + tbdi->mon = mon; + async_safe_run_on_cpu(first_cpu, do_dump_tblist_info_safe, + RUN_ON_CPU_HOST_PTR(tbdi)); +} + +struct tb_dump_info { + int id; + Monitor *mon; +}; + +static void do_dump_tb_info_safe(CPUState *cpu, run_on_cpu_data info) +{ + struct tb_dump_info *tbdi = info.host_ptr; + int id = tbdi->id; + Monitor *mon = tbdi->mon; + g_autoptr(GString) buf = g_string_new(""); + + TBStatistics *tbs = get_tbstats_by_id(id); + if (tbs == NULL) { + monitor_printf(mon, "TB %d information is not recorded\n", id); + return; + } + + monitor_printf(mon, "\n------------------------------\n\n"); + + int valid_tb_num = dump_tb_info(buf, tbs, id); + monitor_printf(mon, "%s", buf->str); + + if (valid_tb_num > 0) { + for (int i = tbs->tbs->len - 1; i >= 0; --i) { + TranslationBlock *tb = g_ptr_array_index(tbs->tbs, i); + if (!(tb->cflags & CF_INVALID)) { + monitor_disas(mon, mon_get_cpu(mon), tbs->phys_pc, tb->icount, + DISAS_GRA); + break; + } + } + } + monitor_printf(mon, "\n------------------------------\n\n"); + + g_free(tbdi); +} + +void hmp_info_tb(Monitor *mon, const QDict *qdict) +{ + const int id = qdict_get_int(qdict, "id"); + + if (!tcg_enabled()) { + monitor_printf(mon, "Only available with accel=tcg\n"); + return; + } + + struct tb_dump_info *tbdi = g_new(struct tb_dump_info, 1); + tbdi->id = id; + tbdi->mon = mon; + async_safe_run_on_cpu(first_cpu, do_dump_tb_info_safe, + RUN_ON_CPU_HOST_PTR(tbdi)); +} + static void hmp_tcg_register(void) { monitor_register_hmp_info_hrt("jit", qmp_x_query_jit); diff --git a/accel/tcg/tb-stats.c b/accel/tcg/tb-stats.c index 7c7f700c89..73f0a25781 100644 --- a/accel/tcg/tb-stats.c +++ b/accel/tcg/tb-stats.c @@ -11,12 +11,16 @@ #include "disas/disas.h" #include "exec/exec-all.h" #include "tcg/tcg.h" +#include "qapi/error.h" #include "qemu/qemu-print.h" +#include "qemu/log.h" #include "exec/tb-stats.h" #include "tb-context.h" +#include "internal.h" + /* TBStatistic collection controls */ enum TBStatsStatus { TB_STATS_STOPPED = 0, @@ -26,6 +30,8 @@ enum TBStatsStatus { static enum TBStatsStatus tcg_collect_tb_stats; static uint32_t tbstats_flag; +static GPtrArray *last_search; + struct jit_profile_info { uint64_t translations; uint64_t aborted; @@ -42,6 +48,18 @@ struct jit_profile_info { #define stat_per_translation(stat, name) \ (stat->translations.total ? stat->name / stat->translations.total : 0) +TBStatistics *get_tbstats_by_id(int id) +{ + if (!last_search) { + return NULL; + } + + if (id < 0 || id >= last_search->len) { + return NULL; + } + return g_ptr_array_index(last_search, id); +} + /* accumulate the statistics from all TBs */ static void collect_jit_profile_info(void *p, uint32_t hash, void *userp) { @@ -98,6 +116,11 @@ static void free_tbstats(void *p, uint32_t hash, void *userp) void clean_tbstats(void) { + if (last_search) { + g_ptr_array_free(last_search, true); + last_search = NULL; + } + /* remove all tb_stats */ qht_iter(&tb_ctx.tb_stats, free_tbstats, NULL); qht_destroy(&tb_ctx.tb_stats); @@ -129,6 +152,154 @@ void init_tb_stats_htable(void) } } +static void collect_tb_stats(void *p, uint32_t hash, void *userp) +{ + int *count = userp; + + g_ptr_array_add(last_search, p); + (*count)++; +} + +static void count_invalid_tbs(gpointer data, gpointer user_data) +{ + TranslationBlock *tb = (TranslationBlock *) data; + unsigned *counter = (unsigned *) user_data; + if (tb->cflags & CF_INVALID) { + *counter = *counter + 1; + } +} + +int dump_tb_info(GString *buf, TBStatistics *tbs, int id) +{ + unsigned g = stat_per_translation(tbs, code.num_guest_inst); + unsigned ops = stat_per_translation(tbs, code.num_tcg_ops); + unsigned ops_opt = stat_per_translation(tbs, code.num_tcg_ops_opt); + unsigned spills = stat_per_translation(tbs, code.spills); + unsigned h = stat_per_translation(tbs, code.out_len); + unsigned act = tbs->tbs->len; + unsigned invalid = 0; + + float guest_host_prop = g ? ((float) h / g) : 0; + + g_ptr_array_foreach(tbs->tbs, &count_invalid_tbs, &invalid); + + g_string_append_printf(buf, + "TB id:%d | phys:0x"TB_PAGE_ADDR_FMT" virt:0x"TARGET_FMT_lx + " flags:0x%08x %d inv/%d\n", + id, tbs->phys_pc, tbs->pc, tbs->flags, invalid, act); + + if (tbs_stats_enabled(tbs, TB_EXEC_STATS)) { + g_string_append_printf(buf, + "\t| exec:%lu/%lu guest inst cov:%.2f%%\n", + tbs->executions.normal, + tbs->executions.atomic, tbs->executions.coverage / 100.0f); + } + + if (tbs_stats_enabled(tbs, TB_JIT_STATS)) { + g_string_append_printf(buf, + "\t| trans:%lu inst: g:%u op:%u op_opt:%u spills:%d" + "\n\t| h/g (host bytes / guest insts): %f\n", + tbs->translations.total, g, ops, ops_opt, spills, + guest_host_prop); + } + + g_string_append_printf(buf, "\n"); + + return act - invalid; +} + +static gint +inverse_sort_tbs_spills(gconstpointer p1, gconstpointer p2) +{ + const TBStatistics *tbs1 = *(TBStatistics **) p1; + const TBStatistics *tbs2 = *(TBStatistics **) p2; + unsigned long c1 = stat_per_translation(tbs1, code.spills); + unsigned long c2 = stat_per_translation(tbs2, code.spills); + return c1 < c2 ? 1 : c1 == c2 ? 0 : -1; +} + +static gint +inverse_sort_tbs_hotness(gconstpointer p1, gconstpointer p2) +{ + const TBStatistics *tbs1 = *(TBStatistics **) p1; + const TBStatistics *tbs2 = *(TBStatistics **) p2; + unsigned long c1 = stat_per_translation(tbs1, executions.normal); + unsigned long c2 = stat_per_translation(tbs2, executions.normal); + return c1 < c2 ? 1 : c1 == c2 ? 0 : -1; +} + +static gint +inverse_sort_tbs_hg(gconstpointer p1, gconstpointer p2) +{ + const TBStatistics *tbs1 = *(TBStatistics **) p1; + const TBStatistics *tbs2 = *(TBStatistics **) p2; + + if (tbs1->code.num_guest_inst == 0) { + return -1; + } + if (tbs2->code.num_guest_inst == 0) { + return 1; + } + + unsigned long c1 = tbs1->code.out_len / tbs1->code.num_guest_inst; + unsigned long c2 = tbs2->code.out_len / tbs2->code.num_guest_inst; + return c1 < c2 ? 1 : c1 == c2 ? 0 : -1; +} + +static void calculate_last_search_coverages(void) +{ + uint64_t total_exec_count = 0; + + /* Compute total execution count for all tbs */ + for (int i = 0; i < last_search->len; ++i) { + TBStatistics *tbs = g_ptr_array_index(last_search, i); + total_exec_count += + (tbs->executions.atomic + tbs->executions.normal) + * stat_per_translation(tbs, code.num_guest_inst); + } + + for (int i = 0; i < last_search->len; ++i) { + TBStatistics *tbs = g_ptr_array_index(last_search, i); + uint64_t tb_total_execs = + (tbs->executions.atomic + tbs->executions.normal) + * stat_per_translation(tbs, code.num_guest_inst); + tbs->executions.coverage = + (10000 * tb_total_execs) / (total_exec_count + 1); + } +} + +void dump_tblist_info(GString *buf, int total, int sort_by) +{ + int array_size = 0; + + if (last_search) { + g_ptr_array_free(last_search, true); + } + last_search = g_ptr_array_new(); + + qht_iter(&tb_ctx.tb_stats, collect_tb_stats, &array_size); + + calculate_last_search_coverages(); + + if (sort_by == SORT_BY_HOTNESS) { + g_ptr_array_sort(last_search, (GCompareFunc)inverse_sort_tbs_hotness); + } else if (sort_by == SORT_BY_SPILLS) { + g_ptr_array_sort(last_search, (GCompareFunc)inverse_sort_tbs_spills); + } else if (sort_by == SORT_BY_HG) { + g_ptr_array_sort(last_search, (GCompareFunc)inverse_sort_tbs_hg); + } else { + return; + } + + array_size = (array_size > total) ? total : array_size; + g_ptr_array_set_size(last_search, array_size); + + for (int i = 0; i < last_search->len; ++i) { + TBStatistics *tbs = g_ptr_array_index(last_search, i); + dump_tb_info(buf, tbs, i); + } +} + void enable_collect_tb_stats(void) { tcg_collect_tb_stats = TB_STATS_RUNNING; @@ -166,3 +337,9 @@ bool tb_stats_enabled(TranslationBlock *tb, uint32_t flag) tb->tb_stats && (tbstats_flag & flag); } + +bool tbs_stats_enabled(struct TBStatistics *tbs, uint32_t flag) +{ + return tb_stats_collection_enabled() && + (tbstats_flag & flag); +} diff --git a/disas/disas-mon.c b/disas/disas-mon.c index 48ac492c6c..e4125b4493 100644 --- a/disas/disas-mon.c +++ b/disas/disas-mon.c @@ -23,9 +23,18 @@ physical_read_memory(bfd_vma memaddr, bfd_byte *myaddr, int length, return res == MEMTX_OK ? 0 : EIO; } +static int +ram_addr_read_memory(bfd_vma memaddr, bfd_byte *myaddr, int length, + struct disassemble_info *info) +{ + void *p = qemu_map_ram_ptr(0, memaddr); + memcpy(myaddr, p, length); + return 0; +} + /* Disassembler for the monitor. */ void monitor_disas(Monitor *mon, CPUState *cpu, uint64_t pc, - int nb_insn, bool is_physical) + int nb_insn, int addr_kind) { int count, i; CPUDebug s; @@ -35,8 +44,10 @@ void monitor_disas(Monitor *mon, CPUState *cpu, uint64_t pc, s.info.fprintf_func = disas_gstring_printf; s.info.stream = (FILE *)ds; /* abuse this slot */ - if (is_physical) { + if (addr_kind == DISAS_GPA) { s.info.read_memory_func = physical_read_memory; + } else if (addr_kind == DISAS_GRA) { + s.info.read_memory_func = ram_addr_read_memory; } s.info.buffer_vma = pc; diff --git a/disas/disas.c b/disas/disas.c index 0d2d06c2ec..3b19b51fca 100644 --- a/disas/disas.c +++ b/disas/disas.c @@ -8,6 +8,8 @@ #include "hw/core/cpu.h" #include "exec/memory.h" +#include "qemu/log-for-trace.h" + /* Filled in by elfload.c. Simplistic, but will do for now. */ struct syminfo *syminfos = NULL; diff --git a/hmp-commands-info.hx b/hmp-commands-info.hx index f5b37eb74a..ace1ecc3c5 100644 --- a/hmp-commands-info.hx +++ b/hmp-commands-info.hx @@ -262,6 +262,22 @@ ERST .params = "", .help = "show dynamic compiler info", }, + { + .name = "tb-list", + .args_type = "number:i?,sortedby:s?", + .params = "[number sortedby]", + .help = "show a [number] translated blocks sorted by [sortedby]" + "sortedby opts: hotness hg spills", + .cmd = hmp_info_tblist, + }, + { + .name = "tb", + .args_type = "id:i,flags:s?", + .params = "id [flag1,flag2,...]", + .help = "show information about one translated block by id." + "dump flags can be used to set dump code level: out_asm in_asm op", + .cmd = hmp_info_tb, + }, #endif SRST diff --git a/include/disas/disas.h b/include/disas/disas.h index 176775eff7..95854abca2 100644 --- a/include/disas/disas.h +++ b/include/disas/disas.h @@ -1,12 +1,18 @@ #ifndef QEMU_DISAS_H #define QEMU_DISAS_H +enum { + DISAS_GVA = 0, + DISAS_GPA, + DISAS_GRA, /* guest ram addr */ +}; + /* Disassemble this for me please... (debugging). */ void disas(FILE *out, const void *code, size_t size); void target_disas(FILE *out, CPUState *cpu, uint64_t code, size_t size); void monitor_disas(Monitor *mon, CPUState *cpu, uint64_t pc, - int nb_insn, bool is_physical); + int nb_insn, int addr_kind); char *plugin_disas(CPUState *cpu, uint64_t addr, size_t size); diff --git a/include/exec/tb-stats.h b/include/exec/tb-stats.h index cef177bc69..0caffdf32b 100644 --- a/include/exec/tb-stats.h +++ b/include/exec/tb-stats.h @@ -54,6 +54,8 @@ struct TBStatistics { struct { unsigned long normal; unsigned long atomic; + /* filled only when dumping x% cover set */ + uint16_t coverage; } executions; /* JIT Stats - protected by lock */ @@ -89,6 +91,7 @@ bool tb_stats_cmp(const void *ap, const void *bp); void init_tb_stats_htable(void); bool tb_stats_enabled(TranslationBlock *tb, uint32_t flag); +bool tbs_stats_enabled(struct TBStatistics *tbs, uint32_t flag); void dump_jit_profile_info(GString *buf); @@ -102,4 +105,26 @@ void clean_tbstats(void); */ void tbstats_reset_tbs(void); +/** + * dump_tbs_info: report the hottest blocks + * + * @buf: output buffer + * @total: the limit of hotblocks + * @sort_by: property in which the dump will be sorted + * + * Report the hottest blocks to either the log or monitor + */ +void dump_tblist_info(GString *buf, int total, int sort_by); + +/** + * dump_tb_info: dump information about one TB + * + * @buf: output buffer + * @tbs: the tbs to dump + * @id: the display id of the block (from previous search) + */ +int dump_tb_info(GString *buf, TBStatistics *tbs, int id); + +TBStatistics *get_tbstats_by_id(int id); + #endif diff --git a/include/monitor/hmp.h b/include/monitor/hmp.h index 2e7f141754..acdd6f1561 100644 --- a/include/monitor/hmp.h +++ b/include/monitor/hmp.h @@ -182,5 +182,7 @@ void hmp_boot_set(Monitor *mon, const QDict *qdict); void hmp_info_mtree(Monitor *mon, const QDict *qdict); void hmp_info_cryptodev(Monitor *mon, const QDict *qdict); void hmp_tbstats(Monitor *mon, const QDict *qdict); +void hmp_info_tblist(Monitor *mon, const QDict *qdict); +void hmp_info_tb(Monitor *mon, const QDict *qdict); #endif diff --git a/monitor/hmp-cmds-target.c b/monitor/hmp-cmds-target.c index 0d3e84d960..7d1433336d 100644 --- a/monitor/hmp-cmds-target.c +++ b/monitor/hmp-cmds-target.c @@ -133,7 +133,8 @@ static void memory_dump(Monitor *mon, int count, int format, int wsize, } if (format == 'i') { - monitor_disas(mon, cs, addr, count, is_physical); + monitor_disas(mon, cs, addr, count, + is_physical ? DISAS_GPA : DISAS_GVA); return; } From patchwork Wed Jun 28 12:04:28 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: "Wu, Fei" X-Patchwork-Id: 13295651 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id A5B07EB64DC for ; Wed, 28 Jun 2023 12:03:52 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1qETsj-0007YF-Vs; Wed, 28 Jun 2023 08:02:46 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qETsh-0007VA-3z for qemu-devel@nongnu.org; Wed, 28 Jun 2023 08:02:43 -0400 Received: from mga01.intel.com ([192.55.52.88]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qETsc-0006gJ-Ew for qemu-devel@nongnu.org; Wed, 28 Jun 2023 08:02:42 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1687953758; x=1719489758; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=qLBNEBjnv9d4StJFq+2PEmcy/WBZor+oo7+NpDLGI2o=; b=XMzP6hPOx6w1prAaF+Y3jiz3UNH+H1WbQBE2DVK0RefzDJPb/iq1bXeO 13DkdYM6lU+QG8uPy6pzGb2sfF8mILRHAVHvXZYBbXr1KxZRzfqjR6x27 NhrcbbgKF8n+6bf9vpjwQ0NL6hexYrNPeLtMQDhHQVgeK2xc2WHj8ZeQN lF9uLprbQscTPSCDwL4XUoe1RJxHa0mck7GSDiZOSAkuBoGpDN4ZkFn14 rnSXFnmhonxDAYl26MPtRDSkD9jPmojUjctza6HBnyVugZbaUrQ6/+br+ EbjR+aYyIysn7Bc+gNHlZ0t/H7xvUqsnJW+GJNLVyQu/tqPyEFAwZ7Hg4 Q==; X-IronPort-AV: E=McAfee;i="6600,9927,10754"; a="392547339" X-IronPort-AV: E=Sophos;i="6.01,165,1684825200"; d="scan'208";a="392547339" Received: from orsmga004.jf.intel.com ([10.7.209.38]) by fmsmga101.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 28 Jun 2023 05:02:28 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10754"; a="841047503" X-IronPort-AV: E=Sophos;i="6.01,165,1684825200"; d="scan'208";a="841047503" Received: from wufei-optiplex-7090.sh.intel.com ([10.238.200.247]) by orsmga004.jf.intel.com with ESMTP; 28 Jun 2023 05:02:26 -0700 From: Fei Wu To: richard.henderson@linaro.org, alex.bennee@linaro.org, qemu-devel@nongnu.org Cc: Fei Wu , "Vanderson M . do Rosario" , Paolo Bonzini Subject: [PATCH v16 7/9] debug: add -d tb_stats to control TBStatistics Date: Wed, 28 Jun 2023 20:04:28 +0800 Message-Id: <20230628120430.73777-8-fei2.wu@intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230628120430.73777-1-fei2.wu@intel.com> References: <20230628120430.73777-1-fei2.wu@intel.com> MIME-Version: 1.0 Received-SPF: pass client-ip=192.55.52.88; envelope-from=fei2.wu@intel.com; helo=mga01.intel.com X-Spam_score_int: -43 X-Spam_score: -4.4 X-Spam_bar: ---- X-Spam_report: (-4.4 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_MED=-2.3, RCVD_IN_MSPIKE_H3=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Capture TBS at startup instead of an explicit 'tb_stats start' command. Signed-off-by: Vanderson M. do Rosario Signed-off-by: Alex Bennée Signed-off-by: Fei Wu --- include/exec/tb-stats-flags.h | 1 + include/qemu/log.h | 1 + stubs/meson.build | 1 + stubs/tb-stats.c | 32 ++++++++++++++++++++++++++++++++ util/log.c | 18 ++++++++++++++++++ 5 files changed, 53 insertions(+) create mode 100644 stubs/tb-stats.c diff --git a/include/exec/tb-stats-flags.h b/include/exec/tb-stats-flags.h index d8b844be99..936bd35707 100644 --- a/include/exec/tb-stats-flags.h +++ b/include/exec/tb-stats-flags.h @@ -14,6 +14,7 @@ #define TB_NONE_STATS (0) /* no stats */ #define TB_EXEC_STATS (1 << 0) #define TB_JIT_STATS (1 << 1) +#define TB_ALL_STATS (TB_EXEC_STATS | TB_JIT_STATS) /* TBStatistic collection controls */ void enable_collect_tb_stats(void); diff --git a/include/qemu/log.h b/include/qemu/log.h index df59bfabcd..eca10f02a3 100644 --- a/include/qemu/log.h +++ b/include/qemu/log.h @@ -36,6 +36,7 @@ bool qemu_log_separate(void); #define LOG_STRACE (1 << 19) #define LOG_PER_THREAD (1 << 20) #define CPU_LOG_TB_VPU (1 << 21) +#define CPU_LOG_TB_STATS (1 << 22) /* Lock/unlock output. */ diff --git a/stubs/meson.build b/stubs/meson.build index a56645e2f7..e926649d40 100644 --- a/stubs/meson.build +++ b/stubs/meson.build @@ -65,3 +65,4 @@ else endif stub_ss.add(files('semihost-all.c')) stub_ss.add(when: 'CONFIG_VFIO_USER_SERVER', if_false: files('vfio-user-obj.c')) +stub_ss.add(files('tb-stats.c')) diff --git a/stubs/tb-stats.c b/stubs/tb-stats.c new file mode 100644 index 0000000000..38ee12313e --- /dev/null +++ b/stubs/tb-stats.c @@ -0,0 +1,32 @@ +/* + * TB Stats Stubs + * + * Copyright (c) 2019 + * Written by Alex Bennée + * + * This code is licensed under the GNU GPL v2, or later. + */ + + +#include "qemu/osdep.h" +#include "exec/tb-stats-flags.h" + +void enable_collect_tb_stats(void) +{ + return; +} + +void disable_collect_tb_stats(void) +{ + return; +} + +bool tb_stats_collection_enabled(void) +{ + return false; +} + +void set_tbstats_flag(uint32_t flag) +{ + return; +} diff --git a/util/log.c b/util/log.c index def88a9402..59c781de36 100644 --- a/util/log.c +++ b/util/log.c @@ -27,6 +27,7 @@ #include "qemu/thread.h" #include "qemu/lockable.h" #include "qemu/rcu.h" +#include "exec/tb-stats-flags.h" #ifdef CONFIG_LINUX #include #endif @@ -497,6 +498,8 @@ const QEMULogItem qemu_log_items[] = { "open a separate log file per thread; filename must contain '%d'" }, { CPU_LOG_TB_VPU, "vpu", "include VPU registers in the 'cpu' logging" }, + { CPU_LOG_TB_STATS, "tb_stats_{all,jit,exec}", + "enable collection of TBs statistics at startup" }, { 0, NULL, NULL }, }; @@ -518,6 +521,21 @@ int qemu_str_to_log_mask(const char *str) trace_enable_events((*tmp) + 6); mask |= LOG_TRACE; #endif + } else if (g_str_has_prefix(*tmp, "tb_stats_")) { + char *p = *tmp + 9; + uint32_t flag = TB_NONE_STATS; + if (g_str_has_prefix(p, "all")) { + flag = TB_ALL_STATS; + } else if (g_str_has_prefix(p, "jit")) { + flag = TB_JIT_STATS; + } else if (g_str_has_prefix(p, "exec")) { + flag = TB_EXEC_STATS; + } + if (flag != TB_NONE_STATS) { + mask |= CPU_LOG_TB_STATS; + set_tbstats_flag(flag); + enable_collect_tb_stats(); + } } else { for (item = qemu_log_items; item->mask != 0; item++) { if (g_str_equal(*tmp, item->name)) { From patchwork Wed Jun 28 12:04:29 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Wu, Fei" X-Patchwork-Id: 13295648 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id AF344EB64DA for ; Wed, 28 Jun 2023 12:03:08 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1qETsl-0007bw-0v; Wed, 28 Jun 2023 08:02:47 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qETsh-0007VB-4P for qemu-devel@nongnu.org; Wed, 28 Jun 2023 08:02:43 -0400 Received: from mga01.intel.com ([192.55.52.88]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qETse-0006hC-E4 for qemu-devel@nongnu.org; Wed, 28 Jun 2023 08:02:42 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1687953760; x=1719489760; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=nUVTgBldWSPg1rhuCH6gbTPrGBKvjK2pyCkdcPpgTVQ=; b=KiLu9GRRhwSpcFBLdcqK8S65JRtqjRk3qzB3IKXgRFcfnLd1DbOMuzw9 DYFSUN5n+sJz1FrDtyZv5AWGxSP/WLLZtE/sSYIevYLr61k1NEh8anIpJ J9Sim8a3D/bZ254x2qfVOU/vS5PTgBczAfcQYWggBDxlt7fvrM0yp/sCD 7Z2oL/EXr6dBdmZVy0e6PNzeIq6gS1fuK/4kYlOo072BQh1a/atd0qKt9 2c5hki/1JRNvNJ1PQgjnsG3H+0LSfNglJppmsDoNbc8J/6NIPp571kWmb GUMaFjU7DIQW2YtWfcIIz3G8RnoDjnyoEfCI039cIVkJbDDdRG++u5Zip A==; X-IronPort-AV: E=McAfee;i="6600,9927,10754"; a="392547359" X-IronPort-AV: E=Sophos;i="6.01,165,1684825200"; d="scan'208";a="392547359" Received: from orsmga004.jf.intel.com ([10.7.209.38]) by fmsmga101.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 28 Jun 2023 05:02:31 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10754"; a="841047516" X-IronPort-AV: E=Sophos;i="6.01,165,1684825200"; d="scan'208";a="841047516" Received: from wufei-optiplex-7090.sh.intel.com ([10.238.200.247]) by orsmga004.jf.intel.com with ESMTP; 28 Jun 2023 05:02:29 -0700 From: Fei Wu To: richard.henderson@linaro.org, alex.bennee@linaro.org, qemu-devel@nongnu.org Cc: Fei Wu , Paolo Bonzini , Laurent Vivier Subject: [PATCH v16 8/9] tb-stats: dump hot TBs at the end of the execution Date: Wed, 28 Jun 2023 20:04:29 +0800 Message-Id: <20230628120430.73777-9-fei2.wu@intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230628120430.73777-1-fei2.wu@intel.com> References: <20230628120430.73777-1-fei2.wu@intel.com> MIME-Version: 1.0 Received-SPF: pass client-ip=192.55.52.88; envelope-from=fei2.wu@intel.com; helo=mga01.intel.com X-Spam_score_int: -43 X-Spam_score: -4.4 X-Spam_bar: ---- X-Spam_report: (-4.4 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_MED=-2.3, RCVD_IN_MSPIKE_H3=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Dump the hottest TBs if -d tb_stats_{all,jit,exec}[:dump_num_at_exit] --- accel/tcg/tb-stats.c | 21 +++++++++++++++++++++ include/exec/tb-stats-dump.h | 21 +++++++++++++++++++++ include/exec/tb-stats-flags.h | 1 + linux-user/exit.c | 2 ++ softmmu/runstate.c | 2 ++ stubs/tb-stats.c | 4 ++++ util/log.c | 12 ++++++++++-- 7 files changed, 61 insertions(+), 2 deletions(-) create mode 100644 include/exec/tb-stats-dump.h diff --git a/accel/tcg/tb-stats.c b/accel/tcg/tb-stats.c index 73f0a25781..1b038b7b85 100644 --- a/accel/tcg/tb-stats.c +++ b/accel/tcg/tb-stats.c @@ -17,6 +17,7 @@ #include "qemu/log.h" #include "exec/tb-stats.h" +#include "exec/tb-stats-dump.h" #include "tb-context.h" #include "internal.h" @@ -29,6 +30,7 @@ enum TBStatsStatus { static enum TBStatsStatus tcg_collect_tb_stats; static uint32_t tbstats_flag; +static int max_dump_tbs; static GPtrArray *last_search; @@ -300,6 +302,20 @@ void dump_tblist_info(GString *buf, int total, int sort_by) } } +/* + * Dump the final stats + */ +void tb_stats_dump(void) +{ + if (!tb_stats_collection_enabled()) { + return; + } + + g_autoptr(GString) buf = g_string_new(""); + dump_tblist_info(buf, max_dump_tbs, SORT_BY_HOTNESS); + qemu_printf("%s", buf->str); +} + void enable_collect_tb_stats(void) { tcg_collect_tb_stats = TB_STATS_RUNNING; @@ -343,3 +359,8 @@ bool tbs_stats_enabled(struct TBStatistics *tbs, uint32_t flag) return tb_stats_collection_enabled() && (tbstats_flag & flag); } + +void set_tbstats_max_tbs(int max) +{ + max_dump_tbs = max; +} diff --git a/include/exec/tb-stats-dump.h b/include/exec/tb-stats-dump.h new file mode 100644 index 0000000000..197c6148e9 --- /dev/null +++ b/include/exec/tb-stats-dump.h @@ -0,0 +1,21 @@ +/* + * TB Stats common dump functions across sysemu/linux-user + * + * Copyright (c) 2019 Linaro + * + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +#ifndef _TB_STATS_DUMP_H_ +#define _TB_STATS_DUMP_H_ + +/** + * tb_stats_dump: dump final tb_stats at end of execution + */ +#ifdef CONFIG_TCG +void tb_stats_dump(void); +#else +static inline void tb_stats_dump(void) { /* do nothing */ }; +#endif + +#endif /* _TB_STATS_DUMP_H_ */ diff --git a/include/exec/tb-stats-flags.h b/include/exec/tb-stats-flags.h index 936bd35707..52d0429eeb 100644 --- a/include/exec/tb-stats-flags.h +++ b/include/exec/tb-stats-flags.h @@ -24,5 +24,6 @@ bool tb_stats_collection_disabled(void); uint32_t get_tbstats_flag(void); void set_tbstats_flag(uint32_t flag); +void set_tbstats_max_tbs(int max); #endif diff --git a/linux-user/exit.c b/linux-user/exit.c index 3017d28a3c..4fd23bcf60 100644 --- a/linux-user/exit.c +++ b/linux-user/exit.c @@ -25,6 +25,7 @@ #ifdef CONFIG_GPROF #include #endif +#include "exec/tb-stats-dump.h" #ifdef CONFIG_GCOV extern void __gcov_dump(void); @@ -41,4 +42,5 @@ void preexit_cleanup(CPUArchState *env, int code) gdb_exit(code); qemu_plugin_user_exit(); perf_exit(); + tb_stats_dump(); } diff --git a/softmmu/runstate.c b/softmmu/runstate.c index a9fbcf4862..74cc7430c6 100644 --- a/softmmu/runstate.c +++ b/softmmu/runstate.c @@ -30,6 +30,7 @@ #include "crypto/cipher.h" #include "crypto/init.h" #include "exec/cpu-common.h" +#include "exec/tb-stats-dump.h" #include "gdbstub/syscalls.h" #include "hw/boards.h" #include "migration/misc.h" @@ -817,6 +818,7 @@ void qemu_cleanup(void) vm_shutdown(); replay_finish(); + tb_stats_dump(); job_cancel_sync_all(); bdrv_close_all(); diff --git a/stubs/tb-stats.c b/stubs/tb-stats.c index 38ee12313e..78ae1aa217 100644 --- a/stubs/tb-stats.c +++ b/stubs/tb-stats.c @@ -30,3 +30,7 @@ void set_tbstats_flag(uint32_t flag) { return; } + +void set_tbstats_max_tbs(int max) { + return; +} diff --git a/util/log.c b/util/log.c index 59c781de36..3c15fcac01 100644 --- a/util/log.c +++ b/util/log.c @@ -498,8 +498,9 @@ const QEMULogItem qemu_log_items[] = { "open a separate log file per thread; filename must contain '%d'" }, { CPU_LOG_TB_VPU, "vpu", "include VPU registers in the 'cpu' logging" }, - { CPU_LOG_TB_STATS, "tb_stats_{all,jit,exec}", - "enable collection of TBs statistics at startup" }, + { CPU_LOG_TB_STATS, "tb_stats_{all,jit,exec}[:dump_num_at_exit]", + "enable collection of TBs statistics at startup " + "and dump at exit until given a limit" }, { 0, NULL, NULL }, }; @@ -526,16 +527,23 @@ int qemu_str_to_log_mask(const char *str) uint32_t flag = TB_NONE_STATS; if (g_str_has_prefix(p, "all")) { flag = TB_ALL_STATS; + p += 3; } else if (g_str_has_prefix(p, "jit")) { flag = TB_JIT_STATS; + p += 3; } else if (g_str_has_prefix(p, "exec")) { flag = TB_EXEC_STATS; + p += 4; } if (flag != TB_NONE_STATS) { mask |= CPU_LOG_TB_STATS; set_tbstats_flag(flag); enable_collect_tb_stats(); } + if (p[0] == ':') { + int max_to_dump = atoi(p + 1); + set_tbstats_max_tbs(max_to_dump); + } } else { for (item = qemu_log_items; item->mask != 0; item++) { if (g_str_equal(*tmp, item->name)) { From patchwork Wed Jun 28 12:04:30 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Wu, Fei" X-Patchwork-Id: 13295649 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 115C9EB64D7 for ; Wed, 28 Jun 2023 12:03:22 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1qETt9-0008BK-1v; Wed, 28 Jun 2023 08:03:11 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qETsj-0007ZQ-Eo for qemu-devel@nongnu.org; Wed, 28 Jun 2023 08:02:46 -0400 Received: from mga01.intel.com ([192.55.52.88]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qETsh-0006fL-Ef for qemu-devel@nongnu.org; Wed, 28 Jun 2023 08:02:45 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1687953763; x=1719489763; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=9LJJviAfYCdAvePXobpw6wkDnhxf+chY/C56H1WEv/Y=; b=Ti57/p4auF4fe7VjbOEGI8B0enGoxOUXc/SUyrsSi/BPnXUOzrXkRdw9 UwPli6sRdEga7OUl2NwZODIFi3oEcJmAc9MbBDg48IwhowvUtr8Yb7Jgy NzUq2GzCqy5LuZXldKMZ5VPexXfS5FYpdHRMaCcXnA1FbZEWjzNBYEMHa rovBuAm+k5rSurRWGMTda4fze4eIf246rVa581z6NAb5Fp60xTAP34BRF d7BsCvN5/Frnx8BHv+c8Nb2nRfsQuG8d8cFREQToPwmhgXg4oaF/IMYcJ 8RMycA7hr1pGWfeOvgWd42PnIudXyQDs73Q6CE9yKbsbikMY7MHUxkHv2 g==; X-IronPort-AV: E=McAfee;i="6600,9927,10754"; a="392547374" X-IronPort-AV: E=Sophos;i="6.01,165,1684825200"; d="scan'208";a="392547374" Received: from orsmga004.jf.intel.com ([10.7.209.38]) by fmsmga101.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 28 Jun 2023 05:02:34 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10754"; a="841047527" X-IronPort-AV: E=Sophos;i="6.01,165,1684825200"; d="scan'208";a="841047527" Received: from wufei-optiplex-7090.sh.intel.com ([10.238.200.247]) by orsmga004.jf.intel.com with ESMTP; 28 Jun 2023 05:02:32 -0700 From: Fei Wu To: richard.henderson@linaro.org, alex.bennee@linaro.org, qemu-devel@nongnu.org Cc: Fei Wu , Paolo Bonzini Subject: [PATCH v16 9/9] docs: add tb-stats how to Date: Wed, 28 Jun 2023 20:04:30 +0800 Message-Id: <20230628120430.73777-10-fei2.wu@intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230628120430.73777-1-fei2.wu@intel.com> References: <20230628120430.73777-1-fei2.wu@intel.com> MIME-Version: 1.0 Received-SPF: pass client-ip=192.55.52.88; envelope-from=fei2.wu@intel.com; helo=mga01.intel.com X-Spam_score_int: -43 X-Spam_score: -4.4 X-Spam_bar: ---- X-Spam_report: (-4.4 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_MED=-2.3, RCVD_IN_MSPIKE_H3=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Signed-off-by: Fei Wu --- docs/devel/index-tcg.rst | 1 + docs/devel/tcg-tbstats.rst | 126 +++++++++++++++++++++++++++++++++++++ 2 files changed, 127 insertions(+) create mode 100644 docs/devel/tcg-tbstats.rst diff --git a/docs/devel/index-tcg.rst b/docs/devel/index-tcg.rst index b44ff8b5a4..8d2832737f 100644 --- a/docs/devel/index-tcg.rst +++ b/docs/devel/index-tcg.rst @@ -14,4 +14,5 @@ are only implementing things for HW accelerated hypervisors. multi-thread-tcg tcg-icount tcg-plugins + tcg-tbstats replay diff --git a/docs/devel/tcg-tbstats.rst b/docs/devel/tcg-tbstats.rst new file mode 100644 index 0000000000..3940a3cb9d --- /dev/null +++ b/docs/devel/tcg-tbstats.rst @@ -0,0 +1,126 @@ +============ +TBStatistics +============ + +What is TBStatistics +==================== + +TBStatistics (tb_stats) is a tool to gather various internal information of TCG +during binary translation, this allows us to identify such as hottest TBs, +guest to host instruction translation ratio, number of spills during register +allocation and more. + +What does TBStatistics collect +=============================== + +TBStatistics mainly collects the following stats: + +* TB exec stats, e.g. the execution count of each TB +* TB jit stats, e.g. guest insn count, tcg ops, tcg spill etc. +* opcount of each instruction, use 'info opcount' to show it + + +How to use TBStatistics +======================= + +1. HMP interface +---------------- + +TBStatistics provides HMP interface, you can try the following examples after +connecting to the monitor. + +* First check the help info:: + + (qemu) help tb_stats + tb_stats command [flag] -- Control tb statistics collection:tb_stats (start|stop|status) [all|jit|exec] + + (qemu) help info tb-list + info tb-list [number sortedby] -- show a [number] translated blocks sorted by [sortedby]sortedby opts: hotness hg spills + + (qemu) help info tb + info tb id [flag1,flag2,...] -- show information about one translated block by id.dump flags can be used to set dump code level: out_asm in_asm op + +* Enable TBStatistics:: + + (qemu) tb_stats start all + (qemu) + +* Get interested TB list:: + + (qemu) info tb-list 2 + TB id:0 | phys:0x79bca0 virt:0xffffffff8059bca0 flags:0x01024001 0 inv/1 + | exec:1464084/0 guest inst cov:0.15% + | trans:1 inst: g:3 op:16 op_opt:15 spills:0 + | h/g (host bytes / guest insts): 64.000000 + + TB id:1 | phys:0x2adf0c virt:0xffffffff800adf0c flags:0x01024001 0 inv/1 + | exec:1033298/0 guest inst cov:0.28% + | trans:1 inst: g:8 op:35 op_opt:33 spills:0 + | h/g (host bytes / guest insts): 86.000000 + +* Dive into the specific TB:: + + (qemu) info tb 0 + ------------------------------ + + TB id:0 | phys:0x63474e virt:0x0000000000000000 flags:0x01028001 0 inv/1 + | exec:131719290/0 guest inst cov:8.44% + | trans:1 ints: g:9 op:36 op_opt:34 spills:0 + | h/g (host bytes / guest insts): 51.555557 + + 0x0063474e: 00194a83 lbu s5,1(s2) + 0x00634752: 00094803 lbu a6,0(s2) + 0x00634756: 0b09 addi s6,s6,2 + 0x00634758: 008a9a9b slliw s5,s5,8 + 0x0063475c: 01586833 or a6,a6,s5 + 0x00634760: ff0b1f23 sh a6,-2(s6) + 0x00634764: 1c7d addi s8,s8,-1 + 0x00634766: 0909 addi s2,s2,2 + 0x00634768: fe0c13e3 bnez s8,-26 # 0x63474e + + ------------------------------ + +* Stop TBStatistics after investigation, this will disable TBStatistics completely.:: + + (qemu) tb_stats stop + (qemu) + +* Definitely, TBStatistics can be restarted for another round of investigation.:: + + (qemu) tb_stats start all + (qemu) + + +2. Start TBStatistics with command line +--------------------------------------- + +If you don't want to missing anything at guest starting, command line option is +provided to start TBStatistics at start::: + + -d tb_stats_{all,jit,exec} + + +3. Dump hottest at exit +----------------------- + +TBStatistics is able to dump hottest TB information at exit as follows::: + + -d tb_stats_{all,jit,exec}[:dump_num_at_exit] + +e.g. starting qemu like this::: + + -d tb_stats_all:2 + +QEMU prints the following at exit::: + + TB id:0 | phys:0x242b8 virt:0x00000000000242b8 flags:0x00024078 0 inv/0 + | exec:1161/0 guest inst cov:10.36% + | trans:1 ints: g:2 op:20 op_opt:19 spills:0 + | h/g (host bytes / guest insts): 61.500000 + + TB id:1 | phys:0x242be virt:0x00000000000242be flags:0x00024078 0 inv/0 + | exec:1161/0 guest inst cov:10.36% + | trans:1 ints: g:2 op:20 op_opt:18 spills:0 + | h/g (host bytes / guest insts): 59.500000 + +This is particularly useful for user mode QEMU.