qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v17 00/16] TCG code quality tracking
@ 2023-10-03 18:30 Richard Henderson
  2023-10-03 18:30 ` [PATCH v17 01/16] accel/tcg: Move HMP info jit and info opcount code Richard Henderson
                   ` (16 more replies)
  0 siblings, 17 replies; 39+ messages in thread
From: Richard Henderson @ 2023-10-03 18:30 UTC (permalink / raw)
  To: qemu-devel; +Cc: fei2.wu

Based-on: <20231003173052.1601813-1-richard.henderson@linaro.org>
("[PULL 00/47] tcg patch queue")

v16: 20230628120430.73777-1-fei2.wu@intel.com

Changes for v17:
  * Split some patches, and other preliminary cleanup.


r~


Fei Wu (2):
  util/log: Add -d tb_stats
  accel/tcg: Dump hot TBs at the end of the execution

Richard Henderson (9):
  accel/tcg: Move HMP info jit and info opcount code
  tcg: Record orig_nb_ops TCGContext
  tcg: Record nb_deleted_ops in TCGContext
  tcg: Record nb_spills in TCGContext
  accel/tcg: Add TBStatistics structure
  accel/tcg: Collect TB jit statistics
  util/log: Add Error argument to qemu_str_to_log_mask
  softmmu: Export qemu_ram_ptr_length
  monitor: Change MonitorDec.get_value return type to int64_t

Vanderson M. do Rosario (5):
  accel/tcg: Collect TB execution statistics
  accel/tcg: Add tb_stats hmp command
  accel/tcg: Add tb_stats_collect and tb_stats_dump
  disas: Allow monitor_disas to read from ram_addr_t
  accel/tcg: Add info [tb-list|tb] commands to HMP

 accel/tcg/internal-common.h      |   2 -
 accel/tcg/tb-context.h           |   4 +-
 bsd-user/bsd-proc.h              |   2 +
 include/disas/disas.h            |   8 +-
 include/exec/cputlb.h            |   1 -
 include/exec/memory.h            |   2 +
 include/exec/translation-block.h |   3 +
 include/monitor/hmp-target.h     |   5 +-
 include/qemu/log.h               |   2 +-
 include/qemu/typedefs.h          |   1 +
 include/tcg/tb-stats.h           | 165 ++++++++++++++++
 include/tcg/tcg.h                |   8 +-
 accel/tcg/cpu-exec.c             |   6 +
 accel/tcg/cputlb.c               |  15 --
 accel/tcg/monitor.c              | 317 ++++++++++++++++++++++++++++++-
 accel/tcg/tb-maint.c             |   3 +-
 accel/tcg/tb-stats.c             | 231 ++++++++++++++++++++++
 accel/tcg/translate-all.c        | 167 ++++------------
 accel/tcg/translator.c           |  28 +++
 bsd-user/main.c                  |   6 +-
 disas/disas-mon.c                |  32 +++-
 linux-user/exit.c                |  10 +-
 linux-user/main.c                |   7 +-
 monitor/hmp-cmds-target.c        |  27 +--
 monitor/hmp-cmds.c               |   5 +-
 monitor/hmp-target.c             |   2 +
 softmmu/physmem.c                |   4 +-
 softmmu/runstate.c               |   2 +
 softmmu/vl.c                     |   7 +-
 stubs/tb-stats.c                 |  20 ++
 target/i386/monitor.c            |   4 +-
 target/ppc/ppc-qmp-cmds.c        |  20 +-
 target/sparc/monitor.c           |   8 +-
 tcg/tcg.c                        |  50 ++---
 util/log.c                       |  51 ++++-
 accel/tcg/meson.build            |   1 +
 hmp-commands-info.hx             |  14 ++
 hmp-commands.hx                  |  15 ++
 stubs/meson.build                |   1 +
 39 files changed, 1027 insertions(+), 229 deletions(-)
 create mode 100644 include/tcg/tb-stats.h
 create mode 100644 accel/tcg/tb-stats.c
 create mode 100644 stubs/tb-stats.c

-- 
2.34.1



^ permalink raw reply	[flat|nested] 39+ messages in thread

* [PATCH v17 01/16] accel/tcg: Move HMP info jit and info opcount code
  2023-10-03 18:30 [PATCH v17 00/16] TCG code quality tracking Richard Henderson
@ 2023-10-03 18:30 ` Richard Henderson
  2023-10-10 12:09   ` Philippe Mathieu-Daudé
  2023-10-15 12:58   ` Alex Bennée
  2023-10-03 18:30 ` [PATCH v17 02/16] tcg: Record orig_nb_ops TCGContext Richard Henderson
                   ` (15 subsequent siblings)
  16 siblings, 2 replies; 39+ messages in thread
From: Richard Henderson @ 2023-10-03 18:30 UTC (permalink / raw)
  To: qemu-devel; +Cc: fei2.wu

Move all of it into accel/tcg/monitor.c.  This puts everything
about tcg that is only used by the monitor in the same place.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 accel/tcg/internal-common.h |   2 -
 include/exec/cputlb.h       |   1 -
 include/tcg/tcg.h           |   3 -
 accel/tcg/cputlb.c          |  15 ----
 accel/tcg/monitor.c         | 154 ++++++++++++++++++++++++++++++++++++
 accel/tcg/translate-all.c   | 127 -----------------------------
 tcg/tcg.c                   |  10 ---
 7 files changed, 154 insertions(+), 158 deletions(-)

diff --git a/accel/tcg/internal-common.h b/accel/tcg/internal-common.h
index 3b2277e6e9..edefd0dcb7 100644
--- a/accel/tcg/internal-common.h
+++ b/accel/tcg/internal-common.h
@@ -14,8 +14,6 @@
 extern int64_t max_delay;
 extern int64_t max_advance;
 
-void dump_exec_info(GString *buf);
-
 /*
  * Return true if CS is not running in parallel with other cpus, either
  * because there are no other cpus or we are within an exclusive context.
diff --git a/include/exec/cputlb.h b/include/exec/cputlb.h
index 19b16e58f8..6da1462c4f 100644
--- a/include/exec/cputlb.h
+++ b/include/exec/cputlb.h
@@ -26,6 +26,5 @@
 /* cputlb.c */
 void tlb_protect_code(ram_addr_t ram_addr);
 void tlb_unprotect_code(ram_addr_t ram_addr);
-void tlb_flush_counts(size_t *full, size_t *part, size_t *elide);
 #endif
 #endif
diff --git a/include/tcg/tcg.h b/include/tcg/tcg.h
index 680ff00722..82b4625773 100644
--- a/include/tcg/tcg.h
+++ b/include/tcg/tcg.h
@@ -842,9 +842,6 @@ static inline TCGv_ptr tcg_temp_new_ptr(void)
     return temp_tcgv_ptr(t);
 }
 
-void tcg_dump_info(GString *buf);
-void tcg_dump_op_count(GString *buf);
-
 #define TCG_CT_CONST  1 /* any constant of register size */
 
 typedef struct TCGArgConstraint {
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
index b8c5e345b8..13986820fe 100644
--- a/accel/tcg/cputlb.c
+++ b/accel/tcg/cputlb.c
@@ -321,21 +321,6 @@ static void flush_all_helper(CPUState *src, run_on_cpu_func fn,
     }
 }
 
-void tlb_flush_counts(size_t *pfull, size_t *ppart, size_t *pelide)
-{
-    CPUState *cpu;
-    size_t full = 0, part = 0, elide = 0;
-
-    CPU_FOREACH(cpu) {
-        full += qatomic_read(&cpu->neg.tlb.c.full_flush_count);
-        part += qatomic_read(&cpu->neg.tlb.c.part_flush_count);
-        elide += qatomic_read(&cpu->neg.tlb.c.elide_flush_count);
-    }
-    *pfull = full;
-    *ppart = part;
-    *pelide = elide;
-}
-
 static void tlb_flush_by_mmuidx_async_work(CPUState *cpu, run_on_cpu_data data)
 {
     uint16_t asked = data.host_int;
diff --git a/accel/tcg/monitor.c b/accel/tcg/monitor.c
index caf1189e0b..093efe9714 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/qht.h"
 #include "qapi/error.h"
 #include "qapi/type-helpers.h"
 #include "qapi/qapi-commands-machine.h"
@@ -17,6 +18,7 @@
 #include "sysemu/tcg.h"
 #include "tcg/tcg.h"
 #include "internal-common.h"
+#include "tb-context.h"
 
 
 static void dump_drift_info(GString *buf)
@@ -50,6 +52,153 @@ static void dump_accel_info(GString *buf)
                            one_insn_per_tb ? "on" : "off");
 }
 
+static void print_qht_statistics(struct qht_stats hst, GString *buf)
+{
+    uint32_t hgram_opts;
+    size_t hgram_bins;
+    char *hgram;
+
+    if (!hst.head_buckets) {
+        return;
+    }
+    g_string_append_printf(buf, "TB hash buckets     %zu/%zu "
+                           "(%0.2f%% head buckets used)\n",
+                           hst.used_head_buckets, hst.head_buckets,
+                           (double)hst.used_head_buckets /
+                           hst.head_buckets * 100);
+
+    hgram_opts =  QDIST_PR_BORDER | QDIST_PR_LABELS;
+    hgram_opts |= QDIST_PR_100X   | QDIST_PR_PERCENT;
+    if (qdist_xmax(&hst.occupancy) - qdist_xmin(&hst.occupancy) == 1) {
+        hgram_opts |= QDIST_PR_NODECIMAL;
+    }
+    hgram = qdist_pr(&hst.occupancy, 10, hgram_opts);
+    g_string_append_printf(buf, "TB hash occupancy   %0.2f%% avg chain occ. "
+                           "Histogram: %s\n",
+                           qdist_avg(&hst.occupancy) * 100, hgram);
+    g_free(hgram);
+
+    hgram_opts = QDIST_PR_BORDER | QDIST_PR_LABELS;
+    hgram_bins = qdist_xmax(&hst.chain) - qdist_xmin(&hst.chain);
+    if (hgram_bins > 10) {
+        hgram_bins = 10;
+    } else {
+        hgram_bins = 0;
+        hgram_opts |= QDIST_PR_NODECIMAL | QDIST_PR_NOBINRANGE;
+    }
+    hgram = qdist_pr(&hst.chain, hgram_bins, hgram_opts);
+    g_string_append_printf(buf, "TB hash avg chain   %0.3f buckets. "
+                           "Histogram: %s\n",
+                           qdist_avg(&hst.chain), hgram);
+    g_free(hgram);
+}
+
+struct tb_tree_stats {
+    size_t nb_tbs;
+    size_t host_size;
+    size_t target_size;
+    size_t max_target_size;
+    size_t direct_jmp_count;
+    size_t direct_jmp2_count;
+    size_t cross_page;
+};
+
+static gboolean tb_tree_stats_iter(gpointer key, gpointer value, gpointer data)
+{
+    const TranslationBlock *tb = value;
+    struct tb_tree_stats *tst = data;
+
+    tst->nb_tbs++;
+    tst->host_size += tb->tc.size;
+    tst->target_size += tb->size;
+    if (tb->size > tst->max_target_size) {
+        tst->max_target_size = tb->size;
+    }
+    if (tb->page_addr[1] != -1) {
+        tst->cross_page++;
+    }
+    if (tb->jmp_reset_offset[0] != TB_JMP_OFFSET_INVALID) {
+        tst->direct_jmp_count++;
+        if (tb->jmp_reset_offset[1] != TB_JMP_OFFSET_INVALID) {
+            tst->direct_jmp2_count++;
+        }
+    }
+    return false;
+}
+
+static void tlb_flush_counts(size_t *pfull, size_t *ppart, size_t *pelide)
+{
+    CPUState *cpu;
+    size_t full = 0, part = 0, elide = 0;
+
+    CPU_FOREACH(cpu) {
+        full += qatomic_read(&cpu->neg.tlb.c.full_flush_count);
+        part += qatomic_read(&cpu->neg.tlb.c.part_flush_count);
+        elide += qatomic_read(&cpu->neg.tlb.c.elide_flush_count);
+    }
+    *pfull = full;
+    *ppart = part;
+    *pelide = elide;
+}
+
+static void tcg_dump_info(GString *buf)
+{
+    g_string_append_printf(buf, "[TCG profiler not compiled]\n");
+}
+
+static void dump_exec_info(GString *buf)
+{
+    struct tb_tree_stats tst = {};
+    struct qht_stats hst;
+    size_t nb_tbs, flush_full, flush_part, flush_elide;
+
+    tcg_tb_foreach(tb_tree_stats_iter, &tst);
+    nb_tbs = tst.nb_tbs;
+    /* XXX: avoid using doubles ? */
+    g_string_append_printf(buf, "Translation buffer state:\n");
+    /*
+     * Report total code size including the padding and TB structs;
+     * otherwise users might think "-accel tcg,tb-size" is not honoured.
+     * For avg host size we use the precise numbers from tb_tree_stats though.
+     */
+    g_string_append_printf(buf, "gen code size       %zu/%zu\n",
+                           tcg_code_size(), tcg_code_capacity());
+    g_string_append_printf(buf, "TB count            %zu\n", nb_tbs);
+    g_string_append_printf(buf, "TB avg target size  %zu max=%zu bytes\n",
+                           nb_tbs ? tst.target_size / nb_tbs : 0,
+                           tst.max_target_size);
+    g_string_append_printf(buf, "TB avg host size    %zu bytes "
+                           "(expansion ratio: %0.1f)\n",
+                           nb_tbs ? tst.host_size / nb_tbs : 0,
+                           tst.target_size ?
+                           (double)tst.host_size / tst.target_size : 0);
+    g_string_append_printf(buf, "cross page TB count %zu (%zu%%)\n",
+                           tst.cross_page,
+                           nb_tbs ? (tst.cross_page * 100) / nb_tbs : 0);
+    g_string_append_printf(buf, "direct jump count   %zu (%zu%%) "
+                           "(2 jumps=%zu %zu%%)\n",
+                           tst.direct_jmp_count,
+                           nb_tbs ? (tst.direct_jmp_count * 100) / nb_tbs : 0,
+                           tst.direct_jmp2_count,
+                           nb_tbs ? (tst.direct_jmp2_count * 100) / nb_tbs : 0);
+
+    qht_statistics_init(&tb_ctx.htable, &hst);
+    print_qht_statistics(hst, buf);
+    qht_statistics_destroy(&hst);
+
+    g_string_append_printf(buf, "\nStatistics:\n");
+    g_string_append_printf(buf, "TB flush count      %u\n",
+                           qatomic_read(&tb_ctx.tb_flush_count));
+    g_string_append_printf(buf, "TB invalidate count %u\n",
+                           qatomic_read(&tb_ctx.tb_phys_invalidate_count));
+
+    tlb_flush_counts(&flush_full, &flush_part, &flush_elide);
+    g_string_append_printf(buf, "TLB full flushes    %zu\n", flush_full);
+    g_string_append_printf(buf, "TLB partial flushes %zu\n", flush_part);
+    g_string_append_printf(buf, "TLB elided flushes  %zu\n", flush_elide);
+    tcg_dump_info(buf);
+}
+
 HumanReadableText *qmp_x_query_jit(Error **errp)
 {
     g_autoptr(GString) buf = g_string_new("");
@@ -66,6 +215,11 @@ HumanReadableText *qmp_x_query_jit(Error **errp)
     return human_readable_text_from_str(buf);
 }
 
+static void tcg_dump_op_count(GString *buf)
+{
+    g_string_append_printf(buf, "[TCG profiler not compiled]\n");
+}
+
 HumanReadableText *qmp_x_query_opcount(Error **errp)
 {
     g_autoptr(GString) buf = g_string_new("");
diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c
index 8cb6ad3511..e579b0891d 100644
--- a/accel/tcg/translate-all.c
+++ b/accel/tcg/translate-all.c
@@ -645,133 +645,6 @@ void cpu_io_recompile(CPUState *cpu, uintptr_t retaddr)
     cpu_loop_exit_noexc(cpu);
 }
 
-static void print_qht_statistics(struct qht_stats hst, GString *buf)
-{
-    uint32_t hgram_opts;
-    size_t hgram_bins;
-    char *hgram;
-
-    if (!hst.head_buckets) {
-        return;
-    }
-    g_string_append_printf(buf, "TB hash buckets     %zu/%zu "
-                           "(%0.2f%% head buckets used)\n",
-                           hst.used_head_buckets, hst.head_buckets,
-                           (double)hst.used_head_buckets /
-                           hst.head_buckets * 100);
-
-    hgram_opts =  QDIST_PR_BORDER | QDIST_PR_LABELS;
-    hgram_opts |= QDIST_PR_100X   | QDIST_PR_PERCENT;
-    if (qdist_xmax(&hst.occupancy) - qdist_xmin(&hst.occupancy) == 1) {
-        hgram_opts |= QDIST_PR_NODECIMAL;
-    }
-    hgram = qdist_pr(&hst.occupancy, 10, hgram_opts);
-    g_string_append_printf(buf, "TB hash occupancy   %0.2f%% avg chain occ. "
-                           "Histogram: %s\n",
-                           qdist_avg(&hst.occupancy) * 100, hgram);
-    g_free(hgram);
-
-    hgram_opts = QDIST_PR_BORDER | QDIST_PR_LABELS;
-    hgram_bins = qdist_xmax(&hst.chain) - qdist_xmin(&hst.chain);
-    if (hgram_bins > 10) {
-        hgram_bins = 10;
-    } else {
-        hgram_bins = 0;
-        hgram_opts |= QDIST_PR_NODECIMAL | QDIST_PR_NOBINRANGE;
-    }
-    hgram = qdist_pr(&hst.chain, hgram_bins, hgram_opts);
-    g_string_append_printf(buf, "TB hash avg chain   %0.3f buckets. "
-                           "Histogram: %s\n",
-                           qdist_avg(&hst.chain), hgram);
-    g_free(hgram);
-}
-
-struct tb_tree_stats {
-    size_t nb_tbs;
-    size_t host_size;
-    size_t target_size;
-    size_t max_target_size;
-    size_t direct_jmp_count;
-    size_t direct_jmp2_count;
-    size_t cross_page;
-};
-
-static gboolean tb_tree_stats_iter(gpointer key, gpointer value, gpointer data)
-{
-    const TranslationBlock *tb = value;
-    struct tb_tree_stats *tst = data;
-
-    tst->nb_tbs++;
-    tst->host_size += tb->tc.size;
-    tst->target_size += tb->size;
-    if (tb->size > tst->max_target_size) {
-        tst->max_target_size = tb->size;
-    }
-    if (tb_page_addr1(tb) != -1) {
-        tst->cross_page++;
-    }
-    if (tb->jmp_reset_offset[0] != TB_JMP_OFFSET_INVALID) {
-        tst->direct_jmp_count++;
-        if (tb->jmp_reset_offset[1] != TB_JMP_OFFSET_INVALID) {
-            tst->direct_jmp2_count++;
-        }
-    }
-    return false;
-}
-
-void dump_exec_info(GString *buf)
-{
-    struct tb_tree_stats tst = {};
-    struct qht_stats hst;
-    size_t nb_tbs, flush_full, flush_part, flush_elide;
-
-    tcg_tb_foreach(tb_tree_stats_iter, &tst);
-    nb_tbs = tst.nb_tbs;
-    /* XXX: avoid using doubles ? */
-    g_string_append_printf(buf, "Translation buffer state:\n");
-    /*
-     * Report total code size including the padding and TB structs;
-     * otherwise users might think "-accel tcg,tb-size" is not honoured.
-     * For avg host size we use the precise numbers from tb_tree_stats though.
-     */
-    g_string_append_printf(buf, "gen code size       %zu/%zu\n",
-                           tcg_code_size(), tcg_code_capacity());
-    g_string_append_printf(buf, "TB count            %zu\n", nb_tbs);
-    g_string_append_printf(buf, "TB avg target size  %zu max=%zu bytes\n",
-                           nb_tbs ? tst.target_size / nb_tbs : 0,
-                           tst.max_target_size);
-    g_string_append_printf(buf, "TB avg host size    %zu bytes "
-                           "(expansion ratio: %0.1f)\n",
-                           nb_tbs ? tst.host_size / nb_tbs : 0,
-                           tst.target_size ?
-                           (double)tst.host_size / tst.target_size : 0);
-    g_string_append_printf(buf, "cross page TB count %zu (%zu%%)\n",
-                           tst.cross_page,
-                           nb_tbs ? (tst.cross_page * 100) / nb_tbs : 0);
-    g_string_append_printf(buf, "direct jump count   %zu (%zu%%) "
-                           "(2 jumps=%zu %zu%%)\n",
-                           tst.direct_jmp_count,
-                           nb_tbs ? (tst.direct_jmp_count * 100) / nb_tbs : 0,
-                           tst.direct_jmp2_count,
-                           nb_tbs ? (tst.direct_jmp2_count * 100) / nb_tbs : 0);
-
-    qht_statistics_init(&tb_ctx.htable, &hst);
-    print_qht_statistics(hst, buf);
-    qht_statistics_destroy(&hst);
-
-    g_string_append_printf(buf, "\nStatistics:\n");
-    g_string_append_printf(buf, "TB flush count      %u\n",
-                           qatomic_read(&tb_ctx.tb_flush_count));
-    g_string_append_printf(buf, "TB invalidate count %u\n",
-                           qatomic_read(&tb_ctx.tb_phys_invalidate_count));
-
-    tlb_flush_counts(&flush_full, &flush_part, &flush_elide);
-    g_string_append_printf(buf, "TLB full flushes    %zu\n", flush_full);
-    g_string_append_printf(buf, "TLB partial flushes %zu\n", flush_part);
-    g_string_append_printf(buf, "TLB elided flushes  %zu\n", flush_elide);
-    tcg_dump_info(buf);
-}
-
 #else /* CONFIG_USER_ONLY */
 
 void cpu_interrupt(CPUState *cpu, int mask)
diff --git a/tcg/tcg.c b/tcg/tcg.c
index f664cf1484..71c25f1974 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -5919,11 +5919,6 @@ static void tcg_out_st_helper_args(TCGContext *s, const TCGLabelQemuLdst *ldst,
     tcg_out_helper_load_common_args(s, ldst, parm, info, next_arg);
 }
 
-void tcg_dump_op_count(GString *buf)
-{
-    g_string_append_printf(buf, "[TCG profiler not compiled]\n");
-}
-
 int tcg_gen_code(TCGContext *s, TranslationBlock *tb, uint64_t pc_start)
 {
     int i, start_words, num_insns;
@@ -6120,11 +6115,6 @@ int tcg_gen_code(TCGContext *s, TranslationBlock *tb, uint64_t pc_start)
     return tcg_current_code_size(s);
 }
 
-void tcg_dump_info(GString *buf)
-{
-    g_string_append_printf(buf, "[TCG profiler not compiled]\n");
-}
-
 #ifdef ELF_HOST_MACHINE
 /* In order to use this feature, the backend needs to do three things:
 
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH v17 02/16] tcg: Record orig_nb_ops TCGContext
  2023-10-03 18:30 [PATCH v17 00/16] TCG code quality tracking Richard Henderson
  2023-10-03 18:30 ` [PATCH v17 01/16] accel/tcg: Move HMP info jit and info opcount code Richard Henderson
