All of lore.kernel.org
 help / color / mirror / Atom feed
From: Christopher Covington <cov@codeaurora.org>
To: qemu-devel@nongnu.org
Cc: Christopher Covington <cov@codeaurora.org>
Subject: [Qemu-devel] [RFC 08/14] Add instruction-counting infrastructure to target-arm
Date: Wed,  5 Aug 2015 12:51:17 -0400	[thread overview]
Message-ID: <1438793483-12721-9-git-send-email-cov@codeaurora.org> (raw)
In-Reply-To: <1438793483-12721-1-git-send-email-cov@codeaurora.org>

This (partially) divorces counting instructions from basic block
collection so instructions can be counted without the bbv plugin being
enabled.

Written by Aaron Lindsay.

Signed-off-by: Christopher Covington <cov@codeaurora.org>
---
 include/exec/cpu-defs.h    |  2 ++
 target-arm/helper.c        | 43 +++++++++++++++++++++++++++++++++++++++++++
 target-arm/helper.h        |  2 ++
 target-arm/translate-a64.c | 18 ++++++++++--------
 target-arm/translate.c     | 18 ++++++++++--------
 5 files changed, 67 insertions(+), 16 deletions(-)

diff --git a/include/exec/cpu-defs.h b/include/exec/cpu-defs.h
index 1eed930..9af080f 100644
--- a/include/exec/cpu-defs.h
+++ b/include/exec/cpu-defs.h
@@ -136,6 +136,8 @@ typedef struct CPUIOTLBEntry {
     CPU_COMMON_TLB                                                      \
     /* Instruction Count (for profiling) */                            	\
     uint64_t prof_ic;                                                   \
+    /* How much of prof_ic's value have we processed? */                \
+    uint64_t prof_ic_last;                                              \
     /* PC (for profiling) */                                            \
     uint64_t prof_pc;                                                   \
     /* next page start (for profiling) */                               \
diff --git a/target-arm/helper.c b/target-arm/helper.c
index 1843ec5..be3ad01 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -673,6 +673,15 @@ static inline bool arm_ccnt_enabled(CPUARMState *env)
     return true;
 }
 
+/* Called by anything that wants to be an input for event counts to the PMU
+ * (except for SWINC, event 0x000, since its events can target specific
+ * counters)
+ */
+static void pmevcntr_increment(CPUARMState *env, uint8_t event_type,
+                               uint64_t increment_by)
+{
+}
+
 void pmccntr_sync(CPUARMState *env)
 {
     uint64_t temp_ticks;
@@ -4060,6 +4069,40 @@ void HELPER(context_check_pid)(CPUARMState *env)
 
     bb_context_check_pid(env->prof_ic, pid);
 }
+
+void HELPER(update_instruction_count)(CPUARMState *env)
+{
+    if (bbtrace_initialized()) {
+      /*
+       * If the bbv plugin is compiled in and enabled, we must account for the
+       * fact that bbv_profile needs to see prof_ic before we clear it.
+       * However, it doesn't always clear the counter every time this gets
+       * called, so we must keep track of the last value seen to ensure we
+       * update the instruction counter correctly in that case.
+       */
+        increment_instruction_counters(env->prof_ic - env->prof_ic_last);
+        if (env->prof_pc && env->prof_is_jmp) {
+            // If this is the end of a basic block, zero out last_seen counter too
+            env->prof_ic_last = 0;
+        } else {
+            env->prof_ic_last = env->prof_ic;
+        }
+    } else {
+        pmevcntr_increment(env, PMU_COUNTER_TYPE_INSTRUCTIONS, env->prof_ic);
+        pmevcntr_increment(env, PMU_COUNTER_TYPE_CYCLES, env->prof_ic);
+        env->prof_ic = 0;
+    }
+}
+
+#else //!CONFIG_BBVEC
+
+void HELPER(update_instruction_count)(CPUARMState *env)
+{
+    pmevcntr_increment(env, PMU_COUNTER_TYPE_INSTRUCTIONS, env->prof_ic);
+    pmevcntr_increment(env, PMU_COUNTER_TYPE_CYCLES, env->prof_ic);
+    env->prof_ic = 0;
+}
+
 #endif //CONFIG_BBVEC
 
 /* Sign/zero extend */
diff --git a/target-arm/helper.h b/target-arm/helper.h
index 41291c9..02edf3a 100644
--- a/target-arm/helper.h
+++ b/target-arm/helper.h
@@ -43,6 +43,8 @@ DEF_HELPER_1(context_check_mode, void, env)
 DEF_HELPER_1(context_check_pid, void, env)
 #endif // CONFIG_BBVEC
 
+DEF_HELPER_1(update_instruction_count, void, env)
+
 DEF_HELPER_3(ssat, i32, env, i32, i32)
 DEF_HELPER_3(usat, i32, env, i32, i32)
 DEF_HELPER_3(ssat16, i32, env, i32, i32)
diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
index 80b27ed..f6f8832 100644
--- a/target-arm/translate-a64.c
+++ b/target-arm/translate-a64.c
@@ -55,9 +55,9 @@ static TCGv_i64 cpu_exclusive_high;
  * keep track of the current pc, so the last pc in the block can be
  * captured.   */
 static TCGv_i64 cpu_prof_pc;
-static TCGv_i64 cpu_prof_ic;
 static TCGv_i64 cpu_prof_is_jmp;
 #endif // CONFIG_BBVEC
+static TCGv_i64 cpu_prof_ic;
 #ifdef CONFIG_USER_ONLY
 static TCGv_i64 cpu_exclusive_test;
 static TCGv_i32 cpu_exclusive_info;
@@ -124,10 +124,11 @@ void a64_translate_init(void)
 
 #ifdef CONFIG_BBVEC
     // bbvec profiling globals
-    cpu_prof_ic = tcg_global_mem_new_i64(TCG_AREG0, offsetof(CPUARMState, prof_ic), "prof_ic");
     cpu_prof_pc = tcg_global_mem_new_i64(TCG_AREG0, offsetof(CPUARMState, prof_pc), "prof_pc");
     cpu_prof_is_jmp = tcg_global_mem_new_i64(TCG_AREG0, offsetof(CPUARMState, prof_is_jmp), "prof_is_jmp");
 #endif // CONFIG_BBVEC
+    cpu_prof_ic = tcg_global_mem_new_i64(TCG_AREG0,
+        offsetof(CPUARMState, prof_ic), "prof_ic");
 
     cpu_exclusive_addr = tcg_global_mem_new_i64(TCG_AREG0,
         offsetof(CPUARMState, exclusive_addr), "exclusive_addr");
@@ -210,11 +211,6 @@ void gen_a64_set_pc_im(uint64_t val)
 
 #ifdef CONFIG_BBVEC
 /* Basic block profiling functions */
-static void gen_insn_cnt_incr(CPUARMState * env, DisasContext *s)
-{
-    tcg_gen_addi_i64(cpu_prof_ic, cpu_prof_ic, 1);
-}
-
 static void gen_pc_incr(CPUARMState * env, DisasContext *s)
 {
     tcg_gen_movi_i64(cpu_prof_pc, s->pc);
@@ -226,6 +222,11 @@ static void gen_store_is_jmp(uint32_t jmp)
 }
 #endif // CONFIG_BBVEC
 
