From patchwork Thu May 18 13:57:43 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: "Wu, Fei" X-Patchwork-Id: 13246843 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 AAE09C7EE23 for ; Thu, 18 May 2023 13:57:14 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1pze7N-0002XQ-Uj; Thu, 18 May 2023 09:56: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 1pze7K-0002T3-8R for qemu-devel@nongnu.org; Thu, 18 May 2023 09:56:30 -0400 Received: from mga12.intel.com ([192.55.52.136]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1pze7H-0002Jo-Rl for qemu-devel@nongnu.org; Thu, 18 May 2023 09:56:29 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1684418187; x=1715954187; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=dicsL1Sgg+9kcUTjdCRPATdgp46CaH6ElptVmxTH39Q=; b=R/1jiQktN65ZlY8NAGLN1lII9a+qLPKZvdj00uOSvQb6qwzDfKM1YxO7 8/eBfeguoYa0vZ0xBaeCMEB/TEYoRuLjcvG1oh5wT6EdhbHa9hkZK25f8 gHm3x+c6XmbVIGSAikOKmtA+kn3BTkW5nnlamOzi1H7GEfQAznMcarP88 Cdmnktrxor2Nedlm4/3VxW20r2HTDz59SNDLeU+mnl/SB6y2JxxoOB54g M+J3rv3PPk1oM7fQ314L3Fl/Gjkw11QFBc0FnZKHHihVoKyrQppCM7dXD +WKODd1rlHggmAX2TigG1DygzuGQYkFJaxllSnU2fT4JMnHCOufkmJ098 A==; X-IronPort-AV: E=McAfee;i="6600,9927,10714"; a="331685583" X-IronPort-AV: E=Sophos;i="5.99,285,1677571200"; d="scan'208";a="331685583" Received: from orsmga005.jf.intel.com ([10.7.209.41]) by fmsmga106.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 18 May 2023 06:56:24 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10714"; a="876428767" X-IronPort-AV: E=Sophos;i="5.99,285,1677571200"; d="scan'208";a="876428767" Received: from wufei-optiplex-7090.sh.intel.com ([10.238.200.247]) by orsmga005.jf.intel.com with ESMTP; 18 May 2023 06:56:22 -0700 From: Fei Wu To: qemu-devel@nongnu.org, richard.henderson@linaro.org, alex.bennee@linaro.org, fei2.wu@intel.com Cc: "Vanderson M. do Rosario" , Paolo Bonzini Subject: [PATCH v12 01/15] accel/tcg: introduce TBStatistics structure Date: Thu, 18 May 2023 21:57:43 +0800 Message-Id: <20230518135757.1442654-2-fei2.wu@intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230518135757.1442654-1-fei2.wu@intel.com> References: <20230518135757.1442654-1-fei2.wu@intel.com> MIME-Version: 1.0 Received-SPF: pass client-ip=192.55.52.136; envelope-from=fei2.wu@intel.com; helo=mga12.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, SPF_HELO_PASS=-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 | 58 +++++++++++++++++++++++++++++++++++ accel/tcg/translate-all.c | 43 ++++++++++++++++++++++++++ include/exec/exec-all.h | 3 ++ include/exec/tb-stats-flags.h | 21 +++++++++++++ include/exec/tb-stats.h | 56 +++++++++++++++++++++++++++++++++ 10 files changed, 210 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 50585117a0..1e5a972be6 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/sysemu/cpus.h F: include/sysemu/tcg.h diff --git a/accel/tcg/meson.build b/accel/tcg/meson.build index aeb20a6ef0..9263bdde11 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 83dc610e4c..87d657a1c6 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, target_ulong pc, uint32_t flags, return qemu_xxhash7(phys_pc, pc, flags, cf_mask, trace_vcpu_dstate); } +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 991746f80f..0980fca358 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; @@ -60,6 +78,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..f988bd8a31 --- /dev/null +++ b/accel/tcg/tb-stats.c @@ -0,0 +1,58 @@ +/* + * 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_DISABLED = 0, + TB_STATS_RUNNING, + TB_STATS_PAUSED, + TB_STATS_STOPPED +}; + +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; +} + +void pause_collect_tb_stats(void) +{ + tcg_collect_tb_stats = TB_STATS_PAUSED; +} + +bool tb_stats_collection_enabled(void) +{ + return tcg_collect_tb_stats == TB_STATS_RUNNING; +} + +bool tb_stats_collection_paused(void) +{ + return tcg_collect_tb_stats == TB_STATS_PAUSED; +} diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c index 353849ca6d..a5ebc5e9e2 100644 --- a/accel/tcg/translate-all.c +++ b/accel/tcg/translate-all.c @@ -54,6 +54,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" @@ -301,6 +302,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, target_ulong pc, target_ulong cs_base, @@ -373,6 +405,17 @@ 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, 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/exec-all.h b/include/exec/exec-all.h index ecded1f112..d7038af3df 100644 --- a/include/exec/exec-all.h +++ b/include/exec/exec-all.h @@ -611,6 +611,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; }; /* Hide the qatomic_read to make code a little easier on the eyes */ diff --git a/include/exec/tb-stats-flags.h b/include/exec/tb-stats-flags.h new file mode 100644 index 0000000000..87ee3d902e --- /dev/null +++ b/include/exec/tb-stats-flags.h @@ -0,0 +1,21 @@ +/* + * 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); +void pause_collect_tb_stats(void); +bool tb_stats_collection_enabled(void); +bool tb_stats_collection_paused(void); + +#endif diff --git a/include/exec/tb-stats.h b/include/exec/tb-stats.h new file mode 100644 index 0000000000..b519465665 --- /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/exec-all.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; + target_ulong pc; + uint32_t flags; + /* cs_base isn't included in the hash but we do check for matches */ + target_ulong cs_base; +}; + +bool tb_stats_cmp(const void *ap, const void *bp); + +void init_tb_stats_htable(void); + +#endif From patchwork Thu May 18 13:57:44 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: "Wu, Fei" X-Patchwork-Id: 13246845 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 E743DC7EE24 for ; Thu, 18 May 2023 13:57:15 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1pze7V-0002kY-KZ; Thu, 18 May 2023 09:56:41 -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 1pze7U-0002hE-JF for qemu-devel@nongnu.org; Thu, 18 May 2023 09:56:40 -0400 Received: from mga12.intel.com ([192.55.52.136]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1pze7R-0002LC-U7 for qemu-devel@nongnu.org; Thu, 18 May 2023 09:56:40 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1684418197; x=1715954197; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=O0CQW1bqgE1OGMeg4d3gEy+QT5FIgjlGDCXFIzI4prU=; b=F0SCOEDW7rXJoO7dlihs+jYRCu13K568OTNbYJm5jZRcJds4pT7P/Bj+ yCvB7cbof5abrzThVSHbBw3leMRlN8IsBabkJalkiYuQysKEmvrGodpP0 C2vzYtC/wOKzFQaJbAb6VZXVqZSh3wXzx9jWT32zMPTM1upMBECdAZsKR /My5E33j96kOk4fpEy+Zy0FtYcaoiiNAKTiIuBzVDLhSuLiCx4HakqZhB tHtriuZ/pIpKQF+LTOztWVwbQqzQ/TWOaoDBj9dtrQPgAy1MXqN6FUsui pOIfuLhkdahV3wTSpnFNV5dsGZy+RYVWMqyiSoCgG5LSiJJkVmouiEfOY Q==; X-IronPort-AV: E=McAfee;i="6600,9927,10714"; a="331685675" X-IronPort-AV: E=Sophos;i="5.99,285,1677571200"; d="scan'208";a="331685675" Received: from orsmga005.jf.intel.com ([10.7.209.41]) by fmsmga106.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 18 May 2023 06:56:36 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10714"; a="876428809" X-IronPort-AV: E=Sophos;i="5.99,285,1677571200"; d="scan'208";a="876428809" Received: from wufei-optiplex-7090.sh.intel.com ([10.238.200.247]) by orsmga005.jf.intel.com with ESMTP; 18 May 2023 06:56:34 -0700 From: Fei Wu To: qemu-devel@nongnu.org, richard.henderson@linaro.org, alex.bennee@linaro.org, fei2.wu@intel.com Cc: "Vanderson M. do Rosario" , Paolo Bonzini Subject: [PATCH v12 02/15] accel: collecting TB execution count Date: Thu, 18 May 2023 21:57:44 +0800 Message-Id: <20230518135757.1442654-3-fei2.wu@intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230518135757.1442654-1-fei2.wu@intel.com> References: <20230518135757.1442654-1-fei2.wu@intel.com> MIME-Version: 1.0 Received-SPF: pass client-ip=192.55.52.136; envelope-from=fei2.wu@intel.com; helo=mga12.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, SPF_HELO_PASS=-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. 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 | 6 ++++++ accel/tcg/tcg-runtime.c | 8 ++++++++ accel/tcg/tcg-runtime.h | 1 + accel/tcg/translate-all.c | 7 +++++-- accel/tcg/translator.c | 10 ++++++++++ include/exec/gen-icount.h | 1 + include/exec/tb-stats-flags.h | 5 +++++ include/exec/tb-stats.h | 13 +++++++++++++ 9 files changed, 55 insertions(+), 2 deletions(-) diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c index bc0e1c3299..a3f24c62a0 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" @@ -564,7 +565,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 f988bd8a31..143a52ef5c 100644 --- a/accel/tcg/tb-stats.c +++ b/accel/tcg/tb-stats.c @@ -22,6 +22,7 @@ enum TBStatsStatus { }; static enum TBStatsStatus tcg_collect_tb_stats; +static uint32_t default_tbstats_flag; void init_tb_stats_htable(void) { @@ -56,3 +57,8 @@ bool tb_stats_collection_paused(void) { return tcg_collect_tb_stats == TB_STATS_PAUSED; } + +uint32_t get_default_tbstats_flag(void) +{ + return default_tbstats_flag; +} diff --git a/accel/tcg/tcg-runtime.c b/accel/tcg/tcg-runtime.c index e4e030043f..85cb795732 100644 --- a/accel/tcg/tcg-runtime.c +++ b/accel/tcg/tcg-runtime.c @@ -27,6 +27,7 @@ #include "exec/helper-proto.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" @@ -148,3 +149,10 @@ void HELPER(exit_atomic)(CPUArchState *env) { cpu_loop_exit_atomic(env_cpu(env), GETPC()); } + +void HELPER(inc_exec_freq)(void *ptr) +{ + TBStatistics *stats = (TBStatistics *) ptr; + tcg_debug_assert(stats); + ++stats->executions.normal; +} diff --git a/accel/tcg/tcg-runtime.h b/accel/tcg/tcg-runtime.h index 6f8c2061d0..8d310e39c0 100644 --- a/accel/tcg/tcg-runtime.h +++ b/accel/tcg/tcg-runtime.h @@ -41,6 +41,7 @@ DEF_HELPER_FLAGS_3(memset, TCG_CALL_NO_RWG, ptr, ptr, int, ptr) DEF_HELPER_FLAGS_3(ld_i128, TCG_CALL_NO_WG, i128, env, i64, i32) DEF_HELPER_FLAGS_4(st_i128, TCG_CALL_NO_WG, void, env, i64, i128, i32) +DEF_HELPER_FLAGS_1(inc_exec_freq, TCG_CALL_NO_RWG, void, ptr) DEF_HELPER_FLAGS_5(atomic_cmpxchgb, TCG_CALL_NO_WG, i32, env, i64, i32, i32, i32) diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c index a5ebc5e9e2..31d4ddf4ab 100644 --- a/accel/tcg/translate-all.c +++ b/accel/tcg/translate-all.c @@ -312,6 +312,7 @@ 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->stats_enabled = get_default_tbstats_flag(); /* * All initialisation must be complete before we insert into qht @@ -408,9 +409,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, pc, cs_base, flags); } else { tb->tb_stats = NULL; diff --git a/accel/tcg/translator.c b/accel/tcg/translator.c index 7bda43ff61..165072c8c3 100644 --- a/accel/tcg/translator.c +++ b/accel/tcg/translator.c @@ -18,6 +18,15 @@ #include "exec/plugin-gen.h" #include "exec/replay-core.h" +static inline void gen_tb_exec_count(TranslationBlock *tb) +{ + if (tb_stats_enabled(tb, TB_EXEC_STATS)) { + TCGv_ptr ptr = tcg_temp_new_ptr(); + tcg_gen_movi_ptr(ptr, (intptr_t)tb->tb_stats); + gen_helper_inc_exec_freq(ptr); + } +} + bool translator_use_goto_tb(DisasContextBase *db, target_ulong dest) { /* Suppress goto_tb if requested. */ @@ -56,6 +65,7 @@ void translator_loop(CPUState *cpu, TranslationBlock *tb, int *max_insns, /* Start translating. */ gen_tb_start(db->tb); + 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/gen-icount.h b/include/exec/gen-icount.h index f6de79a6b4..20e7835ff0 100644 --- a/include/exec/gen-icount.h +++ b/include/exec/gen-icount.h @@ -2,6 +2,7 @@ #define GEN_ICOUNT_H #include "exec/exec-all.h" +#include "exec/tb-stats.h" /* Helpers for instruction counting code generation. */ diff --git a/include/exec/tb-stats-flags.h b/include/exec/tb-stats-flags.h index 87ee3d902e..fa71eb6f0c 100644 --- a/include/exec/tb-stats-flags.h +++ b/include/exec/tb-stats-flags.h @@ -11,6 +11,9 @@ #ifndef TB_STATS_FLAGS #define TB_STATS_FLAGS +#define TB_NOTHING (1 << 0) +#define TB_EXEC_STATS (1 << 1) + /* TBStatistic collection controls */ void enable_collect_tb_stats(void); void disable_collect_tb_stats(void); @@ -18,4 +21,6 @@ void pause_collect_tb_stats(void); bool tb_stats_collection_enabled(void); bool tb_stats_collection_paused(void); +uint32_t get_default_tbstats_flag(void); + #endif diff --git a/include/exec/tb-stats.h b/include/exec/tb-stats.h index b519465665..eb1fa92a4e 100644 --- a/include/exec/tb-stats.h +++ b/include/exec/tb-stats.h @@ -31,6 +31,9 @@ #include "exec/tb-stats-flags.h" #include "tcg/tcg.h" +#define tb_stats_enabled(tb, JIT_STATS) \ + (tb && tb->tb_stats && (tb->tb_stats->stats_enabled & JIT_STATS)) + typedef struct TBStatistics TBStatistics; /* @@ -47,6 +50,16 @@ struct TBStatistics { uint32_t flags; /* cs_base isn't included in the hash but we do check for matches */ target_ulong cs_base; + + /* which stats are enabled for this TBStats */ + uint32_t stats_enabled; + + /* Execution stats */ + struct { + unsigned long normal; + unsigned long atomic; + } executions; + }; bool tb_stats_cmp(const void *ap, const void *bp); From patchwork Thu May 18 13:57:45 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: "Wu, Fei" X-Patchwork-Id: 13246849 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 DA671C7EE23 for ; Thu, 18 May 2023 13:58:01 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1pze7Z-0002vf-AA; Thu, 18 May 2023 09:56:45 -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 1pze7X-0002rp-0D for qemu-devel@nongnu.org; Thu, 18 May 2023 09:56:43 -0400 Received: from mga12.intel.com ([192.55.52.136]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1pze7U-0002LC-Ue for qemu-devel@nongnu.org; Thu, 18 May 2023 09:56:42 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1684418200; x=1715954200; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=2+dvasnkN4nkBGZ+Xt9BHvPwX6Et38MUDrTiipQuFXo=; b=WiCiiVJWurYpyJDiTr1A/U5Bm9/a7U2S04KGohnOaRd6OZJV8/IO/bLO 5R4+iTeZhyxfnWxdDOBB9wqcxZeMgQx7NDblk3m0gOqoEcAthZooEN8h4 Dfe6LlUj0bhfe0ysgBkDHIvGr0IBNEuR1POp4Pqf4XUO7BOc2n4kk2mrF iQWziENO9GVYuAeArnHbNipatThcb9zy35maVRQkydGYXuf5qAs20QyRN TptdAic9ra2L4XckwMnhGvFib9mvfIcfa3kR6iMXWVR8Zcneq9Fm1+Xyp OHNrFEXcIUZbKh05Nj0tuDLNaHOx+mb9kMVwqNw/RSuTs27wfpdNTMuw2 Q==; X-IronPort-AV: E=McAfee;i="6600,9927,10714"; a="331685691" X-IronPort-AV: E=Sophos;i="5.99,285,1677571200"; d="scan'208";a="331685691" Received: from orsmga005.jf.intel.com ([10.7.209.41]) by fmsmga106.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 18 May 2023 06:56:39 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10714"; a="876428816" X-IronPort-AV: E=Sophos;i="5.99,285,1677571200"; d="scan'208";a="876428816" Received: from wufei-optiplex-7090.sh.intel.com ([10.238.200.247]) by orsmga005.jf.intel.com with ESMTP; 18 May 2023 06:56:38 -0700 From: Fei Wu To: qemu-devel@nongnu.org, richard.henderson@linaro.org, alex.bennee@linaro.org, fei2.wu@intel.com Cc: "Vanderson M. do Rosario" , Paolo Bonzini Subject: [PATCH v12 03/15] accel: collecting JIT statistics Date: Thu, 18 May 2023 21:57:45 +0800 Message-Id: <20230518135757.1442654-4-fei2.wu@intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230518135757.1442654-1-fei2.wu@intel.com> References: <20230518135757.1442654-1-fei2.wu@intel.com> MIME-Version: 1.0 Received-SPF: pass client-ip=192.55.52.136; envelope-from=fei2.wu@intel.com; helo=mga12.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, SPF_HELO_PASS=-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_JIT_STATS enabled then we collect statistics of its translation processes and code translation. To help with collection we include the TCGProfile structure unconditionally. It will have further alterations in future commits. Collecting the number of host instructions seems to be not simple as it would imply in having to modify several target source files. So, for now, we are only collecting the size of the host gen code. Signed-off-by: Vanderson M. do Rosario Message-Id: <20190829173437.5926-4-vandersonmr2@gmail.com> Signed-off-by: Alex Bennée Signed-off-by: Fei Wu --- accel/tcg/translate-all.c | 29 +++++++++++++++++++++++++++-- accel/tcg/translator.c | 3 +++ include/exec/tb-stats-flags.h | 1 + include/exec/tb-stats.h | 23 +++++++++++++++++++++++ include/tcg/tcg.h | 22 ++++++++++++++++++++-- tcg/tcg.c | 9 +++++++-- 6 files changed, 81 insertions(+), 6 deletions(-) diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c index 31d4ddf4ab..e36a780a70 100644 --- a/accel/tcg/translate-all.c +++ b/accel/tcg/translate-all.c @@ -313,6 +313,8 @@ static TBStatistics *tb_get_stats(tb_page_addr_t phys_pc, target_ulong pc, new_stats->cs_base = cs_base; new_stats->flags = flags; new_stats->stats_enabled = get_default_tbstats_flag(); + new_stats->tbs = g_ptr_array_sized_new(4); + qemu_mutex_init(&new_stats->jit_stats_lock); /* * All initialisation must be complete before we insert into qht @@ -326,6 +328,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 { @@ -344,9 +347,7 @@ 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; -#ifdef CONFIG_PROFILER TCGProfile *prof = &tcg_ctx->prof; -#endif int64_t ti; void *host_pc; @@ -582,6 +583,30 @@ 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_guest_inst += prof->translation.nb_guest_insns; + ts->code.num_tcg_ops += prof->translation.nb_ops_pre_opt; + ts->code.num_tcg_ops_opt += tcg_ctx->nb_ops; + ts->code.spills += prof->translation.nb_spills; + ts->code.out_len += tb->tc.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 165072c8c3..40a56962b1 100644 --- a/accel/tcg/translator.c +++ b/accel/tcg/translator.c @@ -132,6 +132,9 @@ 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 */ + tcg_ctx->prof.translation.nb_guest_insns = db->num_insns; + #ifdef DEBUG_DISAS if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM) && qemu_log_in_addr_range(db->pc_first)) { diff --git a/include/exec/tb-stats-flags.h b/include/exec/tb-stats-flags.h index fa71eb6f0c..b62eaaca50 100644 --- a/include/exec/tb-stats-flags.h +++ b/include/exec/tb-stats-flags.h @@ -13,6 +13,7 @@ #define TB_NOTHING (1 << 0) #define TB_EXEC_STATS (1 << 1) +#define TB_JIT_STATS (1 << 2) /* TBStatistic collection controls */ void enable_collect_tb_stats(void); diff --git a/include/exec/tb-stats.h b/include/exec/tb-stats.h index eb1fa92a4e..26d4ecae59 100644 --- a/include/exec/tb-stats.h +++ b/include/exec/tb-stats.h @@ -60,6 +60,29 @@ struct TBStatistics { 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 out_len; + } code; + + struct { + unsigned long total; + unsigned long uncached; + 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); diff --git a/include/tcg/tcg.h b/include/tcg/tcg.h index cd6327b175..e15e2ea51d 100644 --- a/include/tcg/tcg.h +++ b/include/tcg/tcg.h @@ -529,7 +529,26 @@ 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 analysing the quality of + * the code generation. The data is split between stuff that is valid + * for the lifetime of a single translation and things that are valid + * for the lifetime of the translator. As the former is reset for each + * new translation so it should be copied elsewhere if you want to + * keep it. + * + * The structure is safe to access within the context of translation + * but accessing the data from elsewhere should be done with safe + * work. + */ typedef struct TCGProfile { + + struct { + int nb_guest_insns; + int nb_spills; + int nb_ops_pre_opt; + } translation; + int64_t cpu_exec_time; int64_t tb_count1; int64_t tb_count; @@ -576,9 +595,7 @@ struct TCGContext { tcg_insn_unit *code_buf; /* pointer for start of tb */ tcg_insn_unit *code_ptr; /* pointer for running end of tb */ -#ifdef CONFIG_PROFILER TCGProfile prof; -#endif #ifdef CONFIG_DEBUG_TCG int goto_tb_issue_mask; @@ -640,6 +657,7 @@ struct TCGContext { /* Exit to translator on overflow. */ sigjmp_buf jmp_trans; + TranslationBlock *current_tb; }; static inline bool temp_readonly(TCGTemp *ts) diff --git a/tcg/tcg.c b/tcg/tcg.c index 0b0fe9c7ad..ef95345084 100644 --- a/tcg/tcg.c +++ b/tcg/tcg.c @@ -1516,6 +1516,7 @@ void tcg_func_start(TCGContext *s) s->nb_labels = 0; s->current_frame_offset = s->frame_start; + s->prof.translation.nb_spills = 0; #ifdef CONFIG_DEBUG_TCG s->goto_tb_issue_mask = 0; #endif @@ -4157,6 +4158,7 @@ static TCGReg tcg_reg_alloc(TCGContext *s, TCGRegSet required_regs, } /* We must spill something. */ + s->prof.translation.nb_spills++; for (j = f; j < 2; j++) { TCGRegSet set = reg_ct[j]; @@ -5972,12 +5974,12 @@ int64_t tcg_cpu_exec_time(void) int tcg_gen_code(TCGContext *s, TranslationBlock *tb, uint64_t pc_start) { -#ifdef CONFIG_PROFILER TCGProfile *prof = &s->prof; -#endif int i, num_insns; TCGOp *op; + s->current_tb = tb; + #ifdef CONFIG_PROFILER { int n = 0; @@ -6011,6 +6013,9 @@ int tcg_gen_code(TCGContext *s, TranslationBlock *tb, uint64_t pc_start) } #endif + /* save pre-optimisation op count */ + prof->translation.nb_ops_pre_opt = s->nb_ops; + #ifdef CONFIG_DEBUG_TCG /* Ensure all labels referenced have been emitted. */ { From patchwork Thu May 18 13:57:46 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: "Wu, Fei" X-Patchwork-Id: 13246853 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 CCA89C77B7D for ; Thu, 18 May 2023 13:59:17 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1pze7c-0002zo-AV; Thu, 18 May 2023 09:56: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 1pze7a-0002yM-TV for qemu-devel@nongnu.org; Thu, 18 May 2023 09:56:46 -0400 Received: from mga12.intel.com ([192.55.52.136]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1pze7Y-0002M9-Fw for qemu-devel@nongnu.org; Thu, 18 May 2023 09:56:46 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1684418204; x=1715954204; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=v2vvx35lGrGku0tQE1S2k7IJ6BNWBcQnESq/aUNMXOU=; b=RPVFAshHlCyULd5Ey5vpCoaWC5flY1Dz+/88SJrAdSqvt3AVfpg4t43c 6glChDtWslj0ynTfh37mlhg5/XwwzNMxYJ0GqmBDWHl8d3Pu36VJcyljZ xQr/imRDmmaDiDCxx8mFifls2EWGPNiTBBL2x/pfIJQ4/JxtRcLcsoJ+i 6vu6BMRTwzQ89mKNRXV1Xet61idm5/R+8Cf6uXpohot1jDn9Hy+Zdpji3 91MxazgEzZDcnb7cmaTW3EKKXSkX9byLEKUykngH7Dnk/6mOQeNBo82hT 4u8g2kZpEHDG1fH4lu4VcG0TTBRSvBMQ9GsWtHFtSEA56JzASVMk8q3Xi A==; X-IronPort-AV: E=McAfee;i="6600,9927,10714"; a="331685706" X-IronPort-AV: E=Sophos;i="5.99,285,1677571200"; d="scan'208";a="331685706" Received: from orsmga005.jf.intel.com ([10.7.209.41]) by fmsmga106.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 18 May 2023 06:56:43 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10714"; a="876428820" X-IronPort-AV: E=Sophos;i="5.99,285,1677571200"; d="scan'208";a="876428820" Received: from wufei-optiplex-7090.sh.intel.com ([10.238.200.247]) by orsmga005.jf.intel.com with ESMTP; 18 May 2023 06:56:41 -0700 From: Fei Wu To: qemu-devel@nongnu.org, richard.henderson@linaro.org, alex.bennee@linaro.org, fei2.wu@intel.com Cc: "Vanderson M. do Rosario" , Paolo Bonzini Subject: [PATCH v12 04/15] accel: replacing part of CONFIG_PROFILER with TBStats Date: Thu, 18 May 2023 21:57:46 +0800 Message-Id: <20230518135757.1442654-5-fei2.wu@intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230518135757.1442654-1-fei2.wu@intel.com> References: <20230518135757.1442654-1-fei2.wu@intel.com> MIME-Version: 1.0 Received-SPF: pass client-ip=192.55.52.136; envelope-from=fei2.wu@intel.com; helo=mga12.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, SPF_HELO_PASS=-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" We add some of the statistics collected in the TCGProfiler into the TBStats, having the statistics not only for the whole emulation but for each TB. Then, we removed these stats from TCGProfiler and reconstruct the information for the "info jit" using the sum of all TBStats statistics. The goal is to have one unique and better way of collecting emulation statistics. Moreover, checking dynamiclly if the profiling is enabled showed to have an insignificant impact on the performance: https://wiki.qemu.org/Internships/ProjectIdeas/TCGCodeQuality#Overheads. Reviewed-by: Alex Bennée Signed-off-by: Vanderson M. do Rosario Message-Id: <20190829173437.5926-5-vandersonmr2@gmail.com> [AJB: fix authorship, use prof structure] Signed-off-by: Alex Bennée Signed-off-by: Fei Wu --- accel/tcg/tb-stats.c | 99 +++++++++++++++++++++++++++++++++ accel/tcg/translate-all.c | 10 ++-- include/exec/tb-stats.h | 11 ++++ include/tcg/tcg.h | 9 +-- tcg/tcg.c | 112 ++++---------------------------------- 5 files changed, 129 insertions(+), 112 deletions(-) diff --git a/accel/tcg/tb-stats.c b/accel/tcg/tb-stats.c index 143a52ef5c..74708d1f40 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" @@ -24,6 +28,101 @@ enum TBStatsStatus { static enum TBStatsStatus tcg_collect_tb_stats; static uint32_t default_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; +}; + +/* 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 statisticis using TCGProfile and TBStats */ +void dump_jit_profile_info(TCGProfile *s, 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); + + if (s) { + int64_t tot = s->interm_time + s->code_time; + g_string_append_printf(buf, "JIT cycles %" PRId64 + " (%0.3f s at 2.4 GHz)\n", + tot, tot / 2.4e9); + g_string_append_printf(buf, "cycles/op %0.1f\n", + jpi->ops ? (double)tot / jpi->ops : 0); + g_string_append_printf(buf, "cycles/in byte %0.1f\n", + jpi->guest ? (double)tot / jpi->guest : 0); + g_string_append_printf(buf, "cycles/out byte %0.1f\n", + jpi->host ? (double)tot / jpi->host : 0); + g_string_append_printf(buf, "cycles/search byte %0.1f\n", + jpi->search_data ? (double)tot / jpi->search_data : 0); + if (tot == 0) { + tot = 1; + } + g_string_append_printf(buf, " gen_interm time %0.1f%%\n", + (double)s->interm_time / tot * 100.0); + g_string_append_printf(buf, " gen_code time %0.1f%%\n", + (double)s->code_time / tot * 100.0); + g_string_append_printf(buf, "optim./code time %0.1f%%\n", + (double)s->opt_time / (s->code_time ? s->code_time : 1) + * 100.0); + g_string_append_printf(buf, "liveness/code time %0.1f%%\n", + (double)s->la_time / (s->code_time ? s->code_time : 1) + * 100.0); + g_string_append_printf(buf, "cpu_restore count %" PRId64 "\n", + s->restore_count); + g_string_append_printf(buf, " avg cycles %0.1f\n", + s->restore_count ? + (double)s->restore_time / s->restore_count : 0); + } + } + 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 e36a780a70..48ce7df121 100644 --- a/accel/tcg/translate-all.c +++ b/accel/tcg/translate-all.c @@ -293,7 +293,6 @@ static int setjmp_gen_code(CPUArchState *env, TranslationBlock *tb, *max_insns = tb->icount; #ifdef CONFIG_PROFILER - qatomic_set(&tcg_ctx->prof.tb_count, tcg_ctx->prof.tb_count + 1); qatomic_set(&tcg_ctx->prof.interm_time, tcg_ctx->prof.interm_time + profile_getclock() - *ti); *ti = profile_getclock(); @@ -400,8 +399,6 @@ TranslationBlock *tb_gen_code(CPUState *cpu, tb_overflow: #ifdef CONFIG_PROFILER - /* includes aborted translations because of exceptions */ - qatomic_set(&prof->tb_count1, prof->tb_count1 + 1); ti = profile_getclock(); #endif @@ -474,9 +471,6 @@ TranslationBlock *tb_gen_code(CPUState *cpu, #ifdef CONFIG_PROFILER qatomic_set(&prof->code_time, prof->code_time + profile_getclock() - ti); - qatomic_set(&prof->code_in_len, prof->code_in_len + tb->size); - qatomic_set(&prof->code_out_len, prof->code_out_len + gen_code_size); - qatomic_set(&prof->search_out_len, prof->search_out_len + search_size); #endif #ifdef DEBUG_DISAS @@ -595,7 +589,11 @@ TranslationBlock *tb_gen_code(CPUState *cpu, ts->code.num_tcg_ops += prof->translation.nb_ops_pre_opt; ts->code.num_tcg_ops_opt += tcg_ctx->nb_ops; ts->code.spills += prof->translation.nb_spills; + ts->code.temps += prof->translation.temp_count; + ts->code.deleted_ops += prof->translation.del_op_count; + 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) { diff --git a/include/exec/tb-stats.h b/include/exec/tb-stats.h index 26d4ecae59..43722ff59d 100644 --- a/include/exec/tb-stats.h +++ b/include/exec/tb-stats.h @@ -34,6 +34,9 @@ #define tb_stats_enabled(tb, JIT_STATS) \ (tb && tb->tb_stats && (tb->tb_stats->stats_enabled & JIT_STATS)) +#define stat_per_translation(stat, name) \ + (stat->translations.total ? stat->name / stat->translations.total : 0) + typedef struct TBStatistics TBStatistics; /* @@ -69,7 +72,13 @@ struct TBStatistics { unsigned num_tcg_ops; unsigned num_tcg_ops_opt; unsigned spills; + + /* CONFIG_PROFILE */ + unsigned temps; + unsigned deleted_ops; + unsigned in_len; unsigned out_len; + unsigned search_out_len; } code; struct { @@ -89,4 +98,6 @@ bool tb_stats_cmp(const void *ap, const void *bp); void init_tb_stats_htable(void); +void dump_jit_profile_info(TCGProfile *s, GString *buf); + #endif diff --git a/include/tcg/tcg.h b/include/tcg/tcg.h index e15e2ea51d..69df21ce4c 100644 --- a/include/tcg/tcg.h +++ b/include/tcg/tcg.h @@ -547,16 +547,13 @@ typedef struct TCGProfile { int nb_guest_insns; int nb_spills; int nb_ops_pre_opt; + + int del_op_count; + int temp_count; } translation; int64_t cpu_exec_time; - int64_t tb_count1; - int64_t tb_count; int64_t op_count; /* total insn count */ - int op_count_max; /* max insn per TB */ - int temp_count_max; - int64_t temp_count; - int64_t del_op_count; int64_t code_in_len; int64_t code_out_len; int64_t search_out_len; diff --git a/tcg/tcg.c b/tcg/tcg.c index ef95345084..a3a42ef387 100644 --- a/tcg/tcg.c +++ b/tcg/tcg.c @@ -44,6 +44,7 @@ #define NO_CPU_IO_DEFS #include "exec/exec-all.h" +#include "exec/tb-stats.h" #include "tcg/tcg-op.h" #if UINTPTR_MAX == UINT32_MAX @@ -1517,6 +1518,8 @@ void tcg_func_start(TCGContext *s) s->current_frame_offset = s->frame_start; s->prof.translation.nb_spills = 0; + s->prof.translation.del_op_count = 0; + s->prof.translation.temp_count = 0; #ifdef CONFIG_DEBUG_TCG s->goto_tb_issue_mask = 0; #endif @@ -2989,10 +2992,8 @@ 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--; - -#ifdef CONFIG_PROFILER - qatomic_set(&s->prof.del_op_count, s->prof.del_op_count + 1); -#endif + /* ? won't this end up op_opt - op = del_op_count ? */ + s->prof.translation.del_op_count++; } void tcg_remove_ops_after(TCGOp *op) @@ -5892,16 +5893,6 @@ void tcg_profile_snapshot(TCGProfile *prof, bool counters, bool table) if (counters) { PROF_ADD(prof, orig, cpu_exec_time); - PROF_ADD(prof, orig, tb_count1); - PROF_ADD(prof, orig, tb_count); - PROF_ADD(prof, orig, op_count); - PROF_MAX(prof, orig, op_count_max); - PROF_ADD(prof, orig, temp_count); - PROF_MAX(prof, orig, temp_count_max); - PROF_ADD(prof, orig, del_op_count); - PROF_ADD(prof, orig, code_in_len); - PROF_ADD(prof, orig, code_out_len); - PROF_ADD(prof, orig, search_out_len); PROF_ADD(prof, orig, interm_time); PROF_ADD(prof, orig, code_time); PROF_ADD(prof, orig, la_time); @@ -5979,26 +5970,9 @@ int tcg_gen_code(TCGContext *s, TranslationBlock *tb, uint64_t pc_start) TCGOp *op; s->current_tb = tb; - -#ifdef CONFIG_PROFILER - { - int n = 0; - - QTAILQ_FOREACH(op, &s->ops, link) { - n++; - } - qatomic_set(&prof->op_count, prof->op_count + n); - if (n > prof->op_count_max) { - qatomic_set(&prof->op_count_max, n); - } - - n = s->nb_temps; - qatomic_set(&prof->temp_count, prof->temp_count + n); - if (n > prof->temp_count_max) { - qatomic_set(&prof->temp_count_max, n); - } - } -#endif + /* save pre-optimisation op count */ + prof->translation.nb_ops_pre_opt = s->nb_ops; + prof->translation.temp_count = s->nb_temps; #ifdef DEBUG_DISAS if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP) @@ -6013,8 +5987,6 @@ int tcg_gen_code(TCGContext *s, TranslationBlock *tb, uint64_t pc_start) } #endif - /* save pre-optimisation op count */ - prof->translation.nb_ops_pre_opt = s->nb_ops; #ifdef CONFIG_DEBUG_TCG /* Ensure all labels referenced have been emitted. */ @@ -6212,76 +6184,16 @@ int tcg_gen_code(TCGContext *s, TranslationBlock *tb, uint64_t pc_start) return tcg_current_code_size(s); } -#ifdef CONFIG_PROFILER void tcg_dump_info(GString *buf) { + TCGProfile *s = NULL; +#ifdef CONFIG_PROFILER TCGProfile prof = {}; - const TCGProfile *s; - int64_t tb_count; - int64_t tb_div_count; - int64_t tot; - tcg_profile_snapshot_counters(&prof); s = &prof; - tb_count = s->tb_count; - tb_div_count = tb_count ? tb_count : 1; - tot = s->interm_time + s->code_time; - - g_string_append_printf(buf, "JIT cycles %" PRId64 - " (%0.3f s at 2.4 GHz)\n", - tot, tot / 2.4e9); - g_string_append_printf(buf, "translated TBs %" PRId64 - " (aborted=%" PRId64 " %0.1f%%)\n", - tb_count, s->tb_count1 - tb_count, - (double)(s->tb_count1 - s->tb_count) - / (s->tb_count1 ? s->tb_count1 : 1) * 100.0); - g_string_append_printf(buf, "avg ops/TB %0.1f max=%d\n", - (double)s->op_count / tb_div_count, s->op_count_max); - g_string_append_printf(buf, "deleted ops/TB %0.2f\n", - (double)s->del_op_count / tb_div_count); - g_string_append_printf(buf, "avg temps/TB %0.2f max=%d\n", - (double)s->temp_count / tb_div_count, - s->temp_count_max); - g_string_append_printf(buf, "avg host code/TB %0.1f\n", - (double)s->code_out_len / tb_div_count); - g_string_append_printf(buf, "avg search data/TB %0.1f\n", - (double)s->search_out_len / tb_div_count); - - g_string_append_printf(buf, "cycles/op %0.1f\n", - s->op_count ? (double)tot / s->op_count : 0); - g_string_append_printf(buf, "cycles/in byte %0.1f\n", - s->code_in_len ? (double)tot / s->code_in_len : 0); - g_string_append_printf(buf, "cycles/out byte %0.1f\n", - s->code_out_len ? (double)tot / s->code_out_len : 0); - g_string_append_printf(buf, "cycles/search byte %0.1f\n", - s->search_out_len ? - (double)tot / s->search_out_len : 0); - if (tot == 0) { - tot = 1; - } - g_string_append_printf(buf, " gen_interm time %0.1f%%\n", - (double)s->interm_time / tot * 100.0); - g_string_append_printf(buf, " gen_code time %0.1f%%\n", - (double)s->code_time / tot * 100.0); - g_string_append_printf(buf, "optim./code time %0.1f%%\n", - (double)s->opt_time / (s->code_time ? - s->code_time : 1) - * 100.0); - g_string_append_printf(buf, "liveness/code time %0.1f%%\n", - (double)s->la_time / (s->code_time ? - s->code_time : 1) * 100.0); - g_string_append_printf(buf, "cpu_restore count %" PRId64 "\n", - s->restore_count); - g_string_append_printf(buf, " avg cycles %0.1f\n", - s->restore_count ? - (double)s->restore_time / s->restore_count : 0); -} -#else -void tcg_dump_info(GString *buf) -{ - g_string_append_printf(buf, "[TCG profiler not compiled]\n"); -} #endif + dump_jit_profile_info(s, buf); +} #ifdef ELF_HOST_MACHINE /* In order to use this feature, the backend needs to do three things: From patchwork Thu May 18 13:57:47 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: "Wu, Fei" X-Patchwork-Id: 13246842 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 EC53FC77B7D for ; Thu, 18 May 2023 13:57:14 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1pze7d-00030R-TW; Thu, 18 May 2023 09:56:49 -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 1pze7c-000304-UN for qemu-devel@nongnu.org; Thu, 18 May 2023 09:56:48 -0400 Received: from mga12.intel.com ([192.55.52.136]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1pze7b-0002MR-EH for qemu-devel@nongnu.org; Thu, 18 May 2023 09:56:48 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1684418207; x=1715954207; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=ArZMSSGO1qFoz9Hu/1LYlf34qg3L88AfoA5zxcaf5bU=; b=hbBjVBlrCAfX4kfCv8wdSVq4ww+zL+6fanDwhEdm22Ke7H8IreSJT2nW y4IliIpAyO2gH6RbjkQ2OouPWy9CsPrXv2akTiVHZaRRlTvwlRz6xZHy3 tEQkk26OhspJlHt+lrW02LOjujk6Y1HrINpVJ5cQsjINesNqPqnwlVE3Q ADH0metPFD8orIAtOr6m9VHp12Qtg57KuiJcyFtznIdKhHZ9qxeqRTHVy VwD49uPnILo320Mg+5dUC+wlqPulMUoatfitS/mx9wWFiXqX9fmETO09x n3KmvtSuLibM8CrEktg7kgDnHNuLIYvpR8wjK0UoEV5vs/wQuGjBxIGx3 A==; X-IronPort-AV: E=McAfee;i="6600,9927,10714"; a="331685718" X-IronPort-AV: E=Sophos;i="5.99,285,1677571200"; d="scan'208";a="331685718" Received: from orsmga005.jf.intel.com ([10.7.209.41]) by fmsmga106.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 18 May 2023 06:56:45 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10714"; a="876428823" X-IronPort-AV: E=Sophos;i="5.99,285,1677571200"; d="scan'208";a="876428823" Received: from wufei-optiplex-7090.sh.intel.com ([10.238.200.247]) by orsmga005.jf.intel.com with ESMTP; 18 May 2023 06:56:44 -0700 From: Fei Wu To: qemu-devel@nongnu.org, richard.henderson@linaro.org, alex.bennee@linaro.org, fei2.wu@intel.com Cc: Paolo Bonzini Subject: [PATCH v12 05/15] accel/tcg: move profiler dev_time to tb_stats Date: Thu, 18 May 2023 21:57:47 +0800 Message-Id: <20230518135757.1442654-6-fei2.wu@intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230518135757.1442654-1-fei2.wu@intel.com> References: <20230518135757.1442654-1-fei2.wu@intel.com> MIME-Version: 1.0 Received-SPF: pass client-ip=192.55.52.136; envelope-from=fei2.wu@intel.com; helo=mga12.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, SPF_HELO_PASS=-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 This shouldn't live in the monitor code anyway. While we are at it make it an uint64_t as we won't be dealing in negative numbers. Signed-off-by: Alex Bennée Signed-off-by: Fei Wu --- accel/tcg/monitor.c | 2 -- accel/tcg/tb-stats.c | 2 ++ include/qemu/timer.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/accel/tcg/monitor.c b/accel/tcg/monitor.c index 92fce580f1..d4e044f7f5 100644 --- a/accel/tcg/monitor.c +++ b/accel/tcg/monitor.c @@ -82,8 +82,6 @@ HumanReadableText *qmp_x_query_opcount(Error **errp) #ifdef CONFIG_PROFILER -int64_t dev_time; - HumanReadableText *qmp_x_query_profile(Error **errp) { g_autoptr(GString) buf = g_string_new(""); diff --git a/accel/tcg/tb-stats.c b/accel/tcg/tb-stats.c index 74708d1f40..7deb617446 100644 --- a/accel/tcg/tb-stats.c +++ b/accel/tcg/tb-stats.c @@ -28,6 +28,8 @@ enum TBStatsStatus { static enum TBStatsStatus tcg_collect_tb_stats; static uint32_t default_tbstats_flag; +uint64_t dev_time; + struct jit_profile_info { uint64_t translations; uint64_t aborted; diff --git a/include/qemu/timer.h b/include/qemu/timer.h index ee071e07d1..d86fc73a17 100644 --- a/include/qemu/timer.h +++ b/include/qemu/timer.h @@ -995,7 +995,7 @@ static inline int64_t profile_getclock(void) return get_clock(); } -extern int64_t dev_time; +extern uint64_t dev_time; #endif #endif From patchwork Thu May 18 13:57:48 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: "Wu, Fei" X-Patchwork-Id: 13246844 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 360B8C7EE25 for ; Thu, 18 May 2023 13:57:16 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1pze7j-00036D-Be; Thu, 18 May 2023 09:56:55 -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 1pze7g-000311-2E for qemu-devel@nongnu.org; Thu, 18 May 2023 09:56:52 -0400 Received: from mga12.intel.com ([192.55.52.136]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1pze7d-0002Mt-UA for qemu-devel@nongnu.org; Thu, 18 May 2023 09:56:51 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1684418209; x=1715954209; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=UewUYScSJzMgwxbTkmjVN4d/9L8PVOCdLPtUgmCIYWg=; b=A0gTHQnTXk6jrKQMGwC9dbCpri7IOioQJbtHUbOTijGKH/zWlgGSorov jCBU5sq6l+JQwsHHW405xCW3OfZIJK7PgZVbYyu3usmltttNUwlkMt9Lk F7Gw1Ab50iWvSZI91V/YaSljnL9rSu1Oy6qqUAg5qxSowcPJYqmSGkrFM +xuA0FDhi2+/hBonEtPKQX3eG0aJ4n5cqrknBKwTBKC6FE3wCgFW7agLp Y9i5VZ71w/c7oAaIUBChVG7EyNuB9VyyuUApQFE52envX/fC9hUg+3T+B 8pQdtwckP+Lb5yhppWt6RDGCs3dbmy79lkJ49MQKmI9QkwRCRTBVUUNun g==; X-IronPort-AV: E=McAfee;i="6600,9927,10714"; a="331685738" X-IronPort-AV: E=Sophos;i="5.99,285,1677571200"; d="scan'208";a="331685738" Received: from orsmga005.jf.intel.com ([10.7.209.41]) by fmsmga106.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 18 May 2023 06:56:48 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10714"; a="876428827" X-IronPort-AV: E=Sophos;i="5.99,285,1677571200"; d="scan'208";a="876428827" Received: from wufei-optiplex-7090.sh.intel.com ([10.238.200.247]) by orsmga005.jf.intel.com with ESMTP; 18 May 2023 06:56:47 -0700 From: Fei Wu To: qemu-devel@nongnu.org, richard.henderson@linaro.org, alex.bennee@linaro.org, fei2.wu@intel.com Cc: Paolo Bonzini Subject: [PATCH v12 06/15] accel/tcg: convert profiling of restore operations to TBStats Date: Thu, 18 May 2023 21:57:48 +0800 Message-Id: <20230518135757.1442654-7-fei2.wu@intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230518135757.1442654-1-fei2.wu@intel.com> References: <20230518135757.1442654-1-fei2.wu@intel.com> MIME-Version: 1.0 Received-SPF: pass client-ip=192.55.52.136; envelope-from=fei2.wu@intel.com; helo=mga12.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, SPF_HELO_PASS=-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 This starts the conversion of CONFIG_PROFILER data collection to under the TBStats system. We introduce a new flag TB_JIT_TIME and start tracking how much time is spent restoring execution state from a given TB. Signed-off-by: Alex Bennée Signed-off-by: Fei Wu --- accel/tcg/translate-all.c | 23 ++++++++++++++--------- include/exec/tb-stats-flags.h | 1 + include/exec/tb-stats.h | 5 +++++ include/qemu/timer.h | 3 --- 4 files changed, 20 insertions(+), 12 deletions(-) diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c index 48ce7df121..beaef03902 100644 --- a/accel/tcg/translate-all.c +++ b/accel/tcg/translate-all.c @@ -204,10 +204,12 @@ void cpu_restore_state_from_tb(CPUState *cpu, TranslationBlock *tb, uintptr_t host_pc) { uint64_t data[TARGET_INSN_START_WORDS]; -#ifdef CONFIG_PROFILER - TCGProfile *prof = &tcg_ctx->prof; - int64_t ti = profile_getclock(); -#endif + uint64_t ti = 0; + + if (tb_stats_enabled(tb, TB_JIT_TIME)) { + ti = profile_getclock(); + } + int insns_left = cpu_unwind_data_from_tb(tb, host_pc, data); if (insns_left < 0) { @@ -225,11 +227,14 @@ void cpu_restore_state_from_tb(CPUState *cpu, TranslationBlock *tb, cpu->cc->tcg_ops->restore_state_to_opc(cpu, tb, data); -#ifdef CONFIG_PROFILER - qatomic_set(&prof->restore_time, - prof->restore_time + profile_getclock() - ti); - qatomic_set(&prof->restore_count, prof->restore_count + 1); -#endif + if (tb_stats_enabled(tb, TB_JIT_TIME)) { + TBStatistics *ts = tb->tb_stats; + uint64_t elapsed = profile_getclock() - ti; + qemu_mutex_lock(&ts->jit_stats_lock); + ts->tb_restore_time += elapsed; + ts->tb_restore_count++; + qemu_mutex_unlock(&ts->jit_stats_lock); + } } bool cpu_restore_state(CPUState *cpu, uintptr_t host_pc) diff --git a/include/exec/tb-stats-flags.h b/include/exec/tb-stats-flags.h index b62eaaca50..f29eff7576 100644 --- a/include/exec/tb-stats-flags.h +++ b/include/exec/tb-stats-flags.h @@ -14,6 +14,7 @@ #define TB_NOTHING (1 << 0) #define TB_EXEC_STATS (1 << 1) #define TB_JIT_STATS (1 << 2) +#define TB_JIT_TIME (1 << 3) /* TBStatistic collection controls */ void enable_collect_tb_stats(void); diff --git a/include/exec/tb-stats.h b/include/exec/tb-stats.h index 43722ff59d..cc9ab686b8 100644 --- a/include/exec/tb-stats.h +++ b/include/exec/tb-stats.h @@ -92,6 +92,11 @@ struct TBStatistics { * this TBStats structure. Has to be reset on a tb_flush. */ GPtrArray *tbs; + + /* Recover state from TB */ + uint64_t tb_restore_time; + uint64_t tb_restore_count; + }; bool tb_stats_cmp(const void *ap, const void *bp); diff --git a/include/qemu/timer.h b/include/qemu/timer.h index d86fc73a17..ad0da18a5f 100644 --- a/include/qemu/timer.h +++ b/include/qemu/timer.h @@ -989,7 +989,6 @@ static inline int64_t cpu_get_host_ticks(void) } #endif -#ifdef CONFIG_PROFILER static inline int64_t profile_getclock(void) { return get_clock(); @@ -997,5 +996,3 @@ static inline int64_t profile_getclock(void) extern uint64_t dev_time; #endif - -#endif From patchwork Thu May 18 13:57:49 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: "Wu, Fei" X-Patchwork-Id: 13246851 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 8AD76C7EE23 for ; Thu, 18 May 2023 13:58:53 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1pze81-0003ej-1b; Thu, 18 May 2023 09:57:13 -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 1pze7r-0003Lc-PZ for qemu-devel@nongnu.org; Thu, 18 May 2023 09:57:04 -0400 Received: from mga12.intel.com ([192.55.52.136]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1pze7i-0002Nb-0b for qemu-devel@nongnu.org; Thu, 18 May 2023 09:57:03 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1684418213; x=1715954213; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=/gZ1PedlpAhomQcxVZxkJ2uY5o2S3xnuNgEuP+lHrrE=; b=HpbUeReckes9cQ+aK4i4xIXmcybHJXnCH6Eaiqtw4tIpf4e+HTqGGyuw JnnCOQXtBe/O7jalyngpEE2nilCziZ0wxAwTFJEGSTuaPZSLukv/Txow+ 5hA8QHpKIIRb3hlkwMWvQxxoALwTN0lREKkJDaCUFskzWSf9WM3++r30q 4t3i3VQMw37eC3/cYNE4Tl1wwe0rWLd+hQKAjA7McIf/PzETy5QO8oOHL q6us8+cGQ4O89kMRDW316GyZsKTGSjU1zvMUOAB3MvcP7UIJ8CJGttYOT vyeBsTCaWXcw8TJx9OYl54Gu4D0Fx1pj3aXUicBi2HgnaWS4zhmka6Dmk Q==; X-IronPort-AV: E=McAfee;i="6600,9927,10714"; a="331685752" X-IronPort-AV: E=Sophos;i="5.99,285,1677571200"; d="scan'208";a="331685752" Received: from orsmga005.jf.intel.com ([10.7.209.41]) by fmsmga106.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 18 May 2023 06:56:52 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10714"; a="876428831" X-IronPort-AV: E=Sophos;i="5.99,285,1677571200"; d="scan'208";a="876428831" Received: from wufei-optiplex-7090.sh.intel.com ([10.238.200.247]) by orsmga005.jf.intel.com with ESMTP; 18 May 2023 06:56:50 -0700 From: Fei Wu To: qemu-devel@nongnu.org, richard.henderson@linaro.org, alex.bennee@linaro.org, fei2.wu@intel.com Cc: Paolo Bonzini Subject: [PATCH v12 07/15] accel/tcg: convert profiling of code generation to TBStats Date: Thu, 18 May 2023 21:57:49 +0800 Message-Id: <20230518135757.1442654-8-fei2.wu@intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230518135757.1442654-1-fei2.wu@intel.com> References: <20230518135757.1442654-1-fei2.wu@intel.com> MIME-Version: 1.0 Received-SPF: pass client-ip=192.55.52.136; envelope-from=fei2.wu@intel.com; helo=mga12.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, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01, T_SPF_HELO_TEMPERROR=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 continue the conversion of CONFIG_PROFILER data to TBStats by measuring the time it takes to generate code. Instead of calculating elapsed time as we do we simply store key timestamps in the profiler structure and then calculate the totals and add them to TBStats under lock. Signed-off-by: Alex Bennée Signed-off-by: Fei Wu --- accel/tcg/tb-stats.c | 33 ------------------- accel/tcg/translate-all.c | 69 ++++++++++++++++++++++----------------- include/exec/tb-stats.h | 7 ++++ include/tcg/tcg.h | 14 ++++---- tcg/tcg.c | 17 ++++------ 5 files changed, 59 insertions(+), 81 deletions(-) diff --git a/accel/tcg/tb-stats.c b/accel/tcg/tb-stats.c index 7deb617446..c40c9a748e 100644 --- a/accel/tcg/tb-stats.c +++ b/accel/tcg/tb-stats.c @@ -88,39 +88,6 @@ void dump_jit_profile_info(TCGProfile *s, GString *buf) jpi->host / (double) jpi->translations); g_string_append_printf(buf, "avg search data/TB %0.1f\n", jpi->search_data / (double) jpi->translations); - - if (s) { - int64_t tot = s->interm_time + s->code_time; - g_string_append_printf(buf, "JIT cycles %" PRId64 - " (%0.3f s at 2.4 GHz)\n", - tot, tot / 2.4e9); - g_string_append_printf(buf, "cycles/op %0.1f\n", - jpi->ops ? (double)tot / jpi->ops : 0); - g_string_append_printf(buf, "cycles/in byte %0.1f\n", - jpi->guest ? (double)tot / jpi->guest : 0); - g_string_append_printf(buf, "cycles/out byte %0.1f\n", - jpi->host ? (double)tot / jpi->host : 0); - g_string_append_printf(buf, "cycles/search byte %0.1f\n", - jpi->search_data ? (double)tot / jpi->search_data : 0); - if (tot == 0) { - tot = 1; - } - g_string_append_printf(buf, " gen_interm time %0.1f%%\n", - (double)s->interm_time / tot * 100.0); - g_string_append_printf(buf, " gen_code time %0.1f%%\n", - (double)s->code_time / tot * 100.0); - g_string_append_printf(buf, "optim./code time %0.1f%%\n", - (double)s->opt_time / (s->code_time ? s->code_time : 1) - * 100.0); - g_string_append_printf(buf, "liveness/code time %0.1f%%\n", - (double)s->la_time / (s->code_time ? s->code_time : 1) - * 100.0); - g_string_append_printf(buf, "cpu_restore count %" PRId64 "\n", - s->restore_count); - g_string_append_printf(buf, " avg cycles %0.1f\n", - s->restore_count ? - (double)s->restore_time / s->restore_count : 0); - } } g_free(jpi); } diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c index beaef03902..ea2b648ffd 100644 --- a/accel/tcg/translate-all.c +++ b/accel/tcg/translate-all.c @@ -282,8 +282,9 @@ void page_init(void) */ static int setjmp_gen_code(CPUArchState *env, TranslationBlock *tb, target_ulong pc, void *host_pc, - int *max_insns, int64_t *ti) + int *max_insns) { + TCGProfile *prof = &tcg_ctx->prof; int ret = sigsetjmp(tcg_ctx->jmp_trans, 0); if (unlikely(ret != 0)) { return ret; @@ -297,11 +298,9 @@ static int setjmp_gen_code(CPUArchState *env, TranslationBlock *tb, tcg_ctx->cpu = NULL; *max_insns = tb->icount; -#ifdef CONFIG_PROFILER - qatomic_set(&tcg_ctx->prof.interm_time, - tcg_ctx->prof.interm_time + profile_getclock() - *ti); - *ti = profile_getclock(); -#endif + if (tb_stats_enabled(tb, TB_JIT_TIME)) { + prof->gen_ir_done_time = profile_getclock(); + } return tcg_gen_code(tcg_ctx, tb, pc); } @@ -352,7 +351,6 @@ TranslationBlock *tb_gen_code(CPUState *cpu, tcg_insn_unit *gen_code_buf; int gen_code_size, search_size, max_insns; TCGProfile *prof = &tcg_ctx->prof; - int64_t ti; void *host_pc; assert_memory_lock(); @@ -403,10 +401,6 @@ TranslationBlock *tb_gen_code(CPUState *cpu, tb_overflow: -#ifdef CONFIG_PROFILER - ti = profile_getclock(); -#endif - trace_translate_block(tb, pc, tb->tc.ptr); /* @@ -418,11 +412,14 @@ TranslationBlock *tb_gen_code(CPUState *cpu, if (tb_stats_collection_enabled() && qemu_log_in_addr_range(tb->pc)) { tb->tb_stats = tb_get_stats(phys_pc, pc, cs_base, flags); + if (tb_stats_enabled(tb, TB_JIT_TIME)) { + prof->gen_start_time = profile_getclock(); + } } else { 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: @@ -474,9 +471,9 @@ TranslationBlock *tb_gen_code(CPUState *cpu, */ perf_report_code(pc, tb, tcg_splitwx_to_rx(gen_code_buf)); -#ifdef CONFIG_PROFILER - qatomic_set(&prof->code_time, prof->code_time + profile_getclock() - ti); -#endif + if (tb_stats_enabled(tb, TB_JIT_TIME)) { + prof->gen_code_done_time = profile_getclock(); + } #ifdef DEBUG_DISAS if (qemu_loglevel_mask(CPU_LOG_TB_OUT_ASM) && @@ -586,26 +583,38 @@ TranslationBlock *tb_gen_code(CPUState *cpu, * 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)) { + if (tb_stats_enabled(tb, (TB_JIT_STATS | TB_JIT_TIME))) { TBStatistics *ts = tb->tb_stats; qemu_mutex_lock(&ts->jit_stats_lock); - ts->code.num_guest_inst += prof->translation.nb_guest_insns; - ts->code.num_tcg_ops += prof->translation.nb_ops_pre_opt; - ts->code.num_tcg_ops_opt += tcg_ctx->nb_ops; - ts->code.spills += prof->translation.nb_spills; - ts->code.temps += prof->translation.temp_count; - ts->code.deleted_ops += prof->translation.del_op_count; - 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++; + if (tb_stats_enabled(tb, TB_JIT_STATS)) { + ts->code.num_guest_inst += prof->translation.nb_guest_insns; + ts->code.num_tcg_ops += prof->translation.nb_ops_pre_opt; + ts->code.num_tcg_ops_opt += tcg_ctx->nb_ops; + ts->code.spills += prof->translation.nb_spills; + ts->code.temps += prof->translation.temp_count; + ts->code.deleted_ops += prof->translation.del_op_count; + 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); } - g_ptr_array_add(ts->tbs, tb); + if (tb_stats_enabled(tb, TB_JIT_TIME)) { + ts->gen_times.ir += prof->gen_ir_done_time - prof->gen_start_time; + ts->gen_times.ir_opt += + prof->gen_opt_done_time - prof->gen_ir_done_time; + ts->gen_times.la += + prof->gen_la_done_time - prof->gen_opt_done_time; + ts->gen_times.code += + prof->gen_code_done_time - prof->gen_la_done_time; + } qemu_mutex_unlock(&ts->jit_stats_lock); } diff --git a/include/exec/tb-stats.h b/include/exec/tb-stats.h index cc9ab686b8..2543367c70 100644 --- a/include/exec/tb-stats.h +++ b/include/exec/tb-stats.h @@ -97,6 +97,12 @@ struct TBStatistics { uint64_t tb_restore_time; uint64_t tb_restore_count; + struct { + uint64_t ir; + uint64_t ir_opt; + uint64_t la; + uint64_t code; + } gen_times; }; bool tb_stats_cmp(const void *ap, const void *bp); @@ -104,5 +110,6 @@ bool tb_stats_cmp(const void *ap, const void *bp); void init_tb_stats_htable(void); void dump_jit_profile_info(TCGProfile *s, GString *buf); +void dump_jit_exec_time_info(uint64_t dev_time); #endif diff --git a/include/tcg/tcg.h b/include/tcg/tcg.h index 69df21ce4c..9b74c5acce 100644 --- a/include/tcg/tcg.h +++ b/include/tcg/tcg.h @@ -557,13 +557,13 @@ typedef struct TCGProfile { int64_t code_in_len; int64_t code_out_len; int64_t search_out_len; - int64_t interm_time; - int64_t code_time; - int64_t la_time; - int64_t opt_time; - int64_t restore_count; - int64_t restore_time; - int64_t table_op_count[NB_OPS]; + + /* Timestamps during translation */ + uint64_t gen_start_time; + uint64_t gen_ir_done_time; + uint64_t gen_opt_done_time; + uint64_t gen_la_done_time; + uint64_t gen_code_done_time; } TCGProfile; struct TCGContext { diff --git a/tcg/tcg.c b/tcg/tcg.c index a3a42ef387..9e657719fa 100644 --- a/tcg/tcg.c +++ b/tcg/tcg.c @@ -6005,18 +6005,13 @@ int tcg_gen_code(TCGContext *s, TranslationBlock *tb, uint64_t pc_start) } #endif -#ifdef CONFIG_PROFILER - qatomic_set(&prof->opt_time, prof->opt_time - profile_getclock()); -#endif - #ifdef USE_TCG_OPTIMIZATIONS tcg_optimize(s); #endif -#ifdef CONFIG_PROFILER - qatomic_set(&prof->opt_time, prof->opt_time + profile_getclock()); - qatomic_set(&prof->la_time, prof->la_time - profile_getclock()); -#endif + if (tb_stats_enabled(tb, TB_JIT_TIME)) { + prof->gen_opt_done_time = profile_getclock(); + } reachable_code_pass(s); liveness_pass_0(s); @@ -6042,9 +6037,9 @@ int tcg_gen_code(TCGContext *s, TranslationBlock *tb, uint64_t pc_start) } } -#ifdef CONFIG_PROFILER - qatomic_set(&prof->la_time, prof->la_time + profile_getclock()); -#endif + if (tb_stats_enabled(tb, TB_JIT_TIME)) { + prof->gen_la_done_time = profile_getclock(); + } #ifdef DEBUG_DISAS if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP_OPT) From patchwork Thu May 18 13:57:50 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: "Wu, Fei" X-Patchwork-Id: 13246846 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 7738FC7EE23 for ; Thu, 18 May 2023 13:57:20 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1pze7u-0003IO-3B; Thu, 18 May 2023 09:57:06 -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 1pze7n-0003Dm-W7 for qemu-devel@nongnu.org; Thu, 18 May 2023 09:57:00 -0400 Received: from mga12.intel.com ([192.55.52.136]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1pze7l-0002PX-Jn for qemu-devel@nongnu.org; Thu, 18 May 2023 09:56:59 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1684418217; x=1715954217; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=4Fx8zmTWGMZeSGq3I1RnLLjklsWjEPTEXW0ciKDnB7k=; b=KRWRK0q7F1lmqZoEFaMTpHW06dBGICnvmiTvU/8dkiGvtOmBaTiT5jwi fXF/+D+nvYpF29LBFW1V0GODQiqcIwq8Z3C2+QHjTZ3VGZgHbm8zqvYxt cxfiyXiTtupTpU+BvHkBqCY/RUnBzNZw1/lVuhNaNn8AVSOFbgHmLZhZ/ Ib9gohAbFqMGWLxe6UqZjejMKDoLsP0h8j1CTnOID81JZvCgZXzmHZKwD ztzHTCL2Hw18B4KI3Rk9ls2A1GcF99iFgOboKBHeI10Mlkm3bSu5fH7Uo M/Cvp40w+e4irzOpcGVHAsSwodgJUI+ReTlUJu51F//GZml31XWvxmdXj g==; X-IronPort-AV: E=McAfee;i="6600,9927,10714"; a="331685771" X-IronPort-AV: E=Sophos;i="5.99,285,1677571200"; d="scan'208";a="331685771" Received: from orsmga005.jf.intel.com ([10.7.209.41]) by fmsmga106.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 18 May 2023 06:56:55 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10714"; a="876428835" X-IronPort-AV: E=Sophos;i="5.99,285,1677571200"; d="scan'208";a="876428835" Received: from wufei-optiplex-7090.sh.intel.com ([10.238.200.247]) by orsmga005.jf.intel.com with ESMTP; 18 May 2023 06:56:53 -0700 From: Fei Wu To: qemu-devel@nongnu.org, richard.henderson@linaro.org, alex.bennee@linaro.org, fei2.wu@intel.com Cc: "Vanderson M. do Rosario" , Paolo Bonzini , Markus Armbruster , Thomas Huth , Laurent Vivier Subject: [PATCH v12 08/15] accel: adding TB_JIT_TIME and full replacing CONFIG_PROFILER Date: Thu, 18 May 2023 21:57:50 +0800 Message-Id: <20230518135757.1442654-9-fei2.wu@intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230518135757.1442654-1-fei2.wu@intel.com> References: <20230518135757.1442654-1-fei2.wu@intel.com> MIME-Version: 1.0 Received-SPF: pass client-ip=192.55.52.136; envelope-from=fei2.wu@intel.com; helo=mga12.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, SPF_HELO_PASS=-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" Replace all others CONFIG_PROFILER statistics and migrate it to TBStatistics system. However, TCGProfiler still exists and can be use to store global statistics and times. All TB related statistics goes to TBStatistics. Signed-off-by: Vanderson M. do Rosario Message-Id: <20190829173437.5926-6-vandersonmr2@gmail.com> [AJB: fix authorship] Signed-off-by: Alex Bennée Signed-off-by: Fei Wu --- accel/tcg/monitor.c | 25 ++++------ accel/tcg/tb-stats.c | 78 +++++++++++++++++++++++++++++ accel/tcg/tcg-accel-ops.c | 15 +++--- include/exec/tb-stats.h | 2 +- include/tcg/tcg.h | 5 +- softmmu/runstate.c | 8 +-- tcg/tcg.c | 100 ++++++++++--------------------------- tests/qtest/qmp-cmd-test.c | 2 +- 8 files changed, 127 insertions(+), 108 deletions(-) diff --git a/accel/tcg/monitor.c b/accel/tcg/monitor.c index d4e044f7f5..2bc87f2642 100644 --- a/accel/tcg/monitor.c +++ b/accel/tcg/monitor.c @@ -15,6 +15,7 @@ #include "sysemu/cpus.h" #include "sysemu/cpu-timers.h" #include "sysemu/tcg.h" +#include "exec/tb-stats.h" #include "internal.h" @@ -69,6 +70,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"); @@ -80,23 +86,12 @@ HumanReadableText *qmp_x_query_opcount(Error **errp) return human_readable_text_from_str(buf); } -#ifdef CONFIG_PROFILER - +#ifdef CONFIG_TCG HumanReadableText *qmp_x_query_profile(Error **errp) { g_autoptr(GString) buf = g_string_new(""); - static int64_t last_cpu_exec_time; - int64_t cpu_exec_time; - int64_t delta; - - cpu_exec_time = tcg_cpu_exec_time(); - delta = cpu_exec_time - last_cpu_exec_time; - - g_string_append_printf(buf, "async time %" PRId64 " (%0.3f)\n", - dev_time, dev_time / (double)NANOSECONDS_PER_SECOND); - g_string_append_printf(buf, "qemu time %" PRId64 " (%0.3f)\n", - delta, delta / (double)NANOSECONDS_PER_SECOND); - last_cpu_exec_time = cpu_exec_time; + + dump_jit_exec_time_info(dev_time, buf); dev_time = 0; return human_readable_text_from_str(buf); @@ -104,7 +99,7 @@ HumanReadableText *qmp_x_query_profile(Error **errp) #else HumanReadableText *qmp_x_query_profile(Error **errp) { - error_setg(errp, "Internal profiler not compiled"); + error_setg(errp, "TCG should be enabled!"); return NULL; } #endif diff --git a/accel/tcg/tb-stats.c b/accel/tcg/tb-stats.c index c40c9a748e..78a3104c7f 100644 --- a/accel/tcg/tb-stats.c +++ b/accel/tcg/tb-stats.c @@ -13,6 +13,7 @@ #include "tcg/tcg.h" #include "qemu/qemu-print.h" +#include "qemu/timer.h" #include "exec/tb-stats.h" #include "tb-context.h" @@ -41,6 +42,13 @@ struct jit_profile_info { uint64_t host; uint64_t guest; uint64_t search_data; + + uint64_t interm_time; + uint64_t code_time; + uint64_t restore_count; + uint64_t restore_time; + uint64_t opt_time; + uint64_t la_time; }; /* accumulate the statistics from all TBs */ @@ -62,6 +70,35 @@ static void collect_jit_profile_info(void *p, uint32_t hash, void *userp) jpi->host += tbs->code.out_len; jpi->guest += tbs->code.in_len; jpi->search_data += tbs->code.search_out_len; + + jpi->interm_time += stat_per_translation(tbs, gen_times.ir); + jpi->opt_time += stat_per_translation(tbs, gen_times.ir_opt); + jpi->la_time += stat_per_translation(tbs, gen_times.la); + jpi->code_time += stat_per_translation(tbs, gen_times.code); + + /* + * The restore time covers how long we have spent restoring state + * from a given TB (e.g. recovering from a fault). It is therefor + * not related to the number of translations we have done. + */ + jpi->restore_time += tbs->tb_restore_time; + jpi->restore_count += tbs->tb_restore_count; +} + +void dump_jit_exec_time_info(uint64_t dev_time, GString *buf) +{ + static uint64_t last_cpu_exec_time; + uint64_t cpu_exec_time; + uint64_t delta; + + cpu_exec_time = tcg_cpu_exec_time(); + delta = cpu_exec_time - last_cpu_exec_time; + + g_string_append_printf(buf, "async time %" PRId64 " (%0.3f)\n", + dev_time, dev_time / (double)NANOSECONDS_PER_SECOND); + g_string_append_printf(buf, "qemu time %" PRId64 " (%0.3f)\n", + delta, delta / (double)NANOSECONDS_PER_SECOND); + last_cpu_exec_time = cpu_exec_time; } /* dump JIT statisticis using TCGProfile and TBStats */ @@ -88,6 +125,47 @@ void dump_jit_profile_info(TCGProfile *s, GString *buf) jpi->host / (double) jpi->translations); g_string_append_printf(buf, "avg search data/TB %0.1f\n", jpi->search_data / (double) jpi->translations); + + uint64_t tot = jpi->interm_time + jpi->code_time; + + g_string_append_printf(buf, "JIT cycles %" PRId64 + " (%0.3fs at 2.4 GHz)\n", + tot, tot / 2.4e9); + g_string_append_printf(buf, " cycles/op %0.1f\n", + jpi->ops ? (double)tot / jpi->ops : 0); + g_string_append_printf(buf, " cycles/in byte %0.1f\n", + jpi->guest ? (double)tot / jpi->guest : 0); + g_string_append_printf(buf, " cycles/out byte %0.1f\n", + jpi->host ? (double)tot / jpi->host : 0); + g_string_append_printf(buf, " cycles/search byte %0.1f\n", + jpi->search_data ? (double)tot / jpi->search_data : 0); + if (tot == 0) { + tot = 1; + } + + g_string_append_printf(buf, " gen_interm time %0.1f%%\n", + (double)jpi->interm_time / tot * 100.0); + g_string_append_printf(buf, " gen_code time %0.1f%%\n", + (double)jpi->code_time / tot * 100.0); + + g_string_append_printf(buf, " optim./code time %0.1f%%\n", + (double)jpi->opt_time / (jpi->code_time ? jpi->code_time : 1) + * 100.0); + g_string_append_printf(buf, " liveness/code time %0.1f%%\n", + (double)jpi->la_time / (jpi->code_time ? jpi->code_time : 1) + * 100.0); + + g_string_append_printf(buf, "cpu_restore count %" PRId64 "\n", + jpi->restore_count); + g_string_append_printf(buf, " avg cycles %0.1f\n", + jpi->restore_count ? + (double)jpi->restore_time / jpi->restore_count : 0); + + if (s) { + g_string_append_printf(buf, "cpu exec time %" PRId64 " (%0.3fs)\n", + s->cpu_exec_time, + s->cpu_exec_time / (double) NANOSECONDS_PER_SECOND); + } } g_free(jpi); } diff --git a/accel/tcg/tcg-accel-ops.c b/accel/tcg/tcg-accel-ops.c index 58c8e64096..749ad182f2 100644 --- a/accel/tcg/tcg-accel-ops.c +++ b/accel/tcg/tcg-accel-ops.c @@ -70,20 +70,17 @@ void tcg_cpus_destroy(CPUState *cpu) int tcg_cpus_exec(CPUState *cpu) { int ret; -#ifdef CONFIG_PROFILER - int64_t ti; -#endif + uint64_t ti; + assert(tcg_enabled()); -#ifdef CONFIG_PROFILER ti = profile_getclock(); -#endif + cpu_exec_start(cpu); ret = cpu_exec(cpu); cpu_exec_end(cpu); -#ifdef CONFIG_PROFILER - qatomic_set(&tcg_ctx->prof.cpu_exec_time, - tcg_ctx->prof.cpu_exec_time + profile_getclock() - ti); -#endif + + qatomic_add(&tcg_ctx->prof.cpu_exec_time, profile_getclock() - ti); + return ret; } diff --git a/include/exec/tb-stats.h b/include/exec/tb-stats.h index 2543367c70..d93d42e085 100644 --- a/include/exec/tb-stats.h +++ b/include/exec/tb-stats.h @@ -110,6 +110,6 @@ bool tb_stats_cmp(const void *ap, const void *bp); void init_tb_stats_htable(void); void dump_jit_profile_info(TCGProfile *s, GString *buf); -void dump_jit_exec_time_info(uint64_t dev_time); +void dump_jit_exec_time_info(uint64_t dev_time, GString *buf); #endif diff --git a/include/tcg/tcg.h b/include/tcg/tcg.h index 9b74c5acce..b987f6a9bd 100644 --- a/include/tcg/tcg.h +++ b/include/tcg/tcg.h @@ -564,6 +564,9 @@ typedef struct TCGProfile { uint64_t gen_opt_done_time; uint64_t gen_la_done_time; uint64_t gen_code_done_time; + + /* Lifetime count of TCGOps per TCGContext */ + uint64_t table_op_count[NB_OPS]; } TCGProfile; struct TCGContext { @@ -932,7 +935,7 @@ static inline TCGv_ptr tcg_temp_new_ptr(void) return temp_tcgv_ptr(t); } -int64_t tcg_cpu_exec_time(void); +uint64_t tcg_cpu_exec_time(void); void tcg_dump_info(GString *buf); void tcg_dump_op_count(GString *buf); diff --git a/softmmu/runstate.c b/softmmu/runstate.c index 2f2396c819..392e03c906 100644 --- a/softmmu/runstate.c +++ b/softmmu/runstate.c @@ -728,18 +728,12 @@ static bool main_loop_should_exit(int *status) int qemu_main_loop(void) { int status = EXIT_SUCCESS; -#ifdef CONFIG_PROFILER - int64_t ti; -#endif + uint64_t ti; while (!main_loop_should_exit(&status)) { -#ifdef CONFIG_PROFILER ti = profile_getclock(); -#endif main_loop_wait(false); -#ifdef CONFIG_PROFILER dev_time += profile_getclock() - ti; -#endif } return status; diff --git a/tcg/tcg.c b/tcg/tcg.c index 9e657719fa..2ff029ae13 100644 --- a/tcg/tcg.c +++ b/tcg/tcg.c @@ -5864,25 +5864,13 @@ static void tcg_out_st_helper_args(TCGContext *s, const TCGLabelQemuLdst *ldst, tcg_out_helper_load_common_args(s, ldst, parm, info, next_arg); } -#ifdef CONFIG_PROFILER - /* avoid copy/paste errors */ #define PROF_ADD(to, from, field) \ do { \ (to)->field += qatomic_read(&((from)->field)); \ } while (0) -#define PROF_MAX(to, from, field) \ - do { \ - typeof((from)->field) val__ = qatomic_read(&((from)->field)); \ - if (val__ > (to)->field) { \ - (to)->field = val__; \ - } \ - } while (0) - -/* Pass in a zero'ed @prof */ -static inline -void tcg_profile_snapshot(TCGProfile *prof, bool counters, bool table) +static void collect_tcg_profiler(TCGProfile *prof) { unsigned int n_ctxs = qatomic_read(&tcg_cur_ctxs); unsigned int i; @@ -5891,55 +5879,19 @@ void tcg_profile_snapshot(TCGProfile *prof, bool counters, bool table) TCGContext *s = qatomic_read(&tcg_ctxs[i]); const TCGProfile *orig = &s->prof; - if (counters) { - PROF_ADD(prof, orig, cpu_exec_time); - PROF_ADD(prof, orig, interm_time); - PROF_ADD(prof, orig, code_time); - PROF_ADD(prof, orig, la_time); - PROF_ADD(prof, orig, opt_time); - PROF_ADD(prof, orig, restore_count); - PROF_ADD(prof, orig, restore_time); - } - if (table) { - int i; + PROF_ADD(prof, orig, cpu_exec_time); - for (i = 0; i < NB_OPS; i++) { - PROF_ADD(prof, orig, table_op_count[i]); - } + for (i = 0; i < NB_OPS; i++) { + PROF_ADD(prof, orig, table_op_count[i]); } } } -#undef PROF_ADD -#undef PROF_MAX - -static void tcg_profile_snapshot_counters(TCGProfile *prof) -{ - tcg_profile_snapshot(prof, true, false); -} - -static void tcg_profile_snapshot_table(TCGProfile *prof) -{ - tcg_profile_snapshot(prof, false, true); -} - -void tcg_dump_op_count(GString *buf) -{ - TCGProfile prof = {}; - int i; - - tcg_profile_snapshot_table(&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]); - } -} - -int64_t tcg_cpu_exec_time(void) +uint64_t tcg_cpu_exec_time(void) { unsigned int n_ctxs = qatomic_read(&tcg_cur_ctxs); unsigned int i; - int64_t ret = 0; + uint64_t ret = 0; for (i = 0; i < n_ctxs; i++) { const TCGContext *s = qatomic_read(&tcg_ctxs[i]); @@ -5949,19 +5901,6 @@ int64_t tcg_cpu_exec_time(void) } return ret; } -#else -void tcg_dump_op_count(GString *buf) -{ - g_string_append_printf(buf, "[TCG profiler not compiled]\n"); -} - -int64_t tcg_cpu_exec_time(void) -{ - error_report("%s: TCG profiler not compiled", __func__); - exit(EXIT_FAILURE); -} -#endif - int tcg_gen_code(TCGContext *s, TranslationBlock *tb, uint64_t pc_start) { @@ -6077,14 +6016,17 @@ int tcg_gen_code(TCGContext *s, TranslationBlock *tb, uint64_t pc_start) s->pool_labels = NULL; #endif + 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; -#ifdef CONFIG_PROFILER - qatomic_set(&prof->table_op_count[opc], prof->table_op_count[opc] + 1); -#endif - switch (opc) { case INDEX_op_mov_i32: case INDEX_op_mov_i64: @@ -6179,14 +6121,24 @@ 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) { TCGProfile *s = NULL; -#ifdef CONFIG_PROFILER TCGProfile prof = {}; - tcg_profile_snapshot_counters(&prof); s = &prof; -#endif + collect_tcg_profiler(s); dump_jit_profile_info(s, buf); } diff --git a/tests/qtest/qmp-cmd-test.c b/tests/qtest/qmp-cmd-test.c index a58de48d2a..749aafe4da 100644 --- a/tests/qtest/qmp-cmd-test.c +++ b/tests/qtest/qmp-cmd-test.c @@ -46,7 +46,7 @@ static int query_error_class(const char *cmd) { "query-balloon", ERROR_CLASS_DEVICE_NOT_ACTIVE }, { "query-hotpluggable-cpus", ERROR_CLASS_GENERIC_ERROR }, { "query-vm-generation-id", ERROR_CLASS_GENERIC_ERROR }, -#ifndef CONFIG_PROFILER +#ifndef CONFIG_TCG { "x-query-profile", ERROR_CLASS_GENERIC_ERROR }, #endif /* Only valid with a USB bus added */ From patchwork Thu May 18 13:57:51 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: "Wu, Fei" X-Patchwork-Id: 13246847 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 C0860C7EE23 for ; Thu, 18 May 2023 13:57:28 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1pze7x-0003ad-53; Thu, 18 May 2023 09:57:09 -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 1pze7q-0003Hw-7z for qemu-devel@nongnu.org; Thu, 18 May 2023 09:57:02 -0400 Received: from mga12.intel.com ([192.55.52.136]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1pze7o-0002PX-B8 for qemu-devel@nongnu.org; Thu, 18 May 2023 09:57:02 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1684418220; x=1715954220; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=BpicQltg9GStGlDLuiZhobjz5q2c3w3IznuP50vrDYM=; b=jm10VVF/0P9hcVi7LkBrqORXNoGQ50vo2kMNBSaXpuWHsQz+uh95PCSg fTaNEylAuuSaDRdKEPXgmd46YrrRh1Hk3t846a9JuZ+BX/mmN9yTZno7F Cu7CweySe4deh5NGnU4A3IU1IZDTnxYndPFYXAN07I2iluzIKNTK5O6q6 ikBI8+tKTCo1EnNAqqHVd4FzGOBFna3U3umwNBu2ByDjJd1uXDTMbqmy8 dXfxxBub/FVRfY+mIuo0S/taO5hiNfj5y6/AWjwLjkIHhWwNhrq11Yjou FpDndJ1zAe4mrGIuDQFymYWrMZU793PBg3m9hefxw8jpC9s0nIL2A/x52 A==; X-IronPort-AV: E=McAfee;i="6600,9927,10714"; a="331685791" X-IronPort-AV: E=Sophos;i="5.99,285,1677571200"; d="scan'208";a="331685791" Received: from orsmga005.jf.intel.com ([10.7.209.41]) by fmsmga106.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 18 May 2023 06:56:59 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10714"; a="876428839" X-IronPort-AV: E=Sophos;i="5.99,285,1677571200"; d="scan'208";a="876428839" Received: from wufei-optiplex-7090.sh.intel.com ([10.238.200.247]) by orsmga005.jf.intel.com with ESMTP; 18 May 2023 06:56:57 -0700 From: Fei Wu To: qemu-devel@nongnu.org, richard.henderson@linaro.org, alex.bennee@linaro.org, fei2.wu@intel.com Cc: "Vanderson M. do Rosario" , Paolo Bonzini Subject: [PATCH v12 09/15] debug: add -d tb_stats to control TBStatistics collection: Date: Thu, 18 May 2023 21:57:51 +0800 Message-Id: <20230518135757.1442654-10-fei2.wu@intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230518135757.1442654-1-fei2.wu@intel.com> References: <20230518135757.1442654-1-fei2.wu@intel.com> MIME-Version: 1.0 Received-SPF: pass client-ip=192.55.52.136; envelope-from=fei2.wu@intel.com; helo=mga12.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, SPF_HELO_PASS=-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" -d tb_stats[[,level=(+all+jit+exec+time)][,dump_limit=]] "dump_limit" is used to limit the number of dumped TBStats in linux-user mode. [all+jit+exec+time] control the profilling level used by the TBStats. Can be used as follow: -d tb_stats -d tb_stats,level=jit+time -d tb_stats,dump_limit=15 ... Signed-off-by: Vanderson M. do Rosario Message-Id: <20190829173437.5926-7-vandersonmr2@gmail.com> [AJB: fix authorship, reword title] Signed-off-by: Alex Bennée Signed-off-by: Fei Wu --- accel/tcg/tb-stats.c | 5 +++++ include/exec/gen-icount.h | 1 + include/exec/tb-stats-flags.h | 3 +++ include/exec/tb-stats.h | 2 ++ include/qemu/log.h | 1 + stubs/meson.build | 1 + stubs/tb-stats.c | 27 +++++++++++++++++++++++++ util/log.c | 37 +++++++++++++++++++++++++++++++++++ 8 files changed, 77 insertions(+) create mode 100644 stubs/tb-stats.c diff --git a/accel/tcg/tb-stats.c b/accel/tcg/tb-stats.c index 78a3104c7f..68ac7d3f73 100644 --- a/accel/tcg/tb-stats.c +++ b/accel/tcg/tb-stats.c @@ -208,3 +208,8 @@ uint32_t get_default_tbstats_flag(void) { return default_tbstats_flag; } + +void set_default_tbstats_flag(uint32_t flags) +{ + default_tbstats_flag = flags; +} diff --git a/include/exec/gen-icount.h b/include/exec/gen-icount.h index 20e7835ff0..4372817951 100644 --- a/include/exec/gen-icount.h +++ b/include/exec/gen-icount.h @@ -3,6 +3,7 @@ #include "exec/exec-all.h" #include "exec/tb-stats.h" +#include "tb-stats-flags.h" /* Helpers for instruction counting code generation. */ diff --git a/include/exec/tb-stats-flags.h b/include/exec/tb-stats-flags.h index f29eff7576..04adaee8d9 100644 --- a/include/exec/tb-stats-flags.h +++ b/include/exec/tb-stats-flags.h @@ -15,6 +15,7 @@ #define TB_EXEC_STATS (1 << 1) #define TB_JIT_STATS (1 << 2) #define TB_JIT_TIME (1 << 3) +#define TB_ALL_STATS (TB_EXEC_STATS | TB_JIT_STATS | TB_JIT_TIME) /* TBStatistic collection controls */ void enable_collect_tb_stats(void); @@ -24,5 +25,7 @@ bool tb_stats_collection_enabled(void); bool tb_stats_collection_paused(void); uint32_t get_default_tbstats_flag(void); +void set_default_tbstats_flag(uint32_t); +void set_tbstats_flags(uint32_t flags); #endif diff --git a/include/exec/tb-stats.h b/include/exec/tb-stats.h index d93d42e085..72585c448a 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" +#include "exec/tb-stats-flags.h" + #define tb_stats_enabled(tb, JIT_STATS) \ (tb && tb->tb_stats && (tb->tb_stats->stats_enabled & JIT_STATS)) diff --git a/include/qemu/log.h b/include/qemu/log.h index c5643d8dd5..6f3b8091cd 100644 --- a/include/qemu/log.h +++ b/include/qemu/log.h @@ -35,6 +35,7 @@ bool qemu_log_separate(void); /* LOG_STRACE is used for user-mode strace logging. */ #define LOG_STRACE (1 << 19) #define LOG_PER_THREAD (1 << 20) +#define CPU_LOG_TB_STATS (1 << 21) /* Lock/unlock output. */ diff --git a/stubs/meson.build b/stubs/meson.build index 8412cad15f..393adb9e47 100644 --- a/stubs/meson.build +++ b/stubs/meson.build @@ -64,3 +64,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..d212c2a1fa --- /dev/null +++ b/stubs/tb-stats.c @@ -0,0 +1,27 @@ +/* + * 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; +} + +bool tb_stats_collection_enabled(void) +{ + return false; +} + +void set_default_tbstats_flag(uint32_t flags) +{ + return; +} diff --git a/util/log.c b/util/log.c index 53b4f6c58e..7ae471d97c 100644 --- a/util/log.c +++ b/util/log.c @@ -19,6 +19,7 @@ #include "qemu/osdep.h" #include "qemu/log.h" +#include "qemu/qemu-print.h" #include "qemu/range.h" #include "qemu/error-report.h" #include "qapi/error.h" @@ -27,6 +28,7 @@ #include "qemu/thread.h" #include "qemu/lockable.h" #include "qemu/rcu.h" +#include "exec/tb-stats-flags.h" #ifdef CONFIG_LINUX #include #endif @@ -47,6 +49,7 @@ static __thread Notifier qemu_log_thread_cleanup_notifier; int qemu_loglevel; static bool log_per_thread; static GArray *debug_regions; +int32_t max_num_hot_tbs_to_dump; /* Returns true if qemu_log() will really write somewhere. */ bool qemu_log_enabled(void) @@ -495,6 +498,10 @@ const QEMULogItem qemu_log_items[] = { "log every user-mode syscall, its input, and its result" }, { LOG_PER_THREAD, "tid", "open a separate log file per thread; filename must contain '%d'" }, + { CPU_LOG_TB_STATS, + "tb_stats[[,level=(+all+jit+exec+time)][,dump_limit=]]", + "enable collection of TBs statistics" + "(and dump until given a limit if in user mode).\n" }, { 0, NULL, NULL }, }; @@ -516,6 +523,36 @@ 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")) { + mask |= CPU_LOG_TB_STATS; + set_default_tbstats_flag(TB_ALL_STATS); + enable_collect_tb_stats(); + } else if (tb_stats_collection_enabled() && + g_str_has_prefix(*tmp, "dump_limit=")) { + max_num_hot_tbs_to_dump = atoi((*tmp) + 11); + } else if (tb_stats_collection_enabled() && + g_str_has_prefix(*tmp, "level=")) { + uint32_t flags = 0; + char **level_parts = g_strsplit(*tmp + 6, "+", 0); + char **level_tmp; + for (level_tmp = level_parts; level_tmp && *level_tmp; + level_tmp++) { + if (g_str_equal(*level_tmp, "jit")) { + flags |= TB_JIT_STATS; + } else if (g_str_equal(*level_tmp, "exec")) { + flags |= TB_EXEC_STATS; + } else if (g_str_equal(*level_tmp, "time")) { + flags |= TB_JIT_TIME; + } else if (g_str_equal(*level_tmp, "all")) { + flags |= TB_ALL_STATS; + } else { + /* FIXME: set errp */ + fprintf(stderr, "no option level=%s, valid options are:" + "all, jit, exec or/and time\n", *level_tmp); + exit(1); + } + set_default_tbstats_flag(flags); + } } else { for (item = qemu_log_items; item->mask != 0; item++) { if (g_str_equal(*tmp, item->name)) { From patchwork Thu May 18 13:57:52 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: "Wu, Fei" X-Patchwork-Id: 13246856 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 A6A6BC77B7D for ; Thu, 18 May 2023 13:59:40 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1pze81-0003i5-GZ; Thu, 18 May 2023 09:57:13 -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 1pze7v-0003So-0W for qemu-devel@nongnu.org; Thu, 18 May 2023 09:57:07 -0400 Received: from mga12.intel.com ([192.55.52.136]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1pze7s-0002Nb-Ua for qemu-devel@nongnu.org; Thu, 18 May 2023 09:57:06 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1684418224; x=1715954224; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=ytZ0iZSv6YOctV7UFpvrLY/kNTjGbnGnOHjqma/5n5w=; b=b77zW4Z/WOA4wBwHsqPk+4KEs2v2xIitOhPp9D9BN/m2vKg9JreYI6n9 3DHI5y9Dd4hCbTRpjqChA7zMWVNBpnvTBX+XEdw4/Ql6yuzMYRT76sDtY pCr2gX5SrjEf/xcTbyNfVOYbXJqpx/kC+1fhGxfFlBuhZnYMohFfyQlab 4GBAoWvaV1M1a/i+AX00k/x79/q/vlkRR/vW2L5fkzoHE4f9e+q8hie7r rD5o/YBQJG4QExVsbfE+UfpSbcF5OT+xSvJ1PAZidJHa+s6fxBB7KQqFr re8+8oRWYA+MFcdnGehlrOTuaZI+fsqinBTNbqAkjr9B1JxrRCwmJiomM A==; X-IronPort-AV: E=McAfee;i="6600,9927,10714"; a="331685822" X-IronPort-AV: E=Sophos;i="5.99,285,1677571200"; d="scan'208";a="331685822" Received: from orsmga005.jf.intel.com ([10.7.209.41]) by fmsmga106.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 18 May 2023 06:57:03 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10714"; a="876428846" X-IronPort-AV: E=Sophos;i="5.99,285,1677571200"; d="scan'208";a="876428846" Received: from wufei-optiplex-7090.sh.intel.com ([10.238.200.247]) by orsmga005.jf.intel.com with ESMTP; 18 May 2023 06:57:01 -0700 From: Fei Wu To: qemu-devel@nongnu.org, richard.henderson@linaro.org, alex.bennee@linaro.org, fei2.wu@intel.com Cc: "Vanderson M. do Rosario" , "Dr . David Alan Gilbert" , Paolo Bonzini , "Dr. David Alan Gilbert" Subject: [PATCH v12 10/15] monitor: adding tb_stats hmp command Date: Thu, 18 May 2023 21:57:52 +0800 Message-Id: <20230518135757.1442654-11-fei2.wu@intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230518135757.1442654-1-fei2.wu@intel.com> References: <20230518135757.1442654-1-fei2.wu@intel.com> MIME-Version: 1.0 Received-SPF: pass client-ip=192.55.52.136; envelope-from=fei2.wu@intel.com; helo=mga12.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, SPF_HELO_PASS=-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|pause|stop|filter] command to hmp. This allows controlling the collection of statistics. It is also possible to set the level of collection: all, jit, or exec. tb_stats filter allow to only collect statistics for the TB in the last_search list. 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 | 45 ++++++++++++++ accel/tcg/tb-stats.c | 112 ++++++++++++++++++++++++++++++++++ hmp-commands.hx | 16 +++++ include/exec/tb-stats-flags.h | 1 + include/exec/tb-stats.h | 10 +++ include/monitor/hmp.h | 1 + softmmu/runstate.c | 6 ++ 7 files changed, 191 insertions(+) diff --git a/accel/tcg/monitor.c b/accel/tcg/monitor.c index 2bc87f2642..2e00f10267 100644 --- a/accel/tcg/monitor.c +++ b/accel/tcg/monitor.c @@ -11,7 +11,9 @@ #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" @@ -87,6 +89,49 @@ HumanReadableText *qmp_x_query_opcount(Error **errp) } #ifdef CONFIG_TCG +void hmp_tbstats(Monitor *mon, const QDict *qdict) +{ + if (!tcg_enabled()) { + error_report("TB information is only available with accel=tcg"); + return; + } + + char *cmd = (char *) qdict_get_try_str(qdict, "command"); + enum TbstatsCmd icmd = -1; + + if (strcmp(cmd, "start") == 0) { + icmd = START; + } else if (strcmp(cmd, "pause") == 0) { + icmd = PAUSE; + } else if (strcmp(cmd, "stop") == 0) { + icmd = STOP; + } else if (strcmp(cmd, "filter") == 0) { + icmd = FILTER; + } else { + error_report("invalid command!"); + return; + } + + char *slevel = (char *) qdict_get_try_str(qdict, "level"); + uint32_t level = TB_EXEC_STATS | TB_JIT_STATS | TB_JIT_TIME; + if (slevel) { + if (strcmp(slevel, "jit") == 0) { + level = TB_JIT_STATS; + } else if (strcmp(slevel, "exec") == 0) { + level = TB_EXEC_STATS; + } else if (strcmp(slevel, "time") == 0) { + level = TB_JIT_TIME; + } + } + + struct TbstatsCommand *tbscommand = g_new0(struct TbstatsCommand, 1); + tbscommand->cmd = icmd; + tbscommand->level = level; + async_safe_run_on_cpu(first_cpu, do_hmp_tbstats_safe, + RUN_ON_CPU_HOST_PTR(tbscommand)); + +} + HumanReadableText *qmp_x_query_profile(Error **errp) { g_autoptr(GString) buf = g_string_new(""); diff --git a/accel/tcg/tb-stats.c b/accel/tcg/tb-stats.c index 68ac7d3f73..55afe6e489 100644 --- a/accel/tcg/tb-stats.c +++ b/accel/tcg/tb-stats.c @@ -16,6 +16,7 @@ #include "qemu/timer.h" #include "exec/tb-stats.h" +#include "exec/tb-flush.h" #include "tb-context.h" /* TBStatistic collection controls */ @@ -28,6 +29,8 @@ enum TBStatsStatus { static enum TBStatsStatus tcg_collect_tb_stats; static uint32_t default_tbstats_flag; +/* only accessed in safe work */ +static GList *last_search; uint64_t dev_time; @@ -170,6 +173,102 @@ void dump_jit_profile_info(TCGProfile *s, GString *buf) g_free(jpi); } +static void free_tbstats(void *p, uint32_t hash, void *userp) +{ + g_free(p); +} + +static void clean_tbstats(void) +{ + /* remove all tb_stats */ + qht_iter(&tb_ctx.tb_stats, free_tbstats, NULL); + qht_destroy(&tb_ctx.tb_stats); +} + +void do_hmp_tbstats_safe(CPUState *cpu, run_on_cpu_data icmd) +{ + struct TbstatsCommand *cmdinfo = icmd.host_ptr; + int cmd = cmdinfo->cmd; + uint32_t level = cmdinfo->level; + + switch (cmd) { + case START: + if (tb_stats_collection_paused()) { + set_tbstats_flags(level); + } else { + if (tb_stats_collection_enabled()) { + qemu_printf("TB information already being recorded"); + return; + } + qht_init(&tb_ctx.tb_stats, tb_stats_cmp, CODE_GEN_HTABLE_SIZE, + QHT_MODE_AUTO_RESIZE); + } + + set_default_tbstats_flag(level); + enable_collect_tb_stats(); + tb_flush(cpu); + break; + case PAUSE: + if (!tb_stats_collection_enabled()) { + qemu_printf("TB information not being recorded"); + return; + } + + /* + * Continue to create TBStatistic structures but stop collecting + * statistics + */ + pause_collect_tb_stats(); + set_default_tbstats_flag(TB_NOTHING); + set_tbstats_flags(TB_PAUSED); + tb_flush(cpu); + break; + case STOP: + if (!tb_stats_collection_enabled()) { + qemu_printf("TB information not being recorded"); + return; + } + + /* Dissalloc all TBStatistics structures and stop creating new ones */ + disable_collect_tb_stats(); + clean_tbstats(); + tb_flush(cpu); + break; + case FILTER: + if (!tb_stats_collection_enabled()) { + qemu_printf("TB information not being recorded"); + return; + } + if (!last_search) { + qemu_printf( + "no search on record! execute info tbs before filtering!"); + return; + } + + set_default_tbstats_flag(TB_NOTHING); + + /* + * Set all tbstats as paused, then return only the ones from last_search + */ + pause_collect_tb_stats(); + set_tbstats_flags(TB_PAUSED); + + for (GList *iter = last_search; iter; iter = g_list_next(iter)) { + TBStatistics *tbs = iter->data; + tbs->stats_enabled = level; + } + + tb_flush(cpu); + + break; + default: /* INVALID */ + g_assert_not_reached(); + break; + } + + g_free(cmdinfo); +} + void init_tb_stats_htable(void) { if (!tb_ctx.tb_stats.map && tb_stats_collection_enabled()) { @@ -204,6 +303,19 @@ bool tb_stats_collection_paused(void) return tcg_collect_tb_stats == TB_STATS_PAUSED; } +static void reset_tbstats_flag(void *p, uint32_t hash, void *userp) +{ + uint32_t flag = *((int *)userp); + TBStatistics *tbs = p; + tbs->stats_enabled = flag; +} + +void set_tbstats_flags(uint32_t flag) +{ + /* iterate over tbstats setting their flag as TB_NOTHING */ + qht_iter(&tb_ctx.tb_stats, reset_tbstats_flag, &flag); +} + uint32_t get_default_tbstats_flag(void) { return default_tbstats_flag; diff --git a/hmp-commands.hx b/hmp-commands.hx index 2cbd0f77a0..9a40215d34 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,level:s?", + .params = "command [stats_level]", + .help = "Control tb statistics collection:" + "tb_stats (start|pause|stop|filter) [all|jit_stats|exec_stats]", + .cmd = hmp_tbstats, + }, +#endif + +SRST +``tb_stats`` *command* *stats_level* + 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 04adaee8d9..8c7abb62e5 100644 --- a/include/exec/tb-stats-flags.h +++ b/include/exec/tb-stats-flags.h @@ -16,6 +16,7 @@ #define TB_JIT_STATS (1 << 2) #define TB_JIT_TIME (1 << 3) #define TB_ALL_STATS (TB_EXEC_STATS | TB_JIT_STATS | TB_JIT_TIME) +#define TB_PAUSED (1 << 4) /* TBStatistic collection controls */ void enable_collect_tb_stats(void); diff --git a/include/exec/tb-stats.h b/include/exec/tb-stats.h index 72585c448a..4bb343870b 100644 --- a/include/exec/tb-stats.h +++ b/include/exec/tb-stats.h @@ -33,6 +33,9 @@ #include "exec/tb-stats-flags.h" +enum SortBy { SORT_BY_HOTNESS, SORT_BY_HG /* Host/Guest */, SORT_BY_SPILLS }; +enum TbstatsCmd { START, PAUSE, STOP, FILTER }; + #define tb_stats_enabled(tb, JIT_STATS) \ (tb && tb->tb_stats && (tb->tb_stats->stats_enabled & JIT_STATS)) @@ -114,4 +117,11 @@ void init_tb_stats_htable(void); void dump_jit_profile_info(TCGProfile *s, GString *buf); void dump_jit_exec_time_info(uint64_t dev_time, GString *buf); +struct TbstatsCommand { + enum TbstatsCmd cmd; + uint32_t level; +}; + +void do_hmp_tbstats_safe(CPUState *cpu, run_on_cpu_data icmd); + #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 diff --git a/softmmu/runstate.c b/softmmu/runstate.c index 392e03c906..37390799f1 100644 --- a/softmmu/runstate.c +++ b/softmmu/runstate.c @@ -728,12 +728,18 @@ static bool main_loop_should_exit(int *status) int qemu_main_loop(void) { int status = EXIT_SUCCESS; +#ifdef CONFIG_TCG uint64_t ti; +#endif while (!main_loop_should_exit(&status)) { +#ifdef CONFIG_TCG ti = profile_getclock(); +#endif main_loop_wait(false); +#ifdef CONFIG_TCG dev_time += profile_getclock() - ti; +#endif } return status; From patchwork Thu May 18 13:57:53 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: "Wu, Fei" X-Patchwork-Id: 13246850 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 40711C7EE23 for ; Thu, 18 May 2023 13:58:18 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1pze83-0003t5-1X; Thu, 18 May 2023 09:57:15 -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 1pze7x-0003ah-3v for qemu-devel@nongnu.org; Thu, 18 May 2023 09:57:09 -0400 Received: from mga12.intel.com ([192.55.52.136]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1pze7v-0002Nb-DY for qemu-devel@nongnu.org; Thu, 18 May 2023 09:57:08 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1684418227; x=1715954227; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=7QNFyBNeGgGdgzd9L+ISvRpqm2xPqBQGWM5cf/izB2Q=; b=jGoONBGaBsgdyqYzRniTG85UiILHgNLXIbXJU/Gs/F5Ax6KpMM2sa3/x 19rn9GgjM62wG1XQM/oy7C+FI0rUfMXmRY+b6ZflSyYvOeH6n5cWqR1JJ Q7oIv1ibVTyQf33b2BKkkHPZmDPulzpyu2V704UANOHMigcjqJ0/kxtQA ERQvhisapIFtFhezdWity/NO2KT259CxTtHSZAdPbRKk+Bn1A9hTRbgHe ArOhTOc7WwFEG1uj3GB+N/cK+sIh6Ql6Plny4WlyyeoljXcXi2raiarCF uDy/kh3T7QV1Fyr1dClv65RXs2JqhKzVsBFlDwV3ooCTWtZVmfUpt/n+f A==; X-IronPort-AV: E=McAfee;i="6600,9927,10714"; a="331685841" X-IronPort-AV: E=Sophos;i="5.99,285,1677571200"; d="scan'208";a="331685841" Received: from orsmga005.jf.intel.com ([10.7.209.41]) by fmsmga106.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 18 May 2023 06:57:06 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10714"; a="876428853" X-IronPort-AV: E=Sophos;i="5.99,285,1677571200"; d="scan'208";a="876428853" Received: from wufei-optiplex-7090.sh.intel.com ([10.238.200.247]) by orsmga005.jf.intel.com with ESMTP; 18 May 2023 06:57:05 -0700 From: Fei Wu To: qemu-devel@nongnu.org, richard.henderson@linaro.org, alex.bennee@linaro.org, fei2.wu@intel.com Cc: Paolo Bonzini Subject: [PATCH v12 11/15] tb-stats: reset the tracked TBs on a tb_flush Date: Thu, 18 May 2023 21:57:53 +0800 Message-Id: <20230518135757.1442654-12-fei2.wu@intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230518135757.1442654-1-fei2.wu@intel.com> References: <20230518135757.1442654-1-fei2.wu@intel.com> MIME-Version: 1.0 Received-SPF: pass client-ip=192.55.52.136; envelope-from=fei2.wu@intel.com; helo=mga12.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, SPF_HELO_PASS=-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 | 19 +++++++++++++++++++ include/exec/tb-stats.h | 8 ++++++++ 3 files changed, 28 insertions(+) diff --git a/accel/tcg/tb-maint.c b/accel/tcg/tb-maint.c index 0980fca358..11ff0ddd90 100644 --- a/accel/tcg/tb-maint.c +++ b/accel/tcg/tb-maint.c @@ -763,6 +763,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 55afe6e489..469e3e024b 100644 --- a/accel/tcg/tb-stats.c +++ b/accel/tcg/tb-stats.c @@ -269,6 +269,25 @@ void do_hmp_tbstats_safe(CPUState *cpu, run_on_cpu_data icmd) g_free(cmdinfo); } +/* + * We have to reset the tbs array on a tb_flush as those + * TranslationBlocks no longer exist and we no loner know if the + * current mapping is still valid. + */ + +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 4bb343870b..30b788f7b2 100644 --- a/include/exec/tb-stats.h +++ b/include/exec/tb-stats.h @@ -124,4 +124,12 @@ struct TbstatsCommand { void do_hmp_tbstats_safe(CPUState *cpu, run_on_cpu_data icmd); +/** + * 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 Thu May 18 13:57:54 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: "Wu, Fei" X-Patchwork-Id: 13246848 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 59E4CC77B7D for ; Thu, 18 May 2023 13:57:38 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1pze84-0004Aj-SI; Thu, 18 May 2023 09:57:16 -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 1pze82-0003sL-Lf for qemu-devel@nongnu.org; Thu, 18 May 2023 09:57:14 -0400 Received: from mga12.intel.com ([192.55.52.136]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1pze7z-0002Nb-2y for qemu-devel@nongnu.org; Thu, 18 May 2023 09:57:14 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1684418231; x=1715954231; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=Ji6pWPBIt4XJSjDe1dBLSV5yGRc1HZZypP7bEDEXy4w=; b=YjQ25YX2GbsATIlMyu4KXpgCJl5v8aTCNwD6FV+RC9GJtJaRGLg3cYnz ImXQQBOt+T6Y/P/Wr6Z2ztRV1punQM1jAV9fqgQf76qd7+h+WvF9VTui+ DLosVoWC32HS6xzF2aKj1ovGQiBw3pqPK8Xg5tO1+Vq1Rg/JrftYWBZ9F uN3cytscFThK9pVPOklr7o8kY9qIQJkT/48RVMVnr0mt3TcF/n2CfeiMm VZ+QFZnjmSvxqnunZvhAxivA3394Hzq1hejv1zvellvoVAMxgOJZvcNUc o5n3zsopU+uSgbAVykNocSCybtkdaf2oQwffv14qUPOF8en9LPka7SKLN Q==; X-IronPort-AV: E=McAfee;i="6600,9927,10714"; a="331685850" X-IronPort-AV: E=Sophos;i="5.99,285,1677571200"; d="scan'208";a="331685850" Received: from orsmga005.jf.intel.com ([10.7.209.41]) by fmsmga106.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 18 May 2023 06:57:10 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10714"; a="876428858" X-IronPort-AV: E=Sophos;i="5.99,285,1677571200"; d="scan'208";a="876428858" Received: from wufei-optiplex-7090.sh.intel.com ([10.238.200.247]) by orsmga005.jf.intel.com with ESMTP; 18 May 2023 06:57:07 -0700 From: Fei Wu To: qemu-devel@nongnu.org, richard.henderson@linaro.org, alex.bennee@linaro.org, fei2.wu@intel.com Cc: "Vanderson M. do Rosario" , "Dr . David Alan Gilbert" , Paolo Bonzini , "Dr. David Alan Gilbert" Subject: [PATCH v12 12/15] Adding info [tb-list|tb] commands to HMP (WIP) Date: Thu, 18 May 2023 21:57:54 +0800 Message-Id: <20230518135757.1442654-13-fei2.wu@intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230518135757.1442654-1-fei2.wu@intel.com> References: <20230518135757.1442654-1-fei2.wu@intel.com> MIME-Version: 1.0 Received-SPF: pass client-ip=192.55.52.136; envelope-from=fei2.wu@intel.com; helo=mga12.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, SPF_HELO_PASS=-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" These commands allow the exploration of TBs generated by the TCG. Understand which one hotter, with more guest/host instructions... and examine their guest, host and IR 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. [AJB: WIP - we still can't be safely sure a translation will succeed] Example of output: TB id:1 | phys:0x34d54 virt:0x0000000000034d54 flags:0x0000f0 | exec:4828932/0 guest inst cov:16.38% | trans:1 ints: g:3 op:82 op_opt:34 spills:3 | h/g (host bytes / guest insts): 90.666664 | time to gen at 2.4GHz => code:3150.83(ns) IR:712.08(ns) | targets: 0x0000000000034d5e (id:11), 0x0000000000034d0d (id:2) TB id:2 | phys:0x34d0d virt:0x0000000000034d0d flags:0x0000f0 | exec:4825842/0 guest inst cov:21.82% | trans:1 ints: g:4 op:80 op_opt:38 spills:2 | h/g (host bytes / guest insts): 84.000000 | time to gen at 2.4GHz => code:3362.92(ns) IR:793.75(ns) | targets: 0x0000000000034d19 (id:12), 0x0000000000034d54 (id:1) TB id:2 | phys:0x34d0d virt:0x0000000000034d0d flags:0x0000f0 | exec:6956495/0 guest inst cov:21.82% | trans:2 ints: g:2 op:40 op_opt:19 spills:1 | h/g (host bytes / guest insts): 84.000000 | time to gen at 2.4GHz => code:3130.83(ns) IR:722.50(ns) | targets: 0x0000000000034d19 (id:12), 0x0000000000034d54 (id:1) ---------------- IN: 0x00034d0d: 89 de movl %ebx, %esi 0x00034d0f: 26 8b 0e movl %es:(%esi), %ecx 0x00034d12: 26 f6 46 08 80 testb $0x80, %es:8(%esi) 0x00034d17: 75 3b jne 0x34d54 ------------------------------ TB id:1 | phys:0x34d54 virt:0x0000000000034d54 flags:0x0000f0 | exec:5202686/0 guest inst cov:11.28% | trans:1 ints: g:3 op:82 op_opt:34 spills:3 | h/g (host bytes / guest insts): 90.666664 | time to gen at 2.4GHz => code:2793.75(ns) IR:614.58(ns) | targets: 0x0000000000034d5e (id:3), 0x0000000000034d0d (id:2) TB id:2 | phys:0x34d0d virt:0x0000000000034d0d flags:0x0000f0 | exec:5199468/0 guest inst cov:15.03% | trans:1 ints: g:4 op:80 op_opt:38 spills:2 | h/g (host bytes / guest insts): 84.000000 | time to gen at 2.4GHz => code:2958.75(ns) IR:719.58(ns) | targets: 0x0000000000034d19 (id:4), 0x0000000000034d54 (id:1) ------------------------------ 2 TBs to reach 25% of guest inst exec coverage Total of guest insts exec: 138346727 ------------------------------ 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 | 54 ++++++ accel/tcg/tb-stats.c | 322 +++++++++++++++++++++++++++++++++++ disas/disas.c | 24 ++- hmp-commands-info.hx | 16 ++ include/exec/tb-stats.h | 33 +++- include/monitor/hmp.h | 2 + include/qemu/log-for-trace.h | 6 +- include/qemu/log.h | 2 + util/log.c | 66 +++++-- 9 files changed, 507 insertions(+), 18 deletions(-) diff --git a/accel/tcg/monitor.c b/accel/tcg/monitor.c index 2e00f10267..a1780c5920 100644 --- a/accel/tcg/monitor.c +++ b/accel/tcg/monitor.c @@ -8,6 +8,7 @@ #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" @@ -18,6 +19,7 @@ #include "sysemu/cpu-timers.h" #include "sysemu/tcg.h" #include "exec/tb-stats.h" +#include "tb-context.h" #include "internal.h" @@ -132,6 +134,58 @@ void hmp_tbstats(Monitor *mon, const QDict *qdict) } +void hmp_info_tblist(Monitor *mon, const QDict *qdict) +{ + int number_int; + const char *sortedby_str = NULL; + if (!tcg_enabled()) { + error_report("TB information is only available with accel=tcg"); + return; + } + if (!tb_ctx.tb_stats.map) { + error_report("no TB information recorded"); + 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 { + error_report("valid sort options are: hotness hg spills"); + return; + } + + dump_tbs_info(number_int, sortedby, true); +} + +void hmp_info_tb(Monitor *mon, const QDict *qdict) +{ + const int id = qdict_get_int(qdict, "id"); + const char *flags = qdict_get_try_str(qdict, "flags"); + int mask; + + if (!tcg_enabled()) { + error_report("TB information is only available with accel=tcg"); + return; + } + + mask = flags ? qemu_str_to_log_mask(flags) : CPU_LOG_TB_IN_ASM; + + if (!mask) { + error_report("Unable to parse log flags, see 'help log'"); + return; + } + + dump_tb_info(id, mask, true); +} + HumanReadableText *qmp_x_query_profile(Error **errp) { g_autoptr(GString) buf = g_string_new(""); diff --git a/accel/tcg/tb-stats.c b/accel/tcg/tb-stats.c index 469e3e024b..cb28879a45 100644 --- a/accel/tcg/tb-stats.c +++ b/accel/tcg/tb-stats.c @@ -11,14 +11,18 @@ #include "disas/disas.h" #include "exec/exec-all.h" #include "tcg/tcg.h" +#include "qapi/error.h" #include "qemu/qemu-print.h" #include "qemu/timer.h" +#include "qemu/log.h" #include "exec/tb-stats.h" #include "exec/tb-flush.h" #include "tb-context.h" +#include "internal.h" + /* TBStatistic collection controls */ enum TBStatsStatus { TB_STATS_DISABLED = 0, @@ -32,8 +36,23 @@ static uint32_t default_tbstats_flag; /* only accessed in safe work */ static GList *last_search; +static int id = 1; /* display_id increment counter */ uint64_t dev_time; +static TBStatistics *get_tbstats_by_id(int id) +{ + GList *iter; + + for (iter = last_search; iter; iter = g_list_next(iter)) { + TBStatistics *tbs = iter->data; + if (tbs && tbs->display_id == id) { + return tbs; + break; + } + } + return NULL; +} + struct jit_profile_info { uint64_t translations; uint64_t aborted; @@ -296,6 +315,309 @@ void init_tb_stats_htable(void) } } +static void collect_tb_stats(void *p, uint32_t hash, void *userp) +{ + last_search = g_list_prepend(last_search, p); +} + +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; + } +} + +static int dump_tb_header(TBStatistics *tbs) +{ + 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); + + qemu_log("TB id:%d | phys:0x"TB_PAGE_ADDR_FMT" virt:0x"TARGET_FMT_lx + " flags:0x%08x %d inv/%d\n", + tbs->display_id, tbs->phys_pc, tbs->pc, tbs->flags, + invalid, act); + + if (tbs_stats_enabled(tbs, TB_EXEC_STATS)) { + qemu_log("\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)) { + qemu_log("\t| trans:%lu ints: 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); + } + + if (tbs_stats_enabled(tbs, TB_JIT_TIME)) { + qemu_log("\t| time to gen at 2.4GHz => code:%0.2lf(ns) IR:%0.2lf(ns)\n", + tbs->gen_times.code / 2.4, tbs->gen_times.ir / 2.4); + } + + qemu_log("\n"); + + return act - invalid; +} + +static gint +inverse_sort_tbs(gconstpointer p1, gconstpointer p2, gpointer psort_by) +{ + const TBStatistics *tbs1 = (TBStatistics *) p1; + const TBStatistics *tbs2 = (TBStatistics *) p2; + int sort_by = *((enum SortBy *) psort_by); + unsigned long c1 = 0; + unsigned long c2 = 0; + + if (sort_by == SORT_BY_SPILLS) { + c1 = stat_per_translation(tbs1, code.spills); + c2 = stat_per_translation(tbs2, code.spills); + } else if (sort_by == SORT_BY_HOTNESS) { + c1 = stat_per_translation(tbs1, executions.normal); + c2 = stat_per_translation(tbs2, executions.normal); + } else if (sort_by == SORT_BY_HG) { + if (tbs1->code.num_guest_inst == 0) { + return -1; + } + if (tbs2->code.num_guest_inst == 0) { + return 1; + } + + c1 = tbs1->code.out_len / tbs1->code.num_guest_inst; + c2 = tbs2->code.out_len / tbs2->code.num_guest_inst; + } + return c1 < c2 ? 1 : c1 == c2 ? 0 : -1; +} + +static void dump_last_search_headers(int count) +{ + if (!last_search) { + qemu_log("No data collected yet\n"); + return; + } + + GList *l = last_search; + while (l != NULL && count--) { + TBStatistics *tbs = (TBStatistics *) l->data; + GList *next = l->next; + dump_tb_header(tbs); + l = next; + } +} + +static uint64_t calculate_last_search_coverages(void) +{ + uint64_t total_exec_count = 0; + GList *i; + + /* Compute total execution count for all tbs */ + for (i = last_search; i; i = i->next) { + TBStatistics *tbs = (TBStatistics *) i->data; + total_exec_count += + (tbs->executions.atomic + tbs->executions.normal) + * tbs->code.num_guest_inst; + } + + for (i = last_search; i; i = i->next) { + TBStatistics *tbs = (TBStatistics *) i->data; + uint64_t tb_total_execs = + (tbs->executions.atomic + tbs->executions.normal) + * tbs->code.num_guest_inst; + tbs->executions.coverage = + (10000 * tb_total_execs) / (total_exec_count + 1); + } + + return total_exec_count; +} + +static void do_dump_tbs_info(int total, int sort_by) +{ + id = 1; + GList *i; + int count = total; + + g_list_free(last_search); + last_search = NULL; + + qht_iter(&tb_ctx.tb_stats, collect_tb_stats, NULL); + + last_search = g_list_sort_with_data(last_search, inverse_sort_tbs, + &sort_by); + + if (!last_search) { + qemu_printf("No data collected yet!\n"); + return; + } + + calculate_last_search_coverages(); + + for (i = last_search; i && count--; i = i->next) { + TBStatistics *tbs = (TBStatistics *) i->data; + tbs->display_id = id++; + } + + /* free the unused bits */ + if (i) { + if (i->next) { + i->next->prev = NULL; + } + g_list_free(i->next); + i->next = NULL; + } + + dump_last_search_headers(total); +} + +struct tbs_dump_info { + int count; + int sort_by; +}; + +static void do_dump_tbs_info_safe(CPUState *cpu, run_on_cpu_data tbdi) +{ + struct tbs_dump_info *info = tbdi.host_ptr; + qemu_log_to_monitor(true); + do_dump_tbs_info(info->count, info->sort_by); + qemu_log_to_monitor(false); + g_free(info); +} + +/* + * When we dump_tbs_info on a live system via the HMP we want to + * ensure the system is quiessent before we start outputting stuff. + * Otherwise we could pollute the output with other logging output. + */ + +void dump_tbs_info(int count, int sort_by, bool use_monitor) +{ + if (use_monitor) { + struct tbs_dump_info *tbdi = g_new(struct tbs_dump_info, 1); + tbdi->count = count; + tbdi->sort_by = sort_by; + async_safe_run_on_cpu(first_cpu, do_dump_tbs_info_safe, + RUN_ON_CPU_HOST_PTR(tbdi)); + } else { + do_dump_tbs_info(count, sort_by); + } +} + +/* + * We cannot always re-generate the code even if we know there are + * valid translations still in the cache. The reason being the guest + * may have un-mapped the page code. In real life this would be + * un-reachable as the jump cache is cleared and the following QHT + * lookup will do a get_page_addr_code() and fault. + * + * TODO: can we do this safely? We need to + * a) somehow recover the mmu_idx for this translation + * b) probe MMU_INST_FETCH to know it will succeed + */ +static GString *get_code_string(TBStatistics *tbs, int log_flags) +{ + int old_log_flags = qemu_loglevel; + + CPUState *cpu = first_cpu; + uint32_t cflags = curr_cflags(cpu); + TranslationBlock *tb = NULL; + + GString *code_s = g_string_new(NULL); + qemu_log_to_string(true, code_s); + + Error *err = NULL; + if (!qemu_set_log(log_flags, &err)) { + g_string_append_printf(code_s, "%s", error_get_pretty(err)); + error_free(err); + } + + if (sigsetjmp(cpu->jmp_env, 0) == 0) { + mmap_lock(); + tb = tb_gen_code(cpu, tbs->pc, tbs->cs_base, tbs->flags, cflags); + tb_phys_invalidate(tb, -1); + mmap_unlock(); + } else { + /* + * The mmap_lock is dropped by tb_gen_code if it runs out of + * memory. + */ + qemu_log("\ncould not gen code for this TB (no longer mapped?)\n"); + assert_no_pages_locked(); + } + + qemu_set_log(old_log_flags, &err); + qemu_log_to_string(false, NULL); + + return code_s; +} + +static void do_tb_dump_with_statistics(TBStatistics *tbs, int log_flags) +{ + g_autoptr(GString) code_s = NULL; + + qemu_log("\n------------------------------\n\n"); + + if (dump_tb_header(tbs) > 0) { + code_s = get_code_string(tbs, log_flags); + } else { + code_s = g_string_new("cannot re-translate non-active translation"); + } + qemu_log("%s", code_s->str); + qemu_log("------------------------------\n"); +} + +struct tb_dump_info { + int id; + int log_flags; + bool use_monitor; +}; + +static void do_dump_tb_info_safe(CPUState *cpu, run_on_cpu_data info) +{ + struct tb_dump_info *tbdi = (struct tb_dump_info *) info.host_ptr; + + if (!last_search) { + qemu_log("no search on record\n"); + return; + } + + qemu_log_to_monitor(tbdi->use_monitor); + + TBStatistics *tbs = get_tbstats_by_id(tbdi->id); + if (tbs) { + do_tb_dump_with_statistics(tbs, tbdi->log_flags); + } else { + qemu_log("no TB statitics found with id %d\n", tbdi->id); + } + + qemu_log_to_monitor(false); + + g_free(tbdi); +} + +void dump_tb_info(int id, int log_mask, bool use_monitor) +{ + struct tb_dump_info *tbdi = g_new(struct tb_dump_info, 1); + + tbdi->id = id; + tbdi->log_flags = log_mask; + tbdi->use_monitor = use_monitor; + + async_safe_run_on_cpu(first_cpu, do_dump_tb_info_safe, + RUN_ON_CPU_HOST_PTR(tbdi)); + + /* tbdi free'd by do_dump_tb_info_safe */ +} + + void enable_collect_tb_stats(void) { tcg_collect_tb_stats = TB_STATS_RUNNING; diff --git a/disas/disas.c b/disas/disas.c index 0d2d06c2ec..6cdd797874 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; @@ -199,6 +201,24 @@ static void initialize_debug_host(CPUDebug *s) #endif } +static int +__attribute__((format(printf, 2, 3))) +fprintf_log(FILE *a, const char *b, ...) +{ + va_list ap; + va_start(ap, b); + + if (!to_string) { + vfprintf(a, b, ap); + } else { + qemu_vlog(b, ap); + } + + va_end(ap); + + return 1; +} + /* Disassemble this for me please... (debugging). */ void target_disas(FILE *out, CPUState *cpu, uint64_t code, size_t size) { @@ -221,9 +241,9 @@ void target_disas(FILE *out, CPUState *cpu, uint64_t code, size_t size) } for (pc = code; size > 0; pc += count, size -= count) { - fprintf(out, "0x%08" PRIx64 ": ", pc); + fprintf_log(out, "0x%08" PRIx64 ": ", pc); count = s.info.print_insn(pc, &s.info); - fprintf(out, "\n"); + fprintf_log(out, "\n"); if (count < 0) { break; } diff --git a/hmp-commands-info.hx b/hmp-commands-info.hx index 47d63d26db..01d9658aea 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/exec/tb-stats.h b/include/exec/tb-stats.h index 30b788f7b2..f2a6b09da9 100644 --- a/include/exec/tb-stats.h +++ b/include/exec/tb-stats.h @@ -36,8 +36,11 @@ enum SortBy { SORT_BY_HOTNESS, SORT_BY_HG /* Host/Guest */, SORT_BY_SPILLS }; enum TbstatsCmd { START, PAUSE, STOP, FILTER }; +#define tbs_stats_enabled(tbs, JIT_STATS) \ + (tbs && (tbs->stats_enabled & JIT_STATS)) + #define tb_stats_enabled(tb, JIT_STATS) \ - (tb && tb->tb_stats && (tb->tb_stats->stats_enabled & JIT_STATS)) + (tb && tb->tb_stats && tbs_stats_enabled(tb->tb_stats, JIT_STATS)) #define stat_per_translation(stat, name) \ (stat->translations.total ? stat->name / stat->translations.total : 0) @@ -66,6 +69,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 */ @@ -88,7 +93,6 @@ struct TBStatistics { struct { unsigned long total; - unsigned long uncached; unsigned long spanning; } translations; @@ -108,6 +112,9 @@ struct TBStatistics { uint64_t la; uint64_t code; } gen_times; + + /* HMP information - used for referring to previous search */ + int display_id; }; bool tb_stats_cmp(const void *ap, const void *bp); @@ -132,4 +139,26 @@ void do_hmp_tbstats_safe(CPUState *cpu, run_on_cpu_data icmd); */ void tbstats_reset_tbs(void); +/** + * dump_tbs_info: report the hottest blocks + * + * @count: the limit of hotblocks + * @sort_by: property in which the dump will be sorted + * @use_monitor: redirect output to monitor + * + * Report the hottest blocks to either the log or monitor + */ +void dump_tbs_info(int count, int sort_by, bool use_monitor); + +/** + * dump_tb_info: dump information about one TB + * + * @id: the display id of the block (from previous search) + * @mask: the temporary logging mask + * @Use_monitor: redirect output to monitor + * + * Re-run a translation of a block at addr for the purposes of debug output + */ +void dump_tb_info(int id, int log_mask, bool use_monitor); + #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/include/qemu/log-for-trace.h b/include/qemu/log-for-trace.h index d47c9cd446..5d0afc56c7 100644 --- a/include/qemu/log-for-trace.h +++ b/include/qemu/log-for-trace.h @@ -20,6 +20,9 @@ /* Private global variable, don't use */ extern int qemu_loglevel; +extern bool to_string; + +extern int32_t max_num_hot_tbs_to_dump; #define LOG_TRACE (1 << 15) @@ -30,6 +33,7 @@ static inline bool qemu_loglevel_mask(int mask) } /* main logging function */ -void G_GNUC_PRINTF(1, 2) qemu_log(const char *fmt, ...); +int G_GNUC_PRINTF(1, 2) qemu_log(const char *fmt, ...); +int G_GNUC_PRINTF(1, 0) qemu_vlog(const char *fmt, va_list va); #endif diff --git a/include/qemu/log.h b/include/qemu/log.h index 6f3b8091cd..26b33151f3 100644 --- a/include/qemu/log.h +++ b/include/qemu/log.h @@ -85,6 +85,8 @@ extern const QEMULogItem qemu_log_items[]; bool qemu_set_log(int log_flags, Error **errp); bool qemu_set_log_filename(const char *filename, Error **errp); bool qemu_set_log_filename_flags(const char *name, int flags, Error **errp); +void qemu_log_to_monitor(bool enable); +void qemu_log_to_string(bool enable, GString *s); void qemu_set_dfilter_ranges(const char *ranges, Error **errp); bool qemu_log_in_addr_range(uint64_t addr); int qemu_str_to_log_mask(const char *str); diff --git a/util/log.c b/util/log.c index 7ae471d97c..6477eb5a5f 100644 --- a/util/log.c +++ b/util/log.c @@ -50,6 +50,8 @@ int qemu_loglevel; static bool log_per_thread; static GArray *debug_regions; int32_t max_num_hot_tbs_to_dump; +static bool to_monitor; +bool to_string; /* Returns true if qemu_log() will really write somewhere. */ bool qemu_log_enabled(void) @@ -146,19 +148,6 @@ void qemu_log_unlock(FILE *logfile) } } -void qemu_log(const char *fmt, ...) -{ - FILE *f = qemu_log_trylock(); - if (f) { - va_list ap; - - va_start(ap, fmt); - vfprintf(f, fmt, ap); - va_end(ap); - qemu_log_unlock(f); - } -} - static void __attribute__((__constructor__)) startup(void) { qemu_mutex_init(&global_mutex); @@ -206,6 +195,55 @@ valid_filename_template(const char *filename, bool per_thread, Error **errp) return filename ? vft_strdup : vft_stderr; } +GString *string; + +int qemu_vlog(const char *fmt, va_list va) +{ + int ret = 0; + + if (to_string && string) { + g_string_append_vprintf(string, fmt, va); + } else if (to_monitor) { + ret = qemu_vprintf(fmt, va); + } else { + FILE *f = qemu_log_trylock(); + if (f) { + ret = vfprintf(f, fmt, va); + } + qemu_log_unlock(f); + } + + /* Don't pass back error results. */ + if (ret < 0) { + ret = 0; + } + return ret; +} + +/* Return the number of characters emitted. */ +int qemu_log(const char *fmt, ...) +{ + int ret = 0; + va_list ap; + + va_start(ap, fmt); + ret = qemu_vlog(fmt, ap); + va_end(ap); + + return ret; +} + +void qemu_log_to_monitor(bool enable) +{ + to_monitor = enable; +} + +void qemu_log_to_string(bool enable, GString *s) +{ + to_string = enable; + string = s; +} + /* enable or disable low levels log */ static bool qemu_set_log_internal(const char *filename, bool changed_name, int log_flags, Error **errp) @@ -523,6 +561,7 @@ int qemu_str_to_log_mask(const char *str) trace_enable_events((*tmp) + 6); mask |= LOG_TRACE; #endif +#ifdef CONFIG_TCG } else if (g_str_has_prefix(*tmp, "tb_stats")) { mask |= CPU_LOG_TB_STATS; set_default_tbstats_flag(TB_ALL_STATS); @@ -553,6 +592,7 @@ int qemu_str_to_log_mask(const char *str) } set_default_tbstats_flag(flags); } +#endif } else { for (item = qemu_log_items; item->mask != 0; item++) { if (g_str_equal(*tmp, item->name)) { From patchwork Thu May 18 13:57:55 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: "Wu, Fei" X-Patchwork-Id: 13246857 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 6160FC7EE23 for ; Thu, 18 May 2023 13:59:49 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1pze86-0004Oa-Bs; Thu, 18 May 2023 09:57:18 -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 1pze85-0004DP-0z for qemu-devel@nongnu.org; Thu, 18 May 2023 09:57:17 -0400 Received: from mga12.intel.com ([192.55.52.136]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1pze82-0002Nb-Ut for qemu-devel@nongnu.org; Thu, 18 May 2023 09:57:16 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1684418234; x=1715954234; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=YjerWOmNHxX5wXROeV/dvywS/jNPNCEXAe+G9kzXeww=; b=OO+0QPL6Y9oV64/G1iwMJXMXD3bInHkUPiq4MhmmKNMmP7QuVWnUxT6b Sg18+lWTXCBN2UeGizr/TCqPEi5/QJGQF2eYpS08pOXUuN7Km7ayAcsWM 1LoDwf6jl0jybEo2IwQPvl0k9LodgdC8VdpLU1hWKSyoCIXYr0snxngSa TxQWj3FZ//Fh2KStbZ4ipKCaCWxnAKBKiIQnQe2W0fQnpMGSz5D7dssE/ GQRbaSN7dKQfJpAslCJpPTkv8Hk6byxPatSauYksPcDDxvwyMWy8GC9S2 Gbm/iW79ewHyFIefUy5HjXaVnZPmZOL8Zzq4Jr4MIoeatid888s0qchva Q==; X-IronPort-AV: E=McAfee;i="6600,9927,10714"; a="331685881" X-IronPort-AV: E=Sophos;i="5.99,285,1677571200"; d="scan'208";a="331685881" Received: from orsmga005.jf.intel.com ([10.7.209.41]) by fmsmga106.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 18 May 2023 06:57:13 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10714"; a="876428865" X-IronPort-AV: E=Sophos;i="5.99,285,1677571200"; d="scan'208";a="876428865" Received: from wufei-optiplex-7090.sh.intel.com ([10.238.200.247]) by orsmga005.jf.intel.com with ESMTP; 18 May 2023 06:57:11 -0700 From: Fei Wu To: qemu-devel@nongnu.org, richard.henderson@linaro.org, alex.bennee@linaro.org, fei2.wu@intel.com Cc: "Vanderson M. do Rosario" , Paolo Bonzini , Laurent Vivier Subject: [PATCH v12 13/15] tb-stats: dump hot TBs at the end of the execution Date: Thu, 18 May 2023 21:57:55 +0800 Message-Id: <20230518135757.1442654-14-fei2.wu@intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230518135757.1442654-1-fei2.wu@intel.com> References: <20230518135757.1442654-1-fei2.wu@intel.com> MIME-Version: 1.0 Received-SPF: pass client-ip=192.55.52.136; envelope-from=fei2.wu@intel.com; helo=mga12.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, SPF_HELO_PASS=-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" Dump the hottest TBs if -d tb_stats,dump_limit=N is used. Example of output for the 3 hottest TBs: TB id:1 | phys:0x34d54 virt:0x0000000000034d54 flags:0x0000f0 | exec:4828932/0 guest inst cov:16.38% | trans:1 ints: g:3 op:82 op_opt:34 spills:3 | h/g (host bytes / guest insts): 90.666664 | time to gen at 2.4GHz => code:3150.83(ns) IR:712.08(ns) | targets: 0x0000000000034d5e (id:11), 0x0000000000034d0d (id:2) TB id:2 | phys:0x34d0d virt:0x0000000000034d0d flags:0x0000f0 | exec:4825842/0 guest inst cov:21.82% | trans:1 ints: g:4 op:80 op_opt:38 spills:2 | h/g (host bytes / guest insts): 84.000000 | time to gen at 2.4GHz => code:3362.92(ns) IR:793.75(ns) | targets: 0x0000000000034d19 (id:12), 0x0000000000034d54 (id:1) TB id:3 | phys:0xec1c1 virt:0x00000000000ec1c1 flags:0x0000b0 | exec:872032/0 guest inst cov:1.97% | trans:1 ints: g:2 op:56 op_opt:26 spills:1 | h/g (host bytes / guest insts): 68.000000 | time to gen at 2.4GHz => code:1692.08(ns) IR:473.75(ns) | targets: 0x00000000000ec1c5 (id:4), 0x00000000000ec1cb (id:13) Signed-off-by: Vanderson M. do Rosario Message-Id: <20190829173437.5926-12-vandersonmr2@gmail.com> [AJB: fix authorship, ad softmmu support] Signed-off-by: Alex Bennée Signed-off-by: Fei Wu --- 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 | 5 +++++ util/log.c | 4 ++-- 7 files changed, 54 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 cb28879a45..3f7159b896 100644 --- a/accel/tcg/tb-stats.c +++ b/accel/tcg/tb-stats.c @@ -19,6 +19,7 @@ #include "exec/tb-stats.h" #include "exec/tb-flush.h" +#include "exec/tb-stats-dump.h" #include "tb-context.h" #include "internal.h" @@ -33,6 +34,7 @@ enum TBStatsStatus { static enum TBStatsStatus tcg_collect_tb_stats; static uint32_t default_tbstats_flag; +static int max_dump_tbs; /* only accessed in safe work */ static GList *last_search; @@ -618,6 +620,20 @@ void dump_tb_info(int id, int log_mask, bool use_monitor) } +/* + * Dump the final stats + */ +void tb_stats_dump(void) +{ + if (!tb_stats_collection_enabled()) { + return; + } + + dump_tbs_info(max_dump_tbs, SORT_BY_HOTNESS, false); +} + +/* TBStatistic collection controls */ + void enable_collect_tb_stats(void) { tcg_collect_tb_stats = TB_STATS_RUNNING; @@ -666,3 +682,8 @@ void set_default_tbstats_flag(uint32_t flags) { default_tbstats_flag = flags; } + +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 8c7abb62e5..ec5a215417 100644 --- a/include/exec/tb-stats-flags.h +++ b/include/exec/tb-stats-flags.h @@ -25,6 +25,7 @@ void pause_collect_tb_stats(void); bool tb_stats_collection_enabled(void); bool tb_stats_collection_paused(void); +void set_tbstats_max_tbs(int max); uint32_t get_default_tbstats_flag(void); void set_default_tbstats_flag(uint32_t); void set_tbstats_flags(uint32_t flags); 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 37390799f1..b5ceb55ffd 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" @@ -827,6 +828,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 d212c2a1fa..a3e1406b88 100644 --- a/stubs/tb-stats.c +++ b/stubs/tb-stats.c @@ -21,6 +21,11 @@ bool tb_stats_collection_enabled(void) return false; } +void set_tbstats_max_tbs(int max) +{ + return; +} + void set_default_tbstats_flag(uint32_t flags) { return; diff --git a/util/log.c b/util/log.c index 6477eb5a5f..d159ca6916 100644 --- a/util/log.c +++ b/util/log.c @@ -49,7 +49,6 @@ static __thread Notifier qemu_log_thread_cleanup_notifier; int qemu_loglevel; static bool log_per_thread; static GArray *debug_regions; -int32_t max_num_hot_tbs_to_dump; static bool to_monitor; bool to_string; @@ -568,7 +567,8 @@ int qemu_str_to_log_mask(const char *str) enable_collect_tb_stats(); } else if (tb_stats_collection_enabled() && g_str_has_prefix(*tmp, "dump_limit=")) { - max_num_hot_tbs_to_dump = atoi((*tmp) + 11); + int hot_tbs = atoi((*tmp) + 11); + set_tbstats_max_tbs(hot_tbs); } else if (tb_stats_collection_enabled() && g_str_has_prefix(*tmp, "level=")) { uint32_t flags = 0; From patchwork Thu May 18 13:57:56 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: "Wu, Fei" X-Patchwork-Id: 13246855 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 566E9C77B7D for ; Thu, 18 May 2023 13:59:34 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1pze8A-0004aq-Ba; Thu, 18 May 2023 09:57:22 -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 1pze89-0004aP-GT for qemu-devel@nongnu.org; Thu, 18 May 2023 09:57:21 -0400 Received: from mga12.intel.com ([192.55.52.136]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1pze87-0002T5-RT for qemu-devel@nongnu.org; Thu, 18 May 2023 09:57:21 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1684418239; x=1715954239; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=hNy0EL7LNfaBhcec/LSO+OfhCuDllSqA/YNjUll1Ck0=; b=dYex0jg50C9agdISKQUwZQpj+zP4bK6DpFp9gf/v/6/rYCnL6hQc/rTK a0/QzzJI1Cfwz5tva1SGuHj5nJxlE9l3fJdhAEiEaRirrOqRkoEhqyzLu fhlg7fvCiWlmBhb3eATidO/5r+TDBOJ1G9QPekuQdpGAn9PE8wZT36QQp IhwadOeSMdG+BaVOWdOOOlb7kp0bEeWDwPGBR+GBhw/D2Jyt9MsCfLyYZ MntYHy/ISn/SiVXARiSgAudfEJ13IMNtkq6sdUxFoo4+AlyBr3fkLzvrK BUazevpcoGkvKcR1w2Z9tMHVlRWHfDi9OGMujWLg/k2de1T1OpWwNtGmt Q==; X-IronPort-AV: E=McAfee;i="6600,9927,10714"; a="331685914" X-IronPort-AV: E=Sophos;i="5.99,285,1677571200"; d="scan'208";a="331685914" Received: from orsmga005.jf.intel.com ([10.7.209.41]) by fmsmga106.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 18 May 2023 06:57:18 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10714"; a="876428871" X-IronPort-AV: E=Sophos;i="5.99,285,1677571200"; d="scan'208";a="876428871" Received: from wufei-optiplex-7090.sh.intel.com ([10.238.200.247]) by orsmga005.jf.intel.com with ESMTP; 18 May 2023 06:57:16 -0700 From: Fei Wu To: qemu-devel@nongnu.org, richard.henderson@linaro.org, alex.bennee@linaro.org, fei2.wu@intel.com Cc: Paolo Bonzini , =?utf-8?q?Marc-Andr=C3=A9_Lureau?= , =?utf-8?q?Daniel_P=2E_Berrang=C3=A9?= , Thomas Huth , =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= Subject: [PATCH v12 14/15] configure: remove the final bits of --profiler support Date: Thu, 18 May 2023 21:57:56 +0800 Message-Id: <20230518135757.1442654-15-fei2.wu@intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230518135757.1442654-1-fei2.wu@intel.com> References: <20230518135757.1442654-1-fei2.wu@intel.com> MIME-Version: 1.0 Received-SPF: pass client-ip=192.55.52.136; envelope-from=fei2.wu@intel.com; helo=mga12.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, SPF_HELO_PASS=-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 Signed-off-by: Alex Bennée Signed-off-by: Fei Wu --- meson.build | 2 -- meson_options.txt | 2 -- scripts/meson-buildoptions.sh | 3 --- 3 files changed, 7 deletions(-) diff --git a/meson.build b/meson.build index 4dddccb890..4be21c9d57 100644 --- a/meson.build +++ b/meson.build @@ -1888,7 +1888,6 @@ if numa.found() dependencies: numa)) endif config_host_data.set('CONFIG_OPENGL', opengl.found()) -config_host_data.set('CONFIG_PROFILER', get_option('profiler')) config_host_data.set('CONFIG_RBD', rbd.found()) config_host_data.set('CONFIG_RDMA', rdma.found()) config_host_data.set('CONFIG_SDL', sdl.found()) @@ -3859,7 +3858,6 @@ if 'objc' in all_languages summary_info += {'QEMU_OBJCFLAGS': ' '.join(qemu_objcflags)} endif summary_info += {'QEMU_LDFLAGS': ' '.join(qemu_ldflags)} -summary_info += {'profiler': get_option('profiler')} summary_info += {'link-time optimization (LTO)': get_option('b_lto')} summary_info += {'PIE': get_option('b_pie')} summary_info += {'static build': config_host.has_key('CONFIG_STATIC')} diff --git a/meson_options.txt b/meson_options.txt index 11aec2a441..9692fa7cdc 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -332,8 +332,6 @@ option('qom_cast_debug', type: 'boolean', value: true, option('gprof', type: 'boolean', value: false, description: 'QEMU profiling with gprof', deprecated: true) -option('profiler', type: 'boolean', value: false, - description: 'profiler support') option('slirp_smbd', type : 'feature', value : 'auto', description: 'use smbd (at path --smbd=*) in slirp networking') diff --git a/scripts/meson-buildoptions.sh b/scripts/meson-buildoptions.sh index 52fb079a60..28c7d21a15 100644 --- a/scripts/meson-buildoptions.sh +++ b/scripts/meson-buildoptions.sh @@ -38,7 +38,6 @@ meson_options_help() { printf "%s\n" ' jemalloc/system/tcmalloc)' printf "%s\n" ' --enable-module-upgrades try to load modules from alternate paths for' printf "%s\n" ' upgrades' - printf "%s\n" ' --enable-profiler profiler support' printf "%s\n" ' --enable-rng-none dummy RNG, avoid using /dev/(u)random and' printf "%s\n" ' getrandom()' printf "%s\n" ' --enable-strip Strip targets on install' @@ -386,8 +385,6 @@ _meson_option_parse() { --with-pkgversion=*) quote_sh "-Dpkgversion=$2" ;; --enable-png) printf "%s" -Dpng=enabled ;; --disable-png) printf "%s" -Dpng=disabled ;; - --enable-profiler) printf "%s" -Dprofiler=true ;; - --disable-profiler) printf "%s" -Dprofiler=false ;; --enable-pvrdma) printf "%s" -Dpvrdma=enabled ;; --disable-pvrdma) printf "%s" -Dpvrdma=disabled ;; --enable-qcow1) printf "%s" -Dqcow1=enabled ;; From patchwork Thu May 18 13:57:57 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Wu, Fei" X-Patchwork-Id: 13246852 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 54DDCC77B7D for ; Thu, 18 May 2023 13:59:01 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1pze8H-0004pt-Tf; Thu, 18 May 2023 09:57:29 -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 1pze8G-0004ly-5z for qemu-devel@nongnu.org; Thu, 18 May 2023 09:57:28 -0400 Received: from mga12.intel.com ([192.55.52.136]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1pze8D-0002T5-8O for qemu-devel@nongnu.org; Thu, 18 May 2023 09:57:27 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1684418245; x=1715954245; h=from:to:subject:date:message-id:in-reply-to:references: mime-version:content-transfer-encoding; bh=nWRAIWMWrMIimTopfekgs94LLyTiAZ7gYt4lq+MEsjs=; b=U6K64On3bOpIVSpDNSeesdl3Mv60KOr+donTwKE+Xtp8FA106ffs6t7M a1bu6wHa4bJLDTLGlpAWEdxfOVB/h+NQLHxvUToCT5tWhtxPw4/p4C8dx gSbkmZXUeWfwLuP2I4VgYXEsdxNaJUB15sKL6hbSuWhDoku8usl/sg3MS YzKCgA/bLTNbx3Lg54wWz6EV19AQOeRF+cCXIgBYBpc94uBX/xXKkcXay THv7rzeF72Vae39spN5kdc3SGuNr5+ZkaR83/yLCx3ebfjQfZCXfOy5nE QArpaS2oXGOvEkjcnLoOowJivpLX/hM4br/yZfUJGOrX86avNXO5pWM93 A==; X-IronPort-AV: E=McAfee;i="6600,9927,10714"; a="331685955" X-IronPort-AV: E=Sophos;i="5.99,285,1677571200"; d="scan'208";a="331685955" Received: from orsmga005.jf.intel.com ([10.7.209.41]) by fmsmga106.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 18 May 2023 06:57:24 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10714"; a="876428879" X-IronPort-AV: E=Sophos;i="5.99,285,1677571200"; d="scan'208";a="876428879" Received: from wufei-optiplex-7090.sh.intel.com ([10.238.200.247]) by orsmga005.jf.intel.com with ESMTP; 18 May 2023 06:57:23 -0700 From: Fei Wu To: qemu-devel@nongnu.org, richard.henderson@linaro.org, alex.bennee@linaro.org, fei2.wu@intel.com Subject: [PATCH v12 15/15] docs/tb-stats: add how to Date: Thu, 18 May 2023 21:57:57 +0800 Message-Id: <20230518135757.1442654-16-fei2.wu@intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230518135757.1442654-1-fei2.wu@intel.com> References: <20230518135757.1442654-1-fei2.wu@intel.com> MIME-Version: 1.0 Received-SPF: pass client-ip=192.55.52.136; envelope-from=fei2.wu@intel.com; helo=mga12.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, SPF_HELO_PASS=-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/tb-stats.txt | 116 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 116 insertions(+) create mode 100644 docs/tb-stats.txt diff --git a/docs/tb-stats.txt b/docs/tb-stats.txt new file mode 100644 index 0000000000..2f96ebb741 --- /dev/null +++ b/docs/tb-stats.txt @@ -0,0 +1,116 @@ +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. + + +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 [stats_level] -- Control tb statistics collection:tb_stats (start|pause|stop|filter) [all|jit_stats|exec_stats] + + (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:1 | phys:0x79bca0 virt:0xffffffff8059bca0 flags:0x01024001 0 inv/1 + | exec:1464084/0 guest inst cov:0.15% + | trans:1 ints: g:3 op:16 op_opt:15 spills:0 + | h/g (host bytes / guest insts): 64.000000 + | time to gen at 2.4GHz => code:607.08(ns) IR:250.83(ns) + + TB id:2 | phys:0x2adf0c virt:0xffffffff800adf0c flags:0x01024001 0 inv/1 + | exec:1033298/0 guest inst cov:0.28% + | trans:1 ints: g:8 op:35 op_opt:33 spills:0 + | h/g (host bytes / guest insts): 86.000000 + | time to gen at 2.4GHz => code:1429.58(ns) IR:545.42(ns) + +* Dive into the specific TB + (qemu) info tb 1 op + ------------------------------ + + TB id:1 | phys:0x79bca0 virt:0xffffffff8059bca0 flags:0x01024001 7 inv/19 + | exec:2038349/0 guest inst cov:0.15% + | trans:19 ints: g:3 op:16 op_opt:15 spills:0 + | h/g (host bytes / guest insts): 64.000000 + | time to gen at 2.4GHz => code:133434.17(ns) IR:176988.33(ns) + + OP: + ld_i32 loc1,env,$0xfffffffffffffff0 + brcond_i32 loc1,$0x0,lt,$L0 + mov_i64 loc3,$0x7f3c70b3a4e0 + call inc_exec_freq,$0x1,$0,loc3 + + ---- ffffffff8059bca0 0000000000006422 + add_i64 loc5,x2/sp,$0x8 + qemu_ld_i64 x8/s0,loc5,un+leq,1 + + ---- ffffffff8059bca2 0000000000000000 + add_i64 x2/sp,x2/sp,$0x10 + + ---- ffffffff8059bca4 0000000000000000 + mov_i64 pc,x1/ra + and_i64 pc,pc,$0xfffffffffffffffe + call lookup_tb_ptr,$0x6,$1,tmp9,env + goto_ptr tmp9 + set_label $L0 + exit_tb $0x7f3e887a8043 + + ------------------------------ + +* Stop TBStatistics after investigation, this will disable TBStatistics completely. + (qemu) tb_stats stop + (qemu) + +* Alternatively, TBStatistics can be paused, the previous collected TBStatistics + are not cleared but there is no TBStatistics recorded for new TBs. + (qemu) tb_stats pause + (qemu) + +* Definitely, TBStatistics can be restarted for another round of investigation. + (qemu) tb_stats start all + (qemu) + + +2. Dump at exit +--------------- +New command line options have been added to enable dump TB information at exit: + -d tb_stats[[,level=(+all+jit+exec+time)][,dump_limit=]] + +e.g. starting qemu like this: + -d tb_stats,dump_limit=2 + +Qemu prints the following at exit: + QEMU: Terminated + TB id:1 | phys:0x61be02 virt:0xffffffff8041be02 flags:0x01024001 0 inv/1 + | exec:72739176/0 guest inst cov:20.22% + | trans:1 ints: g:9 op:35 op_opt:33 spills:0 + | h/g (host bytes / guest insts): 51.555557 + | time to gen at 2.4GHz => code:1065.42(ns) IR:554.17(ns) + + TB id:2 | phys:0x61bc66 virt:0xffffffff8041bc66 flags:0x01024001 0 inv/1 + | exec:25069507/0 guest inst cov:0.77% + | trans:1 ints: g:1 op:15 op_opt:14 spills:0 + | h/g (host bytes / guest insts): 128.000000 + | time to gen at 2.4GHz => code:312.50(ns) IR:152.08(ns)