@ 2023-10-03 18:30 ` Richard Henderson
  2023-10-15 12:57   ` Alex Bennée
  2023-10-03 18:30 ` [PATCH v17 03/16] tcg: Record nb_deleted_ops in TCGContext Richard Henderson
                   ` (14 subsequent siblings)
  16 siblings, 1 reply; 39+ messages in thread
From: Richard Henderson @ 2023-10-03 18:30 UTC (permalink / raw)
  To: qemu-devel; +Cc: fei2.wu

Remember the value of nb_ops before optimization.
To be copied into TBStatistics when desired.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 include/tcg/tcg.h | 3 +++
 tcg/tcg.c         | 2 ++
 2 files changed, 5 insertions(+)

diff --git a/include/tcg/tcg.h b/include/tcg/tcg.h
index 82b4625773..e49574b7c7 100644
--- a/include/tcg/tcg.h
+++ b/include/tcg/tcg.h
@@ -564,6 +564,9 @@ struct TCGContext {
     uint16_t gen_insn_end_off[TCG_MAX_INSNS];
     uint64_t *gen_insn_data;
 
+    /* Used by TBStatistics */
+    int orig_nb_ops;
+
     /* Exit to translator on overflow. */
     sigjmp_buf jmp_trans;
 };
diff --git a/tcg/tcg.c b/tcg/tcg.c
index 71c25f1974..e90b0a0c69 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -5924,6 +5924,8 @@ int tcg_gen_code(TCGContext *s, TranslationBlock *tb, uint64_t pc_start)
     int i, start_words, num_insns;
     TCGOp *op;
 
+    s->orig_nb_ops = s->nb_ops;
+
     if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP)
                  && qemu_log_in_addr_range(pc_start))) {
         FILE *logfile = qemu_log_trylock();
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH v17 03/16] tcg: Record nb_deleted_ops in TCGContext
  2023-10-03 18:30 [PATCH v17 00/16] TCG code quality tracking Richard Henderson
  2023-10-03 18:30 ` [PATCH v17 01/16] accel/tcg: Move HMP info jit and info opcount code Richard Henderson
  2023-10-03 18:30 ` [PATCH v17 02/16] tcg: Record orig_nb_ops TCGContext Richard Henderson
@ 2023-10-03 18:30 ` Richard Henderson
  2023-10-15 12:58   ` Alex Bennée
  2023-10-03 18:30 ` [PATCH v17 04/16] tcg: Record nb_spills " Richard Henderson
                   ` (13 subsequent siblings)
  16 siblings, 1 reply; 39+ messages in thread
From: Richard Henderson @ 2023-10-03 18:30 UTC (permalink / raw)
  To: qemu-devel; +Cc: fei2.wu

Record the number of ops that are removed during optimization.
To be copied into TBStatistics when desired.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 include/tcg/tcg.h | 1 +
 tcg/tcg.c         | 2 ++
 2 files changed, 3 insertions(+)

diff --git a/include/tcg/tcg.h b/include/tcg/tcg.h
index e49574b7c7..d60349878f 100644
--- a/include/tcg/tcg.h
+++ b/include/tcg/tcg.h
@@ -566,6 +566,7 @@ struct TCGContext {
 
     /* Used by TBStatistics */
     int orig_nb_ops;
+    int nb_deleted_ops;
 
     /* Exit to translator on overflow. */
     sigjmp_buf jmp_trans;
diff --git a/tcg/tcg.c b/tcg/tcg.c
index e90b0a0c69..60be2f429c 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -1494,6 +1494,7 @@ void tcg_func_start(TCGContext *s)
 
     s->nb_ops = 0;
     s->nb_labels = 0;
+    s->nb_deleted_ops = 0;
     s->current_frame_offset = s->frame_start;
 
 #ifdef CONFIG_DEBUG_TCG
@@ -3049,6 +3050,7 @@ 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--;
+    s->nb_deleted_ops++;
 }
 
 void tcg_remove_ops_after(TCGOp *op)
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH v17 04/16] tcg: Record nb_spills in TCGContext
  2023-10-03 18:30 [PATCH v17 00/16] TCG code quality tracking Richard Henderson
                   ` (2 preceding siblings ...)
  2023-10-03 18:30 ` [PATCH v17 03/16] tcg: Record nb_deleted_ops in TCGContext Richard Henderson
@ 2023-10-03 18:30 ` Richard Henderson
  2023-10-15 12:59   ` Alex Bennée
  2023-10-03 18:30 ` [PATCH v17 05/16] accel/tcg: Add TBStatistics structure Richard Henderson
                   ` (12 subsequent siblings)
  16 siblings, 1 reply; 39+ messages in thread
From: Richard Henderson @ 2023-10-03 18:30 UTC (permalink / raw)
  To: qemu-devel; +Cc: fei2.wu

Record the number of times a temporary is forced into memory
and the store would not have been required if there an infinite
number of call-saved cpu registers available.  This excludes
stores that are required by semantics to return computed values
to their home slot in ENV, i.e. NEED_SYNC_ARG.

To be copied into TBStatistics when desired.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 include/tcg/tcg.h |  1 +
 tcg/tcg.c         | 36 +++++++++++++++++++++++-------------
 2 files changed, 24 insertions(+), 13 deletions(-)

