@@ -166,6 +166,15 @@ typedef struct CPUTLBCommon {
* mmu_idx may be discarded. Protected by tlb_c.lock.
*/
uint16_t pending_flush;
+
+ /*
+ * Statistics. These are not lock protected, but are read and
+ * written atomically. This allows the monitor to print a snapshot
+ * of the stats without interfering with the cpu.
+ */
+ size_t full_flush_count;
+ size_t part_flush_count;
+ size_t elide_flush_count;
} CPUTLBCommon;
/*
@@ -179,8 +188,7 @@ typedef struct CPUTLBCommon {
CPUTLBEntry tlb_table[NB_MMU_MODES][CPU_TLB_SIZE]; \
CPUTLBEntry tlb_v_table[NB_MMU_MODES][CPU_VTLB_SIZE]; \
CPUIOTLBEntry iotlb[NB_MMU_MODES][CPU_TLB_SIZE]; \
- CPUIOTLBEntry iotlb_v[NB_MMU_MODES][CPU_VTLB_SIZE]; \
- size_t tlb_flush_count;
+ CPUIOTLBEntry iotlb_v[NB_MMU_MODES][CPU_VTLB_SIZE];
#else
@@ -23,6 +23,6 @@
/* cputlb.c */
void tlb_protect_code(ram_addr_t ram_addr);
void tlb_unprotect_code(ram_addr_t ram_addr);
-size_t tlb_flush_count(void);
+void tlb_flush_counts(size_t *full, size_t *part, size_t *elide);
#endif
#endif
@@ -100,17 +100,21 @@ static void flush_all_helper(CPUState *src, run_on_cpu_func fn,
}
}
-size_t tlb_flush_count(void)
+void tlb_flush_counts(size_t *pfull, size_t *ppart, size_t *pelide)
{
CPUState *cpu;
- size_t count = 0;
+ size_t full = 0, part = 0, elide = 0;
CPU_FOREACH(cpu) {
CPUArchState *env = cpu->env_ptr;
- count += atomic_read(&env->tlb_flush_count);
+ full += atomic_read(&env->tlb_c.full_flush_count);
+ part += atomic_read(&env->tlb_c.part_flush_count);
+ elide += atomic_read(&env->tlb_c.elide_flush_count);
}
- return count;
+ *pfull = full;
+ *ppart = part;
+ *pelide = elide;
}
static void tlb_flush_one_mmuidx_locked(CPUArchState *env, int mmu_idx)
@@ -145,7 +149,11 @@ static void tlb_flush_by_mmuidx_async_work(CPUState *cpu, run_on_cpu_data data)
cpu_tb_jmp_cache_clear(cpu);
if (mmu_idx_bitmask == ALL_MMUIDX_BITS) {
- atomic_set(&env->tlb_flush_count, env->tlb_flush_count + 1);
+ atomic_set(&env->tlb_c.full_flush_count,
+ env->tlb_c.full_flush_count + 1);
+ } else {
+ atomic_set(&env->tlb_c.part_flush_count,
+ env->tlb_c.part_flush_count + ctpop16(mmu_idx_bitmask));
}
}
@@ -2290,7 +2290,7 @@ void dump_exec_info(FILE *f, fprintf_function cpu_fprintf)
{
struct tb_tree_stats tst = {};
struct qht_stats hst;
- size_t nb_tbs;
+ size_t nb_tbs, flush_full, flush_part, flush_elide;
tcg_tb_foreach(tb_tree_stats_iter, &tst);
nb_tbs = tst.nb_tbs;
@@ -2326,7 +2326,11 @@ void dump_exec_info(FILE *f, fprintf_function cpu_fprintf)
cpu_fprintf(f, "TB flush count %u\n",
atomic_read(&tb_ctx.tb_flush_count));
cpu_fprintf(f, "TB invalidate count %zu\n", tcg_tb_phys_invalidate_count());
- cpu_fprintf(f, "TLB flush count %zu\n", tlb_flush_count());
+
+ tlb_flush_counts(&flush_full, &flush_part, &flush_elide);
+ cpu_fprintf(f, "TLB full flushes %zu\n", flush_full);
+ cpu_fprintf(f, "TLB partial flushes %zu\n", flush_part);
+ cpu_fprintf(f, "TLB elided flushes %zu\n", flush_elide);
tcg_dump_info(f, cpu_fprintf);
}