* [PATCH v2 0/5] Re-write PPC64 PMU instruction count using TCG Ops
@ 2021-12-23 20:18 Daniel Henrique Barboza
2021-12-23 20:18 ` [PATCH v2 1/5] target/ppc: introduce power8-pmu-insn-cnt.c.inc Daniel Henrique Barboza
` (5 more replies)
0 siblings, 6 replies; 9+ messages in thread
From: Daniel Henrique Barboza @ 2021-12-23 20:18 UTC (permalink / raw)
To: qemu-devel
Cc: richard.henderson, Daniel Henrique Barboza, qemu-ppc, clg, david
Hi,
In this version the tedious repetition was taken away from the
code by using a helper that increments the PMCs based on specified
conditions.
As far as Avocado test goes, the performance is the same as the previous
version. All PMU-EBB kernel selftests are also passing. Basically we have
the same benefits from v1 but 150+ lines shorter.
changes from v1:
- former patches 2-6: removed
- new patch 2:
* added inc_spr_if_cond() helper
- new patch 3:
* add insn count for PMCs 1-4
- patch 4 (former 7):
* use a loop to reduce code repetition when checking for counter
overflows
- v1 link: https://lists.gnu.org/archive/html/qemu-devel/2021-12/msg03871.html
Daniel Henrique Barboza (5):
target/ppc: introduce power8-pmu-insn-cnt.c.inc
target/ppc/power8-pmu-insn-cnt: introduce inc_spr_if_cond()
target/ppc/power8-pmu-insn-cnt: add PMCs1-4 insn count
target/ppc/power8-pmu-insn-cnt: add pmu_check_overflow()
target/ppc/power8-pmu.c: remove helper_insns_inc()
target/ppc/helper.h | 2 +-
target/ppc/power8-pmu-insn-cnt.c.inc | 213 +++++++++++++++++++++++++++
target/ppc/power8-pmu.c | 60 +-------
target/ppc/translate.c | 44 +-----
4 files changed, 220 insertions(+), 99 deletions(-)
create mode 100644 target/ppc/power8-pmu-insn-cnt.c.inc
--
2.33.1
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH v2 1/5] target/ppc: introduce power8-pmu-insn-cnt.c.inc
2021-12-23 20:18 [PATCH v2 0/5] Re-write PPC64 PMU instruction count using TCG Ops Daniel Henrique Barboza
@ 2021-12-23 20:18 ` Daniel Henrique Barboza
2021-12-23 20:18 ` [PATCH v2 2/5] target/ppc/power8-pmu-insn-cnt: introduce inc_spr_if_cond() Daniel Henrique Barboza
` (4 subsequent siblings)
5 siblings, 0 replies; 9+ messages in thread
From: Daniel Henrique Barboza @ 2021-12-23 20:18 UTC (permalink / raw)
To: qemu-devel
Cc: richard.henderson, Daniel Henrique Barboza, qemu-ppc, clg, david
We're going to add a significant amount of TCG ops code for
instruction counting, eventually getting rid of the 'helper_insn_inc'
helper entirely.
Create a new file to avoid putting even more stuff on the already
crowded target/ppc/translate.c.
Signed-off-by: Daniel Henrique Barboza <danielhb413@gmail.com>
---
target/ppc/power8-pmu-insn-cnt.c.inc | 54 ++++++++++++++++++++++++++++
target/ppc/translate.c | 44 ++---------------------
2 files changed, 56 insertions(+), 42 deletions(-)
create mode 100644 target/ppc/power8-pmu-insn-cnt.c.inc
diff --git a/target/ppc/power8-pmu-insn-cnt.c.inc b/target/ppc/power8-pmu-insn-cnt.c.inc
new file mode 100644
index 0000000000..6cdf2d2d88
--- /dev/null
+++ b/target/ppc/power8-pmu-insn-cnt.c.inc
@@ -0,0 +1,54 @@
+/*
+ * IBM Power8+ PMU TCG instruction count functions
+ *
+ * Copyright IBM Corp. 2021
+ *
+ * Authors:
+ * Daniel Henrique Barboza <danielhb413@gmail.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#if defined(TARGET_PPC64)
+static void pmu_count_insns(DisasContext *ctx)
+{
+ /*
+ * Do not bother calling the helper if the PMU isn't counting
+ * instructions.
+ */
+ if (!ctx->pmu_insn_cnt) {
+ return;
+ }
+
+ #if !defined(CONFIG_USER_ONLY)
+ /*
+ * The PMU insns_inc() helper stops the internal PMU timer if a
+ * counter overflows happens. In that case, if the guest is
+ * running with icount and we do not handle it beforehand,
+ * the helper can trigger a 'bad icount read'.
+ */
+ gen_icount_io_start(ctx);
+
+ gen_helper_insns_inc(cpu_env, tcg_constant_i32(ctx->base.num_insns));
+#else
+ /*
+ * User mode can read (but not write) PMC5 and start/stop
+ * the PMU via MMCR0_FC. In this case just increment
+ * PMC5 with base.num_insns.
+ */
+ TCGv t0 = tcg_temp_new();
+
+ gen_load_spr(t0, SPR_POWER_PMC5);
+ tcg_gen_addi_tl(t0, t0, ctx->base.num_insns);
+ gen_store_spr(SPR_POWER_PMC5, t0);
+
+ tcg_temp_free(t0);
+#endif /* #if !defined(CONFIG_USER_ONLY) */
+}
+#else
+static void pmu_count_insns(DisasContext *ctx)
+{
+ return;
+}
+#endif /* #if defined(TARGET_PPC64) */
diff --git a/target/ppc/translate.c b/target/ppc/translate.c
index 114456148c..44773bc6cd 100644
--- a/target/ppc/translate.c
+++ b/target/ppc/translate.c
@@ -4183,48 +4183,8 @@ static inline void gen_update_cfar(DisasContext *ctx, target_ulong nip)
#endif
}
-#if defined(TARGET_PPC64)
-static void pmu_count_insns(DisasContext *ctx)
-{
- /*
- * Do not bother calling the helper if the PMU isn't counting
- * instructions.
- */
- if (!ctx->pmu_insn_cnt) {
- return;
- }
-
- #if !defined(CONFIG_USER_ONLY)
- /*
- * The PMU insns_inc() helper stops the internal PMU timer if a
- * counter overflows happens. In that case, if the guest is
- * running with icount and we do not handle it beforehand,
- * the helper can trigger a 'bad icount read'.
- */
- gen_icount_io_start(ctx);
-
- gen_helper_insns_inc(cpu_env, tcg_constant_i32(ctx->base.num_insns));
-#else
- /*
- * User mode can read (but not write) PMC5 and start/stop
- * the PMU via MMCR0_FC. In this case just increment
- * PMC5 with base.num_insns.
- */
- TCGv t0 = tcg_temp_new();
-
- gen_load_spr(t0, SPR_POWER_PMC5);
- tcg_gen_addi_tl(t0, t0, ctx->base.num_insns);
- gen_store_spr(SPR_POWER_PMC5, t0);
-
- tcg_temp_free(t0);
-#endif /* #if !defined(CONFIG_USER_ONLY) */
-}
-#else
-static void pmu_count_insns(DisasContext *ctx)
-{
- return;
-}
-#endif /* #if defined(TARGET_PPC64) */
+/* For pmu_count_insns */
+#include "target/ppc/power8-pmu-insn-cnt.c.inc"
static inline bool use_goto_tb(DisasContext *ctx, target_ulong dest)
{
--
2.33.1
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH v2 2/5] target/ppc/power8-pmu-insn-cnt: introduce inc_spr_if_cond()
2021-12-23 20:18 [PATCH v2 0/5] Re-write PPC64 PMU instruction count using TCG Ops Daniel Henrique Barboza
2021-12-23 20:18 ` [PATCH v2 1/5] target/ppc: introduce power8-pmu-insn-cnt.c.inc Daniel Henrique Barboza
@ 2021-12-23 20:18 ` Daniel Henrique Barboza
2021-12-23 21:14 ` Richard Henderson
2021-12-23 20:18 ` [PATCH v2 3/5] target/ppc/power8-pmu-insn-cnt: add PMCs1-4 insn count Daniel Henrique Barboza
` (3 subsequent siblings)
5 siblings, 1 reply; 9+ messages in thread
From: Daniel Henrique Barboza @ 2021-12-23 20:18 UTC (permalink / raw)
To: qemu-devel
Cc: richard.henderson, Daniel Henrique Barboza, qemu-ppc, clg, david
The code that increments a PMC is repetitive: check if a given register
has a bit/mask set or cleared and increment the counter.
inc_spr_if_cond() will help deal with this repetition. This patch also
gives a sample of how the function works by incrementing PMC5, which is
supposed to be incremented only if MMCR0_FC56 is not set.
We've also removing the call from the helper since that would cause
PMC5 to be counted twice.
Signed-off-by: Daniel Henrique Barboza <danielhb413@gmail.com>
---
target/ppc/power8-pmu-insn-cnt.c.inc | 43 ++++++++++++++++++++++------
1 file changed, 34 insertions(+), 9 deletions(-)
diff --git a/target/ppc/power8-pmu-insn-cnt.c.inc b/target/ppc/power8-pmu-insn-cnt.c.inc
index 6cdf2d2d88..3cfb801c69 100644
--- a/target/ppc/power8-pmu-insn-cnt.c.inc
+++ b/target/ppc/power8-pmu-insn-cnt.c.inc
@@ -10,6 +10,38 @@
* See the COPYING file in the top-level directory.
*/
+#if defined(TARGET_PPC64) && !defined(CONFIG_USER_ONLY)
+/*
+ * This function increments a SPR 'spr' by 'inc_val' if a given
+ * register 'reg' has a bitmask 'mask' set (cond = TCG_COND_EQ) or
+ * not set (TCG_COND_NE).
+ */
+static void inc_spr_if_cond(int reg, uint64_t mask, TCGCond cond,
+ int spr, int inc_val)
+{
+ TCGCond exit_cond = tcg_invert_cond(cond);
+ TCGLabel *l_exit;
+ TCGv t0, t1;
+
+ l_exit = gen_new_label();
+
+ t0 = tcg_temp_new();
+ gen_load_spr(t0, reg);
+ tcg_gen_andi_tl(t0, t0, mask);
+ tcg_gen_brcondi_tl(exit_cond, t0, mask, l_exit);
+
+ t1 = tcg_temp_new();
+ gen_load_spr(t1, spr);
+ tcg_gen_addi_tl(t1, t1, inc_val);
+ gen_store_spr(spr, t1);
+
+ gen_set_label(l_exit);
+
+ tcg_temp_free(t0);
+ tcg_temp_free(t1);
+}
+#endif /* #if defined(TARGET_PPC64) && !defined(CONFIG_USER_ONLY) */
+
#if defined(TARGET_PPC64)
static void pmu_count_insns(DisasContext *ctx)
{
@@ -22,15 +54,8 @@ static void pmu_count_insns(DisasContext *ctx)
}
#if !defined(CONFIG_USER_ONLY)
- /*
- * The PMU insns_inc() helper stops the internal PMU timer if a
- * counter overflows happens. In that case, if the guest is
- * running with icount and we do not handle it beforehand,
- * the helper can trigger a 'bad icount read'.
- */
- gen_icount_io_start(ctx);
-
- gen_helper_insns_inc(cpu_env, tcg_constant_i32(ctx->base.num_insns));
+ inc_spr_if_cond(SPR_POWER_MMCR0, MMCR0_FC56, TCG_COND_NE,
+ SPR_POWER_PMC5, ctx->base.num_insns);
#else
/*
* User mode can read (but not write) PMC5 and start/stop
--
2.33.1
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH v2 3/5] target/ppc/power8-pmu-insn-cnt: add PMCs1-4 insn count
2021-12-23 20:18 [PATCH v2 0/5] Re-write PPC64 PMU instruction count using TCG Ops Daniel Henrique Barboza
2021-12-23 20:18 ` [PATCH v2 1/5] target/ppc: introduce power8-pmu-insn-cnt.c.inc Daniel Henrique Barboza
2021-12-23 20:18 ` [PATCH v2 2/5] target/ppc/power8-pmu-insn-cnt: introduce inc_spr_if_cond() Daniel Henrique Barboza
@ 2021-12-23 20:18 ` Daniel Henrique Barboza
2021-12-23 20:18 ` [PATCH v2 4/5] target/ppc/power8-pmu-insn-cnt: add pmu_check_overflow() Daniel Henrique Barboza
` (2 subsequent siblings)
5 siblings, 0 replies; 9+ messages in thread
From: Daniel Henrique Barboza @ 2021-12-23 20:18 UTC (permalink / raw)
To: qemu-devel
Cc: richard.henderson, Daniel Henrique Barboza, qemu-ppc, clg, david
Use inc_spr_if_cond() to count instructions of all other PMCs that are
capable of counting instructions (all PMCs but PMC6).
Signed-off-by: Daniel Henrique Barboza <danielhb413@gmail.com>
---
target/ppc/power8-pmu-insn-cnt.c.inc | 62 ++++++++++++++++++++++++++++
1 file changed, 62 insertions(+)
diff --git a/target/ppc/power8-pmu-insn-cnt.c.inc b/target/ppc/power8-pmu-insn-cnt.c.inc
index 3cfb801c69..a5a0d42e71 100644
--- a/target/ppc/power8-pmu-insn-cnt.c.inc
+++ b/target/ppc/power8-pmu-insn-cnt.c.inc
@@ -11,6 +11,13 @@
*/
#if defined(TARGET_PPC64) && !defined(CONFIG_USER_ONLY)
+#define MMCR1_PMC1_INS_CNT 0x02000000
+#define MMCR1_PMC1_INS_CNT2 0xFE000000
+#define MMCR1_PMC2_INS_CNT 0x00020000
+#define MMCR1_PMC3_INS_CNT 0x00000200
+#define MMCR1_PMC4_INS_CNT 0x00000002
+#define MMCR1_PMC4_INS_LATCH_CNT 0x000000FA
+
/*
* This function increments a SPR 'spr' by 'inc_val' if a given
* register 'reg' has a bitmask 'mask' set (cond = TCG_COND_EQ) or
@@ -54,8 +61,63 @@ static void pmu_count_insns(DisasContext *ctx)
}
#if !defined(CONFIG_USER_ONLY)
+ TCGv t_mmcr0, t_mmcr1, t_ctrl;
+ TCGLabel *l_skip_pmc14;
+
inc_spr_if_cond(SPR_POWER_MMCR0, MMCR0_FC56, TCG_COND_NE,
SPR_POWER_PMC5, ctx->base.num_insns);
+
+ /*
+ * Skip PMC1-4 increment if:
+ * - MMCR0_FC14 is set OR
+ * - MMCR1 is cleared
+ */
+ l_skip_pmc14 = gen_new_label();
+
+ t_mmcr0 = tcg_temp_new();
+ gen_load_spr(t_mmcr0, SPR_POWER_MMCR0);
+ tcg_gen_andi_tl(t_mmcr0, t_mmcr0, MMCR0_FC14);
+ tcg_gen_brcondi_tl(TCG_COND_EQ, t_mmcr0, MMCR0_FC14, l_skip_pmc14);
+
+ t_mmcr1 = tcg_temp_new();
+ gen_load_spr(t_mmcr1, SPR_POWER_MMCR1);
+ tcg_gen_brcondi_tl(TCG_COND_EQ, t_mmcr1, 0x0, l_skip_pmc14);
+
+ /* PMC1 is incremented if PMC1SEL = 0x02 or 0xFE */
+ inc_spr_if_cond(SPR_POWER_MMCR1, MMCR1_PMC1_INS_CNT, TCG_COND_EQ,
+ SPR_POWER_PMC1, ctx->base.num_insns);
+ inc_spr_if_cond(SPR_POWER_MMCR1, MMCR1_PMC1_INS_CNT2, TCG_COND_EQ,
+ SPR_POWER_PMC1, ctx->base.num_insns);
+
+ /* PMC2 is incremented if PMC2SEL = 0x02 */
+ inc_spr_if_cond(SPR_POWER_MMCR1, MMCR1_PMC2_INS_CNT, TCG_COND_EQ,
+ SPR_POWER_PMC2, ctx->base.num_insns);
+
+ /* PMC3 is incremented if PMC3SEL = 0x02 */
+ inc_spr_if_cond(SPR_POWER_MMCR1, MMCR1_PMC3_INS_CNT, TCG_COND_EQ,
+ SPR_POWER_PMC3, ctx->base.num_insns);
+
+ /*
+ * PMC4 is incremented if PMC4SEL = 0x02 or 0xFA. 0xFA depends on the
+ * run latch (SPR_CTRL & CTRL_RUN). Check for the run latch before
+ * checking for PMC4SEL = 0xFA.
+ */
+ inc_spr_if_cond(SPR_POWER_MMCR1, MMCR1_PMC4_INS_CNT, TCG_COND_EQ,
+ SPR_POWER_PMC4, ctx->base.num_insns);
+
+ t_ctrl = tcg_temp_new();
+ gen_load_spr(t_ctrl, SPR_CTRL);
+ tcg_gen_andi_tl(t_ctrl, t_ctrl, CTRL_RUN);
+ tcg_gen_brcondi_tl(TCG_COND_NE, t_ctrl, CTRL_RUN, l_skip_pmc14);
+
+ inc_spr_if_cond(SPR_POWER_MMCR1, MMCR1_PMC4_INS_LATCH_CNT, TCG_COND_EQ,
+ SPR_POWER_PMC4, ctx->base.num_insns);
+
+ gen_set_label(l_skip_pmc14);
+
+ tcg_temp_free(t_mmcr0);
+ tcg_temp_free(t_mmcr1);
+ tcg_temp_free(t_ctrl);
#else
/*
* User mode can read (but not write) PMC5 and start/stop
--
2.33.1
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH v2 4/5] target/ppc/power8-pmu-insn-cnt: add pmu_check_overflow()
2021-12-23 20:18 [PATCH v2 0/5] Re-write PPC64 PMU instruction count using TCG Ops Daniel Henrique Barboza
` (2 preceding siblings ...)
2021-12-23 20:18 ` [PATCH v2 3/5] target/ppc/power8-pmu-insn-cnt: add PMCs1-4 insn count Daniel Henrique Barboza
@ 2021-12-23 20:18 ` Daniel Henrique Barboza
2021-12-23 20:18 ` [PATCH v2 5/5] target/ppc/power8-pmu.c: remove helper_insns_inc() Daniel Henrique Barboza
2022-01-03 6:46 ` [PATCH v2 0/5] Re-write PPC64 PMU instruction count using TCG Ops Cédric Le Goater
5 siblings, 0 replies; 9+ messages in thread
From: Daniel Henrique Barboza @ 2021-12-23 20:18 UTC (permalink / raw)
To: qemu-devel
Cc: richard.henderson, Daniel Henrique Barboza, qemu-ppc, clg, david
pmu_check_overflow() will verify for overflow in the PMC1-5 counters,
firing a performance monitor alert if an overflow happened with the
proper MMCR0 bits set.
The alert is fired by using helper_pmu_overflow().
Signed-off-by: Daniel Henrique Barboza <danielhb413@gmail.com>
---
target/ppc/helper.h | 1 +
target/ppc/power8-pmu-insn-cnt.c.inc | 76 ++++++++++++++++++++++++++++
target/ppc/power8-pmu.c | 8 +++
3 files changed, 85 insertions(+)
diff --git a/target/ppc/helper.h b/target/ppc/helper.h
index fb6cac38b4..4d8193caab 100644
--- a/target/ppc/helper.h
+++ b/target/ppc/helper.h
@@ -26,6 +26,7 @@ DEF_HELPER_2(store_mmcr1, void, env, tl)
DEF_HELPER_3(store_pmc, void, env, i32, i64)
DEF_HELPER_2(read_pmc, tl, env, i32)
DEF_HELPER_2(insns_inc, void, env, i32)
+DEF_HELPER_1(pmu_overflow, void, env)
#endif
DEF_HELPER_1(check_tlb_flush_local, void, env)
DEF_HELPER_1(check_tlb_flush_global, void, env)
diff --git a/target/ppc/power8-pmu-insn-cnt.c.inc b/target/ppc/power8-pmu-insn-cnt.c.inc
index a5a0d42e71..6e0e4e1270 100644
--- a/target/ppc/power8-pmu-insn-cnt.c.inc
+++ b/target/ppc/power8-pmu-insn-cnt.c.inc
@@ -18,6 +18,8 @@
#define MMCR1_PMC4_INS_CNT 0x00000002
#define MMCR1_PMC4_INS_LATCH_CNT 0x000000FA
+#define PMC_COUNTER_NEGATIVE_VAL 0x80000000UL
+
/*
* This function increments a SPR 'spr' by 'inc_val' if a given
* register 'reg' has a bitmask 'mask' set (cond = TCG_COND_EQ) or
@@ -47,6 +49,78 @@ static void inc_spr_if_cond(int reg, uint64_t mask, TCGCond cond,
tcg_temp_free(t0);
tcg_temp_free(t1);
}
+
+/*
+ * Check for overflow of PMC1-PMC5 counters and call the overflow
+ * helper in case any counter has overflown.
+ */
+static void pmu_check_overflow(DisasContext *ctx)
+{
+ TCGv t0, t1, t_pmc1, t_pmc;
+ TCGLabel *l_pmc_overflow;
+ TCGLabel *l_skip_pmc1_overflow;
+ TCGLabel *l_skip_overflow;
+ int i;
+
+ /*
+ * Check if we have overflow bits set and fire an overflow
+ * event if necessary. Skip directly to 'l_pmc_overflow'
+ * right after finding the first overflow.
+ */
+ l_pmc_overflow = gen_new_label();
+ l_skip_pmc1_overflow = gen_new_label();
+
+ t0 = tcg_temp_new();
+ gen_load_spr(t0, SPR_POWER_MMCR0);
+ tcg_gen_andi_tl(t0, t0, MMCR0_PMC1CE);
+ tcg_gen_brcondi_tl(TCG_COND_NE, t0, MMCR0_PMC1CE, l_skip_pmc1_overflow);
+
+ t_pmc1 = tcg_temp_new();
+ gen_load_spr(t_pmc1, SPR_POWER_PMC1);
+ tcg_gen_brcondi_tl(TCG_COND_GE, t_pmc1, PMC_COUNTER_NEGATIVE_VAL,
+ l_pmc_overflow);
+
+ gen_set_label(l_skip_pmc1_overflow);
+
+ l_skip_overflow = gen_new_label();
+
+ /*
+ * At this point we're sure PMC1 didn't overflow. If MMCR0_PMCjCE
+ * isn't set we can skip everything since PMC2-5 overflow is
+ * disabled.
+ */
+ t1 = tcg_temp_new();
+ gen_load_spr(t1, SPR_POWER_MMCR0);
+ tcg_gen_andi_tl(t1, t1, MMCR0_PMCjCE);
+ tcg_gen_brcondi_tl(TCG_COND_NE, t1, MMCR0_PMCjCE, l_skip_overflow);
+
+ for (i = SPR_POWER_PMC2; i < SPR_POWER_PMC6; i++) {
+ t_pmc = tcg_temp_new();
+ gen_load_spr(t_pmc, i);
+ tcg_gen_brcondi_tl(TCG_COND_GE, t_pmc, PMC_COUNTER_NEGATIVE_VAL,
+ l_pmc_overflow);
+ tcg_temp_free(t_pmc);
+ }
+
+ tcg_gen_br(l_skip_overflow);
+
+ gen_set_label(l_pmc_overflow);
+
+ /*
+ * The PMU overflow helper manipulates the internal PMU timer.
+ * In that case, if the guest is running with icount and we do not
+ * handle it beforehand, the helper can trigger a 'bad icount
+ * read'.
+ */
+ gen_icount_io_start(ctx);
+ gen_helper_pmu_overflow(cpu_env);
+
+ gen_set_label(l_skip_overflow);
+
+ tcg_temp_free(t0);
+ tcg_temp_free(t1);
+ tcg_temp_free(t_pmc1);
+}
#endif /* #if defined(TARGET_PPC64) && !defined(CONFIG_USER_ONLY) */
#if defined(TARGET_PPC64)
@@ -115,6 +189,8 @@ static void pmu_count_insns(DisasContext *ctx)
gen_set_label(l_skip_pmc14);
+ pmu_check_overflow(ctx);
+
tcg_temp_free(t_mmcr0);
tcg_temp_free(t_mmcr1);
tcg_temp_free(t_ctrl);
diff --git a/target/ppc/power8-pmu.c b/target/ppc/power8-pmu.c
index 08d1902cd5..6696c9b3ae 100644
--- a/target/ppc/power8-pmu.c
+++ b/target/ppc/power8-pmu.c
@@ -323,6 +323,14 @@ void helper_insns_inc(CPUPPCState *env, uint32_t num_insns)
}
}
+/* Helper to fire a PMC interrupt from TCG code */
+void helper_pmu_overflow(CPUPPCState *env)
+{
+ PowerPCCPU *cpu = env_archcpu(env);
+
+ fire_PMC_interrupt(cpu);
+}
+
static void cpu_ppc_pmu_timer_cb(void *opaque)
{
PowerPCCPU *cpu = opaque;
--
2.33.1
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH v2 5/5] target/ppc/power8-pmu.c: remove helper_insns_inc()
2021-12-23 20:18 [PATCH v2 0/5] Re-write PPC64 PMU instruction count using TCG Ops Daniel Henrique Barboza
` (3 preceding siblings ...)
2021-12-23 20:18 ` [PATCH v2 4/5] target/ppc/power8-pmu-insn-cnt: add pmu_check_overflow() Daniel Henrique Barboza
@ 2021-12-23 20:18 ` Daniel Henrique Barboza
2022-01-03 6:46 ` [PATCH v2 0/5] Re-write PPC64 PMU instruction count using TCG Ops Cédric Le Goater
5 siblings, 0 replies; 9+ messages in thread
From: Daniel Henrique Barboza @ 2021-12-23 20:18 UTC (permalink / raw)
To: qemu-devel
Cc: richard.henderson, Daniel Henrique Barboza, qemu-ppc, clg, david
After moving all the instruction counting to TCG Ops code
this helper is not needed anymore.
Signed-off-by: Daniel Henrique Barboza <danielhb413@gmail.com>
---
target/ppc/helper.h | 1 -
target/ppc/power8-pmu-insn-cnt.c.inc | 4 --
target/ppc/power8-pmu.c | 60 ----------------------------
3 files changed, 65 deletions(-)
diff --git a/target/ppc/helper.h b/target/ppc/helper.h
index 4d8193caab..de80e82ebe 100644
--- a/target/ppc/helper.h
+++ b/target/ppc/helper.h
@@ -25,7 +25,6 @@ DEF_HELPER_2(store_mmcr0, void, env, tl)
DEF_HELPER_2(store_mmcr1, void, env, tl)
DEF_HELPER_3(store_pmc, void, env, i32, i64)
DEF_HELPER_2(read_pmc, tl, env, i32)
-DEF_HELPER_2(insns_inc, void, env, i32)
DEF_HELPER_1(pmu_overflow, void, env)
#endif
DEF_HELPER_1(check_tlb_flush_local, void, env)
diff --git a/target/ppc/power8-pmu-insn-cnt.c.inc b/target/ppc/power8-pmu-insn-cnt.c.inc
index 6e0e4e1270..adb796c1c1 100644
--- a/target/ppc/power8-pmu-insn-cnt.c.inc
+++ b/target/ppc/power8-pmu-insn-cnt.c.inc
@@ -126,10 +126,6 @@ static void pmu_check_overflow(DisasContext *ctx)
#if defined(TARGET_PPC64)
static void pmu_count_insns(DisasContext *ctx)
{
- /*
- * Do not bother calling the helper if the PMU isn't counting
- * instructions.
- */
if (!ctx->pmu_insn_cnt) {
return;
}
diff --git a/target/ppc/power8-pmu.c b/target/ppc/power8-pmu.c
index 6696c9b3ae..bfc052b49e 100644
--- a/target/ppc/power8-pmu.c
+++ b/target/ppc/power8-pmu.c
@@ -135,52 +135,6 @@ bool pmu_insn_cnt_enabled(CPUPPCState *env)
return false;
}
-static bool pmu_increment_insns(CPUPPCState *env, uint32_t num_insns)
-{
- bool overflow_triggered = false;
- int sprn;
-
- /* PMC6 never counts instructions */
- for (sprn = SPR_POWER_PMC1; sprn <= SPR_POWER_PMC5; sprn++) {
- PMUEventType evt_type = pmc_get_event(env, sprn);
- bool insn_event = evt_type == PMU_EVENT_INSTRUCTIONS ||
- evt_type == PMU_EVENT_INSN_RUN_LATCH;
-
- if (pmc_is_inactive(env, sprn) || !insn_event) {
- continue;
- }
-
- if (evt_type == PMU_EVENT_INSTRUCTIONS) {
- env->spr[sprn] += num_insns;
- }
-
- if (evt_type == PMU_EVENT_INSN_RUN_LATCH &&
- env->spr[SPR_CTRL] & CTRL_RUN) {
- env->spr[sprn] += num_insns;
- }
-
- if (env->spr[sprn] >= PMC_COUNTER_NEGATIVE_VAL &&
- pmc_has_overflow_enabled(env, sprn)) {
-
- overflow_triggered = true;
-
- /*
- * The real PMU will always trigger a counter overflow with
- * PMC_COUNTER_NEGATIVE_VAL. We don't have an easy way to
- * do that since we're counting block of instructions at
- * the end of each translation block, and we're probably
- * passing this value at this point.
- *
- * Let's write PMC_COUNTER_NEGATIVE_VAL to the overflowed
- * counter to simulate what the real hardware would do.
- */
- env->spr[sprn] = PMC_COUNTER_NEGATIVE_VAL;
- }
- }
-
- return overflow_triggered;
-}
-
static void pmu_update_cycles(CPUPPCState *env)
{
uint64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
@@ -309,20 +263,6 @@ static void fire_PMC_interrupt(PowerPCCPU *cpu)
return;
}
-/* This helper assumes that the PMC is running. */
-void helper_insns_inc(CPUPPCState *env, uint32_t num_insns)
-{
- bool overflow_triggered;
- PowerPCCPU *cpu;
-
- overflow_triggered = pmu_increment_insns(env, num_insns);
-
- if (overflow_triggered) {
- cpu = env_archcpu(env);
- fire_PMC_interrupt(cpu);
- }
-}
-
/* Helper to fire a PMC interrupt from TCG code */
void helper_pmu_overflow(CPUPPCState *env)
{
--
2.33.1
^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH v2 2/5] target/ppc/power8-pmu-insn-cnt: introduce inc_spr_if_cond()
2021-12-23 20:18 ` [PATCH v2 2/5] target/ppc/power8-pmu-insn-cnt: introduce inc_spr_if_cond() Daniel Henrique Barboza
@ 2021-12-23 21:14 ` Richard Henderson
0 siblings, 0 replies; 9+ messages in thread
From: Richard Henderson @ 2021-12-23 21:14 UTC (permalink / raw)
To: Daniel Henrique Barboza, qemu-devel; +Cc: qemu-ppc, clg, david
On 12/23/21 12:18 PM, Daniel Henrique Barboza wrote:
> The code that increments a PMC is repetitive: check if a given register
> has a bit/mask set or cleared and increment the counter.
>
> inc_spr_if_cond() will help deal with this repetition. This patch also
> gives a sample of how the function works by incrementing PMC5, which is
> supposed to be incremented only if MMCR0_FC56 is not set.
>
> We've also removing the call from the helper since that would cause
> PMC5 to be counted twice.
>
> Signed-off-by: Daniel Henrique Barboza <danielhb413@gmail.com>
> ---
> target/ppc/power8-pmu-insn-cnt.c.inc | 43 ++++++++++++++++++++++------
> 1 file changed, 34 insertions(+), 9 deletions(-)
>
> diff --git a/target/ppc/power8-pmu-insn-cnt.c.inc b/target/ppc/power8-pmu-insn-cnt.c.inc
> index 6cdf2d2d88..3cfb801c69 100644
> --- a/target/ppc/power8-pmu-insn-cnt.c.inc
> +++ b/target/ppc/power8-pmu-insn-cnt.c.inc
> @@ -10,6 +10,38 @@
> * See the COPYING file in the top-level directory.
> */
>
> +#if defined(TARGET_PPC64) && !defined(CONFIG_USER_ONLY)
> +/*
> + * This function increments a SPR 'spr' by 'inc_val' if a given
> + * register 'reg' has a bitmask 'mask' set (cond = TCG_COND_EQ) or
> + * not set (TCG_COND_NE).
> + */
> +static void inc_spr_if_cond(int reg, uint64_t mask, TCGCond cond,
> + int spr, int inc_val)
> +{
> + TCGCond exit_cond = tcg_invert_cond(cond);
> + TCGLabel *l_exit;
> + TCGv t0, t1;
> +
> + l_exit = gen_new_label();
> +
> + t0 = tcg_temp_new();
> + gen_load_spr(t0, reg);
> + tcg_gen_andi_tl(t0, t0, mask);
> + tcg_gen_brcondi_tl(exit_cond, t0, mask, l_exit);
When testing a single bit, compare against 0, not the bit.
> + t1 = tcg_temp_new();
> + gen_load_spr(t1, spr);
> + tcg_gen_addi_tl(t1, t1, inc_val);
> + gen_store_spr(spr, t1);
It will probably perform better to make this a true conditional add.
I.e.
gen_load_spr(t0, spr);
tcg_gen_addi_tl(t1, t0, inc);
tcg_gen_movcond_tl(cond, t0, reg, zero, t1, t0);
gen_store_spr(spr, t0);
> - /*
> - * The PMU insns_inc() helper stops the internal PMU timer if a
> - * counter overflows happens. In that case, if the guest is
> - * running with icount and we do not handle it beforehand,
> - * the helper can trigger a 'bad icount read'.
> - */
> - gen_icount_io_start(ctx);
Removing this is incorrect.
> - gen_helper_insns_inc(cpu_env, tcg_constant_i32(ctx->base.num_insns));
> + inc_spr_if_cond(SPR_POWER_MMCR0, MMCR0_FC56, TCG_COND_NE,
> + SPR_POWER_PMC5, ctx->base.num_insns);
This is non-bisectable. You're removing support for all registers and only adding back
PMC5. You add them all back before the end of the series, but the middle patches do not
behave correctly.
r~
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v2 0/5] Re-write PPC64 PMU instruction count using TCG Ops
2021-12-23 20:18 [PATCH v2 0/5] Re-write PPC64 PMU instruction count using TCG Ops Daniel Henrique Barboza
` (4 preceding siblings ...)
2021-12-23 20:18 ` [PATCH v2 5/5] target/ppc/power8-pmu.c: remove helper_insns_inc() Daniel Henrique Barboza
@ 2022-01-03 6:46 ` Cédric Le Goater
2022-01-03 18:14 ` Daniel Henrique Barboza
5 siblings, 1 reply; 9+ messages in thread
From: Cédric Le Goater @ 2022-01-03 6:46 UTC (permalink / raw)
To: Daniel Henrique Barboza, qemu-devel; +Cc: richard.henderson, qemu-ppc, david
On 12/23/21 21:18, Daniel Henrique Barboza wrote:
> Hi,
>
> In this version the tedious repetition was taken away from the
> code by using a helper that increments the PMCs based on specified
> conditions.
>
> As far as Avocado test goes, the performance is the same as the previous
> version. All PMU-EBB kernel selftests are also passing. Basically we have
> the same benefits from v1 but 150+ lines shorter.
>
> changes from v1:
> - former patches 2-6: removed
> - new patch 2:
> * added inc_spr_if_cond() helper
> - new patch 3:
> * add insn count for PMCs 1-4
> - patch 4 (former 7):
> * use a loop to reduce code repetition when checking for counter
> overflows
> - v1 link: https://lists.gnu.org/archive/html/qemu-devel/2021-12/msg03871.html
I understand that you are going to rebase on top of Richard's patchset.
and so this series is now obsolete ?
Thanks,
C.
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v2 0/5] Re-write PPC64 PMU instruction count using TCG Ops
2022-01-03 6:46 ` [PATCH v2 0/5] Re-write PPC64 PMU instruction count using TCG Ops Cédric Le Goater
@ 2022-01-03 18:14 ` Daniel Henrique Barboza
0 siblings, 0 replies; 9+ messages in thread
From: Daniel Henrique Barboza @ 2022-01-03 18:14 UTC (permalink / raw)
To: Cédric Le Goater, qemu-devel; +Cc: richard.henderson, qemu-ppc, david
On 1/3/22 03:46, Cédric Le Goater wrote:
> On 12/23/21 21:18, Daniel Henrique Barboza wrote:
>> Hi,
>>
>> In this version the tedious repetition was taken away from the
>> code by using a helper that increments the PMCs based on specified
>> conditions.
>>
>> As far as Avocado test goes, the performance is the same as the previous
>> version. All PMU-EBB kernel selftests are also passing. Basically we have
>> the same benefits from v1 but 150+ lines shorter.
>>
>> changes from v1:
>> - former patches 2-6: removed
>> - new patch 2:
>> * added inc_spr_if_cond() helper
>> - new patch 3:
>> * add insn count for PMCs 1-4
>> - patch 4 (former 7):
>> * use a loop to reduce code repetition when checking for counter
>> overflows
>> - v1 link: https://lists.gnu.org/archive/html/qemu-devel/2021-12/msg03871.html
>
> I understand that you are going to rebase on top of Richard's patchset.
> and so this series is now obsolete ?
Yes it is. I'll post a new version of Richard's patchset shortly.
Daniel
>
> Thanks,
>
> C.
>
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2022-01-03 18:16 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-12-23 20:18 [PATCH v2 0/5] Re-write PPC64 PMU instruction count using TCG Ops Daniel Henrique Barboza
2021-12-23 20:18 ` [PATCH v2 1/5] target/ppc: introduce power8-pmu-insn-cnt.c.inc Daniel Henrique Barboza
2021-12-23 20:18 ` [PATCH v2 2/5] target/ppc/power8-pmu-insn-cnt: introduce inc_spr_if_cond() Daniel Henrique Barboza
2021-12-23 21:14 ` Richard Henderson
2021-12-23 20:18 ` [PATCH v2 3/5] target/ppc/power8-pmu-insn-cnt: add PMCs1-4 insn count Daniel Henrique Barboza
2021-12-23 20:18 ` [PATCH v2 4/5] target/ppc/power8-pmu-insn-cnt: add pmu_check_overflow() Daniel Henrique Barboza
2021-12-23 20:18 ` [PATCH v2 5/5] target/ppc/power8-pmu.c: remove helper_insns_inc() Daniel Henrique Barboza
2022-01-03 6:46 ` [PATCH v2 0/5] Re-write PPC64 PMU instruction count using TCG Ops Cédric Le Goater
2022-01-03 18:14 ` Daniel Henrique Barboza
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.