diff --git a/include/tcg/tcg.h b/include/tcg/tcg.h
index d60349878f..c2b1a2e187 100644
--- a/include/tcg/tcg.h
+++ b/include/tcg/tcg.h
@@ -567,6 +567,7 @@ struct TCGContext {
     /* Used by TBStatistics */
     int orig_nb_ops;
     int nb_deleted_ops;
+    int nb_spills;
 
     /* Exit to translator on overflow. */
     sigjmp_buf jmp_trans;
diff --git a/tcg/tcg.c b/tcg/tcg.c
index 60be2f429c..471e5eaad9 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -1495,6 +1495,7 @@ void tcg_func_start(TCGContext *s)
     s->nb_ops = 0;
     s->nb_labels = 0;
     s->nb_deleted_ops = 0;
+    s->nb_spills = 0;
     s->current_frame_offset = s->frame_start;
 
 #ifdef CONFIG_DEBUG_TCG
@@ -4118,8 +4119,11 @@ static inline void temp_dead(TCGContext *s, TCGTemp *ts)
    is non-zero, subsequently release the temporary; if it is positive, the
    temp is dead; if it is negative, the temp is free.  */
 static void temp_sync(TCGContext *s, TCGTemp *ts, TCGRegSet allocated_regs,
-                      TCGRegSet preferred_regs, int free_or_dead)
+                      TCGRegSet preferred_regs, int free_or_dead,
+                      bool account_spill)
 {
+    bool did_spill = false;
+
     if (!temp_readonly(ts) && !ts->mem_coherent) {
         if (!ts->mem_allocated) {
             temp_allocate_frame(s, ts);
@@ -4132,6 +4136,7 @@ static void temp_sync(TCGContext *s, TCGTemp *ts, TCGRegSet allocated_regs,
             if (free_or_dead
                 && tcg_out_sti(s, ts->type, ts->val,
                                ts->mem_base->reg, ts->mem_offset)) {
+                did_spill = account_spill;
                 break;
             }
             temp_load(s, ts, tcg_target_available_regs[ts->type],
@@ -4139,6 +4144,7 @@ static void temp_sync(TCGContext *s, TCGTemp *ts, TCGRegSet allocated_regs,
             /* fallthrough */
 
         case TEMP_VAL_REG:
+            did_spill = account_spill;
             tcg_out_st(s, ts->type, ts->reg,
                        ts->mem_base->reg, ts->mem_offset);
             break;
@@ -4155,6 +4161,9 @@ static void temp_sync(TCGContext *s, TCGTemp *ts, TCGRegSet allocated_regs,
     if (free_or_dead) {
         temp_free_or_dead(s, ts, free_or_dead);
     }
+    if (did_spill) {
+        s->nb_spills += 1;
+    }
 }
 
 /* free register 'reg' by spilling the corresponding temporary if necessary */
@@ -4162,7 +4171,7 @@ static void tcg_reg_free(TCGContext *s, TCGReg reg, TCGRegSet allocated_regs)
 {
     TCGTemp *ts = s->reg_to_temp[reg];
     if (ts != NULL) {
-        temp_sync(s, ts, allocated_regs, 0, -1);
+        temp_sync(s, ts, allocated_regs, 0, -1, true);
     }
 }
 
@@ -4442,7 +4451,8 @@ static void tcg_reg_alloc_do_movi(TCGContext *s, TCGTemp *ots,
     ots->val = val;
     ots->mem_coherent = 0;
     if (NEED_SYNC_ARG(0)) {
-        temp_sync(s, ots, s->reserved_regs, preferred_regs, IS_DEAD_ARG(0));
+        temp_sync(s, ots, s->reserved_regs, preferred_regs,
+                  IS_DEAD_ARG(0), false);
     } else if (IS_DEAD_ARG(0)) {
         temp_dead(s, ots);
     }
@@ -4544,7 +4554,7 @@ static void tcg_reg_alloc_mov(TCGContext *s, const TCGOp *op)
     ots->mem_coherent = 0;
 
     if (NEED_SYNC_ARG(0)) {
-        temp_sync(s, ots, allocated_regs, 0, 0);
+        temp_sync(s, ots, allocated_regs, 0, 0, false);
     }
 }
 
@@ -4621,7 +4631,7 @@ static void tcg_reg_alloc_dup(TCGContext *s, const TCGOp *op)
                 break;
             }
             /* Sync the temp back to its slot and load from there.  */
-            temp_sync(s, its, s->reserved_regs, 0, 0);
+            temp_sync(s, its, s->reserved_regs, 0, 0, true);
         }
         /* fall through */
 
@@ -4652,7 +4662,7 @@ static void tcg_reg_alloc_dup(TCGContext *s, const TCGOp *op)
         temp_dead(s, its);
     }
     if (NEED_SYNC_ARG(0)) {
-        temp_sync(s, ots, s->reserved_regs, 0, 0);
+        temp_sync(s, ots, s->reserved_regs, 0, 0, false);
     }
     if (IS_DEAD_ARG(0)) {
         temp_dead(s, ots);
@@ -4870,7 +4880,7 @@ static void tcg_reg_alloc_op(TCGContext *s, const TCGOp *op)
                  * Cross register class move not supported.  Sync the
                  * temp back to its slot and load from there.
                  */
-                temp_sync(s, ts, i_allocated_regs, 0, 0);
+                temp_sync(s, ts, i_allocated_regs, 0, 0, true);
                 tcg_out_ld(s, ts->type, reg,
                            ts->mem_base->reg, ts->mem_offset);
             }
@@ -5019,7 +5029,7 @@ static void tcg_reg_alloc_op(TCGContext *s, const TCGOp *op)
         tcg_debug_assert(!temp_readonly(ts));
 
         if (NEED_SYNC_ARG(i)) {
-            temp_sync(s, ts, o_allocated_regs, 0, IS_DEAD_ARG(i));
+            temp_sync(s, ts, o_allocated_regs, 0, IS_DEAD_ARG(i), false);
         } else if (IS_DEAD_ARG(i)) {
             temp_dead(s, ts);
         }
@@ -5086,8 +5096,8 @@ static bool tcg_reg_alloc_dup2(TCGContext *s, const TCGOp *op)
         itsl == itsh + (HOST_BIG_ENDIAN ? 1 : -1)) {
         TCGTemp *its = itsl - HOST_BIG_ENDIAN;
 
-        temp_sync(s, its + 0, s->reserved_regs, 0, 0);
-        temp_sync(s, its + 1, s->reserved_regs, 0, 0);
+        temp_sync(s, its + 0, s->reserved_regs, 0, 0, true);
+        temp_sync(s, its + 1, s->reserved_regs, 0, 0, true);
 
         if (tcg_out_dupm_vec(s, vtype, MO_64, ots->reg,
                              its->mem_base->reg, its->mem_offset)) {
@@ -5107,7 +5117,7 @@ static bool tcg_reg_alloc_dup2(TCGContext *s, const TCGOp *op)
         temp_dead(s, itsh);
     }
     if (NEED_SYNC_ARG(0)) {
-        temp_sync(s, ots, s->reserved_regs, 0, IS_DEAD_ARG(0));
+        temp_sync(s, ots, s->reserved_regs, 0, IS_DEAD_ARG(0), false);
     } else if (IS_DEAD_ARG(0)) {
         temp_dead(s, ots);
     }
@@ -5125,7 +5135,7 @@ static void load_arg_reg(TCGContext *s, TCGReg reg, TCGTemp *ts,
                  * Cross register class move not supported.  Sync the
                  * temp back to its slot and load from there.
                  */
-                temp_sync(s, ts, allocated_regs, 0, 0);
+                temp_sync(s, ts, allocated_regs, 0, 0, true);
                 tcg_out_ld(s, ts->type, reg,
                            ts->mem_base->reg, ts->mem_offset);
             }
@@ -5307,7 +5317,7 @@ static void tcg_reg_alloc_call(TCGContext *s, TCGOp *op)
     for (i = 0; i < nb_oargs; i++) {
         TCGTemp *ts = arg_temp(op->args[i]);
         if (NEED_SYNC_ARG(i)) {
-            temp_sync(s, ts, s->reserved_regs, 0, IS_DEAD_ARG(i));
+            temp_sync(s, ts, s->reserved_regs, 0, IS_DEAD_ARG(i), false);
         } else if (IS_DEAD_ARG(i)) {
             temp_dead(s, ts);
         }
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH v17 05/16] accel/tcg: Add TBStatistics structure
  2023-10-03 18:30 [PATCH v17 00/16] TCG code quality tracking Richard Henderson
                   ` (3 preceding siblings ...)
  2023-10-03 18:30 ` [PATCH v17 04/16] tcg: Record nb_spills " Richard Henderson
@ 2023-10-03 18:30 ` Richard Henderson
  2023-10-16 14:38   ` Alex Bennée
  2023-10-03 18:30 ` [PATCH v17 06/16] accel/tcg: Collect TB execution statistics Richard Henderson
                   ` (11 subsequent siblings)
  16 siblings, 1 reply; 39+ messages in thread
From: Richard Henderson @ 2023-10-03 18:30 UTC (permalink / raw)
  To: qemu-devel; +Cc: fei2.wu, Vanderson M . do Rosario

Add code to allocate, reset, and free the structures along
with their corresponding TranslationBlocks.  We do not yet
collect, display, or enable the statistics.

Signed-off-by: Vanderson M. do Rosario <vandersonmr2@gmail.com>
Signed-off-by: Fei Wu <fei2.wu@intel.com>
[rth: Significantly reorganized.]
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 accel/tcg/tb-context.h           |   2 +-
 include/exec/translation-block.h |   3 +
 include/qemu/typedefs.h          |   1 +
 include/tcg/tb-stats.h           | 132 +++++++++++++++++++++++++++++++
 accel/tcg/tb-maint.c             |   3 +-
 accel/tcg/tb-stats.c             |  85 ++++++++++++++++++++
 accel/tcg/translate-all.c        |  19 +++++
 accel/tcg/meson.build            |   1 +
 8 files changed, 244 insertions(+), 2 deletions(-)
 create mode 100644 include/tcg/tb-stats.h
 create mode 100644 accel/tcg/tb-stats.c

diff --git a/accel/tcg/tb-context.h b/accel/tcg/tb-context.h
index cac62d9749..4b1abe392b 100644
--- a/accel/tcg/tb-context.h
+++ b/accel/tcg/tb-context.h
@@ -29,8 +29,8 @@
 typedef struct TBContext TBContext;
 
 struct TBContext {
-
     struct qht htable;
+    struct qht stats;
 
     /* statistics */
     unsigned tb_flush_count;
diff --git a/include/exec/translation-block.h b/include/exec/translation-block.h
index b785751774..4206a72600 100644
--- a/include/exec/translation-block.h
+++ b/include/exec/translation-block.h
@@ -141,6 +141,9 @@ struct TranslationBlock {
     uintptr_t jmp_list_head;
     uintptr_t jmp_list_next[2];
     uintptr_t jmp_dest[2];
+
+    /* Pointer to a struct where statistics from the TB is stored */
+    TBStatistics *tb_stats;
 };
 
 /* The alignment given to TranslationBlock during allocation. */
diff --git a/include/qemu/typedefs.h b/include/qemu/typedefs.h
index 5abdbc3874..68011da95b 100644
--- a/include/qemu/typedefs.h
+++ b/include/qemu/typedefs.h
@@ -131,6 +131,7 @@ typedef struct Range Range;
 typedef struct ReservedRegion ReservedRegion;
 typedef struct SHPCDevice SHPCDevice;
 typedef struct SSIBus SSIBus;
+typedef struct TBStatistics TBStatistics;
 typedef struct TCGHelperInfo TCGHelperInfo;
 typedef struct TranslationBlock TranslationBlock;
 typedef struct VirtIODevice VirtIODevice;
diff --git a/include/tcg/tb-stats.h b/include/tcg/tb-stats.h
new file mode 100644
index 0000000000..1ec0d13eff
--- /dev/null
+++ b/include/tcg/tb-stats.h
@@ -0,0 +1,132 @@
+/*
+ * QEMU System Emulator, Code Quality Monitor System
+ *
+ * Copyright (c) 2019 Vanderson M. do Rosario <vandersonmr2@gmail.com>
+ *
+ * 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 TCG_TB_STATS_H
+#define TCG_TB_STATS_H 1
+
+#include "qemu/thread.h"
+#include "exec/translation-block.h"
+
+enum {
+    TB_STATS_EXEC = 1u << 0,
+    TB_STATS_JIT  = 1u << 1,
+
+    TB_STATS_NONE = 0,
+    TB_STATS_ALL  = TB_STATS_EXEC | TB_STATS_JIT,
+};
+
+extern uint32_t tb_stats_enabled;
+
+/**
+ * tb_stats_init:
+ * @flags: TB_STATS_* flags to enable.
+ *
+ * Initialize translation block statistics, enabling @flags.
+ * If @flags is 0, disable all statistics.
+ */
+void tb_stats_init(uint32_t flags);
+
+/*
+ * This struct stores statistics such as execution count of the
+ * TranslationBlocks. Each sets of TBs for a given phys_pc/pc/flags
+ * has its own TBStatistics which will persist over tb_flush.
+ *
+ * We include additional counters to track number of translations as
+ * well as variants for compile flags.
+ */
+struct TBStatistics {
+    tb_page_addr_t phys_pc;
+    vaddr pc;
+    uint32_t flags;
+    uint64_t flags2;
+
+    /* Execution stats */
+    struct {
+        unsigned long normal;
+        unsigned long atomic;
+        /* filled only when dumping x% cover set */
+        double coverage;
+    } executions;
+
+    /* JIT Stats - protected by lock */
+    QemuMutex jit_stats_lock;
+
+    /* Sum of all operations for all translations */
+    struct {
+        unsigned long num_guest_inst;
+        unsigned long num_tcg_ops;
+        unsigned long num_tcg_ops_opt;
+        unsigned long spills;
+
+        unsigned long temps;
+        unsigned long deleted_ops;
+        unsigned long in_len;
+        unsigned long out_len;
+        unsigned long search_out_len;
+    } code;
+
+    struct {
+        unsigned long total;
+        unsigned long spanning;
+    } translations;
+
+    /*
+     * All persistent (cached) TranslationBlocks using
+     * this TBStats structure. Has to be reset on a tb_flush.
+     */
+    GPtrArray *tbs;
+};
+
+/**
+ * tb_stats_enabled:
+ * @tb: TranslationBlock
+ * @f: flag to check
+ *
+ * Return true if any stats are enabled for @tb and
+ * if @f is enabled globally.
+ */
+static inline bool tb_stats_enabled_for_tb(TranslationBlock *tb, uint32_t f)
+{
+    return unlikely(tb_stats_enabled & f) && tb->tb_stats;
+}
+
+/**
+ * tb_stats_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 tb_stats_reset_tbs(void);
+
+/**
+ * tb_stats_lookup:
+ *
+ * If any tb_stats are enabled, return a new or existing struct
+ * for the tuple (phys_pc, pc, flags, flags2).  To be used when
+ * building a new TranslationBlock.
+ */
+TBStatistics *tb_stats_lookup(tb_page_addr_t phys_pc, vaddr pc,
+                              uint32_t flags, uint64_t flags2);
+
+#endif /* TCG_TB_STATS_H */
diff --git a/accel/tcg/tb-maint.c b/accel/tcg/tb-maint.c
index e678d20dc2..9025459fb1 100644
--- a/accel/tcg/tb-maint.c
+++ b/accel/tcg/tb-maint.c
@@ -27,6 +27,7 @@
 #include "exec/translate-all.h"
 #include "sysemu/tcg.h"
 #include "tcg/tcg.h"
+#include "tcg/tb-stats.h"
 #include "tb-hash.h"
 #include "tb-context.h"
 #include "internal-common.h"
@@ -772,7 +773,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();
-
+    tb_stats_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
new file mode 100644
index 0000000000..424c9a90ec
--- /dev/null
+++ b/accel/tcg/tb-stats.c
@@ -0,0 +1,85 @@
+/*
+ * QEMU System Emulator, Code Quality Monitor System
+ *
+ * Copyright (c) 2019 Vanderson M. do Rosario <vandersonmr2@gmail.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/xxhash.h"
+#include "tcg/tb-stats.h"
+#include "tb-context.h"
+
+uint32_t tb_stats_enabled;
+
+static 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->flags == b->flags &&
+           a->flags2 == b->flags2;
+
+}
+
+static void tb_stats_free(void *p, uint32_t hash, void *userp)
+{
+    TBStatistics *s = p;
+
+    qemu_mutex_destroy(&s->jit_stats_lock);
+    g_ptr_array_free(s->tbs, true);
+    g_free(s);
+}
+
+void tb_stats_init(uint32_t flags)
+{
+    tb_stats_enabled = flags;
+    if (flags) {
+        if (!tb_ctx.stats.map) {
+            qht_init(&tb_ctx.stats, tb_stats_cmp,
+                     CODE_GEN_HTABLE_SIZE, QHT_MODE_AUTO_RESIZE);
+        }
+    } else {
+        qht_iter(&tb_ctx.stats, tb_stats_free, NULL);
+        qht_destroy(&tb_ctx.stats);
+    }
+}
+
+static void tb_stats_reset(void *p, uint32_t hash, void *userp)
+{
+    TBStatistics *s = p;
+    g_ptr_array_set_size(s->tbs, 0);
+}
+
+void tb_stats_reset_tbs(void)
+{
+    if (tb_ctx.stats.map) {
+        qht_iter(&tb_ctx.stats, tb_stats_reset, NULL);
+    }
+}
+
+TBStatistics *tb_stats_lookup(tb_page_addr_t phys_pc, vaddr pc,
+                              uint32_t flags, uint64_t flags2)
+{
+    TBStatistics *s;
+    uint32_t h;
+    void *existing;
+
+    s = g_new0(TBStatistics, 1);
+    s->phys_pc = phys_pc;
+    s->pc = pc;
+    s->flags = flags;
+    s->flags2 = flags2;
+    s->tbs = g_ptr_array_new();
+    qemu_mutex_init(&s->jit_stats_lock);
+
+    h = qemu_xxhash7(phys_pc, pc, flags2, flags);
+    if (!qht_insert(&tb_ctx.stats, s, h, &existing)) {
+        tb_stats_free(s, 0, NULL);
+        return existing;
+    }
+    return s;
+}
diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c
index e579b0891d..6e64ae2dbe 100644
--- a/accel/tcg/translate-all.c
+++ b/accel/tcg/translate-all.c
@@ -65,6 +65,7 @@
 #include "internal-target.h"
 #include "perf.h"
 #include "tcg/insn-start-words.h"
+#include "tcg/tb-stats.h"
 
 TBContext tb_ctx;
 
@@ -353,6 +354,24 @@ TranslationBlock *tb_gen_code(CPUState *cpu,
     tcg_ctx->guest_mo = TCG_MO_ALL;
 #endif
 
+    /*
+     * Insert the TB into the corresponding stats structure, if required.
+     * Do this before code generation so that translator_loop can see
+     * the structure address.
+     */
+    tb->tb_stats = NULL;
+    if (unlikely(tb_stats_enabled) && qemu_log_in_addr_range(pc)) {
+        TBStatistics *s = tb_stats_lookup(phys_pc,
+                                          cflags & CF_PCREL ? 0 : pc,
+                                          flags, cs_base);
+        if (s) {
+            tb->tb_stats = s;
+            qemu_mutex_lock(&s->jit_stats_lock);
+            g_ptr_array_add(s->tbs, tb);
+            qemu_mutex_unlock(&s->jit_stats_lock);
+        }
+    }
+
  restart_translate:
     trace_translate_block(tb, pc, tb->tc.ptr);
 
diff --git a/accel/tcg/meson.build b/accel/tcg/meson.build
index 8783edd06e..34312f7a8b 100644
--- a/accel/tcg/meson.build
+++ b/accel/tcg/meson.build
@@ -6,6 +6,7 @@ tcg_ss.add(files(
   'tcg-all.c',
   'cpu-exec.c',
   'tb-maint.c',
+  'tb-stats.c',
   'tcg-runtime-gvec.c',
   'tcg-runtime.c',
   'translate-all.c',
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH v17 06/16] accel/tcg: Collect TB execution statistics
  2023-10-03 18:30 [PATCH v17 00/16] TCG code quality tracking Richard Henderson
                   ` (4 preceding siblings ...)
  2023-10-03 18:30 ` [PATCH v17 05/16] accel/tcg: Add TBStatistics structure Richard Henderson
@ 2023-10-03 18:30 ` Richard Henderson
  2023-10-03 18:30 ` [PATCH v17 07/16] accel/tcg: Collect TB jit statistics Richard Henderson
                   ` (10 subsequent siblings)
  16 siblings, 0 replies; 39+ messages in thread
From: Richard Henderson @ 2023-10-03 18:30 UTC (permalink / raw)
  To: qemu-devel; +Cc: fei2.wu, Vanderson M. do Rosario, Alex Bennée

From: "Vanderson M. do Rosario" <vandersonmr2@gmail.com>

Collect atomic and normal execution counts for TBs which
have allocated a stats structure.

Signed-off-by: Vanderson M. do Rosario <vandersonmr2@gmail.com>
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
Signed-off-by: Fei Wu <fei2.wu@intel.com>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 accel/tcg/cpu-exec.c   |  6 ++++++
 accel/tcg/translator.c | 28 ++++++++++++++++++++++++++++
 2 files changed, 34 insertions(+)

diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c
index 1a5bc90220..1114eae5c4 100644
--- a/accel/tcg/cpu-exec.c
+++ b/accel/tcg/cpu-exec.c
@@ -26,6 +26,7 @@
 #include "disas/disas.h"
 #include "exec/exec-all.h"
 #include "tcg/tcg.h"
+#include "tcg/tb-stats.h"
 #include "qemu/atomic.h"
 #include "qemu/rcu.h"
 #include "exec/log.h"
@@ -601,6 +602,11 @@ void cpu_exec_step_atomic(CPUState *cpu)
         }
 
         cpu_exec_enter(cpu);
+
+        if (tb_stats_enabled_for_tb(tb, TB_STATS_EXEC)) {
+            tb->tb_stats->executions.atomic++;
+        }
+
         /* execute the generated code */
         trace_exec_tb(tb, pc);
         cpu_tb_exec(cpu, tb, &tb_exit);
diff --git a/accel/tcg/translator.c b/accel/tcg/translator.c
index e7abcd86c1..eac281b229 100644
--- a/accel/tcg/translator.c
+++ b/accel/tcg/translator.c
@@ -14,6 +14,8 @@
 #include "exec/translator.h"
 #include "exec/plugin-gen.h"
 #include "tcg/tcg-op-common.h"
+#include "tcg/tcg-temp-internal.h"
+#include "tcg/tb-stats.h"
 #include "internal-target.h"
 
 static void set_can_do_io(DisasContextBase *db, bool val)
@@ -112,6 +114,31 @@ static void gen_tb_end(const TranslationBlock *tb, uint32_t cflags,
     }
 }
 
+static void gen_tb_exec_count(TranslationBlock *tb)
+{
+    if (tb_stats_enabled_for_tb(tb, TB_STATS_EXEC)) {
+        TCGv_ptr ptr = tcg_temp_ebb_new_ptr();
+
+        tcg_gen_movi_ptr(ptr, (intptr_t)&tb->tb_stats->executions.normal);
+        if (sizeof(tb->tb_stats->executions.normal) == 4) {
+            TCGv_i32 t = tcg_temp_ebb_new_i32();
+            tcg_gen_ld_i32(t, ptr, 0);
+            tcg_gen_addi_i32(t, t, 1);
+            tcg_gen_st_i32(t, ptr, 0);
+            tcg_temp_free_i32(t);
+        } else if (sizeof(tb->tb_stats->executions.normal) == 8) {
+            TCGv_i64 t = tcg_temp_ebb_new_i64();
+            tcg_gen_ld_i64(t, ptr, 0);
+            tcg_gen_addi_i64(t, t, 1);
+            tcg_gen_st_i64(t, ptr, 0);
+            tcg_temp_free_i64(t);
+        } else {
+            qemu_build_not_reached_always();
+        }
+        tcg_temp_free_ptr(ptr);
+    }
+}
+
 bool translator_use_goto_tb(DisasContextBase *db, vaddr dest)
 {
     /* Suppress goto_tb if requested. */
@@ -148,6 +175,7 @@ void translator_loop(CPUState *cpu, TranslationBlock *tb, int *max_insns,
 
     /* Start translating.  */
     icount_start_insn = gen_tb_start(db, cflags);
+    gen_tb_exec_count(tb);
     ops->tb_start(db, cpu);
     tcg_debug_assert(db->is_jmp == DISAS_NEXT);  /* no early exit */
 
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH v17 07/16] accel/tcg: Collect TB jit statistics
  2023-10-03 18:30 [PATCH v17 00/16] TCG code quality tracking Richard Henderson
                   ` (5 preceding siblings ...)
  2023-10-03 18:30 ` [PATCH v17 06/16] accel/tcg: Collect TB execution statistics Richard Henderson
@ 2023-10-03 18:30 ` Richard Henderson
  2023-10-10 12:13   ` Philippe Mathieu-Daudé
  2023-10-03 18:30 ` [PATCH v17 08/16] accel/tcg: Add tb_stats hmp command Richard Henderson
                   ` (9 subsequent siblings)
  16 siblings, 1 reply; 39+ messages in thread
From: Richard Henderson @ 2023-10-03 18:30 UTC (permalink / raw)
  To: qemu-devel; +Cc: fei2.wu, Vanderson M . do Rosario, Alex Bennée

Collect items like input and output code size, guest instruction count,
intermediate ops, spills, etc.

Signed-off-by: Vanderson M. do Rosario <vandersonmr2@gmail.com>
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
Signed-off-by: Fei Wu <fei2.wu@intel.com>
[rth: Consolidated at the end of translation.]
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 accel/tcg/translate-all.c | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)

diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c
index 6e64ae2dbe..ad4538f169 100644
--- a/accel/tcg/translate-all.c
+++ b/accel/tcg/translate-all.c
@@ -557,6 +557,27 @@ TranslationBlock *tb_gen_code(CPUState *cpu,
         return tb;
     }
 
+    /* Record JIT statistics, if required. */
+    if (unlikely(tb_stats_enabled & TB_STATS_JIT)) {
+        TBStatistics *s = tb->tb_stats;
+        if (s) {
+            s->code.num_tcg_ops += tcg_ctx->orig_nb_ops;
+            s->code.num_tcg_ops_opt += tcg_ctx->nb_ops;
+            s->code.temps += tcg_ctx->nb_temps;
+            s->code.deleted_ops += tcg_ctx->nb_deleted_ops;
+            s->code.spills += tcg_ctx->nb_spills;
+
+            s->code.num_guest_inst += tb->icount;
+            s->code.in_len += tb->size;
+            s->code.out_len += tb->tc.size;
+            s->code.search_out_len += search_size;
+            s->translations.total += 1;
+            if (tb_page_addr1(tb) != -1) {
+                s->translations.spanning += 1;
+            }
+        }
+    }
+
     /*
      * Insert TB into the corresponding region tree before publishing it
      * through QHT. Otherwise rewinding happened in the TB might fail to
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH v17 08/16] accel/tcg: Add tb_stats hmp command
  2023-10-03 18:30 [PATCH v17 00/16] TCG code quality tracking Richard Henderson
                   ` (6 preceding siblings ...)
  2023-10-03 18:30 ` [PATCH v17 07/16] accel/tcg: Collect TB jit statistics Richard Henderson
@ 2023-10-03 18:30 ` Richard Henderson
  2023-10-03 18:30 ` [PATCH v17 09/16] util/log: Add Error argument to qemu_str_to_log_mask Richard Henderson
                   ` (8 subsequent siblings)
  16 siblings, 0 replies; 39+ messages in thread
From: Richard Henderson @ 2023-10-03 18:30 UTC (permalink / raw)
  To: qemu-devel
  Cc: fei2.wu, Vanderson M. do Rosario, Dr . David Alan Gilbert,
	Alex Bennée

From: "Vanderson M. do Rosario" <vandersonmr2@gmail.com>

Add tb_stats [start|stop|status] command to hmp.
This allows controlling the collection of statistics.

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 considered worthwhile.

Acked-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
Signed-off-by: Vanderson M. do Rosario <vandersonmr2@gmail.com>
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
Signed-off-by: Fei Wu <fei2.wu@intel.com>
[rth: Significantly reorganized.]
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 accel/tcg/monitor.c | 70 ++++++++++++++++++++++++++++++++++++++++++++-
 hmp-commands.hx     | 15 ++++++++++
 2 files changed, 84 insertions(+), 1 deletion(-)

diff --git a/accel/tcg/monitor.c b/accel/tcg/monitor.c
index 093efe9714..370fea883c 100644
--- a/accel/tcg/monitor.c
+++ b/accel/tcg/monitor.c
@@ -12,11 +12,15 @@
 #include "qapi/error.h"
 #include "qapi/type-helpers.h"
 #include "qapi/qapi-commands-machine.h"
+#include "qapi/qmp/qdict.h"
 #include "monitor/monitor.h"
+#include "monitor/hmp.h"
 #include "sysemu/cpus.h"
 #include "sysemu/cpu-timers.h"
 #include "sysemu/tcg.h"
 #include "tcg/tcg.h"
+#include "tcg/tb-stats.h"
+#include "exec/tb-flush.h"
 #include "internal-common.h"
 #include "tb-context.h"
 
@@ -235,10 +239,74 @@ HumanReadableText *qmp_x_query_opcount(Error **errp)
     return human_readable_text_from_str(buf);
 }
 
+static void tb_stats_init_safe(CPUState *cpu, run_on_cpu_data icmd)
+{
+    uint32_t flags = icmd.host_int;
+
+    tb_stats_init(flags);
+    tb_flush(cpu);
+}
+
+static void hmp_tbstats(Monitor *mon, const QDict *qdict)
+{
+    uint32_t flags = TB_STATS_NONE;
+    const char *cmd;
+
+    if (!tcg_enabled()) {
+        monitor_printf(mon, "Only available with accel=tcg\n");
+        return;
+    }
+
+    cmd = qdict_get_try_str(qdict, "command");
+
+    if (strcmp(cmd, "start") == 0) {
+        const char *sflag = qdict_get_try_str(qdict, "flag");
+
+        flags = TB_STATS_ALL;
+        if (sflag) {
+            if (strcmp(sflag, "all") == 0) {
+                flags = TB_STATS_ALL;
+            } else if (strcmp(sflag, "jit") == 0) {
+                flags = TB_STATS_JIT;
+            } else if (strcmp(sflag, "exec") == 0) {
+                flags = TB_STATS_EXEC;
+            } else {
+                monitor_printf(mon, "Invalid argument to tb_stats start\n");
+                return;
+            }
+        }
+
+        if (tb_stats_enabled) {
+            monitor_printf(mon, "TB statistics already being recorded\n");
+            return;
+        }
+    } else if (strcmp(cmd, "stop") == 0) {
+        if (!tb_stats_enabled) {
+            monitor_printf(mon, "TB statistics not being recorded\n");
+            return;
+        }
+    } else if (strcmp(cmd, "status") == 0) {
+        if (tb_stats_enabled) {
+            monitor_printf(mon, "TB statistics are enabled:%s%s\n",
+                           tb_stats_enabled & TB_STATS_EXEC ? " EXEC" : "",
+                           tb_stats_enabled & TB_STATS_JIT ? " JIT" : "");
+        } else {
+            monitor_printf(mon, "TB statistics are disabled\n");
+        }
+        return;
+    } else {
+        monitor_printf(mon, "Invalid command\n");
+        return;
+    }
+
+    async_safe_run_on_cpu(first_cpu, tb_stats_init_safe,
+                          RUN_ON_CPU_HOST_INT(flags));
+}
+
 static void hmp_tcg_register(void)
 {
     monitor_register_hmp_info_hrt("jit", qmp_x_query_jit);
     monitor_register_hmp_info_hrt("opcount", qmp_x_query_opcount);
+    monitor_register_hmp("tb_stats", false, hmp_tbstats);
 }
-
 type_init(hmp_tcg_register);
diff --git a/hmp-commands.hx b/hmp-commands.hx
index 63eac22734..e1d78ab69d 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -1673,6 +1673,21 @@ SRST
   Executes a qemu-io command on the given block device.
 ERST
 
+#if defined(CONFIG_TCG)
+    {
+        .name       = "tb_stats",
+        .args_type  = "command:s,flag:s?",
+        .params     = "command [flag]",
+        .help       = "Control tb statistics collection:"
+                        "tb_stats (start|stop|status) [all|jit|exec]",
+    },
+#endif
+
+SRST
+``tb_stats`` *command* *flag*
+  Control recording tb statistics
+ERST
+
     {
         .name       = "qom-list",
         .args_type  = "path:s?",
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH v17 09/16] util/log: Add Error argument to qemu_str_to_log_mask
  2023-10-03 18:30 [PATCH v17 00/16] TCG code quality tracking Richard Henderson
                   ` (7 preceding siblings ...)
  2023-10-03 18:30 ` [PATCH v17 08/16] accel/tcg: Add tb_stats hmp command Richard Henderson
@ 2023-10-03 18:30 ` Richard Henderson
  2023-10-10 12:55   ` Markus Armbruster
  2023-10-03 18:30 ` [PATCH v17 10/16] util/log: Add -d tb_stats Richard Henderson
                   ` (7 subsequent siblings)
  16 siblings, 1 reply; 39+ messages in thread
From: Richard Henderson @ 2023-10-03 18:30 UTC (permalink / raw)
  To: qemu-devel; +Cc: fei2.wu

Do not rely on return value of 0 to indicate error,
pass along an Error pointer to be set.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 include/qemu/log.h | 2 +-
 bsd-user/main.c    | 6 ++++--
 linux-user/main.c  | 7 +++++--
 monitor/hmp-cmds.c | 5 +++--
 softmmu/vl.c       | 7 +++++--
 util/log.c         | 5 +++--
 6 files changed, 21 insertions(+), 11 deletions(-)

diff --git a/include/qemu/log.h b/include/qemu/log.h
index df59bfabcd..9b92d2663e 100644
--- a/include/qemu/log.h
+++ b/include/qemu/log.h
@@ -87,7 +87,7 @@ 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_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);
+int qemu_str_to_log_mask(const char *str, Error **errp);
 
 /* Print a usage message listing all the valid logging categories
  * to the specified FILE*.
diff --git a/bsd-user/main.c b/bsd-user/main.c
index 703f3e2c41..a981239a0b 100644
--- a/bsd-user/main.c
+++ b/bsd-user/main.c
@@ -411,8 +411,10 @@ int main(int argc, char **argv)
     {
         int mask = 0;
         if (log_mask) {
-            mask = qemu_str_to_log_mask(log_mask);
-            if (!mask) {
+            Error *err = NULL;
+            mask = qemu_str_to_log_mask(log_mask, &err);
+            if (err) {
+                error_report_err(err);
                 qemu_print_log_usage(stdout);
                 exit(1);
             }
diff --git a/linux-user/main.c b/linux-user/main.c
index 0c23584a96..d0464736cc 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -264,8 +264,11 @@ static void handle_arg_help(const char *arg)
 
 static void handle_arg_log(const char *arg)
 {
-    last_log_mask = qemu_str_to_log_mask(arg);
-    if (!last_log_mask) {
+    Error *err = NULL;
+
+    last_log_mask = qemu_str_to_log_mask(arg, &err);
+    if (err) {
+        error_report_err(err);
         qemu_print_log_usage(stdout);
         exit(EXIT_FAILURE);
     }
diff --git a/monitor/hmp-cmds.c b/monitor/hmp-cmds.c
index 6c559b48c8..c4bd97d467 100644
--- a/monitor/hmp-cmds.c
+++ b/monitor/hmp-cmds.c
@@ -291,8 +291,9 @@ void hmp_log(Monitor *mon, const QDict *qdict)
     if (!strcmp(items, "none")) {
         mask = 0;
     } else {
-        mask = qemu_str_to_log_mask(items);
-        if (!mask) {
+        mask = qemu_str_to_log_mask(items, &err);
+        if (err) {
+            error_free(err);
             hmp_help_cmd(mon, "log");
             return;
         }
diff --git a/softmmu/vl.c b/softmmu/vl.c
index 98e071e63b..02193696b9 100644
--- a/softmmu/vl.c
+++ b/softmmu/vl.c
@@ -2486,8 +2486,11 @@ static void qemu_process_early_options(void)
     {
         int mask = 0;
         if (log_mask) {
-            mask = qemu_str_to_log_mask(log_mask);
-            if (!mask) {
+            Error *err = NULL;
+
+            mask = qemu_str_to_log_mask(log_mask, &err);
+            if (err) {
+                error_report_err(err);
                 qemu_print_log_usage(stdout);
                 exit(1);
             }
diff --git a/util/log.c b/util/log.c
index def88a9402..b5f08db202 100644
--- a/util/log.c
+++ b/util/log.c
@@ -500,8 +500,8 @@ const QEMULogItem qemu_log_items[] = {
     { 0, NULL, NULL },
 };
 
-/* takes a comma separated list of log masks. Return 0 if error. */
-int qemu_str_to_log_mask(const char *str)
+/* Takes a comma separated list of log masks. */
+int qemu_str_to_log_mask(const char *str, Error **errp)
 {
     const QEMULogItem *item;
     int mask = 0;
@@ -524,6 +524,7 @@ int qemu_str_to_log_mask(const char *str)
                     goto found;
                 }
             }
+            error_setg(errp, "Invalid -d option \"%s\"", *tmp);
             goto error;
         found:
             mask |= item->mask;
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH v17 10/16] util/log: Add -d tb_stats
  2023-10-03 18:30 [PATCH v17 00/16] TCG code quality tracking Richard Henderson
                   ` (8 preceding siblings ...)
  2023-10-03 18:30 ` [PATCH v17 09/16] util/log: Add Error argument to qemu_str_to_log_mask Richard Henderson
@ 2023-10-03 18:30 ` Richard Henderson
  2023-10-10 12:34   ` Philippe Mathieu-Daudé
  2023-10-03 18:30 ` [PATCH v17 11/16] accel/tcg: Add tb_stats_collect and tb_stats_dump Richard Henderson
                   ` (6 subsequent siblings)
  16 siblings, 1 reply; 39+ messages in thread
From: Richard Henderson @ 2023-10-03 18:30 UTC (permalink / raw)
  To: qemu-devel; +Cc: fei2.wu, Vanderson M . do Rosario, Alex Bennée

From: Fei Wu <fei2.wu@intel.com>

Enable TBStatistics collection from startup.

Signed-off-by: Vanderson M. do Rosario <vandersonmr2@gmail.com>
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
Signed-off-by: Fei Wu <fei2.wu@intel.com>
[rth: Change "tb_stats_foo" to "tb_stats:foo"]
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 stubs/tb-stats.c  | 16 ++++++++++++++++
 util/log.c        | 36 +++++++++++++++++++++++++++++++-----
 stubs/meson.build |  1 +
 3 files changed, 48 insertions(+), 5 deletions(-)
 create mode 100644 stubs/tb-stats.c

diff --git a/stubs/tb-stats.c b/stubs/tb-stats.c
new file mode 100644
index 0000000000..ceaa1622ce
--- /dev/null
+++ b/stubs/tb-stats.c
@@ -0,0 +1,16 @@
+/*
+ * TB Stats Stubs
+ *
+ * Copyright (c) 2019
+ * Written by Alex Bennée <alex.bennee@linaro.org>
+ *
+ * This code is licensed under the GNU GPL v2, or later.
+ */
+
+
+#include "qemu/osdep.h"
+#include "tcg/tb-stats.h"
+
+void tb_stats_init(uint32_t flags)
+{
+}
diff --git a/util/log.c b/util/log.c
index b5f08db202..0cb987fb74 100644
--- a/util/log.c
+++ b/util/log.c
@@ -30,6 +30,9 @@
 #ifdef CONFIG_LINUX
 #include <sys/syscall.h>
 #endif
+#ifdef CONFIG_TCG
+#include "tcg/tb-stats.h"
+#endif
 
 
 typedef struct RCUCloseFILE {
@@ -509,22 +512,41 @@ int qemu_str_to_log_mask(const char *str, Error **errp)
     char **tmp;
 
     for (tmp = parts; tmp && *tmp; tmp++) {
-        if (g_str_equal(*tmp, "all")) {
+        char *t = *tmp;
+
+        if (g_str_equal(t, "all")) {
             for (item = qemu_log_items; item->mask != 0; item++) {
                 mask |= item->mask;
             }
 #ifdef CONFIG_TRACE_LOG
-        } else if (g_str_has_prefix(*tmp, "trace:") && (*tmp)[6] != '\0') {
-            trace_enable_events((*tmp) + 6);
+        } else if (g_str_has_prefix(t, "trace:") && t[6] != '\0') {
+            trace_enable_events(t + 6);
             mask |= LOG_TRACE;
+#endif
+#ifdef CONFIG_TCG
+        } else if (g_str_has_prefix(t, "tb_stats:") && t[9] != '\0') {
+            int flags = TB_STATS_NONE;
+            char *v = t + 9;
+
+            if (g_str_equal(v, "all")) {
+                flags = TB_STATS_ALL;
+            } else if (g_str_equal(v, "jit")) {
+                flags = TB_STATS_JIT;
+            } else if (g_str_equal(v, "exec")) {
+                flags = TB_STATS_EXEC;
+            } else {
+                error_setg(errp, "Invalid -d option \"%s\"", t);
+                goto error;
+            }
+            tb_stats_init(flags);
 #endif
         } else {
             for (item = qemu_log_items; item->mask != 0; item++) {
-                if (g_str_equal(*tmp, item->name)) {
+                if (g_str_equal(t, item->name)) {
                     goto found;
                 }
             }
-            error_setg(errp, "Invalid -d option \"%s\"", *tmp);
+            error_setg(errp, "Invalid -d option \"%s\"", t);
             goto error;
         found:
             mask |= item->mask;
@@ -546,6 +568,10 @@ void qemu_print_log_usage(FILE *f)
     for (item = qemu_log_items; item->mask != 0; item++) {
         fprintf(f, "%-15s %s\n", item->name, item->help);
     }
+#ifdef CONFIG_TCG
+    fprintf(f, "tb_stats:WHICH  enable translation block statistics"
+            " (all, exec, jit)\n");
+#endif
 #ifdef CONFIG_TRACE_LOG
     fprintf(f, "trace:PATTERN   enable trace events\n");
     fprintf(f, "\nUse \"-d trace:help\" to get a list of trace events.\n\n");
diff --git a/stubs/meson.build b/stubs/meson.build
index ef6e39a64d..37ca25ea01 100644
--- a/stubs/meson.build
+++ b/stubs/meson.build
@@ -65,4 +65,5 @@ else
   stub_ss.add(files('qdev.c'))
 endif
 stub_ss.add(files('semihost-all.c'))
+stub_ss.add(files('tb-stats.c'))
 stub_ss.add(when: 'CONFIG_VFIO_USER_SERVER', if_false: files('vfio-user-obj.c'))
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH v17 11/16] accel/tcg: Add tb_stats_collect and tb_stats_dump
  2023-10-03 18:30 [PATCH v17 00/16] TCG code quality tracking Richard Henderson
                   ` (9 preceding siblings ...)
  2023-10-03 18:30 ` [PATCH v17 10/16] util/log: Add -d tb_stats Richard Henderson
@ 2023-10-03 18:30 ` Richard Henderson
  2023-10-16 14:48   ` Alex Bennée
  2023-10-03 18:30 ` [PATCH v17 12/16] softmmu: Export qemu_ram_ptr_length Richard Henderson
                   ` (5 subsequent siblings)
  16 siblings, 1 reply; 39+ messages in thread
From: Richard Henderson @ 2023-10-03 18:30 UTC (permalink / raw)
  To: qemu-devel; +Cc: fei2.wu, Vanderson M. do Rosario, Alex Bennée

From: "Vanderson M. do Rosario" <vandersonmr2@gmail.com>

These functions will be used together to output statistics.

Signed-off-by: Vanderson M. do Rosario <vandersonmr2@gmail.com>
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
Signed-off-by: Fei Wu <fei2.wu@intel.com>
[rth: Split out of a larger patch]
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 include/tcg/tb-stats.h |  25 +++++++++
 accel/tcg/tb-stats.c   | 119 +++++++++++++++++++++++++++++++++++++++++
 2 files changed, 144 insertions(+)

diff --git a/include/tcg/tb-stats.h b/include/tcg/tb-stats.h
index 1ec0d13eff..edee73b63b 100644
--- a/include/tcg/tb-stats.h
+++ b/include/tcg/tb-stats.h
@@ -129,4 +129,29 @@ void tb_stats_reset_tbs(void);
 TBStatistics *tb_stats_lookup(tb_page_addr_t phys_pc, vaddr pc,
                               uint32_t flags, uint64_t flags2);
 
+/**
+ * tb_stats_collect:
+ * @max: maximum number of results
+ * @sort: sort function
+ *
+ * Collect all TBStatistics and return the first @max items,
+ * as dictated by the sort criteria.
+ */
+GPtrArray *tb_stats_collect(unsigned max, GCompareFunc sort);
+
+/* Sort functions for tb_stats_collect. */
+gint tb_stats_sort_by_spills(gconstpointer, gconstpointer);
+gint tb_stats_sort_by_coverage(gconstpointer, gconstpointer);
+gint tb_stats_sort_by_hg(gconstpointer, gconstpointer);
+
+/**
+ * tb_stats_dump:
+ * @s: structure to dump
+ * @index: label to emit
+ *
+ * Return a string with the rendering of the data in @s;
+ * @index is included in the output.
+ */
+GString *tb_stats_dump(TBStatistics *s, unsigned index);
+
 #endif /* TCG_TB_STATS_H */
diff --git a/accel/tcg/tb-stats.c b/accel/tcg/tb-stats.c
index 424c9a90ec..b2c9445b67 100644
--- a/accel/tcg/tb-stats.c
+++ b/accel/tcg/tb-stats.c
@@ -83,3 +83,122 @@ TBStatistics *tb_stats_lookup(tb_page_addr_t phys_pc, vaddr pc,
     }
     return s;
 }
+
+static void tb_stats_collect_iter(void *p, uint32_t hash, void *u)
+{
+    g_ptr_array_add(u, p);
+}
+
+static void calculate_coverages(GPtrArray *array)
+{
+    double total_exec_count = 0;
+    guint i, n = array->len;
+
+    for (i = 0; i < n; ++i) {
+        TBStatistics *s = g_ptr_array_index(array, i);
+        double avg_insns = 1;
+        double exec_count;
+
+        if (s->translations.total) {
+            avg_insns = s->code.num_guest_inst / (double)s->translations.total;
+        }
+        exec_count = ((double)s->executions.atomic + s->executions.normal)
+                     / avg_insns;
+        s->executions.coverage = exec_count;
+        total_exec_count += exec_count;
+    }
+
+    for (i = 0; i < n; ++i) {
+        TBStatistics *s = g_ptr_array_index(array, i);
+        s->executions.coverage /= total_exec_count;
+    }
+}
+
+GPtrArray *tb_stats_collect(unsigned max, GCompareFunc sort)
+{
+    GPtrArray *array = g_ptr_array_new();
+
+    /*
+     * Collect all TBStatistics and sort.
+     * Note that coverage data requires both execution and jit collection.
+     */
+    qht_iter(&tb_ctx.stats, tb_stats_collect_iter, array);
+    calculate_coverages(array);
+    g_ptr_array_sort(array, sort);
+
+    /* Truncate to the first MAX entries. */
+    if (max < array->len) {
+        g_ptr_array_set_size(array, max);
+    }
+    return array;
+}
+
+gint tb_stats_sort_by_spills(gconstpointer p1, gconstpointer p2)
+{
+    const TBStatistics *s1 = *(TBStatistics **)p1;
+    const TBStatistics *s2 = *(TBStatistics **)p2;
+    double c1 = (double)s1->code.spills / s1->translations.total;
+    double c2 = (double)s2->code.spills / s2->translations.total;
+
+    return c1 < c2 ? 1 : c1 == c2 ? 0 : -1;
+}
+
+gint tb_stats_sort_by_coverage(gconstpointer p1, gconstpointer p2)
+{
+    const TBStatistics *s1 = *(TBStatistics **)p1;
+    const TBStatistics *s2 = *(TBStatistics **)p2;
+    double c1 = s1->executions.coverage;
+    double c2 = s2->executions.coverage;
+
+    return c1 < c2 ? 1 : c1 == c2 ? 0 : -1;
+}
+
+gint tb_stats_sort_by_hg(gconstpointer p1, gconstpointer p2)
+{
+    const TBStatistics *s1 = *(TBStatistics **)p1;
+    const TBStatistics *s2 = *(TBStatistics **)p2;
+    double c1 = (double)s1->code.out_len / s1->code.num_guest_inst;
+    double c2 = (double)s2->code.out_len / s2->code.num_guest_inst;
+
+    return c1 < c2 ? 1 : c1 == c2 ? 0 : -1;
+}
+
+GString *tb_stats_dump(TBStatistics *s, unsigned index)
+{
+    unsigned n = s->tbs->len;
+    unsigned invalid = 0;
+    GString *buf;
+
+    for (unsigned i = 0; i < n; ++i) {
+        TranslationBlock *tb = g_ptr_array_index(s->tbs, i);
+        if (tb->cflags & CF_INVALID) {
+            invalid += 1;
+        }
+    }
+
+    buf = g_string_new("");
+    g_string_append_printf(buf,
+        "TB id:%u | phys:0x" TB_PAGE_ADDR_FMT " virt=%" VADDR_PRIx
+        " flags:0x%08x invalid:%u/%u\n",
+        index, s->phys_pc, s->pc, s->flags, invalid, n - invalid);
+
+    if (tb_stats_enabled & TB_STATS_EXEC) {
+        g_string_append_printf(buf,
+            "\t| exec:%lu/%lu coverage:%.2f%%\n",
+            s->executions.normal, s->executions.atomic,
+            s->executions.coverage * 100);
+    }
+
+    if (tb_stats_enabled & TB_STATS_JIT) {
+        g_string_append_printf(buf,
+            "\t| trans:%lu inst: g:%lu op:%lu op_opt:%lu spills:%ld\n"
+            "\t| h/g (host bytes / guest insts): %f\n",
+            s->translations.total,
+            s->code.num_guest_inst / s->translations.total,
+            s->code.num_tcg_ops / s->translations.total,
+            s->code.num_tcg_ops_opt / s->translations.total,
+            s->code.spills / s->translations.total,
+            (double)s->code.out_len / s->code.num_guest_inst);
+    }
+    return buf;
+}
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH v17 12/16] softmmu: Export qemu_ram_ptr_length
  2023-10-03 18:30 [PATCH v17 00/16] TCG code quality tracking Richard Henderson
                   ` (10 preceding siblings ...)
  2023-10-03 18:30 ` [PATCH v17 11/16] accel/tcg: Add tb_stats_collect and tb_stats_dump Richard Henderson
@ 2023-10-03 18:30 ` Richard Henderson
  2023-10-10 12:31   ` Philippe Mathieu-Daudé
  2023-10-03 18:30 ` [PATCH v17 13/16] disas: Allow monitor_disas to read from ram_addr_t Richard Henderson
                   ` (4 subsequent siblings)
  16 siblings, 1 reply; 39+ messages in thread
From: Richard Henderson @ 2023-10-03 18:30 UTC (permalink / raw)
  To: qemu-devel; +Cc: fei2.wu

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 include/exec/memory.h | 2 ++
 softmmu/physmem.c     | 4 ++--
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/include/exec/memory.h b/include/exec/memory.h
index ef23d65afc..ebdecf64a6 100644
--- a/include/exec/memory.h
+++ b/include/exec/memory.h
@@ -2874,6 +2874,8 @@ MemTxResult flatview_read_continue(FlatView *fv, hwaddr addr,
                                    hwaddr len, hwaddr addr1, hwaddr l,
                                    MemoryRegion *mr);
 void *qemu_map_ram_ptr(RAMBlock *ram_block, ram_addr_t addr);
+void *qemu_ram_ptr_length(RAMBlock *ram_block, ram_addr_t addr,
+                          hwaddr *size, bool lock);
 
 /* Internal functions, part of the implementation of address_space_read_cached
  * and address_space_write_cached.  */
diff --git a/softmmu/physmem.c b/softmmu/physmem.c
index 309653c722..69a853c27a 100644
--- a/softmmu/physmem.c
+++ b/softmmu/physmem.c
@@ -2182,8 +2182,8 @@ void *qemu_map_ram_ptr(RAMBlock *ram_block, ram_addr_t addr)
  *
  * Called within RCU critical section.
  */
-static void *qemu_ram_ptr_length(RAMBlock *ram_block, ram_addr_t addr,
-                                 hwaddr *size, bool lock)
+void *qemu_ram_ptr_length(RAMBlock *ram_block, ram_addr_t addr,
+                          hwaddr *size, bool lock)
 {
     RAMBlock *block = ram_block;
     if (*size == 0) {
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH v17 13/16] disas: Allow monitor_disas to read from ram_addr_t
  2023-10-03 18:30 [PATCH v17 00/16] TCG code quality tracking Richard Henderson
                   ` (11 preceding siblings ...)
  2023-10-03 18:30 ` [PATCH v17 12/16] softmmu: Export qemu_ram_ptr_length Richard Henderson
@ 2023-10-03 18:30 ` Richard Henderson
  2023-10-10 12:46   ` Philippe Mathieu-Daudé
  2023-10-03 18:30 ` [PATCH v17 14/16] monitor: Change MonitorDec.get_value return type to int64_t Richard Henderson
                   ` (3 subsequent siblings)
  16 siblings, 1 reply; 39+ messages in thread
From: Richard Henderson @ 2023-10-03 18:30 UTC (permalink / raw)
  To: qemu-devel; +Cc: fei2.wu, Vanderson M. do Rosario, Alex Bennée

From: "Vanderson M. do Rosario" <vandersonmr2@gmail.com>

Introduce a MonitorDisasSpace to replace the current is_physical
boolean argument to monitor_disas.  Generate an error if we attempt
to read past the end of a single RAMBlock.

Signed-off-by: Vanderson M. do Rosario <vandersonmr2@gmail.com>
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
Signed-off-by: Fei Wu <fei2.wu@intel.com>
[rth: Split out of a larger patch; validate the RAMBlock size]
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 include/disas/disas.h     |  8 +++++++-
 disas/disas-mon.c         | 32 ++++++++++++++++++++++++++++++--
 monitor/hmp-cmds-target.c | 27 ++++++++++++++++-----------
 3 files changed, 53 insertions(+), 14 deletions(-)

diff --git a/include/disas/disas.h b/include/disas/disas.h
index 176775eff7..cd99b0ccd0 100644
--- a/include/disas/disas.h
+++ b/include/disas/disas.h
@@ -5,8 +5,14 @@
 void disas(FILE *out, const void *code, size_t size);
 void target_disas(FILE *out, CPUState *cpu, uint64_t code, size_t size);
 
+typedef enum {
+    MON_DISAS_GVA, /* virtual */
+    MON_DISAS_GPA, /* physical */
+    MON_DISAS_GRA, /* ram_addr_t */
+} MonitorDisasSpace;
+
 void monitor_disas(Monitor *mon, CPUState *cpu, uint64_t pc,
-                   int nb_insn, bool is_physical);
+                   int nb_insn, MonitorDisasSpace space);
 
 char *plugin_disas(CPUState *cpu, uint64_t addr, size_t size);
 
diff --git a/disas/disas-mon.c b/disas/disas-mon.c
index 48ac492c6c..d486f64c92 100644
--- a/disas/disas-mon.c
+++ b/disas/disas-mon.c
@@ -23,9 +23,27 @@ physical_read_memory(bfd_vma memaddr, bfd_byte *myaddr, int length,
     return res == MEMTX_OK ? 0 : EIO;
 }
 
+static int
+ram_addr_read_memory(bfd_vma memaddr, bfd_byte *myaddr, int length,
+                     struct disassemble_info *info)
+{
+    hwaddr hw_length;
+    void *p;
+
+    RCU_READ_LOCK_GUARD();
+
+    hw_length = length;
+    p = qemu_ram_ptr_length(NULL, memaddr, &hw_length, false);
+    if (hw_length < length) {
+        return EIO;
+    }
+    memcpy(myaddr, p, length);
+    return 0;
+}
+
 /* Disassembler for the monitor.  */
 void monitor_disas(Monitor *mon, CPUState *cpu, uint64_t pc,
-                   int nb_insn, bool is_physical)
+                   int nb_insn, MonitorDisasSpace space)
 {
     int count, i;
     CPUDebug s;
@@ -35,8 +53,18 @@ void monitor_disas(Monitor *mon, CPUState *cpu, uint64_t pc,
     s.info.fprintf_func = disas_gstring_printf;
     s.info.stream = (FILE *)ds;  /* abuse this slot */
 
-    if (is_physical) {
+    switch (space) {
+    case MON_DISAS_GVA:
+        /* target_read_memory set in disas_initialize_debug_target */
+        break;
+    case MON_DISAS_GPA:
         s.info.read_memory_func = physical_read_memory;
+        break;
+    case MON_DISAS_GRA:
+        s.info.read_memory_func = ram_addr_read_memory;
+        break;
+    default:
+        g_assert_not_reached();
     }
     s.info.buffer_vma = pc;
 
diff --git a/monitor/hmp-cmds-target.c b/monitor/hmp-cmds-target.c
index d9fbcac08d..476cf68e81 100644
--- a/monitor/hmp-cmds-target.c
+++ b/monitor/hmp-cmds-target.c
@@ -120,21 +120,20 @@ void hmp_info_registers(Monitor *mon, const QDict *qdict)
 }
 
 static void memory_dump(Monitor *mon, int count, int format, int wsize,
-                        hwaddr addr, int is_physical)
+                        hwaddr addr, MonitorDisasSpace space)
 {
     int l, line_size, i, max_digits, len;
     uint8_t buf[16];
     uint64_t v;
     CPUState *cs = mon_get_cpu(mon);
 
-    if (!cs && (format == 'i' || !is_physical)) {
+    if (space == MON_DISAS_GVA || format == 'i') {
         monitor_printf(mon, "Can not dump without CPU\n");
         return;
     }
 
     if (format == 'i') {
-        monitor_disas(mon, cs, addr, count, is_physical);
-        return;
+        monitor_disas(mon, cs, addr, count, space);
     }
 
     len = wsize * count;
@@ -163,15 +162,21 @@ static void memory_dump(Monitor *mon, int count, int format, int wsize,
     }
 
     while (len > 0) {
-        if (is_physical) {
-            monitor_printf(mon, HWADDR_FMT_plx ":", addr);
-        } else {
+        switch (space) {
+        case MON_DISAS_GVA:
             monitor_printf(mon, TARGET_FMT_lx ":", (target_ulong)addr);
+            break;
+        case MON_DISAS_GPA:
+            monitor_printf(mon, HWADDR_FMT_plx ":", addr);
+            break;
+        default:
+            g_assert_not_reached();
         }
         l = len;
-        if (l > line_size)
+        if (l > line_size) {
             l = line_size;
-        if (is_physical) {
+        }
+        if (space == MON_DISAS_GPA) {
             AddressSpace *as = cs ? cs->as : &address_space_memory;
             MemTxResult r = address_space_read(as, addr,
                                                MEMTXATTRS_UNSPECIFIED, buf, l);
@@ -235,7 +240,7 @@ void hmp_memory_dump(Monitor *mon, const QDict *qdict)
     int size = qdict_get_int(qdict, "size");
     target_long addr = qdict_get_int(qdict, "addr");
 
-    memory_dump(mon, count, format, size, addr, 0);
+    memory_dump(mon, count, format, size, addr, MON_DISAS_GVA);
 }
 
 void hmp_physical_memory_dump(Monitor *mon, const QDict *qdict)
@@ -245,7 +250,7 @@ void hmp_physical_memory_dump(Monitor *mon, const QDict *qdict)
     int size = qdict_get_int(qdict, "size");
     hwaddr addr = qdict_get_int(qdict, "addr");
 
-    memory_dump(mon, count, format, size, addr, 1);
+    memory_dump(mon, count, format, size, addr, MON_DISAS_GPA);
 }
 
 void *gpa2hva(MemoryRegion **p_mr, hwaddr addr, uint64_t size, Error **errp)
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH v17 14/16] monitor: Change MonitorDec.get_value return type to int64_t
  2023-10-03 18:30 [PATCH v17 00/16] TCG code quality tracking Richard Henderson
                   ` (12 preceding siblings ...)
  2023-10-03 18:30 ` [PATCH v17 13/16] disas: Allow monitor_disas to read from ram_addr_t Richard Henderson
@ 2023-10-03 18:30 ` Richard Henderson
  2023-10-16 14:59   ` Alex Bennée
  2023-10-16 15:43   ` Alex Bennée
  2023-10-03 18:30 ` [PATCH v17 15/16] accel/tcg: Add info [tb-list|tb] commands to HMP Richard Henderson
                   ` (2 subsequent siblings)
  16 siblings, 2 replies; 39+ messages in thread
From: Richard Henderson @ 2023-10-03 18:30 UTC (permalink / raw)
  To: qemu-devel; +Cc: fei2.wu

This matches the type of the pval parameter to get_monitor_def.
This means that "monitor/hmp-target.h" itself is now target
independent, even if monitor/hmp-target.c isn't.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 include/monitor/hmp-target.h |  5 +----
 monitor/hmp-target.c         |  2 ++
 target/i386/monitor.c        |  4 ++--
 target/ppc/ppc-qmp-cmds.c    | 20 ++++++++++----------
 target/sparc/monitor.c       |  8 ++++----
 5 files changed, 19 insertions(+), 20 deletions(-)

diff --git a/include/monitor/hmp-target.h b/include/monitor/hmp-target.h
index d78e979f05..730507bd65 100644
--- a/include/monitor/hmp-target.h
+++ b/include/monitor/hmp-target.h
@@ -25,16 +25,13 @@
 #ifndef MONITOR_HMP_TARGET_H
 #define MONITOR_HMP_TARGET_H
 
-#include "cpu.h"
-
 #define MD_TLONG 0
 #define MD_I32   1
 
 struct MonitorDef {
     const char *name;
     int offset;
-    target_long (*get_value)(Monitor *mon, const struct MonitorDef *md,
-                             int val);
+    int64_t (*get_value)(Monitor *mon, const struct MonitorDef *md, int val);
     int type;
 };
 
diff --git a/monitor/hmp-target.c b/monitor/hmp-target.c
index 1eb72ac1bf..ed7149b5ff 100644
--- a/monitor/hmp-target.c
+++ b/monitor/hmp-target.c
@@ -35,6 +35,8 @@
 #include "qapi/qapi-commands-machine.h"
 #include "qapi/error.h"
 #include "qemu/cutils.h"
+#include "cpu-param.h"
+#include "exec/target_long.h"
 
 #if defined(TARGET_S390X)
 #include "hw/s390x/storage-keys.h"
diff --git a/target/i386/monitor.c b/target/i386/monitor.c
index 6512846327..6759ec7ca0 100644
--- a/target/i386/monitor.c
+++ b/target/i386/monitor.c
@@ -600,8 +600,8 @@ void hmp_mce(Monitor *mon, const QDict *qdict)
     }
 }
 
-static target_long monitor_get_pc(Monitor *mon, const struct MonitorDef *md,
-                                  int val)
+static int64_t monitor_get_pc(Monitor *mon, const struct MonitorDef *md,
+                              int val)
 {
     CPUArchState *env = mon_get_cpu_env(mon);
     return env->eip + env->segs[R_CS].base;
diff --git a/target/ppc/ppc-qmp-cmds.c b/target/ppc/ppc-qmp-cmds.c
index f9acc21056..ea2c152228 100644
--- a/target/ppc/ppc-qmp-cmds.c
+++ b/target/ppc/ppc-qmp-cmds.c
@@ -32,8 +32,8 @@
 #include "cpu-models.h"
 #include "cpu-qom.h"
 
-static target_long monitor_get_ccr(Monitor *mon, const struct MonitorDef *md,
-                                   int val)
+static int64_t monitor_get_ccr(Monitor *mon, const struct MonitorDef *md,
+                               int val)
 {
     CPUArchState *env = mon_get_cpu_env(mon);
     unsigned int u;
@@ -43,15 +43,15 @@ static target_long monitor_get_ccr(Monitor *mon, const struct MonitorDef *md,
     return u;
 }
 
-static target_long monitor_get_xer(Monitor *mon, const struct MonitorDef *md,
-                                   int val)
+static int64_t monitor_get_xer(Monitor *mon, const struct MonitorDef *md,
+                               int val)
 {
     CPUArchState *env = mon_get_cpu_env(mon);
     return cpu_read_xer(env);
 }
 
-static target_long monitor_get_decr(Monitor *mon, const struct MonitorDef *md,
-                                    int val)
+static int64_t monitor_get_decr(Monitor *mon, const struct MonitorDef *md,
+                                int val)
 {
     CPUArchState *env = mon_get_cpu_env(mon);
     if (!env->tb_env) {
@@ -60,8 +60,8 @@ static target_long monitor_get_decr(Monitor *mon, const struct MonitorDef *md,
     return cpu_ppc_load_decr(env);
 }
 
-static target_long monitor_get_tbu(Monitor *mon, const struct MonitorDef *md,
-                                   int val)
+static int64_t monitor_get_tbu(Monitor *mon, const struct MonitorDef *md,
+                               int val)
 {
     CPUArchState *env = mon_get_cpu_env(mon);
     if (!env->tb_env) {
@@ -70,8 +70,8 @@ static target_long monitor_get_tbu(Monitor *mon, const struct MonitorDef *md,
     return cpu_ppc_load_tbu(env);
 }
 
-static target_long monitor_get_tbl(Monitor *mon, const struct MonitorDef *md,
-                                   int val)
+static int64_t monitor_get_tbl(Monitor *mon, const struct MonitorDef *md,
+                               int val)
 {
     CPUArchState *env = mon_get_cpu_env(mon);
     if (!env->tb_env) {
diff --git a/target/sparc/monitor.c b/target/sparc/monitor.c
index 73f15aa272..24cc3dbf68 100644
--- a/target/sparc/monitor.c
+++ b/target/sparc/monitor.c
@@ -40,8 +40,8 @@ void hmp_info_tlb(Monitor *mon, const QDict *qdict)
 }
 
 #ifndef TARGET_SPARC64
-static target_long monitor_get_psr(Monitor *mon, const struct MonitorDef *md,
-                                   int val)
+static int64_t monitor_get_psr(Monitor *mon, const struct MonitorDef *md,
+                               int val)
 {
     CPUArchState *env = mon_get_cpu_env(mon);
 
@@ -49,8 +49,8 @@ static target_long monitor_get_psr(Monitor *mon, const struct MonitorDef *md,
 }
 #endif
 
-static target_long monitor_get_reg(Monitor *mon, const struct MonitorDef *md,
-                                   int val)
+static int64_t monitor_get_reg(Monitor *mon, const struct MonitorDef *md,
+                               int val)
 {
     CPUArchState *env = mon_get_cpu_env(mon);
     return env->regwptr[val];
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH v17 15/16] accel/tcg: Add info [tb-list|tb] commands to HMP
  2023-10-03 18:30 [PATCH v17 00/16] TCG code quality tracking Richard Henderson
                   ` (13 preceding siblings ...)
  2023-10-03 18:30 ` [PATCH v17 14/16] monitor: Change MonitorDec.get_value return type to int64_t Richard Henderson
@ 2023-10-03 18:30 ` Richard Henderson
  2023-10-16 15:02   ` Alex Bennée
  2023-10-03 18:30 ` [PATCH v17 16/16] accel/tcg: Dump hot TBs at the end of the execution Richard Henderson
  2024-11-14  9:28 ` [PATCH v17 00/16] TCG code quality tracking Nikita Shubin
  16 siblings, 1 reply; 39+ messages in thread
From: Richard Henderson @ 2023-10-03 18:30 UTC (permalink / raw)
  To: qemu-devel; +Cc: fei2.wu, Vanderson M. do Rosario, Alex Bennée

From: "Vanderson M. do Rosario" <vandersonmr2@gmail.com>

These commands allow the exploration of TBs generated by the TCG.
Understand which one hotter, with more guest/host instructions,
and examine the guest code.

The goal of this command is to allow the dynamic exploration of
TCG behavior and code quality. Therefore, for now, a corresponding
QMP command is not worthwhile.

Example of output:

------------------------------

TB id:0 | phys:0xa21f562e virt:0x0000000000000000 flags:0x00028010 0 inv/1
        | exec:6171503732/0 guest inst cov:94.77%
        | trans:1 ints: g:8 op:28 op_opt:24 spills:0
        | h/g (host bytes / guest insts): 37.000000

0xa21f562e:  00002797      auipc         a5,8192           # 0xa21f762e
0xa21f5632:  a2278793      addi          a5,a5,-1502
0xa21f5636:  639c          ld            a5,0(a5)
0xa21f5638:  00178713      addi          a4,a5,1
0xa21f563c:  00002797      auipc         a5,8192           # 0xa21f763c
0xa21f5640:  a1478793      addi          a5,a5,-1516
0xa21f5644:  e398          sd            a4,0(a5)
0xa21f5646:  b7e5          j             -24               # 0xa21f562e

Signed-off-by: Vanderson M. do Rosario <vandersonmr2@gmail.com>
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
Signed-off-by: Fei Wu <fei2.wu@intel.com>
[rth: Split out of a larger patch]
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 accel/tcg/tb-context.h |  2 +
 accel/tcg/monitor.c    | 91 ++++++++++++++++++++++++++++++++++++++++++
 accel/tcg/tb-stats.c   |  2 +
 hmp-commands-info.hx   | 14 +++++++
 4 files changed, 109 insertions(+)

diff --git a/accel/tcg/tb-context.h b/accel/tcg/tb-context.h
index 4b1abe392b..29d87200b6 100644
--- a/accel/tcg/tb-context.h
+++ b/accel/tcg/tb-context.h
@@ -35,6 +35,8 @@ struct TBContext {
     /* statistics */
     unsigned tb_flush_count;
     unsigned tb_phys_invalidate_count;
+
+    GPtrArray *last_search;
 };
 
 extern TBContext tb_ctx;
diff --git a/accel/tcg/monitor.c b/accel/tcg/monitor.c
index 370fea883c..1be3218715 100644
--- a/accel/tcg/monitor.c
+++ b/accel/tcg/monitor.c
@@ -15,12 +15,14 @@
 #include "qapi/qmp/qdict.h"
 #include "monitor/monitor.h"
 #include "monitor/hmp.h"
+#include "monitor/hmp-target.h"
 #include "sysemu/cpus.h"
 #include "sysemu/cpu-timers.h"
 #include "sysemu/tcg.h"
 #include "tcg/tcg.h"
 #include "tcg/tb-stats.h"
 #include "exec/tb-flush.h"
+#include "disas/disas.h"
 #include "internal-common.h"
 #include "tb-context.h"
 
@@ -303,10 +305,99 @@ static void hmp_tbstats(Monitor *mon, const QDict *qdict)
                           RUN_ON_CPU_HOST_INT(flags));
 }
 
+static void hmp_info_tblist(Monitor *mon, const QDict *qdict)
+{
+    int max;
+    const char *sortedby_str;
+    GCompareFunc sort;
+    GPtrArray *array;
+
+    if (!tcg_enabled()) {
+        monitor_printf(mon, "Only available with accel=tcg\n");
+        return;
+    }
+    if (!tb_stats_enabled) {
+        monitor_printf(mon, "TB statistics not being recorded\n");
+        return;
+    }
+
+    max = qdict_get_try_int(qdict, "number", 10);
+    sortedby_str = qdict_get_try_str(qdict, "sortedby");
+
+    if (sortedby_str == NULL || g_str_equal(sortedby_str, "hotness")) {
+        sort = tb_stats_sort_by_coverage;
+    } else if (g_str_equal(sortedby_str, "hg")) {
+        sort = tb_stats_sort_by_hg;
+    } else if (g_str_equal(sortedby_str, "spills")) {
+        sort = tb_stats_sort_by_spills;
+    } else {
+        monitor_printf(mon, "Sort options are: hotness, hg, spills\n");
+        return;
+    }
+
+    g_ptr_array_unref(tb_ctx.last_search);
+    tb_ctx.last_search = NULL;
+
+    array = tb_stats_collect(max, sort);
+    max = array->len;
+    if (max == 0) {
+        monitor_printf(mon, "No TB statistics collected\n");
+        g_ptr_array_free(array, true);
+        return;
+    }
+
+    for (int i = 0; i < max; ++i) {
+        TBStatistics *s = g_ptr_array_index(array, i);
+        g_autoptr(GString) buf = tb_stats_dump(s, i);
+        monitor_puts(mon, buf->str);
+    }
+
+    /* Remember for the next "info tb" */
+    tb_ctx.last_search = array;
+}
+
+static void hmp_info_tb(Monitor *mon, const QDict *qdict)
+{
+    GPtrArray *array;
+    int id;
+
+    if (!tcg_enabled()) {
+        monitor_printf(mon, "Only available with accel=tcg\n");
+        return;
+    }
+
+    array = g_ptr_array_ref(tb_ctx.last_search);
+    if (!array) {
+        monitor_printf(mon, "No TB statistics collected\n");
+        return;
+    }
+
+    id = qdict_get_int(qdict, "id");
+    if (id < array->len) {
+        TBStatistics *s = g_ptr_array_index(array, id);
+        g_autoptr(GString) buf = tb_stats_dump(s, id);
+        monitor_puts(mon, buf->str);
+
+        for (int i = s->tbs->len - 1; i >= 0; --i) {
+            TranslationBlock *tb = g_ptr_array_index(s->tbs, i);
+            if (!(tb->cflags & CF_INVALID)) {
+                monitor_disas(mon, mon_get_cpu(mon), s->phys_pc,
+                              tb->icount, MON_DISAS_GRA);
+            }
+        }
+    } else {
+        monitor_printf(mon, "TB %d information not recorded\n", id);
+    }
+
+    g_ptr_array_unref(array);
+}
+
 static void hmp_tcg_register(void)
 {
     monitor_register_hmp_info_hrt("jit", qmp_x_query_jit);
     monitor_register_hmp_info_hrt("opcount", qmp_x_query_opcount);
     monitor_register_hmp("tb_stats", false, hmp_tbstats);
+    monitor_register_hmp("tb-list", true, hmp_info_tblist);
+    monitor_register_hmp("tb", true, hmp_info_tb);
 }
 type_init(hmp_tcg_register);
diff --git a/accel/tcg/tb-stats.c b/accel/tcg/tb-stats.c
index b2c9445b67..0f84c14a88 100644
--- a/accel/tcg/tb-stats.c
+++ b/accel/tcg/tb-stats.c
@@ -43,6 +43,8 @@ void tb_stats_init(uint32_t flags)
                      CODE_GEN_HTABLE_SIZE, QHT_MODE_AUTO_RESIZE);
         }
     } else {
+        g_ptr_array_unref(tb_ctx.last_search);
+        tb_ctx.last_search = NULL;
         qht_iter(&tb_ctx.stats, tb_stats_free, NULL);
         qht_destroy(&tb_ctx.stats);
     }
diff --git a/hmp-commands-info.hx b/hmp-commands-info.hx
index f5b37eb74a..8e9b64cf7f 100644
--- a/hmp-commands-info.hx
+++ b/hmp-commands-info.hx
@@ -262,6 +262,20 @@ 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",
+    },
+    {
+        .name       = "tb",
+        .args_type  = "id:i",
+        .params     = "id",
+        .help       = "show information about one translated block by id,"
+                      "from the result of a previous \"info tb-list\"",
+    },
 #endif
 
 SRST
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH v17 16/16] accel/tcg: Dump hot TBs at the end of the execution
  2023-10-03 18:30 [PATCH v17 00/16] TCG code quality tracking Richard Henderson
                   ` (14 preceding siblings ...)
  2023-10-03 18:30 ` [PATCH v17 15/16] accel/tcg: Add info [tb-list|tb] commands to HMP Richard Henderson
@ 2023-10-03 18:30 ` Richard Henderson
  2023-10-10 12:36   ` Philippe Mathieu-Daudé
  2024-11-14  9:28 ` [PATCH v17 00/16] TCG code quality tracking Nikita Shubin
  16 siblings, 1 reply; 39+ messages in thread
From: Richard Henderson @ 2023-10-03 18:30 UTC (permalink / raw)
  To: qemu-devel; +Cc: fei2.wu

From: Fei Wu <fei2.wu@intel.com>

Dump the hottest TBs if -d tb_stats:{all,jit,exec}[:dump_num_at_exit]

Signed-off-by: Fei Wu <fei2.wu@intel.com>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 bsd-user/bsd-proc.h    |  2 ++
 include/tcg/tb-stats.h | 10 +++++++++-
 accel/tcg/monitor.c    |  8 +++++---
 accel/tcg/tb-stats.c   | 27 ++++++++++++++++++++++++++-
 linux-user/exit.c      | 10 ++++++----
 softmmu/runstate.c     |  2 ++
 stubs/tb-stats.c       |  6 +++++-
 util/log.c             | 20 ++++++++++++++++----
 8 files changed, 71 insertions(+), 14 deletions(-)

diff --git a/bsd-user/bsd-proc.h b/bsd-user/bsd-proc.h
index 0e1d461c4c..84b52b399a 100644
--- a/bsd-user/bsd-proc.h
+++ b/bsd-user/bsd-proc.h
@@ -21,12 +21,14 @@
 #define BSD_PROC_H_
 
 #include <sys/resource.h>
+#include "tcg/tb-stats.h"
 
 /* exit(2) */
 static inline abi_long do_bsd_exit(void *cpu_env, abi_long arg1)
 {
     gdb_exit(arg1);
     qemu_plugin_user_exit();
+    tb_stats_dump_atexit();
     _exit(arg1);
 
     return 0;
diff --git a/include/tcg/tb-stats.h b/include/tcg/tb-stats.h
index edee73b63b..d3cca94f84 100644
--- a/include/tcg/tb-stats.h
+++ b/include/tcg/tb-stats.h
@@ -41,11 +41,12 @@ extern uint32_t tb_stats_enabled;
 /**
  * tb_stats_init:
  * @flags: TB_STATS_* flags to enable.
+ * @atexit: count of hottest tbs to log.
  *
  * Initialize translation block statistics, enabling @flags.
  * If @flags is 0, disable all statistics.
  */
-void tb_stats_init(uint32_t flags);
+void tb_stats_init(uint32_t flags, uint32_t atexit);
 
 /*
  * This struct stores statistics such as execution count of the
@@ -154,4 +155,11 @@ gint tb_stats_sort_by_hg(gconstpointer, gconstpointer);
  */
 GString *tb_stats_dump(TBStatistics *s, unsigned index);
 
+/**
+ * tb_stats_dump_atexit:
+ *
+ * Log any requested TBs at end of execution.
+ */
+void tb_stats_dump_atexit(void);
+
 #endif /* TCG_TB_STATS_H */
diff --git a/accel/tcg/monitor.c b/accel/tcg/monitor.c
index 1be3218715..7719583654 100644
--- a/accel/tcg/monitor.c
+++ b/accel/tcg/monitor.c
@@ -245,7 +245,7 @@ static void tb_stats_init_safe(CPUState *cpu, run_on_cpu_data icmd)
 {
     uint32_t flags = icmd.host_int;
 
-    tb_stats_init(flags);
+    tb_stats_init(flags, 0);
     tb_flush(cpu);
 }
 
@@ -335,8 +335,10 @@ static void hmp_info_tblist(Monitor *mon, const QDict *qdict)
         return;
     }
 
-    g_ptr_array_unref(tb_ctx.last_search);
-    tb_ctx.last_search = NULL;
+    if (tb_ctx.last_search) {
+        g_ptr_array_unref(tb_ctx.last_search);
+        tb_ctx.last_search = NULL;
+    }
 
     array = tb_stats_collect(max, sort);
     max = array->len;
diff --git a/accel/tcg/tb-stats.c b/accel/tcg/tb-stats.c
index 0f84c14a88..62a6228799 100644
--- a/accel/tcg/tb-stats.c
+++ b/accel/tcg/tb-stats.c
@@ -8,10 +8,12 @@
 
 #include "qemu/osdep.h"
 #include "qemu/xxhash.h"
+#include "qemu/log.h"
 #include "tcg/tb-stats.h"
 #include "tb-context.h"
 
 uint32_t tb_stats_enabled;
+static uint32_t tb_stats_atexit;
 
 static bool tb_stats_cmp(const void *ap, const void *bp)
 {
@@ -34,7 +36,7 @@ static void tb_stats_free(void *p, uint32_t hash, void *userp)
     g_free(s);
 }
 
-void tb_stats_init(uint32_t flags)
+void tb_stats_init(uint32_t flags, uint32_t atexit)
 {
     tb_stats_enabled = flags;
     if (flags) {
@@ -48,6 +50,14 @@ void tb_stats_init(uint32_t flags)
         qht_iter(&tb_ctx.stats, tb_stats_free, NULL);
         qht_destroy(&tb_ctx.stats);
     }
+
+    /*
+     * This function is also used by HMP, when atexit is 0.
+     * Preserve the value set from the command-line.
+     */
+    if (atexit) {
+        tb_stats_atexit = atexit;
+    }
 }
 
 static void tb_stats_reset(void *p, uint32_t hash, void *userp)
@@ -204,3 +214,18 @@ GString *tb_stats_dump(TBStatistics *s, unsigned index)
     }
     return buf;
 }
+
+void tb_stats_dump_atexit(void)
+{
+    if (tb_stats_enabled && tb_stats_atexit) {
+        g_autoptr(GPtrArray) array =
+            tb_stats_collect(tb_stats_atexit, tb_stats_sort_by_coverage);
+
+        for (uint32_t i = 0, n = array->len; i < n; ++i) {
+            TBStatistics *s = g_ptr_array_index(array, i);
+            g_autoptr(GString) str = tb_stats_dump(s, i);
+
+            qemu_log("%s\n", str->str);
+        }
+    }
+}
diff --git a/linux-user/exit.c b/linux-user/exit.c
index 50266314e0..4487aaac7e 100644
--- a/linux-user/exit.c
+++ b/linux-user/exit.c
@@ -22,6 +22,7 @@
 #include "qemu.h"
 #include "user-internals.h"
 #include "qemu/plugin.h"
+#include "tcg/tb-stats.h"
 
 #ifdef CONFIG_GCOV
 extern void __gcov_dump(void);
@@ -30,9 +31,10 @@ extern void __gcov_dump(void);
 void preexit_cleanup(CPUArchState *env, int code)
 {
 #ifdef CONFIG_GCOV
-        __gcov_dump();
+    __gcov_dump();
 #endif
-        gdb_exit(code);
-        qemu_plugin_user_exit();
-        perf_exit();
+    gdb_exit(code);
+    qemu_plugin_user_exit();
+    perf_exit();
+    tb_stats_dump_atexit();
 }
diff --git a/softmmu/runstate.c b/softmmu/runstate.c
index 1652ed0439..2c6fb9bff1 100644
--- a/softmmu/runstate.c
+++ b/softmmu/runstate.c
@@ -59,6 +59,7 @@
 #include "sysemu/runstate-action.h"
 #include "sysemu/sysemu.h"
 #include "sysemu/tpm.h"
+#include "tcg/tb-stats.h"
 #include "trace.h"
 
 static NotifierList exit_notifiers =
@@ -846,6 +847,7 @@ void qemu_cleanup(void)
     /* No more vcpu or device emulation activity beyond this point */
     vm_shutdown();
     replay_finish();
+    tb_stats_dump_atexit();
 
     /*
      * We must cancel all block jobs while the block layer is drained,
diff --git a/stubs/tb-stats.c b/stubs/tb-stats.c
index ceaa1622ce..f9e4ef5d04 100644
--- a/stubs/tb-stats.c
+++ b/stubs/tb-stats.c
@@ -11,6 +11,10 @@
 #include "qemu/osdep.h"
 #include "tcg/tb-stats.h"
 
-void tb_stats_init(uint32_t flags)
+void tb_stats_init(uint32_t flags, uint32_t atexit)
+{
+}
+
+void tb_stats_dump_atexit(void)
 {
 }
diff --git a/util/log.c b/util/log.c
index 0cb987fb74..789b19a226 100644
--- a/util/log.c
+++ b/util/log.c
@@ -526,19 +526,31 @@ int qemu_str_to_log_mask(const char *str, Error **errp)
 #ifdef CONFIG_TCG
         } else if (g_str_has_prefix(t, "tb_stats:") && t[9] != '\0') {
             int flags = TB_STATS_NONE;
+            unsigned atexit = 0;
             char *v = t + 9;
+            char *e = strchr(v, ':');
+            size_t len;
 
-            if (g_str_equal(v, "all")) {
+            if (e) {
+                len = e - v;
+                if (qemu_strtoui(e + 1, NULL, 10, &atexit) < 0) {
+                    error_setg(errp, "Invalid -d option \"%s\"", t);
+                    goto error;
+                }
+            } else {
+                len = strlen(v);
+            }
+            if (strncmp(v, "all", len) == 0) {
                 flags = TB_STATS_ALL;
-            } else if (g_str_equal(v, "jit")) {
+            } else if (strncmp(v, "jit", len) == 0) {
                 flags = TB_STATS_JIT;
-            } else if (g_str_equal(v, "exec")) {
+            } else if (strncmp(v, "exec", len) == 0) {
                 flags = TB_STATS_EXEC;
             } else {
                 error_setg(errp, "Invalid -d option \"%s\"", t);
                 goto error;
             }
-            tb_stats_init(flags);
+            tb_stats_init(flags, atexit);
 #endif
         } else {
             for (item = qemu_log_items; item->mask != 0; item++) {
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 39+ messages in thread

* Re: [PATCH v17 01/16] accel/tcg: Move HMP info jit and info opcount code
  2023-10-03 18:30 ` [PATCH v17 01/16] accel/tcg: Move HMP info jit and info opcount code Richard Henderson
@ 2023-10-10 12:09   ` Philippe Mathieu-Daudé
  2023-10-15 12:58   ` Alex Bennée
  1 sibling, 0 replies; 39+ messages in thread
From: Philippe Mathieu-Daudé @ 2023-10-10 12:09 UTC (permalink / raw)
  To: Richard Henderson, qemu-devel; +Cc: fei2.wu

On 3/10/23 20:30, Richard Henderson wrote:
> Move all of it into accel/tcg/monitor.c.  This puts everything
> about tcg that is only used by the monitor in the same place.
> 
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>   accel/tcg/internal-common.h |   2 -
>   include/exec/cputlb.h       |   1 -
>   include/tcg/tcg.h           |   3 -
>   accel/tcg/cputlb.c          |  15 ----
>   accel/tcg/monitor.c         | 154 ++++++++++++++++++++++++++++++++++++
>   accel/tcg/translate-all.c   | 127 -----------------------------
>   tcg/tcg.c                   |  10 ---
>   7 files changed, 154 insertions(+), 158 deletions(-)

Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Tested-by: Philippe Mathieu-Daudé <philmd@linaro.org>



^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH v17 07/16] accel/tcg: Collect TB jit statistics
  2023-10-03 18:30 ` [PATCH v17 07/16] accel/tcg: Collect TB jit statistics Richard Henderson
@ 2023-10-10 12:13   ` Philippe Mathieu-Daudé
  0 siblings, 0 replies; 39+ messages in thread
From: Philippe Mathieu-Daudé @ 2023-10-10 12:13 UTC (permalink / raw)
  To: Richard Henderson, qemu-devel
  Cc: fei2.wu, Vanderson M . do Rosario, Alex Bennée

On 3/10/23 20:30, Richard Henderson wrote:
> Collect items like input and output code size, guest instruction count,
> intermediate ops, spills, etc.
> 
> Signed-off-by: Vanderson M. do Rosario <vandersonmr2@gmail.com>
> Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
> Signed-off-by: Fei Wu <fei2.wu@intel.com>
> [rth: Consolidated at the end of translation.]
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>   accel/tcg/translate-all.c | 21 +++++++++++++++++++++
>   1 file changed, 21 insertions(+)

Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>




^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH v17 12/16] softmmu: Export qemu_ram_ptr_length
  2023-10-03 18:30 ` [PATCH v17 12/16] softmmu: Export qemu_ram_ptr_length Richard Henderson
@ 2023-10-10 12:31   ` Philippe Mathieu-Daudé
  0 siblings, 0 replies; 39+ messages in thread
From: Philippe Mathieu-Daudé @ 2023-10-10 12:31 UTC (permalink / raw)
  To: Richard Henderson, qemu-devel; +Cc: fei2.wu

On 3/10/23 20:30, Richard Henderson wrote:
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>   include/exec/memory.h | 2 ++
>   softmmu/physmem.c     | 4 ++--
>   2 files changed, 4 insertions(+), 2 deletions(-)
> 
> diff --git a/include/exec/memory.h b/include/exec/memory.h
> index ef23d65afc..ebdecf64a6 100644
> --- a/include/exec/memory.h
> +++ b/include/exec/memory.h
> @@ -2874,6 +2874,8 @@ MemTxResult flatview_read_continue(FlatView *fv, hwaddr addr,
>                                      hwaddr len, hwaddr addr1, hwaddr l,
>                                      MemoryRegion *mr);
>   void *qemu_map_ram_ptr(RAMBlock *ram_block, ram_addr_t addr);
> +void *qemu_ram_ptr_length(RAMBlock *ram_block, ram_addr_t addr,
> +                          hwaddr *size, bool lock);
>   
>   /* Internal functions, part of the implementation of address_space_read_cached
>    * and address_space_write_cached.  */
> diff --git a/softmmu/physmem.c b/softmmu/physmem.c
> index 309653c722..69a853c27a 100644
> --- a/softmmu/physmem.c
> +++ b/softmmu/physmem.c
> @@ -2182,8 +2182,8 @@ void *qemu_map_ram_ptr(RAMBlock *ram_block, ram_addr_t addr)
>    *
>    * Called within RCU critical section.
>    */
> -static void *qemu_ram_ptr_length(RAMBlock *ram_block, ram_addr_t addr,
> -                                 hwaddr *size, bool lock)
> +void *qemu_ram_ptr_length(RAMBlock *ram_block, ram_addr_t addr,
> +                          hwaddr *size, bool lock)
>   {
>       RAMBlock *block = ram_block;
>       if (*size == 0) {

Pre-existing, function named with '_length' suffix but takes a 'size'
parameter.

Preferably moving the docstring along with the public declaration:
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>



^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH v17 10/16] util/log: Add -d tb_stats
  2023-10-03 18:30 ` [PATCH v17 10/16] util/log: Add -d tb_stats Richard Henderson
@ 2023-10-10 12:34   ` Philippe Mathieu-Daudé
  2023-10-15 19:53     ` Richard Henderson
  0 siblings, 1 reply; 39+ messages in thread
From: Philippe Mathieu-Daudé @ 2023-10-10 12:34 UTC (permalink / raw)
  To: Richard Henderson, qemu-devel
  Cc: fei2.wu, Vanderson M . do Rosario, Alex Bennée

On 3/10/23 20:30, Richard Henderson wrote:
> From: Fei Wu <fei2.wu@intel.com>
> 
> Enable TBStatistics collection from startup.
> 
> Signed-off-by: Vanderson M. do Rosario <vandersonmr2@gmail.com>
> Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
> Signed-off-by: Fei Wu <fei2.wu@intel.com>
> [rth: Change "tb_stats_foo" to "tb_stats:foo"]
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>   stubs/tb-stats.c  | 16 ++++++++++++++++
>   util/log.c        | 36 +++++++++++++++++++++++++++++++-----
>   stubs/meson.build |  1 +
>   3 files changed, 48 insertions(+), 5 deletions(-)
>   create mode 100644 stubs/tb-stats.c
> 
> diff --git a/stubs/tb-stats.c b/stubs/tb-stats.c
> new file mode 100644
> index 0000000000..ceaa1622ce
> --- /dev/null
> +++ b/stubs/tb-stats.c
> @@ -0,0 +1,16 @@
> +/*
> + * TB Stats Stubs
> + *
> + * Copyright (c) 2019
> + * Written by Alex Bennée <alex.bennee@linaro.org>
> + *
> + * This code is licensed under the GNU GPL v2, or later.
> + */
> +
> +
> +#include "qemu/osdep.h"
> +#include "tcg/tb-stats.h"
> +
> +void tb_stats_init(uint32_t flags)
> +{
> +}

We don't need this stub anymore.


^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH v17 16/16] accel/tcg: Dump hot TBs at the end of the execution
  2023-10-03 18:30 ` [PATCH v17 16/16] accel/tcg: Dump hot TBs at the end of the execution Richard Henderson
@ 2023-10-10 12:36   ` Philippe Mathieu-Daudé
  2023-10-10 13:23     ` Alex Bennée
  0 siblings, 1 reply; 39+ messages in thread
From: Philippe Mathieu-Daudé @ 2023-10-10 12:36 UTC (permalink / raw)
  To: Richard Henderson, qemu-devel; +Cc: fei2.wu

On 3/10/23 20:30, Richard Henderson wrote:
> From: Fei Wu <fei2.wu@intel.com>
> 
> Dump the hottest TBs if -d tb_stats:{all,jit,exec}[:dump_num_at_exit]
> 
> Signed-off-by: Fei Wu <fei2.wu@intel.com>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>   bsd-user/bsd-proc.h    |  2 ++
>   include/tcg/tb-stats.h | 10 +++++++++-
>   accel/tcg/monitor.c    |  8 +++++---
>   accel/tcg/tb-stats.c   | 27 ++++++++++++++++++++++++++-
>   linux-user/exit.c      | 10 ++++++----
>   softmmu/runstate.c     |  2 ++
>   stubs/tb-stats.c       |  6 +++++-
>   util/log.c             | 20 ++++++++++++++++----
>   8 files changed, 71 insertions(+), 14 deletions(-)


> diff --git a/softmmu/runstate.c b/softmmu/runstate.c
> index 1652ed0439..2c6fb9bff1 100644
> --- a/softmmu/runstate.c
> +++ b/softmmu/runstate.c
> @@ -59,6 +59,7 @@
>   #include "sysemu/runstate-action.h"
>   #include "sysemu/sysemu.h"
>   #include "sysemu/tpm.h"
> +#include "tcg/tb-stats.h"
>   #include "trace.h"
>   
>   static NotifierList exit_notifiers =
> @@ -846,6 +847,7 @@ void qemu_cleanup(void)
>       /* No more vcpu or device emulation activity beyond this point */
>       vm_shutdown();
>       replay_finish();
> +    tb_stats_dump_atexit();
>   
>       /*
>        * We must cancel all block jobs while the block layer is drained,
> diff --git a/stubs/tb-stats.c b/stubs/tb-stats.c
> index ceaa1622ce..f9e4ef5d04 100644
> --- a/stubs/tb-stats.c
> +++ b/stubs/tb-stats.c
> @@ -11,6 +11,10 @@
>   #include "qemu/osdep.h"
>   #include "tcg/tb-stats.h"
>   
> -void tb_stats_init(uint32_t flags)
> +void tb_stats_init(uint32_t flags, uint32_t atexit)
> +{
> +}
> +
> +void tb_stats_dump_atexit(void)
>   {
>   }

The stub isn't needed using:

-- >8 --
diff --git a/softmmu/runstate.c b/softmmu/runstate.c
index 2c6fb9bff1..d05e2b8e1c 100644
--- a/softmmu/runstate.c
+++ b/softmmu/runstate.c
@@ -52,6 +52,7 @@
  #include "qom/object.h"
  #include "qom/object_interfaces.h"
  #include "sysemu/cpus.h"
+#include "sysemu/tcg.h"
  #include "sysemu/qtest.h"
  #include "sysemu/replay.h"
  #include "sysemu/reset.h"
@@ -847,7 +848,9 @@ void qemu_cleanup(void)
      /* No more vcpu or device emulation activity beyond this point */
      vm_shutdown();
      replay_finish();
-    tb_stats_dump_atexit();
+    if (tcg_enabled()) {
+        tb_stats_dump_atexit();
+    }

      /*
       * We must cancel all block jobs while the block layer is drained,
---


^ permalink raw reply related	[flat|nested] 39+ messages in thread

* Re: [PATCH v17 13/16] disas: Allow monitor_disas to read from ram_addr_t
  2023-10-03 18:30 ` [PATCH v17 13/16] disas: Allow monitor_disas to read from ram_addr_t Richard Henderson
@ 2023-10-10 12:46   ` Philippe Mathieu-Daudé
  2023-10-15 19:21     ` Alex Bennée
  0 siblings, 1 reply; 39+ messages in thread
From: Philippe Mathieu-Daudé @ 2023-10-10 12:46 UTC (permalink / raw)
  To: Richard Henderson, qemu-devel
  Cc: fei2.wu, Vanderson M. do Rosario, Alex Bennée

On 3/10/23 20:30, Richard Henderson wrote:
> From: "Vanderson M. do Rosario" <vandersonmr2@gmail.com>
> 
> Introduce a MonitorDisasSpace to replace the current is_physical
> boolean argument to monitor_disas.  Generate an error if we attempt
> to read past the end of a single RAMBlock.
> 
> Signed-off-by: Vanderson M. do Rosario <vandersonmr2@gmail.com>
> Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
> Signed-off-by: Fei Wu <fei2.wu@intel.com>
> [rth: Split out of a larger patch; validate the RAMBlock size]
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>   include/disas/disas.h     |  8 +++++++-
>   disas/disas-mon.c         | 32 ++++++++++++++++++++++++++++++--
>   monitor/hmp-cmds-target.c | 27 ++++++++++++++++-----------
>   3 files changed, 53 insertions(+), 14 deletions(-)
> 
> diff --git a/include/disas/disas.h b/include/disas/disas.h
> index 176775eff7..cd99b0ccd0 100644
> --- a/include/disas/disas.h
> +++ b/include/disas/disas.h
> @@ -5,8 +5,14 @@
>   void disas(FILE *out, const void *code, size_t size);
>   void target_disas(FILE *out, CPUState *cpu, uint64_t code, size_t size);
>   
> +typedef enum {
> +    MON_DISAS_GVA, /* virtual */
> +    MON_DISAS_GPA, /* physical */
> +    MON_DISAS_GRA, /* ram_addr_t */
> +} MonitorDisasSpace;


Obviously I'd rather see MonitorDisasSpace = {MON_DISAS_GVA/GPA}
introduced in a preliminary patch, but just saying.

>   static void memory_dump(Monitor *mon, int count, int format, int wsize,
> -                        hwaddr addr, int is_physical)
> +                        hwaddr addr, MonitorDisasSpace space)
>   {
>       int l, line_size, i, max_digits, len;
>       uint8_t buf[16];
>       uint64_t v;
>       CPUState *cs = mon_get_cpu(mon);
>   
> -    if (!cs && (format == 'i' || !is_physical)) {

Why is the '!cs' check removed? Otherwise LGTM.

> +    if (space == MON_DISAS_GVA || format == 'i') {
>           monitor_printf(mon, "Can not dump without CPU\n");
>           return;
>       }
>   
>       if (format == 'i') {
> -        monitor_disas(mon, cs, addr, count, is_physical);
> -        return;
> +        monitor_disas(mon, cs, addr, count, space);
>       }
>   
>       len = wsize * count;
> @@ -163,15 +162,21 @@ static void memory_dump(Monitor *mon, int count, int format, int wsize,
>       }
>   
>       while (len > 0) {
> -        if (is_physical) {
> -            monitor_printf(mon, HWADDR_FMT_plx ":", addr);
> -        } else {
> +        switch (space) {
> +        case MON_DISAS_GVA:
>               monitor_printf(mon, TARGET_FMT_lx ":", (target_ulong)addr);
> +            break;
> +        case MON_DISAS_GPA:
> +            monitor_printf(mon, HWADDR_FMT_plx ":", addr);
> +            break;
> +        default:
> +            g_assert_not_reached();
>           }
>           l = len;
> -        if (l > line_size)
> +        if (l > line_size) {
>               l = line_size;
> -        if (is_physical) {
> +        }
> +        if (space == MON_DISAS_GPA) {
>               AddressSpace *as = cs ? cs->as : &address_space_memory;
>               MemTxResult r = address_space_read(as, addr,
>                                                  MEMTXATTRS_UNSPECIFIED, buf, l);
> @@ -235,7 +240,7 @@ void hmp_memory_dump(Monitor *mon, const QDict *qdict)
>       int size = qdict_get_int(qdict, "size");
>       target_long addr = qdict_get_int(qdict, "addr");
>   
> -    memory_dump(mon, count, format, size, addr, 0);
> +    memory_dump(mon, count, format, size, addr, MON_DISAS_GVA);
>   }



^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH v17 09/16] util/log: Add Error argument to qemu_str_to_log_mask
  2023-10-03 18:30 ` [PATCH v17 09/16] util/log: Add Error argument to qemu_str_to_log_mask Richard Henderson
@ 2023-10-10 12:55   ` Markus Armbruster
  2023-10-15 18:55     ` Richard Henderson
  0 siblings, 1 reply; 39+ messages in thread
From: Markus Armbruster @ 2023-10-10 12:55 UTC (permalink / raw)
  To: Richard Henderson; +Cc: qemu-devel, fei2.wu, Philippe Mathieu-Daudé

Richard Henderson <richard.henderson@linaro.org> writes:

> Do not rely on return value of 0 to indicate error,
> pass along an Error pointer to be set.

Not wrong, but goes against error.h's recommendation

 * - Whenever practical, also return a value that indicates success /
 *   failure.  This can make the error checking more concise, and can
 *   avoid useless error object creation and destruction.  Note that
 *   we still have many functions returning void.  We recommend
 *   • bool-valued functions return true on success / false on failure,
 *   • pointer-valued functions return non-null / null pointer, and
 *   • integer-valued functions return non-negative / negative.

>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>  include/qemu/log.h | 2 +-
>  bsd-user/main.c    | 6 ++++--
>  linux-user/main.c  | 7 +++++--
>  monitor/hmp-cmds.c | 5 +++--
>  softmmu/vl.c       | 7 +++++--
>  util/log.c         | 5 +++--
>  6 files changed, 21 insertions(+), 11 deletions(-)
>
> diff --git a/include/qemu/log.h b/include/qemu/log.h
> index df59bfabcd..9b92d2663e 100644
> --- a/include/qemu/log.h
> +++ b/include/qemu/log.h
> @@ -87,7 +87,7 @@ 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_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);
> +int qemu_str_to_log_mask(const char *str, Error **errp);
>  
>  /* Print a usage message listing all the valid logging categories
>   * to the specified FILE*.
> diff --git a/bsd-user/main.c b/bsd-user/main.c
> index 703f3e2c41..a981239a0b 100644
> --- a/bsd-user/main.c
> +++ b/bsd-user/main.c
> @@ -411,8 +411,10 @@ int main(int argc, char **argv)
>      {
>          int mask = 0;
>          if (log_mask) {
> -            mask = qemu_str_to_log_mask(log_mask);
> -            if (!mask) {
> +            Error *err = NULL;
> +            mask = qemu_str_to_log_mask(log_mask, &err);
> +            if (err) {
> +                error_report_err(err);
>                  qemu_print_log_usage(stdout);
>                  exit(1);
>              }
> diff --git a/linux-user/main.c b/linux-user/main.c
> index 0c23584a96..d0464736cc 100644
> --- a/linux-user/main.c
> +++ b/linux-user/main.c
> @@ -264,8 +264,11 @@ static void handle_arg_help(const char *arg)
>  
>  static void handle_arg_log(const char *arg)
>  {
> -    last_log_mask = qemu_str_to_log_mask(arg);
> -    if (!last_log_mask) {
> +    Error *err = NULL;
> +
> +    last_log_mask = qemu_str_to_log_mask(arg, &err);
> +    if (err) {
> +        error_report_err(err);
>          qemu_print_log_usage(stdout);
>          exit(EXIT_FAILURE);
>      }
> diff --git a/monitor/hmp-cmds.c b/monitor/hmp-cmds.c
> index 6c559b48c8..c4bd97d467 100644
> --- a/monitor/hmp-cmds.c
> +++ b/monitor/hmp-cmds.c
> @@ -291,8 +291,9 @@ void hmp_log(Monitor *mon, const QDict *qdict)
>      if (!strcmp(items, "none")) {
>          mask = 0;
>      } else {
> -        mask = qemu_str_to_log_mask(items);
> -        if (!mask) {
> +        mask = qemu_str_to_log_mask(items, &err);
> +        if (err) {
> +            error_free(err);
>              hmp_help_cmd(mon, "log");
>              return;
>          }
> diff --git a/softmmu/vl.c b/softmmu/vl.c
> index 98e071e63b..02193696b9 100644
> --- a/softmmu/vl.c
> +++ b/softmmu/vl.c
> @@ -2486,8 +2486,11 @@ static void qemu_process_early_options(void)
>      {
>          int mask = 0;
>          if (log_mask) {
> -            mask = qemu_str_to_log_mask(log_mask);
> -            if (!mask) {
> +            Error *err = NULL;
> +
> +            mask = qemu_str_to_log_mask(log_mask, &err);
> +            if (err) {
> +                error_report_err(err);
>                  qemu_print_log_usage(stdout);
>                  exit(1);
>              }
> diff --git a/util/log.c b/util/log.c
> index def88a9402..b5f08db202 100644
> --- a/util/log.c
> +++ b/util/log.c
> @@ -500,8 +500,8 @@ const QEMULogItem qemu_log_items[] = {
>      { 0, NULL, NULL },
>  };
>  
> -/* takes a comma separated list of log masks. Return 0 if error. */
> -int qemu_str_to_log_mask(const char *str)
> +/* Takes a comma separated list of log masks. */
> +int qemu_str_to_log_mask(const char *str, Error **errp)
>  {
>      const QEMULogItem *item;
>      int mask = 0;
> @@ -524,6 +524,7 @@ int qemu_str_to_log_mask(const char *str)
       char **parts = g_strsplit(str, ",", 0);
       char **tmp;

When @parts is null or "", the loop runs zero times, and ...

       for (tmp = parts; tmp && *tmp; tmp++) {
           if (g_str_equal(*tmp, "all")) {
               for (item = qemu_log_items; item->mask != 0; item++) {
                   mask |= item->mask;
               }
   #ifdef CONFIG_TRACE_LOG
           } else if (g_str_has_prefix(*tmp, "trace:") && (*tmp)[6] != '\0') {
               trace_enable_events((*tmp) + 6);
               mask |= LOG_TRACE;
   #endif
           } else {
               for (item = qemu_log_items; item->mask != 0; item++) {
                   if (g_str_equal(*tmp, item->name)) {
>                      goto found;
>                  }
>              }
> +            error_setg(errp, "Invalid -d option \"%s\"", *tmp);
>              goto error;
>          found:
>              mask |= item->mask;
           }
       }

... we end up here with mask zero and no error set.

       g_strfreev(parts);
       return mask;

Before the patch, this counted as error.  Afterwards, it doesn't.
Impact?  Worth mentioning in the commit message?

    error:
       g_strfreev(parts);
       return 0;

Returning -1 here would stick to error.h's recommendation.

   }



^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH v17 16/16] accel/tcg: Dump hot TBs at the end of the execution
  2023-10-10 12:36   ` Philippe Mathieu-Daudé
@ 2023-10-10 13:23     ` Alex Bennée
  0 siblings, 0 replies; 39+ messages in thread
From: Alex Bennée @ 2023-10-10 13:23 UTC (permalink / raw)
  To: Philippe Mathieu-Daudé; +Cc: Richard Henderson, fei2.wu, qemu-devel


Philippe Mathieu-Daudé <philmd@linaro.org> writes:

> On 3/10/23 20:30, Richard Henderson wrote:
>> From: Fei Wu <fei2.wu@intel.com>
>> Dump the hottest TBs if -d
>> tb_stats:{all,jit,exec}[:dump_num_at_exit]
>> Signed-off-by: Fei Wu <fei2.wu@intel.com>
>> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
>> ---
>>   bsd-user/bsd-proc.h    |  2 ++
>>   include/tcg/tb-stats.h | 10 +++++++++-
>>   accel/tcg/monitor.c    |  8 +++++---
>>   accel/tcg/tb-stats.c   | 27 ++++++++++++++++++++++++++-
>>   linux-user/exit.c      | 10 ++++++----
>>   softmmu/runstate.c     |  2 ++
>>   stubs/tb-stats.c       |  6 +++++-
>>   util/log.c             | 20 ++++++++++++++++----
>>   8 files changed, 71 insertions(+), 14 deletions(-)
>
>
>> diff --git a/softmmu/runstate.c b/softmmu/runstate.c
>> index 1652ed0439..2c6fb9bff1 100644
>> --- a/softmmu/runstate.c
>> +++ b/softmmu/runstate.c
>> @@ -59,6 +59,7 @@
>>   #include "sysemu/runstate-action.h"
>>   #include "sysemu/sysemu.h"
>>   #include "sysemu/tpm.h"
>> +#include "tcg/tb-stats.h"
>>   #include "trace.h"
>>     static NotifierList exit_notifiers =
>> @@ -846,6 +847,7 @@ void qemu_cleanup(void)
>>       /* No more vcpu or device emulation activity beyond this point */
>>       vm_shutdown();
>>       replay_finish();
>> +    tb_stats_dump_atexit();
>>         /*
>>        * We must cancel all block jobs while the block layer is drained,
>> diff --git a/stubs/tb-stats.c b/stubs/tb-stats.c
>> index ceaa1622ce..f9e4ef5d04 100644
>> --- a/stubs/tb-stats.c
>> +++ b/stubs/tb-stats.c
>> @@ -11,6 +11,10 @@
>>   #include "qemu/osdep.h"
>>   #include "tcg/tb-stats.h"
>>   -void tb_stats_init(uint32_t flags)
>> +void tb_stats_init(uint32_t flags, uint32_t atexit)
>> +{
>> +}
>> +
>> +void tb_stats_dump_atexit(void)
>>   {
>>   }
>
> The stub isn't needed using:
>
> -- >8 --
> diff --git a/softmmu/runstate.c b/softmmu/runstate.c
> index 2c6fb9bff1..d05e2b8e1c 100644
> --- a/softmmu/runstate.c
> +++ b/softmmu/runstate.c
> @@ -52,6 +52,7 @@
>  #include "qom/object.h"
>  #include "qom/object_interfaces.h"
>  #include "sysemu/cpus.h"
> +#include "sysemu/tcg.h"
>  #include "sysemu/qtest.h"
>  #include "sysemu/replay.h"
>  #include "sysemu/reset.h"
> @@ -847,7 +848,9 @@ void qemu_cleanup(void)
>      /* No more vcpu or device emulation activity beyond this point */
>      vm_shutdown();
>      replay_finish();
> -    tb_stats_dump_atexit();
> +    if (tcg_enabled()) {
> +        tb_stats_dump_atexit();
> +    }

Why be different from replay_finish() which is a stub?

-- 
Alex Bennée
Virtualisation Tech Lead @ Linaro


^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH v17 02/16] tcg: Record orig_nb_ops TCGContext
  2023-10-03 18:30 ` [PATCH v17 02/16] tcg: Record orig_nb_ops TCGContext Richard Henderson
@ 2023-10-15 12:57   ` Alex Bennée
  0 siblings, 0 replies; 39+ messages in thread
From: Alex Bennée @ 2023-10-15 12:57 UTC (permalink / raw)
  To: Richard Henderson; +Cc: fei2.wu, qemu-devel


Richard Henderson <richard.henderson@linaro.org> writes:

> Remember the value of nb_ops before optimization.
> To be copied into TBStatistics when desired.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>

Reviewed-by: Alex Bennée <alex.bennee@linaro.org>

-- 
Alex Bennée
Virtualisation Tech Lead @ Linaro


^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH v17 01/16] accel/tcg: Move HMP info jit and info opcount code
  2023-10-03 18:30 ` [PATCH v17 01/16] accel/tcg: Move HMP info jit and info opcount code Richard Henderson
  2023-10-10 12:09   ` Philippe Mathieu-Daudé
@ 2023-10-15 12:58   ` Alex Bennée
  1 sibling, 0 replies; 39+ messages in thread
From: Alex Bennée @ 2023-10-15 12:58 UTC (permalink / raw)
  To: Richard Henderson; +Cc: fei2.wu, qemu-devel


Richard Henderson <richard.henderson@linaro.org> writes:

> Move all of it into accel/tcg/monitor.c.  This puts everything
> about tcg that is only used by the monitor in the same place.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>

Reviewed-by: Alex Bennée <alex.bennee@linaro.org>

-- 
Alex Bennée
Virtualisation Tech Lead @ Linaro


^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH v17 03/16] tcg: Record nb_deleted_ops in TCGContext
  2023-10-03 18:30 ` [PATCH v17 03/16] tcg: Record nb_deleted_ops in TCGContext Richard Henderson
@ 2023-10-15 12:58   ` Alex Bennée
  0 siblings, 0 replies; 39+ messages in thread
From: Alex Bennée @ 2023-10-15 12:58 UTC (permalink / raw)
  To: Richard Henderson; +Cc: fei2.wu, qemu-devel


Richard Henderson <richard.henderson@linaro.org> writes:

> Record the number of ops that are removed during optimization.
> To be copied into TBStatistics when desired.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>

Reviewed-by: Alex Bennée <alex.bennee@linaro.org>

-- 
Alex Bennée
Virtualisation Tech Lead @ Linaro


^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH v17 04/16] tcg: Record nb_spills in TCGContext
  2023-10-03 18:30 ` [PATCH v17 04/16] tcg: Record nb_spills " Richard Henderson
@ 2023-10-15 12:59   ` Alex Bennée
  0 siblings, 0 replies; 39+ messages in thread
From: Alex Bennée @ 2023-10-15 12:59 UTC (permalink / raw)
  To: Richard Henderson; +Cc: fei2.wu, qemu-devel


Richard Henderson <richard.henderson@linaro.org> writes:

> Record the number of times a temporary is forced into memory
> and the store would not have been required if there an infinite
> number of call-saved cpu registers available.  This excludes
> stores that are required by semantics to return computed values
> to their home slot in ENV, i.e. NEED_SYNC_ARG.
>
> To be copied into TBStatistics when desired.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>

Reviewed-by: Alex Bennée <alex.bennee@linaro.org>

-- 
Alex Bennée
Virtualisation Tech Lead @ Linaro


^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH v17 09/16] util/log: Add Error argument to qemu_str_to_log_mask
  2023-10-10 12:55   ` Markus Armbruster
@ 2023-10-15 18:55     ` Richard Henderson
  0 siblings, 0 replies; 39+ messages in thread
From: Richard Henderson @ 2023-10-15 18:55 UTC (permalink / raw)
  To: Markus Armbruster; +Cc: qemu-devel, fei2.wu, Philippe Mathieu-Daudé

On 10/10/23 05:55, Markus Armbruster wrote:
> Richard Henderson <richard.henderson@linaro.org> writes:
> 
>> Do not rely on return value of 0 to indicate error,
>> pass along an Error pointer to be set.
> 
> Not wrong, but goes against error.h's recommendation
> 
>   * - Whenever practical, also return a value that indicates success /
>   *   failure.  This can make the error checking more concise, and can
>   *   avoid useless error object creation and destruction.  Note that
>   *   we still have many functions returning void.  We recommend
>   *   • bool-valued functions return true on success / false on failure,
>   *   • pointer-valued functions return non-null / null pointer, and
>   *   • integer-valued functions return non-negative / negative.
> 
...
> Returning -1 here would stick to error.h's recommendation.

The problem had been that 0 would become a valid result in the next patch.
But using -1 would work, particularly with bit 31 of the log mask as yet unused.


r~



^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH v17 13/16] disas: Allow monitor_disas to read from ram_addr_t
  2023-10-10 12:46   ` Philippe Mathieu-Daudé
@ 2023-10-15 19:21     ` Alex Bennée
  0 siblings, 0 replies; 39+ messages in thread
From: Alex Bennée @ 2023-10-15 19:21 UTC (permalink / raw)
  To: Philippe Mathieu-Daudé
  Cc: Richard Henderson, qemu-devel, fei2.wu, Vanderson M. do Rosario


Philippe Mathieu-Daudé <philmd@linaro.org> writes:

> On 3/10/23 20:30, Richard Henderson wrote:
>> From: "Vanderson M. do Rosario" <vandersonmr2@gmail.com>
>> Introduce a MonitorDisasSpace to replace the current is_physical
>> boolean argument to monitor_disas.  Generate an error if we attempt
>> to read past the end of a single RAMBlock.
>> Signed-off-by: Vanderson M. do Rosario <vandersonmr2@gmail.com>
>> Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
>> Signed-off-by: Fei Wu <fei2.wu@intel.com>
>> [rth: Split out of a larger patch; validate the RAMBlock size]
>> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
>> ---
>>   include/disas/disas.h     |  8 +++++++-
>>   disas/disas-mon.c         | 32 ++++++++++++++++++++++++++++++--
>>   monitor/hmp-cmds-target.c | 27 ++++++++++++++++-----------
>>   3 files changed, 53 insertions(+), 14 deletions(-)
>> diff --git a/include/disas/disas.h b/include/disas/disas.h
>> index 176775eff7..cd99b0ccd0 100644
>> --- a/include/disas/disas.h
>> +++ b/include/disas/disas.h
>> @@ -5,8 +5,14 @@
>>   void disas(FILE *out, const void *code, size_t size);
>>   void target_disas(FILE *out, CPUState *cpu, uint64_t code, size_t size);
>>   +typedef enum {
>> +    MON_DISAS_GVA, /* virtual */
>> +    MON_DISAS_GPA, /* physical */
>> +    MON_DISAS_GRA, /* ram_addr_t */
>> +} MonitorDisasSpace;
>
>
> Obviously I'd rather see MonitorDisasSpace = {MON_DISAS_GVA/GPA}
> introduced in a preliminary patch, but just saying.
>
>>   static void memory_dump(Monitor *mon, int count, int format, int wsize,
>> -                        hwaddr addr, int is_physical)
>> +                        hwaddr addr, MonitorDisasSpace space)
>>   {
>>       int l, line_size, i, max_digits, len;
>>       uint8_t buf[16];
>>       uint64_t v;
>>       CPUState *cs = mon_get_cpu(mon);
>>   -    if (!cs && (format == 'i' || !is_physical)) {
>
> Why is the '!cs' check removed? Otherwise LGTM.

Yeah it breaks the monitor I think with should be:

  if (!cs && (space == MON_DISAS_GVA || format == 'i'))

>
>> +    if (space == MON_DISAS_GVA || format == 'i') {
>>           monitor_printf(mon, "Can not dump without CPU\n");
>>           return;
>>       }
>>         if (format == 'i') {
>> -        monitor_disas(mon, cs, addr, count, is_physical);
>> -        return;
>> +        monitor_disas(mon, cs, addr, count, space);
>>       }
>>         len = wsize * count;
>> @@ -163,15 +162,21 @@ static void memory_dump(Monitor *mon, int count, int format, int wsize,
>>       }
>>         while (len > 0) {
>> -        if (is_physical) {
>> -            monitor_printf(mon, HWADDR_FMT_plx ":", addr);
>> -        } else {
>> +        switch (space) {
>> +        case MON_DISAS_GVA:
>>               monitor_printf(mon, TARGET_FMT_lx ":", (target_ulong)addr);
>> +            break;
>> +        case MON_DISAS_GPA:
>> +            monitor_printf(mon, HWADDR_FMT_plx ":", addr);
>> +            break;
>> +        default:
>> +            g_assert_not_reached();
>>           }
>>           l = len;
>> -        if (l > line_size)
>> +        if (l > line_size) {
>>               l = line_size;
>> -        if (is_physical) {
>> +        }
>> +        if (space == MON_DISAS_GPA) {
>>               AddressSpace *as = cs ? cs->as : &address_space_memory;
>>               MemTxResult r = address_space_read(as, addr,
>>                                                  MEMTXATTRS_UNSPECIFIED, buf, l);
>> @@ -235,7 +240,7 @@ void hmp_memory_dump(Monitor *mon, const QDict *qdict)
>>       int size = qdict_get_int(qdict, "size");
>>       target_long addr = qdict_get_int(qdict, "addr");
>>   -    memory_dump(mon, count, format, size, addr, 0);
>> +    memory_dump(mon, count, format, size, addr, MON_DISAS_GVA);
>>   }


-- 
Alex Bennée
Virtualisation Tech Lead @ Linaro


^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH v17 10/16] util/log: Add -d tb_stats
  2023-10-10 12:34   ` Philippe Mathieu-Daudé
@ 2023-10-15 19:53     ` Richard Henderson
  0 siblings, 0 replies; 39+ messages in thread
From: Richard Henderson @ 2023-10-15 19:53 UTC (permalink / raw)
  To: Philippe Mathieu-Daudé, qemu-devel
  Cc: fei2.wu, Vanderson M . do Rosario, Alex Bennée

On 10/10/23 05:34, Philippe Mathieu-Daudé wrote:
> On 3/10/23 20:30, Richard Henderson wrote:
>> From: Fei Wu <fei2.wu@intel.com>
>>
>> Enable TBStatistics collection from startup.
>>
>> Signed-off-by: Vanderson M. do Rosario <vandersonmr2@gmail.com>
>> Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
>> Signed-off-by: Fei Wu <fei2.wu@intel.com>
>> [rth: Change "tb_stats_foo" to "tb_stats:foo"]
>> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
>> ---
>>   stubs/tb-stats.c  | 16 ++++++++++++++++
>>   util/log.c        | 36 +++++++++++++++++++++++++++++++-----
>>   stubs/meson.build |  1 +
>>   3 files changed, 48 insertions(+), 5 deletions(-)
>>   create mode 100644 stubs/tb-stats.c
>>
>> diff --git a/stubs/tb-stats.c b/stubs/tb-stats.c
>> new file mode 100644
>> index 0000000000..ceaa1622ce
>> --- /dev/null
>> +++ b/stubs/tb-stats.c
>> @@ -0,0 +1,16 @@
>> +/*
>> + * TB Stats Stubs
>> + *
>> + * Copyright (c) 2019
>> + * Written by Alex Bennée <alex.bennee@linaro.org>
>> + *
>> + * This code is licensed under the GNU GPL v2, or later.
>> + */
>> +
>> +
>> +#include "qemu/osdep.h"
>> +#include "tcg/tb-stats.h"
>> +
>> +void tb_stats_init(uint32_t flags)
>> +{
>> +}
> 
> We don't need this stub anymore.

Certainly we do, within the tools and tests.


r~


^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH v17 05/16] accel/tcg: Add TBStatistics structure
  2023-10-03 18:30 ` [PATCH v17 05/16] accel/tcg: Add TBStatistics structure Richard Henderson
@ 2023-10-16 14:38   ` Alex Bennée
  0 siblings, 0 replies; 39+ messages in thread
From: Alex Bennée @ 2023-10-16 14:38 UTC (permalink / raw)
  To: Richard Henderson; +Cc: fei2.wu, Vanderson M . do Rosario, qemu-devel


Richard Henderson <richard.henderson@linaro.org> writes:

> Add code to allocate, reset, and free the structures along
> with their corresponding TranslationBlocks.  We do not yet
> collect, display, or enable the statistics.
>
> Signed-off-by: Vanderson M. do Rosario <vandersonmr2@gmail.com>
> Signed-off-by: Fei Wu <fei2.wu@intel.com>
> [rth: Significantly reorganized.]
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>

Reviewed-by: Alex Bennée <alex.bennee@linaro.org>

-- 
Alex Bennée
Virtualisation Tech Lead @ Linaro


^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH v17 11/16] accel/tcg: Add tb_stats_collect and tb_stats_dump
  2023-10-03 18:30 ` [PATCH v17 11/16] accel/tcg: Add tb_stats_collect and tb_stats_dump Richard Henderson
@ 2023-10-16 14:48   ` Alex Bennée
  0 siblings, 0 replies; 39+ messages in thread
From: Alex Bennée @ 2023-10-16 14:48 UTC (permalink / raw)
  To: Richard Henderson; +Cc: qemu-devel, fei2.wu, Vanderson M. do Rosario


Richard Henderson <richard.henderson@linaro.org> writes:

> From: "Vanderson M. do Rosario" <vandersonmr2@gmail.com>
>
> These functions will be used together to output statistics.
>
> Signed-off-by: Vanderson M. do Rosario <vandersonmr2@gmail.com>
> Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
> Signed-off-by: Fei Wu <fei2.wu@intel.com>
> [rth: Split out of a larger patch]
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>  include/tcg/tb-stats.h |  25 +++++++++
>  accel/tcg/tb-stats.c   | 119 +++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 144 insertions(+)
>
> diff --git a/include/tcg/tb-stats.h b/include/tcg/tb-stats.h
> index 1ec0d13eff..edee73b63b 100644
> --- a/include/tcg/tb-stats.h
> +++ b/include/tcg/tb-stats.h
> @@ -129,4 +129,29 @@ void tb_stats_reset_tbs(void);
>  TBStatistics *tb_stats_lookup(tb_page_addr_t phys_pc, vaddr pc,
>                                uint32_t flags, uint64_t flags2);
>  
> +/**
> + * tb_stats_collect:
> + * @max: maximum number of results
> + * @sort: sort function
> + *
> + * Collect all TBStatistics and return the first @max items,
> + * as dictated by the sort criteria.
> + */
> +GPtrArray *tb_stats_collect(unsigned max, GCompareFunc sort);
> +
> +/* Sort functions for tb_stats_collect. */
> +gint tb_stats_sort_by_spills(gconstpointer, gconstpointer);
> +gint tb_stats_sort_by_coverage(gconstpointer, gconstpointer);
> +gint tb_stats_sort_by_hg(gconstpointer, gconstpointer);
> +
> +/**
> + * tb_stats_dump:
> + * @s: structure to dump
> + * @index: label to emit
> + *
> + * Return a string with the rendering of the data in @s;
> + * @index is included in the output.
> + */
> +GString *tb_stats_dump(TBStatistics *s, unsigned index);
> +
>  #endif /* TCG_TB_STATS_H */
> diff --git a/accel/tcg/tb-stats.c b/accel/tcg/tb-stats.c
> index 424c9a90ec..b2c9445b67 100644
> --- a/accel/tcg/tb-stats.c
> +++ b/accel/tcg/tb-stats.c
> @@ -83,3 +83,122 @@ TBStatistics *tb_stats_lookup(tb_page_addr_t phys_pc, vaddr pc,
>      }
>      return s;
>  }
> +
> +static void tb_stats_collect_iter(void *p, uint32_t hash, void *u)
> +{
> +    g_ptr_array_add(u, p);
> +}
> +
> +static void calculate_coverages(GPtrArray *array)
> +{
> +    double total_exec_count = 0;
> +    guint i, n = array->len;
> +
> +    for (i = 0; i < n; ++i) {
> +        TBStatistics *s = g_ptr_array_index(array, i);
> +        double avg_insns = 1;
> +        double exec_count;
> +
> +        if (s->translations.total) {
> +            avg_insns = s->code.num_guest_inst / (double)s->translations.total;
> +        }
> +        exec_count = ((double)s->executions.atomic + s->executions.normal)
> +                     / avg_insns;
> +        s->executions.coverage = exec_count;
> +        total_exec_count += exec_count;
> +    }
> +
> +    for (i = 0; i < n; ++i) {
> +        TBStatistics *s = g_ptr_array_index(array, i);
> +        s->executions.coverage /= total_exec_count;
> +    }
> +}
> +
> +GPtrArray *tb_stats_collect(unsigned max, GCompareFunc sort)
> +{
> +    GPtrArray *array = g_ptr_array_new();
> +
> +    /*
> +     * Collect all TBStatistics and sort.
> +     * Note that coverage data requires both execution and jit collection.
> +     */
> +    qht_iter(&tb_ctx.stats, tb_stats_collect_iter, array);
> +    calculate_coverages(array);
> +    g_ptr_array_sort(array, sort);
> +
> +    /* Truncate to the first MAX entries. */
> +    if (max < array->len) {
> +        g_ptr_array_set_size(array, max);
> +    }
> +    return array;
> +}
> +
> +gint tb_stats_sort_by_spills(gconstpointer p1, gconstpointer p2)
> +{
> +    const TBStatistics *s1 = *(TBStatistics **)p1;
> +    const TBStatistics *s2 = *(TBStatistics **)p2;
> +    double c1 = (double)s1->code.spills / s1->translations.total;
> +    double c2 = (double)s2->code.spills / s2->translations.total;
> +
> +    return c1 < c2 ? 1 : c1 == c2 ? 0 : -1;
> +}
> +
> +gint tb_stats_sort_by_coverage(gconstpointer p1, gconstpointer p2)
> +{
> +    const TBStatistics *s1 = *(TBStatistics **)p1;
> +    const TBStatistics *s2 = *(TBStatistics **)p2;
> +    double c1 = s1->executions.coverage;
> +    double c2 = s2->executions.coverage;
> +
> +    return c1 < c2 ? 1 : c1 == c2 ? 0 : -1;
> +}
> +
> +gint tb_stats_sort_by_hg(gconstpointer p1, gconstpointer p2)
> +{
> +    const TBStatistics *s1 = *(TBStatistics **)p1;
> +    const TBStatistics *s2 = *(TBStatistics **)p2;
> +    double c1 = (double)s1->code.out_len / s1->code.num_guest_inst;
> +    double c2 = (double)s2->code.out_len / s2->code.num_guest_inst;
> +
> +    return c1 < c2 ? 1 : c1 == c2 ? 0 : -1;
> +}
> +
> +GString *tb_stats_dump(TBStatistics *s, unsigned index)
> +{
> +    unsigned n = s->tbs->len;
> +    unsigned invalid = 0;
> +    GString *buf;
> +
> +    for (unsigned i = 0; i < n; ++i) {
> +        TranslationBlock *tb = g_ptr_array_index(s->tbs, i);
> +        if (tb->cflags & CF_INVALID) {
> +            invalid += 1;
> +        }
> +    }
> +
> +    buf = g_string_new("");
> +    g_string_append_printf(buf,
> +        "TB id:%u | phys:0x" TB_PAGE_ADDR_FMT " virt=%" VADDR_PRIx
> +        " flags:0x%08x invalid:%u/%u\n",
> +        index, s->phys_pc, s->pc, s->flags, invalid, n - invalid);

This is a little unclear in the output maybe:

  flags:0x%08x translations:%u (of which %u invalidated)

and adjust the names appropriately?

> +
> +    if (tb_stats_enabled & TB_STATS_EXEC) {
> +        g_string_append_printf(buf,
> +            "\t| exec:%lu/%lu coverage:%.2f%%\n",
> +            s->executions.normal, s->executions.atomic,
> +            s->executions.coverage * 100);
> +    }
> +
> +    if (tb_stats_enabled & TB_STATS_JIT) {
> +        g_string_append_printf(buf,
> +            "\t| trans:%lu inst: g:%lu op:%lu op_opt:%lu spills:%ld\n"
> +            "\t| h/g (host bytes / guest insts): %f\n",
> +            s->translations.total,
> +            s->code.num_guest_inst / s->translations.total,
> +            s->code.num_tcg_ops / s->translations.total,
> +            s->code.num_tcg_ops_opt / s->translations.total,
> +            s->code.spills / s->translations.total,
> +            (double)s->code.out_len / s->code.num_guest_inst);
> +    }
> +    return buf;
> +}


-- 
Alex Bennée
Virtualisation Tech Lead @ Linaro


^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH v17 14/16] monitor: Change MonitorDec.get_value return type to int64_t
  2023-10-03 18:30 ` [PATCH v17 14/16] monitor: Change MonitorDec.get_value return type to int64_t Richard Henderson
@ 2023-10-16 14:59   ` Alex Bennée
  2023-10-16 15:43   ` Alex Bennée
  1 sibling, 0 replies; 39+ messages in thread
From: Alex Bennée @ 2023-10-16 14:59 UTC (permalink / raw)
  To: Richard Henderson; +Cc: fei2.wu, qemu-devel


Richard Henderson <richard.henderson@linaro.org> writes:

> This matches the type of the pval parameter to get_monitor_def.
> This means that "monitor/hmp-target.h" itself is now target
> independent, even if monitor/hmp-target.c isn't.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>

Reviewed-by: Alex Bennée <alex.bennee@linaro.org>

-- 
Alex Bennée
Virtualisation Tech Lead @ Linaro


^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH v17 15/16] accel/tcg: Add info [tb-list|tb] commands to HMP
  2023-10-03 18:30 ` [PATCH v17 15/16] accel/tcg: Add info [tb-list|tb] commands to HMP Richard Henderson
@ 2023-10-16 15:02   ` Alex Bennée
  0 siblings, 0 replies; 39+ messages in thread
From: Alex Bennée @ 2023-10-16 15:02 UTC (permalink / raw)
  To: Richard Henderson; +Cc: qemu-devel, fei2.wu, Vanderson M. do Rosario


Richard Henderson <richard.henderson@linaro.org> writes:

> From: "Vanderson M. do Rosario" <vandersonmr2@gmail.com>
>
> These commands allow the exploration of TBs generated by the TCG.
> Understand which one hotter, with more guest/host instructions,
> and examine the guest code.
>
> The goal of this command is to allow the dynamic exploration of
> TCG behavior and code quality. Therefore, for now, a corresponding
> QMP command is not worthwhile.
>
> Example of output:
>
> ------------------------------
>
> TB id:0 | phys:0xa21f562e virt:0x0000000000000000 flags:0x00028010 0 inv/1
>         | exec:6171503732/0 guest inst cov:94.77%
>         | trans:1 ints: g:8 op:28 op_opt:24 spills:0
>         | h/g (host bytes / guest insts): 37.000000
>
> 0xa21f562e:  00002797      auipc         a5,8192           # 0xa21f762e
> 0xa21f5632:  a2278793      addi          a5,a5,-1502
> 0xa21f5636:  639c          ld            a5,0(a5)
> 0xa21f5638:  00178713      addi          a4,a5,1
> 0xa21f563c:  00002797      auipc         a5,8192           # 0xa21f763c
> 0xa21f5640:  a1478793      addi          a5,a5,-1516
> 0xa21f5644:  e398          sd            a4,0(a5)
> 0xa21f5646:  b7e5          j             -24               # 0xa21f562e
>
> Signed-off-by: Vanderson M. do Rosario <vandersonmr2@gmail.com>
> Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
> Signed-off-by: Fei Wu <fei2.wu@intel.com>
> [rth: Split out of a larger patch]
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>  accel/tcg/tb-context.h |  2 +
>  accel/tcg/monitor.c    | 91 ++++++++++++++++++++++++++++++++++++++++++
>  accel/tcg/tb-stats.c   |  2 +
>  hmp-commands-info.hx   | 14 +++++++
>  4 files changed, 109 insertions(+)
>
> diff --git a/accel/tcg/tb-context.h b/accel/tcg/tb-context.h
> index 4b1abe392b..29d87200b6 100644
> --- a/accel/tcg/tb-context.h
> +++ b/accel/tcg/tb-context.h
> @@ -35,6 +35,8 @@ struct TBContext {
>      /* statistics */
>      unsigned tb_flush_count;
>      unsigned tb_phys_invalidate_count;
> +
> +    GPtrArray *last_search;
>  };
>  
>  extern TBContext tb_ctx;
> diff --git a/accel/tcg/monitor.c b/accel/tcg/monitor.c
> index 370fea883c..1be3218715 100644
> --- a/accel/tcg/monitor.c
> +++ b/accel/tcg/monitor.c
> @@ -15,12 +15,14 @@
>  #include "qapi/qmp/qdict.h"
>  #include "monitor/monitor.h"
>  #include "monitor/hmp.h"
> +#include "monitor/hmp-target.h"
>  #include "sysemu/cpus.h"
>  #include "sysemu/cpu-timers.h"
>  #include "sysemu/tcg.h"
>  #include "tcg/tcg.h"
>  #include "tcg/tb-stats.h"
>  #include "exec/tb-flush.h"
> +#include "disas/disas.h"
>  #include "internal-common.h"
>  #include "tb-context.h"
>  
> @@ -303,10 +305,99 @@ static void hmp_tbstats(Monitor *mon, const QDict *qdict)
>                            RUN_ON_CPU_HOST_INT(flags));
>  }
>  
> +static void hmp_info_tblist(Monitor *mon, const QDict *qdict)
> +{
> +    int max;
> +    const char *sortedby_str;
> +    GCompareFunc sort;
> +    GPtrArray *array;
> +
> +    if (!tcg_enabled()) {
> +        monitor_printf(mon, "Only available with accel=tcg\n");
> +        return;
> +    }
> +    if (!tb_stats_enabled) {
> +        monitor_printf(mon, "TB statistics not being recorded\n");
> +        return;
> +    }
> +
> +    max = qdict_get_try_int(qdict, "number", 10);
> +    sortedby_str = qdict_get_try_str(qdict, "sortedby");
> +
> +    if (sortedby_str == NULL || g_str_equal(sortedby_str, "hotness")) {
> +        sort = tb_stats_sort_by_coverage;
> +    } else if (g_str_equal(sortedby_str, "hg")) {
> +        sort = tb_stats_sort_by_hg;
> +    } else if (g_str_equal(sortedby_str, "spills")) {
> +        sort = tb_stats_sort_by_spills;
> +    } else {
> +        monitor_printf(mon, "Sort options are: hotness, hg, spills\n");
> +        return;
> +    }
> +
> +    g_ptr_array_unref(tb_ctx.last_search);
> +    tb_ctx.last_search = NULL;
> +
> +    array = tb_stats_collect(max, sort);
> +    max = array->len;
> +    if (max == 0) {
> +        monitor_printf(mon, "No TB statistics collected\n");
> +        g_ptr_array_free(array, true);
> +        return;
> +    }
> +
> +    for (int i = 0; i < max; ++i) {
> +        TBStatistics *s = g_ptr_array_index(array, i);
> +        g_autoptr(GString) buf = tb_stats_dump(s, i);
> +        monitor_puts(mon, buf->str);
> +    }
> +
> +    /* Remember for the next "info tb" */
> +    tb_ctx.last_search = array;
> +}
> +
> +static void hmp_info_tb(Monitor *mon, const QDict *qdict)
> +{
> +    GPtrArray *array;
> +    int id;
> +
> +    if (!tcg_enabled()) {
> +        monitor_printf(mon, "Only available with accel=tcg\n");
> +        return;
> +    }
> +
> +    array = g_ptr_array_ref(tb_ctx.last_search);
> +    if (!array) {
> +        monitor_printf(mon, "No TB statistics collected\n");
> +        return;
> +    }
> +
> +    id = qdict_get_int(qdict, "id");
> +    if (id < array->len) {
> +        TBStatistics *s = g_ptr_array_index(array, id);
> +        g_autoptr(GString) buf = tb_stats_dump(s, id);
> +        monitor_puts(mon, buf->str);
> +
> +        for (int i = s->tbs->len - 1; i >= 0; --i) {
> +            TranslationBlock *tb = g_ptr_array_index(s->tbs, i);
> +            if (!(tb->cflags & CF_INVALID)) {
> +                monitor_disas(mon, mon_get_cpu(mon), s->phys_pc,
> +                              tb->icount, MON_DISAS_GRA);
> +            }

I'm confused by the state I've got to:

  (qemu) info tb 0
  TB id:0 | phys:0x1f59d5918 virt=0 flags:0x00000051 invalid:0/1
          | exec:57340981/0 coverage:20.73%
          | trans:1 inst: g:1 op:19 op_opt:18 spills:0
          | h/g (host bytes / guest insts): 136.000000
  0x1f59d5918:  35000354  cbnz     w20, #0x1f59d5980
  (qemu) xp/5i 0x1f59d5918
  0x1f59d5918:  00000000  .byte    0x00, 0x00, 0x00, 0x00
  0x1f59d591c:  00000000  .byte    0x00, 0x00, 0x00, 0x00
  0x1f59d5920:  00000000  .byte    0x00, 0x00, 0x00, 0x00
  0x1f59d5924:  00000000  .byte    0x00, 0x00, 0x00, 0x00
  0x1f59d5928:  00000000  .byte    0x00, 0x00, 0x00, 0x00

It seems this is the kernels busy loop (so I assume resident in memory)
but trying to dump the instructions directly it fails. I assume the
physical memory address in each case is the same right?

-- 
Alex Bennée
Virtualisation Tech Lead @ Linaro


^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH v17 14/16] monitor: Change MonitorDec.get_value return type to int64_t
  2023-10-03 18:30 ` [PATCH v17 14/16] monitor: Change MonitorDec.get_value return type to int64_t Richard Henderson
  2023-10-16 14:59   ` Alex Bennée
@ 2023-10-16 15:43   ` Alex Bennée
  1 sibling, 0 replies; 39+ messages in thread
From: Alex Bennée @ 2023-10-16 15:43 UTC (permalink / raw)
  To: Richard Henderson; +Cc: fei2.wu, qemu-devel


Richard Henderson <richard.henderson@linaro.org> writes:

> This matches the type of the pval parameter to get_monitor_def.
> This means that "monitor/hmp-target.h" itself is now target
> independent, even if monitor/hmp-target.c isn't.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>

Reviewed-by: Alex Bennée <alex.bennee@linaro.org>

-- 
Alex Bennée
Virtualisation Tech Lead @ Linaro


^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH v17 00/16] TCG code quality tracking
  2023-10-03 18:30 [PATCH v17 00/16] TCG code quality tracking Richard Henderson
                   ` (15 preceding siblings ...)
  2023-10-03 18:30 ` [PATCH v17 16/16] accel/tcg: Dump hot TBs at the end of the execution Richard Henderson
@ 2024-11-14  9:28 ` Nikita Shubin
  2025-01-21 10:22   ` Chinmay Rath
  16 siblings, 1 reply; 39+ messages in thread
From: Nikita Shubin @ 2024-11-14  9:28 UTC (permalink / raw)
  To: richard.henderson; +Cc: fei2.wu, qemu-devel, Vanderson M. do Rosario

Hello Richard and Vanderson !

Any news on this series ? It's been 26 spins already (yep i am counting
Vanderson series also).

