@@ -25,6 +25,7 @@
#include "trace.h"
#include "disas/disas.h"
#include "exec/exec-all.h"
+#include "exec/tb-stats.h"
#include "tcg/tcg.h"
#include "qemu/atomic.h"
#include "qemu/rcu.h"
@@ -562,7 +563,12 @@ void cpu_exec_step_atomic(CPUState *cpu)
mmap_unlock();
}
+ if (tb_stats_enabled(tb, TB_EXEC_STATS)) {
+ tb->tb_stats->executions.atomic++;
+ }
+
cpu_exec_enter(cpu);
+
/* execute the generated code */
trace_exec_tb(tb, pc);
cpu_tb_exec(cpu, tb, &tb_exit);
@@ -20,6 +20,7 @@ enum TBStatsStatus {
};
static enum TBStatsStatus tcg_collect_tb_stats;
+static uint32_t tbstats_flag;
void init_tb_stats_htable(void)
{
@@ -44,3 +45,20 @@ bool tb_stats_collection_enabled(void)
{
return tcg_collect_tb_stats == TB_STATS_RUNNING;
}
+
+uint32_t get_tbstats_flag(void)
+{
+ return tbstats_flag;
+}
+
+void set_tbstats_flag(uint32_t flag)
+{
+ tbstats_flag = flag;
+}
+
+bool tb_stats_enabled(TranslationBlock *tb, uint32_t flag)
+{
+ return tb_stats_collection_enabled() &&
+ tb->tb_stats &&
+ (tbstats_flag & flag);
+}
@@ -27,6 +27,7 @@
#include "exec/helper-proto.h"
#include "exec/cpu_ldst.h"
#include "exec/exec-all.h"
+#include "exec/tb-stats.h"
#include "disas/disas.h"
#include "exec/log.h"
#include "tcg/tcg.h"
@@ -382,9 +382,11 @@ TranslationBlock *tb_gen_code(CPUState *cpu,
/*
* We want to fetch the stats structure before we start code
* generation so we can count interesting things about this
- * generation.
+ * generation. If dfilter is in effect we will only collect stats
+ * for the specified range.
*/
- if (tb_stats_collection_enabled()) {
+ if (tb_stats_collection_enabled() &&
+ qemu_log_in_addr_range(tb->pc)) {
tb->tb_stats = tb_get_stats(phys_pc, cflags & CF_PCREL ? 0 : pc,
cs_base, flags);
} else {
@@ -11,6 +11,7 @@
#include "qemu/error-report.h"
#include "tcg/tcg.h"
#include "tcg/tcg-op.h"
+#include "tcg/tcg-temp-internal.h"
#include "exec/exec-all.h"
#include "exec/gen-icount.h"
#include "exec/log.h"
@@ -18,6 +19,29 @@
#include "exec/plugin-gen.h"
#include "exec/replay-core.h"
+static void gen_tb_exec_count(TranslationBlock *tb)
+{
+ if (tb_stats_enabled(tb, TB_EXEC_STATS)) {
+ TCGv_ptr ptr = tcg_temp_ebb_new_ptr();
+
+ tcg_gen_movi_ptr(ptr, (intptr_t)&tb->tb_stats->executions.normal);
+ if (sizeof(tb->tb_stats->executions.normal) == 4) {
+ TCGv_i32 t = tcg_temp_ebb_new_i32();
+ tcg_gen_ld_i32(t, ptr, 0);
+ tcg_gen_addi_i32(t, t, 1);
+ tcg_gen_st_i32(t, ptr, 0);
+ tcg_temp_free_i32(t);
+ } else {
+ TCGv_i64 t = tcg_temp_ebb_new_i64();
+ tcg_gen_ld_i64(t, ptr, 0);
+ tcg_gen_addi_i64(t, t, 1);
+ tcg_gen_st_i64(t, ptr, 0);
+ tcg_temp_free_i64(t);
+ }
+ tcg_temp_free_ptr(ptr);
+ }
+}
+
bool translator_use_goto_tb(DisasContextBase *db, target_ulong dest)
{
/* Suppress goto_tb if requested. */
@@ -56,6 +80,7 @@ void translator_loop(CPUState *cpu, TranslationBlock *tb, int *max_insns,
/* Start translating. */
gen_tb_start(db->tb);
+ gen_tb_exec_count(tb);
ops->tb_start(db, cpu);
tcg_debug_assert(db->is_jmp == DISAS_NEXT); /* no early exit */
@@ -2,6 +2,7 @@
#define GEN_ICOUNT_H
#include "exec/exec-all.h"
+#include "exec/tb-stats.h"
/* Helpers for instruction counting code generation. */
@@ -11,9 +11,15 @@
#ifndef TB_STATS_FLAGS
#define TB_STATS_FLAGS
+#define TB_NONE_STATS (0) /* no stats */
+#define TB_EXEC_STATS (1 << 0)
+
/* TBStatistic collection controls */
void enable_collect_tb_stats(void);
void disable_collect_tb_stats(void);
bool tb_stats_collection_enabled(void);
+uint32_t get_tbstats_flag(void);
+void set_tbstats_flag(uint32_t flag);
+
#endif
@@ -47,10 +47,18 @@ struct TBStatistics {
uint32_t flags;
/* cs_base isn't included in the hash but we do check for matches */
target_ulong cs_base;
+
+ /* Execution stats */
+ struct {
+ unsigned long normal;
+ unsigned long atomic;
+ } executions;
+
};
bool tb_stats_cmp(const void *ap, const void *bp);
void init_tb_stats_htable(void);
+bool tb_stats_enabled(TranslationBlock *tb, uint32_t flag);
#endif