Message ID | 20231003183058.1639121-17-richard.henderson@linaro.org |
---|---|
State | New |
Headers | show |
Series | TCG code quality tracking | expand |
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, ---
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?
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++) {