While it's a really great idea in general, it also has great
educational purpose.

I've rebased v17 on the top of current master branch, but maybe we can
hope for another spin ? Especially with graphs, which are missing in
latest series.

---
Yours,

Nikita Shubin


^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH v17 00/16] TCG code quality tracking
  2024-11-14  9:28 ` [PATCH v17 00/16] TCG code quality tracking Nikita Shubin
@ 2025-01-21 10:22   ` Chinmay Rath
  0 siblings, 0 replies; 39+ messages in thread
From: Chinmay Rath @ 2025-01-21 10:22 UTC (permalink / raw)
  To: Nikita Shubin, richard.henderson
  Cc: fei2.wu, qemu-devel, Vanderson M. do Rosario, harshpb

Hello Richard,

Are you planning to come up with any new iterations of this patch series, or planning to merge it sometime ?
This seems to be very useful, hence wanted to know your plans with this.

Thanks,
Chinmay

On 11/14/24 14:58, Nikita Shubin wrote:
> Hello Richard and Vanderson !
>
> Any news on this series ? It's been 26 spins already (yep i am counting
> Vanderson series also).
>
> While it's a really great idea in general, it also has great
> educational purpose.
>
> I've rebased v17 on the top of current master branch, but maybe we can
> hope for another spin ? Especially with graphs, which are missing in
> latest series.
>
> ---
> Yours,
>
> Nikita Shubin
>


