@@ -955,6 +955,15 @@ static bool event_always_supported(CPUARMState *env)
return true;
}
+static uint64_t swinc_get_count(CPUARMState *env, uint64_t cycles)
+{
+ /*
+ * SW_INCR events are written directly to the pmevcntr's by writes to
+ * PMSWINC, so there is no underlying count maintained by the PMU itself
+ */
+ return 0;
+}
+
#ifndef CONFIG_USER_ONLY
static uint64_t cycles_get_count(CPUARMState *env, uint64_t cycles)
{
@@ -974,6 +983,10 @@ static uint64_t instructions_get_count(CPUARMState *env, uint64_t cycles)
#define SUPPORTED_EVENT_SENTINEL UINT16_MAX
static const pm_event pm_events[] = {
+ { .number = 0x000, /* SW_INCR */
+ .supported = event_always_supported,
+ .get_count = swinc_get_count
+ },
#ifndef CONFIG_USER_ONLY
{ .number = 0x008, /* INST_RETIRED */
.supported = instructions_supported,
@@ -1273,6 +1286,29 @@ static void pmcr_write(CPUARMState *env, const ARMCPRegInfo *ri,
pmu_op_finish(env, saved_cycles);
}
+static void pmswinc_write(CPUARMState *env, const ARMCPRegInfo *ri,
+ uint64_t value)
+{
+ unsigned int i;
+ for (i = 0; i < PMU_NUM_COUNTERS(env); i++) {
+ /* Increment a counter's count iff: */
+ if ((value & (1 << i)) && /* counter's bit is set */
+ /* counter is enabled and not filtered */
+ pmu_counter_enabled(env, i) &&
+ !pmu_counter_filtered(env, env->cp15.c14_pmevtyper[i]) &&
+ /* counter is SW_INCR */
+ (env->cp15.c14_pmevtyper[i] & PMXEVTYPER_EVTCOUNT) == 0x0) {
+ uint64_t cycles = 0;
+#ifndef CONFIG_USER_ONLY
+ cycles = get_cycle_count(env);
+#endif
+ pmu_sync_counter(env, i, cycles);
+ env->cp15.c14_pmevcntr[i]++;
+ pmu_sync_counter(env, i, cycles);
+ }
+ }
+}
+
static uint64_t pmccntr_read(CPUARMState *env, const ARMCPRegInfo *ri)
{
uint64_t ret;
@@ -1619,9 +1655,13 @@ static const ARMCPRegInfo v7_cp_reginfo[] = {
.fieldoffset = offsetof(CPUARMState, cp15.c9_pmovsr),
.writefn = pmovsr_write,
.raw_writefn = raw_write },
- /* Unimplemented so WI. */
{ .name = "PMSWINC", .cp = 15, .crn = 9, .crm = 12, .opc1 = 0, .opc2 = 4,
- .access = PL0_W, .accessfn = pmreg_access_swinc, .type = ARM_CP_NOP },
+ .access = PL0_W, .accessfn = pmreg_access_swinc, .type = ARM_CP_NO_RAW,
+ .writefn = pmswinc_write },
+ { .name = "PMSWINC_EL0", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 3, .crn = 9, .crm = 12, .opc2 = 4,
+ .access = PL0_W, .accessfn = pmreg_access_swinc, .type = ARM_CP_NO_RAW,
+ .writefn = pmswinc_write },
{ .name = "PMSELR", .cp = 15, .crn = 9, .crm = 12, .opc1 = 0, .opc2 = 5,
.access = PL0_RW, .type = ARM_CP_ALIAS,
.fieldoffset = offsetoflow32(CPUARMState, cp15.c9_pmselr),
Signed-off-by: Aaron Lindsay <alindsay@codeaurora.org> --- target/arm/helper.c | 44 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 42 insertions(+), 2 deletions(-)