From: Daniel Henrique Barboza <danielhb413@gmail.com>
To: qemu-devel@nongnu.org
Cc: richard.henderson@linaro.org,
Daniel Henrique Barboza <danielhb413@gmail.com>,
qemu-ppc@nongnu.org, clg@kaod.org, david@gibson.dropbear.id.au
Subject: [PATCH for-7.0 v7 03/10] target/ppc: enable PMU counter overflow with cycle events
Date: Fri, 19 Nov 2021 15:22:09 -0300 [thread overview]
Message-ID: <20211119182216.628676-4-danielhb413@gmail.com> (raw)
In-Reply-To: <20211119182216.628676-1-danielhb413@gmail.com>
The PowerISA v3.1 defines that if the proper bits are set (MMCR0_PMC1CE
for PMC1 and MMCR0_PMCjCE for the remaining PMCs), counter negative
conditions are enabled. This means that if the counter value overflows
(i.e. exceeds 0x80000000) a performance monitor alert will occur. This alert
can trigger an event-based exception (to be implemented in the next patches)
if the MMCR0_EBE bit is set.
For now, overflowing the counter when the PMC is counting cycles will
just trigger a performance monitor alert. This is done by starting the
overflow timer to expire in the moment the overflow would be occuring. The
timer will call fire_PMC_interrupt() (via cpu_ppc_pmu_timer_cb) which will
trigger the PMU alert and, if the conditions are met, an EBB exception.
Signed-off-by: Daniel Henrique Barboza <danielhb413@gmail.com>
---
target/ppc/cpu.h | 2 +
target/ppc/power8-pmu.c | 86 ++++++++++++++++++++++++++++++++++++++++-
2 files changed, 86 insertions(+), 2 deletions(-)
diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
index 233fd8a9ca..f6265be974 100644
--- a/target/ppc/cpu.h
+++ b/target/ppc/cpu.h
@@ -363,6 +363,8 @@ typedef enum {
#define MMCR0_PMCC PPC_BITMASK(44, 45) /* PMC Control */
#define MMCR0_FC14 PPC_BIT(58) /* PMC Freeze Counters 1-4 bit */
#define MMCR0_FC56 PPC_BIT(59) /* PMC Freeze Counters 5-6 bit */
+#define MMCR0_PMC1CE PPC_BIT(48) /* MMCR0 PMC1 Condition Enabled */
+#define MMCR0_PMCjCE PPC_BIT(49) /* MMCR0 PMCj Condition Enabled */
/* MMCR0 userspace r/w mask */
#define MMCR0_UREG_MASK (MMCR0_FC | MMCR0_PMAO | MMCR0_PMAE)
/* MMCR2 userspace r/w mask */
diff --git a/target/ppc/power8-pmu.c b/target/ppc/power8-pmu.c
index 8674b8f0d6..68409b2236 100644
--- a/target/ppc/power8-pmu.c
+++ b/target/ppc/power8-pmu.c
@@ -23,6 +23,8 @@
#if defined(TARGET_PPC64) && !defined(CONFIG_USER_ONLY)
+#define PMC_COUNTER_NEGATIVE_VAL 0x80000000UL
+
/*
* For PMCs 1-4, IBM POWER chips has support for an implementation
* dependent event, 0x1E, that enables cycle counting. The Linux kernel
@@ -93,6 +95,15 @@ static bool pmc_is_active(CPUPPCState *env, int sprn, uint64_t mmcr0)
return !(mmcr0 & MMCR0_FC56);
}
+static bool pmc_has_overflow_enabled(CPUPPCState *env, int sprn)
+{
+ if (sprn == SPR_POWER_PMC1) {
+ return env->spr[SPR_POWER_MMCR0] & MMCR0_PMC1CE;
+ }
+
+ return env->spr[SPR_POWER_MMCR0] & MMCR0_PMCjCE;
+}
+
static void pmu_update_cycles(CPUPPCState *env, uint64_t old_mmcr0)
{
uint64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
@@ -116,6 +127,63 @@ static void pmu_update_cycles(CPUPPCState *env, uint64_t old_mmcr0)
env->pmu_base_time = now;
}
+static void pmu_delete_timers(CPUPPCState *env)
+{
+ int i;
+
+ for (i = 0; i < PMU_TIMERS_NUM; i++) {
+ timer_del(env->pmu_cyc_overflow_timers[i]);
+ }
+}
+
+/*
+ * Helper function to retrieve the cycle overflow timer of the
+ * 'sprn' counter. Given that PMC5 doesn't have a timer, the
+ * amount of timers is less than the total counters and the PMC6
+ * timer is the last of the array.
+ */
+static QEMUTimer *get_cyc_overflow_timer(CPUPPCState *env, int sprn)
+{
+ if (sprn == SPR_POWER_PMC5) {
+ return NULL;
+ }
+
+ if (sprn == SPR_POWER_PMC6) {
+ return env->pmu_cyc_overflow_timers[PMU_TIMERS_NUM - 1];
+ }
+
+ return env->pmu_cyc_overflow_timers[sprn - SPR_POWER_PMC1];
+}
+
+static void pmu_start_overflow_timers(CPUPPCState *env)
+{
+ uint64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
+ int64_t timeout;
+ int sprn;
+
+ env->pmu_base_time = now;
+
+ /*
+ * Scroll through all PMCs and start counter overflow timers for
+ * PM_CYC events, if needed.
+ */
+ for (sprn = SPR_POWER_PMC1; sprn <= SPR_POWER_PMC6; sprn++) {
+ if (!pmc_is_active(env, sprn, env->spr[SPR_POWER_MMCR0]) ||
+ !(getPMUEventType(env, sprn) == PMU_EVENT_CYCLES) ||
+ !pmc_has_overflow_enabled(env, sprn)) {
+ continue;
+ }
+
+ if (env->spr[sprn] >= PMC_COUNTER_NEGATIVE_VAL) {
+ timeout = 0;
+ } else {
+ timeout = PMC_COUNTER_NEGATIVE_VAL - env->spr[sprn];
+ }
+
+ timer_mod(get_cyc_overflow_timer(env, sprn), now + timeout);
+ }
+}
+
/*
* A cycle count session consists of the basic operations we
* need to do to support PM_CYC events: redefine a new base_time
@@ -123,8 +191,22 @@ static void pmu_update_cycles(CPUPPCState *env, uint64_t old_mmcr0)
*/
static void start_cycle_count_session(CPUPPCState *env)
{
- /* Just define pmu_base_time for now */
- env->pmu_base_time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
+ bool overflow_enabled = env->spr[SPR_POWER_MMCR0] &
+ (MMCR0_PMC1CE | MMCR0_PMCjCE);
+
+ /*
+ * Always delete existing overflow timers when starting a
+ * new cycle counting session.
+ */
+ pmu_delete_timers(env);
+
+ if (!overflow_enabled) {
+ /* Define pmu_base_time and leave */
+ env->pmu_base_time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
+ return;
+ }
+
+ pmu_start_overflow_timers(env);
}
void helper_store_mmcr0(CPUPPCState *env, target_ulong value)
--
2.31.1
next prev parent reply other threads:[~2021-11-19 18:29 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-11-19 18:22 [PATCH for-7.0 v7 00/10] PMU-EBB support for PPC64 TCG Daniel Henrique Barboza
2021-11-19 18:22 ` [PATCH for-7.0 v7 01/10] target/ppc: introduce PMUEventType and PMU overflow timers Daniel Henrique Barboza
2021-11-22 4:29 ` David Gibson
2021-11-19 18:22 ` [PATCH for-7.0 v7 02/10] target/ppc: PMU basic cycle count for pseries TCG Daniel Henrique Barboza
2021-11-22 5:07 ` David Gibson
2021-11-25 1:06 ` Daniel Henrique Barboza
2021-11-19 18:22 ` Daniel Henrique Barboza [this message]
2021-11-19 18:22 ` [PATCH for-7.0 v7 04/10] target/ppc: enable PMU instruction count Daniel Henrique Barboza
2021-11-19 18:22 ` [PATCH for-7.0 v7 05/10] target/ppc/power8-pmu.c: add PM_RUN_INST_CMPL (0xFA) event Daniel Henrique Barboza
2021-11-19 18:22 ` [PATCH for-7.0 v7 06/10] target/ppc: PMU: handle setting of PMCs while running Daniel Henrique Barboza
2021-11-19 18:22 ` [PATCH for-7.0 v7 07/10] target/ppc/power8-pmu.c: handle overflow bits when PMU is running Daniel Henrique Barboza
2021-11-19 18:22 ` [PATCH for-7.0 v7 08/10] PPC64/TCG: Implement 'rfebb' instruction Daniel Henrique Barboza
2021-11-19 18:22 ` [PATCH for-7.0 v7 09/10] target/ppc: PMU Event-Based exception support Daniel Henrique Barboza
2021-11-19 18:22 ` [PATCH for-7.0 v7 10/10] target/ppc/excp_helper.c: EBB handling adjustments Daniel Henrique Barboza
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=20211119182216.628676-4-danielhb413@gmail.com \
--to=danielhb413@gmail.com \
--cc=clg@kaod.org \
--cc=david@gibson.dropbear.id.au \
--cc=qemu-devel@nongnu.org \
--cc=qemu-ppc@nongnu.org \
--cc=richard.henderson@linaro.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.