@@ -907,6 +907,15 @@ static bool event_always_supported(CPUARMState *env)
return true;
}
+static uint64_t swinc_get_count(CPUARMState *env)
+{
+ /*
+ * SW_INCR events are written directly to the pmevcntr's by writes to
+ * PMSWINC, so don't do anything here...
+ */
+ return 0;
+}
+
static uint64_t cycles_get_count(CPUARMState *env)
{
uint64_t ret;
@@ -941,6 +950,10 @@ static uint64_t instructions_get_count(CPUARMState *env)
#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
+ },
{ .number = 0x008, /* INST_RETIRED */
.supported = instructions_supported,
.get_count = instructions_get_count
@@ -1191,6 +1204,25 @@ static void pmcr_write(CPUARMState *env, const ARMCPRegInfo *ri,
pmu_sync(env);
}
+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) {
+ pmu_sync_counter(env, i);
+ env->cp15.c14_pmevcntr[i]++;
+ pmu_sync_counter(env, i);
+ }
+ }
+}
+
static uint64_t pmccntr_read(CPUARMState *env, const ARMCPRegInfo *ri)
{
uint64_t ret;
@@ -1559,9 +1591,13 @@ static const ARMCPRegInfo v7_cp_reginfo[] = {
.fieldoffset = offsetof(CPUARMState, cp15.c9_pmovsr),
.writefn = pmovsset_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 },
#ifndef CONFIG_USER_ONLY
{ .name = "PMSELR", .cp = 15, .crn = 9, .crm = 12, .opc1 = 0, .opc2 = 5,
.access = PL0_RW, .type = ARM_CP_ALIAS,
Signed-off-by: Aaron Lindsay <alindsay@codeaurora.org> --- target/arm/helper.c | 40 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 38 insertions(+), 2 deletions(-)