+static void gen_insn_cnt_incr(CPUARMState * env, DisasContext *s)
+{
+    tcg_gen_addi_i64(cpu_prof_ic, cpu_prof_ic, 1);
+}
+
 static void gen_exception_internal(int excp)
 {
     TCGv_i32 tcg_excp = tcg_const_i32(excp);
@@ -11068,6 +11069,7 @@ void gen_intermediate_code_internal_a64(ARMCPU *cpu,
 
     tcg_clear_temp_count();
 
+    gen_helper_update_instruction_count(cpu_env);
 #ifdef CONFIG_BBVEC
     /* Profile previously run block, check for PID change, and initialize
      * prof_is_jmp flag.   */
@@ -11082,10 +11084,10 @@ void gen_intermediate_code_internal_a64(ARMCPU *cpu,
 #ifdef CONFIG_BBVEC
         if (bbtrace_initialized()) {
             gen_helper_context_check_mode(cpu_env);
-            gen_insn_cnt_incr(env, dc);
             gen_pc_incr(env, dc);
         }
 #endif // CONFIG_BBVEC
+        gen_insn_cnt_incr(env, dc);
 
         if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
             QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
diff --git a/target-arm/translate.c b/target-arm/translate.c
index 7a19a8b..113e3b6 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -71,10 +71,10 @@ static TCGv_i32 cpu_CF, cpu_NF, cpu_VF, cpu_ZF;
 static TCGv_i64 cpu_exclusive_addr;
 static TCGv_i64 cpu_exclusive_val;
 #ifdef CONFIG_BBVEC
-static TCGv_i64 cpu_prof_ic;
 static TCGv_i64 cpu_prof_pc;
 static TCGv_i64 cpu_prof_is_jmp;
 #endif
+static TCGv_i64 cpu_prof_ic;
 #ifdef CONFIG_USER_ONLY
 static TCGv_i64 cpu_exclusive_test;
 static TCGv_i32 cpu_exclusive_info;
@@ -109,10 +109,11 @@ void arm_translate_init(void)
 
 #ifdef CONFIG_BBVEC
     // bbvec profiling globals
-    cpu_prof_ic = tcg_global_mem_new_i64(TCG_AREG0, offsetof(CPUARMState, prof_ic), "prof_ic");
     cpu_prof_pc = tcg_global_mem_new_i64(TCG_AREG0, offsetof(CPUARMState, prof_pc), "prof_pc");
     cpu_prof_is_jmp = tcg_global_mem_new_i64(TCG_AREG0, offsetof(CPUARMState, prof_is_jmp), "prof_is_jmp");
 #endif
+    cpu_prof_ic = tcg_global_mem_new_i64(TCG_AREG0,
+        offsetof(CPUARMState, prof_ic), "prof_ic");
 
     cpu_exclusive_addr = tcg_global_mem_new_i64(TCG_AREG0,
         offsetof(CPUARMState, exclusive_addr), "exclusive_addr");
@@ -194,11 +195,6 @@ static inline TCGv_i32 load_reg(DisasContext *s, int reg)
 
 #ifdef CONFIG_BBVEC
 /* Basic block profiling functions */
-static void gen_insn_cnt_incr(CPUARMState * env, DisasContext *s)
-{
-    tcg_gen_addi_i64(cpu_prof_ic, cpu_prof_ic, 1);
-}
-
 static void gen_pc_incr(CPUARMState * env, DisasContext *s)
 {
     tcg_gen_movi_i64(cpu_prof_pc, s->pc);
@@ -210,6 +206,11 @@ static void gen_store_is_jmp(uint32_t jmp)
 }
 #endif
 
+static void gen_insn_cnt_incr(CPUARMState * env, DisasContext *s)
+{
+    tcg_gen_addi_i64(cpu_prof_ic, cpu_prof_ic, 1);
+}
+
 /* Set a CPU register.  The source must be a temporary and will be
    marked as dead.  */
 static void store_reg(DisasContext *s, int reg, TCGv_i32 var)
@@ -11627,6 +11628,7 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu,
         store_cpu_field(tmp, condexec_bits);
       }
 
+    gen_helper_update_instruction_count(cpu_env);
 #ifdef CONFIG_BBVEC
     /* Profile previously run block, check for PID change, and initialize
      * prof_is_jmp flag.   */
@@ -11641,13 +11643,13 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu,
 #ifdef CONFIG_BBVEC
         if (bbtrace_initialized()) {
             gen_helper_context_check_mode(cpu_env);
-            gen_insn_cnt_incr(env, dc);
             gen_pc_incr(env, dc);
             /* FIXME: this call should not be necessary if all the cases
                where the prof_is_jmp flag gets set are correct.   */
             gen_store_is_jmp(0);
         }
 #endif
+        gen_insn_cnt_incr(env, dc);
 
 #ifdef CONFIG_USER_ONLY
         /* Intercept jump to the magic kernel page.  */
-- 
Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

  parent reply	other threads:[~2015-08-05 16:52 UTC|newest]

Thread overview: 25+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-08-05 16:51 [Qemu-devel] RFC: ARM Semihosting, PMU, and BBV Changes Christopher Covington
2015-08-05 16:51 ` [Qemu-devel] [RFC 01/14] Make unknown semihosting calls non-fatal Christopher Covington
2015-08-06  9:11   ` Alex Bennée
2015-08-06 17:59     ` Christopher Covington
2015-08-05 16:51 ` [Qemu-devel] [RFC 02/14] Added semihosting support for A64 in full-system mode Christopher Covington
2015-08-11 18:16   ` Peter Maydell
2015-08-05 16:51 ` [Qemu-devel] [RFC 03/14] Fix makefile Christopher Covington
2015-08-05 16:51 ` [Qemu-devel] [RFC 04/14] Modify load exclusive/store exclusive to use physical addresses with the monitor Christopher Covington
2015-09-23 17:19   ` [Qemu-devel] [PATCHv2] target-arm: Use physical addresses for ldrex/strex Christopher Covington
2015-08-05 16:51 ` [Qemu-devel] [RFC 05/14] Fixed TLB invalidate ops Christopher Covington
2015-08-05 16:51 ` [Qemu-devel] [RFC 06/14] Added support for block profiling for AArch32 and Aarch64 Christopher Covington
2015-08-05 16:51 ` [Qemu-devel] [RFC 07/14] Add PMU to ARM virt platform Christopher Covington
2015-08-05 16:51 ` Christopher Covington [this message]
2015-08-05 16:51 ` [Qemu-devel] [RFC 09/14] Implement remaining PMU functionality Christopher Covington
2016-02-02 21:22   ` Alistair Francis
2016-02-02 23:01     ` Christopher Covington
2016-02-02 23:22       ` Alistair Francis
2016-02-03 18:37         ` Peter Maydell
2016-02-04  0:37           ` Alistair Francis
2015-08-05 16:51 ` [Qemu-devel] [RFC 10/14] bbvec: Move mode/PID change detection to register writes Christopher Covington
2015-08-05 16:51 ` [Qemu-devel] [RFC 11/14] Print bbvec stats on 'magic' exceptions Christopher Covington
2015-08-05 16:51 ` [Qemu-devel] [RFC 12/14] bbvec: Detect mode changes after uncached_cpsr update Christopher Covington
2015-08-05 16:51 ` [Qemu-devel] [RFC 13/14] Enable negative icount values for QEMU Christopher Covington
2015-08-05 16:51 ` [Qemu-devel] [RFC 14/14] bbvec: Properly detect conditional thumb2 branching instructions Christopher Covington
2015-08-11 15:27 ` [Qemu-devel] RFC: ARM Semihosting, PMU, and BBV Changes Peter Maydell

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1438793483-12721-9-git-send-email-cov@codeaurora.org \
    --to=cov@codeaurora.org \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.