[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH v4 06/15] target/ppc: initialize PMUEvents on MMCR1 write
From: |
Daniel Henrique Barboza |
Subject: |
[PATCH v4 06/15] target/ppc: initialize PMUEvents on MMCR1 write |
Date: |
Sun, 17 Oct 2021 22:01:24 -0300 |
The value of MMCR1 determines the events that are going to be sampled by
the programmable counters (PMCs 1-4). PMCs 5 and 6 are always counting
instructions and cycles respectively and aren't affected by MMCR1.
This patch adds a helper to initialize PMCs 1-4 PMUEvents when writing
the MMCR1 register. The following events are considered valid at this
moment:
- For PMCs 1-4, event 0x2 is the implementation dependent value of
PMU_EVENT_INSTRUCTIONS and event 0x1E is the implementation dependent
value of PMU_EVENT_CYCLES. These events are supported by IBM Power chips
since Power8, at least, and the Linux Perf driver makes use of these
events until kernel v5.15;
- for PMC1, event 0xF0 is the architected PowerISA event for cycles.
Event 0xFE is the architected PowerISA event for instructions.
Signed-off-by: Daniel Henrique Barboza <danielhb413@gmail.com>
---
target/ppc/cpu.h | 11 ++++++
target/ppc/cpu_init.c | 2 +-
target/ppc/helper.h | 1 +
target/ppc/power8-pmu-regs.c.inc | 16 +++++++++
target/ppc/power8-pmu.c | 59 ++++++++++++++++++++++++++++++++
target/ppc/spr_tcg.h | 1 +
6 files changed, 89 insertions(+), 1 deletion(-)
diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
index 21591ec725..aaf503c8ff 100644
--- a/target/ppc/cpu.h
+++ b/target/ppc/cpu.h
@@ -382,6 +382,17 @@ typedef struct PMUEvent {
#define MMCR2_UREG_MASK (MMCR2_FC1P0 | MMCR2_FC2P0 | MMCR2_FC3P0 | \
MMCR2_FC4P0 | MMCR2_FC5P0 | MMCR2_FC6P0)
+#define MMCR1_EVT_SIZE 8
+/* extract64() does a right shift before extracting */
+#define MMCR1_PMC1SEL_START 32
+#define MMCR1_PMC1EVT_EXTR (64 - MMCR1_PMC1SEL_START - MMCR1_EVT_SIZE)
+#define MMCR1_PMC2SEL_START 40
+#define MMCR1_PMC2EVT_EXTR (64 - MMCR1_PMC2SEL_START - MMCR1_EVT_SIZE)
+#define MMCR1_PMC3SEL_START 48
+#define MMCR1_PMC3EVT_EXTR (64 - MMCR1_PMC3SEL_START - MMCR1_EVT_SIZE)
+#define MMCR1_PMC4SEL_START 56
+#define MMCR1_PMC4EVT_EXTR (64 - MMCR1_PMC4SEL_START - MMCR1_EVT_SIZE)
+
/* LPCR bits */
#define LPCR_VPM0 PPC_BIT(0)
#define LPCR_VPM1 PPC_BIT(1)
diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c
index 65545ba9ca..7c9ed5dfe1 100644
--- a/target/ppc/cpu_init.c
+++ b/target/ppc/cpu_init.c
@@ -6824,7 +6824,7 @@ static void register_book3s_pmu_sup_sprs(CPUPPCState *env)
KVM_REG_PPC_MMCR0, 0x00000000);
spr_register_kvm(env, SPR_POWER_MMCR1, "MMCR1",
SPR_NOACCESS, SPR_NOACCESS,
- &spr_read_generic, &spr_write_generic,
+ &spr_read_generic, &spr_write_MMCR1,
KVM_REG_PPC_MMCR1, 0x00000000);
spr_register_kvm(env, SPR_POWER_MMCRA, "MMCRA",
SPR_NOACCESS, SPR_NOACCESS,
diff --git a/target/ppc/helper.h b/target/ppc/helper.h
index 4076aa281e..fc5bae8330 100644
--- a/target/ppc/helper.h
+++ b/target/ppc/helper.h
@@ -20,6 +20,7 @@ DEF_HELPER_1(rfscv, void, env)
DEF_HELPER_1(hrfid, void, env)
DEF_HELPER_2(store_lpcr, void, env, tl)
DEF_HELPER_2(store_pcr, void, env, tl)
+DEF_HELPER_2(store_mmcr1, void, env, tl)
#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-regs.c.inc b/target/ppc/power8-pmu-regs.c.inc
index 7391851238..a0a64e76ad 100644
--- a/target/ppc/power8-pmu-regs.c.inc
+++ b/target/ppc/power8-pmu-regs.c.inc
@@ -219,6 +219,17 @@ void spr_write_PMC56_ureg(DisasContext *ctx, int sprn, int
gprn)
/* The remaining steps are similar to PMCs 1-4 userspace write */
spr_write_PMC14_ureg(ctx, sprn, gprn);
}
+
+void spr_write_MMCR1(DisasContext *ctx, int sprn, int gprn)
+{
+ gen_helper_store_mmcr1(cpu_env, cpu_gpr[gprn]);
+
+ /*
+ * Writes in MMCR1 must force a new translation block, allowing
+ * the PMU to calculate events with more accuracy.
+ */
+ ctx->base.is_jmp = DISAS_EXIT_UPDATE;
+}
#else
void spr_read_MMCR0_ureg(DisasContext *ctx, int gprn, int sprn)
{
@@ -259,4 +270,9 @@ void spr_write_PMC56_ureg(DisasContext *ctx, int sprn, int
gprn)
{
spr_noaccess(ctx, gprn, sprn);
}
+
+void spr_write_MMCR1(DisasContext *ctx, int sprn, int gprn)
+{
+ spr_write_generic(ctx, sprn, gprn);
+}
#endif /* defined(TARGET_PPC64) && !defined(CONFIG_USER_ONLY) */
diff --git a/target/ppc/power8-pmu.c b/target/ppc/power8-pmu.c
index 42452b5870..9a0b544b04 100644
--- a/target/ppc/power8-pmu.c
+++ b/target/ppc/power8-pmu.c
@@ -23,6 +23,65 @@
#if defined(TARGET_PPC64) && !defined(CONFIG_USER_ONLY)
+/*
+ * For PMCs 1-4, IBM POWER chips has support for an implementation
+ * dependent event, 0x1E, that enables cycle counting. The Linux kernel
+ * makes extensive use of 0x1E, so let's also support it.
+ *
+ * Likewise, event 0x2 is an implementation-dependent event that IBM
+ * POWER chips implement (at least since POWER8) that is equivalent to
+ * PM_INST_CMPL. Let's support this event on PMCs 1-4 as well.
+ */
+static void define_enabled_events(CPUPPCState *env)
+{
+ uint8_t mmcr1_evt_extr[] = { MMCR1_PMC1EVT_EXTR, MMCR1_PMC2EVT_EXTR,
+ MMCR1_PMC3EVT_EXTR, MMCR1_PMC4EVT_EXTR };
+ int i;
+
+ for (i = 0; i < 4; i++) {
+ uint8_t pmcsel = extract64(env->spr[SPR_POWER_MMCR1],
+ mmcr1_evt_extr[i],
+ MMCR1_EVT_SIZE);
+ PMUEvent *event = &env->pmu_events[i];
+
+ switch (pmcsel) {
+ case 0x2:
+ event->type = PMU_EVENT_INSTRUCTIONS;
+ break;
+ case 0x1E:
+ event->type = PMU_EVENT_CYCLES;
+ break;
+ case 0xF0:
+ /*
+ * PMC1SEL = 0xF0 is the architected PowerISA v3.1
+ * event that counts cycles using PMC1.
+ */
+ if (event->sprn == SPR_POWER_PMC1) {
+ event->type = PMU_EVENT_CYCLES;
+ }
+ break;
+ case 0xFE:
+ /*
+ * PMC1SEL = 0xFE is the architected PowerISA v3.1
+ * event to sample instructions using PMC1.
+ */
+ if (event->sprn == SPR_POWER_PMC1) {
+ event->type = PMU_EVENT_INSTRUCTIONS;
+ }
+ break;
+ default:
+ event->type = PMU_EVENT_INVALID;
+ }
+ }
+}
+
+void helper_store_mmcr1(CPUPPCState *env, uint64_t value)
+{
+ env->spr[SPR_POWER_MMCR1] = value;
+
+ define_enabled_events(env);
+}
+
static void fire_PMC_interrupt(PowerPCCPU *cpu)
{
CPUPPCState *env = &cpu->env;
diff --git a/target/ppc/spr_tcg.h b/target/ppc/spr_tcg.h
index 520f1ef233..85852f236e 100644
--- a/target/ppc/spr_tcg.h
+++ b/target/ppc/spr_tcg.h
@@ -25,6 +25,7 @@
void spr_noaccess(DisasContext *ctx, int gprn, int sprn);
void spr_read_generic(DisasContext *ctx, int gprn, int sprn);
void spr_write_generic(DisasContext *ctx, int sprn, int gprn);
+void spr_write_MMCR1(DisasContext *ctx, int sprn, int gprn);
void spr_read_xer(DisasContext *ctx, int gprn, int sprn);
void spr_write_xer(DisasContext *ctx, int sprn, int gprn);
void spr_read_lr(DisasContext *ctx, int gprn, int sprn);
--
2.31.1
- [PATCH v4 00/15] PPC64/TCG: Implement 'rfebb' instruction, Daniel Henrique Barboza, 2021/10/17
- [PATCH v4 01/15] target/ppc: add MMCR0 PMCC bits to hflags, Daniel Henrique Barboza, 2021/10/17
- [PATCH v4 04/15] target/ppc: adding user read/write functions for PMCs, Daniel Henrique Barboza, 2021/10/17
- [PATCH v4 03/15] target/ppc: add user read/write functions for MMCR2, Daniel Henrique Barboza, 2021/10/17
- [PATCH v4 02/15] target/ppc: add user read/write functions for MMCR0, Daniel Henrique Barboza, 2021/10/17
- [PATCH v4 06/15] target/ppc: initialize PMUEvents on MMCR1 write,
Daniel Henrique Barboza <=
- [PATCH v4 05/15] target/ppc: introduce PMU events, Daniel Henrique Barboza, 2021/10/17
- [PATCH v4 08/15] target/ppc: enable PMU counter overflow with cycle events, Daniel Henrique Barboza, 2021/10/17
- [PATCH v4 07/15] target/ppc: PMU basic cycle count for pseries TCG, Daniel Henrique Barboza, 2021/10/17
- [PATCH v4 12/15] target/ppc/power8-pmu.c: handle overflow bits when PMU is running, Daniel Henrique Barboza, 2021/10/17
- [PATCH v4 14/15] target/ppc: PMU Event-Based exception support, Daniel Henrique Barboza, 2021/10/17
- [PATCH v4 09/15] target/ppc: enable PMU instruction count, Daniel Henrique Barboza, 2021/10/17
- [PATCH v4 11/15] target/ppc: PMU: handle setting of PMCs while running, Daniel Henrique Barboza, 2021/10/17
- [PATCH v4 10/15] target/ppc/power8-pmu.c: add PM_RUN_INST_CMPL (0xFA) event, Daniel Henrique Barboza, 2021/10/17
- [PATCH v4 15/15] target/ppc/excp_helper.c: EBB handling adjustments, Daniel Henrique Barboza, 2021/10/17
- [PATCH v4 13/15] PPC64/TCG: Implement 'rfebb' instruction, Daniel Henrique Barboza, 2021/10/17