From 64b3a741f558c9fcfe70d27d74fe2c25d96770d7 Mon Sep 17 00:00:00 2001 From: Giacomo Travaglini Date: Tue, 4 Sep 2018 13:17:15 +0200 Subject: [PATCH] arch-arm: raise/clear IRQ when writing to PMOVSCLR/SET Writing a 1 to the Overflow Flag Status register should trigger an interrupt raise/clear depending on the register we are currently using (PMOVSCLR for clearing and PMOVSSET for raising). Change-Id: I2091456685a245712045cf7a4932ac36b7dded1d Signed-off-by: Giacomo Travaglini Reviewed-by: Andreas Sandberg Reviewed-on: https://gem5-review.googlesource.com/12531 Maintainer: Andreas Sandberg --- src/arch/arm/pmu.cc | 30 ++++++++++++++++++++++++++++-- src/arch/arm/pmu.hh | 17 +++++++++++++++++ 2 files changed, 45 insertions(+), 2 deletions(-) diff --git a/src/arch/arm/pmu.cc b/src/arch/arm/pmu.cc index b569b6967..90d9f1a08 100644 --- a/src/arch/arm/pmu.cc +++ b/src/arch/arm/pmu.cc @@ -214,7 +214,7 @@ PMU::setMiscReg(int misc_reg, MiscReg val) case MISCREG_PMOVSCLR_EL0: case MISCREG_PMOVSR: - reg_pmovsr &= ~val; + setOverflowStatus(reg_pmovsr & ~val); return; case MISCREG_PMSWINC_EL0: @@ -286,7 +286,7 @@ PMU::setMiscReg(int misc_reg, MiscReg val) case MISCREG_PMOVSSET_EL0: case MISCREG_PMOVSSET: - reg_pmovsr |= val; + setOverflowStatus(reg_pmovsr | val); return; default: @@ -644,6 +644,20 @@ PMU::setCounterTypeRegister(CounterId id, PMEVTYPER_t val) } } +void +PMU::setOverflowStatus(MiscReg new_val) +{ + const bool int_old = reg_pmovsr != 0; + const bool int_new = new_val != 0; + + reg_pmovsr = new_val; + if (int_old && !int_new) { + clearInterrupt(); + } else if (!int_old && int_new && (reg_pminten & reg_pmovsr)) { + raiseInterrupt(); + } +} + void PMU::raiseInterrupt() { @@ -656,6 +670,18 @@ PMU::raiseInterrupt() } } +void +PMU::clearInterrupt() +{ + if (interrupt) { + DPRINTF(PMUVerbose, "Clearing PMU interrupt.\n"); + interrupt->clear(); + } else { + warn_once("Dropping PMU interrupt as no interrupt has " + "been specified\n"); + } +} + void PMU::serialize(CheckpointOut &cp) const { diff --git a/src/arch/arm/pmu.hh b/src/arch/arm/pmu.hh index 61516cffd..ee68272e7 100644 --- a/src/arch/arm/pmu.hh +++ b/src/arch/arm/pmu.hh @@ -218,6 +218,11 @@ class PMU : public SimObject, public ArmISA::BaseISADevice { */ void raiseInterrupt(); + /** + * Clear a PMU interrupt. + */ + void clearInterrupt(); + /** * Get the value of a performance counter. * @@ -269,6 +274,18 @@ class PMU : public SimObject, public ArmISA::BaseISADevice { */ void setCounterTypeRegister(CounterId id, PMEVTYPER_t type); + /** + * Used for writing the Overflow Flag Status Register (SET/CLR) + * + * This method implements a write to the PMOVSSET/PMOVSCLR registers. + * It is capturing change of state in the register bits so that + * the overflow interrupt can be raised/cleared as a side effect + * of the write. + * + * @param new_val New value of the Overflow Status Register + */ + void setOverflowStatus(MiscReg new_val); + protected: /* Probe handling and counter state */ struct CounterState; -- 2.30.2