^ permalink raw reply	[flat|nested] 39+ messages in thread

end of thread, other threads:[~2025-01-21 10:23 UTC | newest]

Thread overview: 39+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-10-03 18:30 [PATCH v17 00/16] TCG code quality tracking Richard Henderson
2023-10-03 18:30 ` [PATCH v17 01/16] accel/tcg: Move HMP info jit and info opcount code Richard Henderson
2023-10-10 12:09   ` Philippe Mathieu-Daudé
2023-10-15 12:58   ` Alex Bennée
2023-10-03 18:30 ` [PATCH v17 02/16] tcg: Record orig_nb_ops TCGContext Richard Henderson
2023-10-15 12:57   ` Alex Bennée
2023-10-03 18:30 ` [PATCH v17 03/16] tcg: Record nb_deleted_ops in TCGContext Richard Henderson
2023-10-15 12:58   ` Alex Bennée
2023-10-03 18:30 ` [PATCH v17 04/16] tcg: Record nb_spills " Richard Henderson
2023-10-15 12:59   ` Alex Bennée
2023-10-03 18:30 ` [PATCH v17 05/16] accel/tcg: Add TBStatistics structure Richard Henderson
2023-10-16 14:38   ` Alex Bennée
2023-10-03 18:30 ` [PATCH v17 06/16] accel/tcg: Collect TB execution statistics Richard Henderson
2023-10-03 18:30 ` [PATCH v17 07/16] accel/tcg: Collect TB jit statistics Richard Henderson
2023-10-10 12:13   ` Philippe Mathieu-Daudé
2023-10-03 18:30 ` [PATCH v17 08/16] accel/tcg: Add tb_stats hmp command Richard Henderson
2023-10-03 18:30 ` [PATCH v17 09/16] util/log: Add Error argument to qemu_str_to_log_mask Richard Henderson
2023-10-10 12:55   ` Markus Armbruster
2023-10-15 18:55     ` Richard Henderson
2023-10-03 18:30 ` [PATCH v17 10/16] util/log: Add -d tb_stats Richard Henderson
2023-10-10 12:34   ` Philippe Mathieu-Daudé
2023-10-15 19:53     ` Richard Henderson
2023-10-03 18:30 ` [PATCH v17 11/16] accel/tcg: Add tb_stats_collect and tb_stats_dump Richard Henderson
2023-10-16 14:48   ` Alex Bennée
2023-10-03 18:30 ` [PATCH v17 12/16] softmmu: Export qemu_ram_ptr_length Richard Henderson
2023-10-10 12:31   ` Philippe Mathieu-Daudé
2023-10-03 18:30 ` [PATCH v17 13/16] disas: Allow monitor_disas to read from ram_addr_t Richard Henderson
2023-10-10 12:46   ` Philippe Mathieu-Daudé
2023-10-15 19:21     ` Alex Bennée
2023-10-03 18:30 ` [PATCH v17 14/16] monitor: Change MonitorDec.get_value return type to int64_t Richard Henderson
2023-10-16 14:59   ` Alex Bennée
2023-10-16 15:43   ` Alex Bennée
2023-10-03 18:30 ` [PATCH v17 15/16] accel/tcg: Add info [tb-list|tb] commands to HMP Richard Henderson
2023-10-16 15:02   ` Alex Bennée
2023-10-03 18:30 ` [PATCH v17 16/16] accel/tcg: Dump hot TBs at the end of the execution Richard Henderson
2023-10-10 12:36   ` Philippe Mathieu-Daudé
2023-10-10 13:23     ` Alex Bennée
2024-11-14  9:28 ` [PATCH v17 00/16] TCG code quality tracking Nikita Shubin
2025-01-21 10:22   ` Chinmay Rath

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).