summaryrefslogtreecommitdiff
path: root/src/arch
diff options
context:
space:
mode:
authorGiacomo Travaglini <giacomo.travaglini@arm.com>2018-09-04 13:17:15 +0200
committerGiacomo Travaglini <giacomo.travaglini@arm.com>2018-09-28 10:13:05 +0000
commit64b3a741f558c9fcfe70d27d74fe2c25d96770d7 (patch)
tree4f2f525b61ab5de3d69078e2c2a8384a4febd803 /src/arch
parent7a6183aa6162419912daa5647d13f030ab0904e2 (diff)
downloadgem5-64b3a741f558c9fcfe70d27d74fe2c25d96770d7.tar.xz
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 <giacomo.travaglini@arm.com> Reviewed-by: Andreas Sandberg <andreas.sandberg@arm.com> Reviewed-on: https://gem5-review.googlesource.com/12531 Maintainer: Andreas Sandberg <andreas.sandberg@arm.com>
Diffstat (limited to 'src/arch')
-rw-r--r--src/arch/arm/pmu.cc30
-rw-r--r--src/arch/arm/pmu.hh17
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:
@@ -645,6 +645,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()
{
if (interrupt) {
@@ -657,6 +671,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
{
DPRINTF(Checkpoint, "Serializing Arm PMU\n");
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
@@ -219,6 +219,11 @@ class PMU : public SimObject, public ArmISA::BaseISADevice {
void raiseInterrupt();
/**
+ * Clear a PMU interrupt.
+ */
+ void clearInterrupt();
+
+ /**
* Get the value of a performance counter.
*
* This method returns the value of a general purpose performance
@@ -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;