case MISCREG_PMOVSCLR_EL0:
case MISCREG_PMOVSR:
- reg_pmovsr &= ~val;
+ setOverflowStatus(reg_pmovsr & ~val);
return;
case MISCREG_PMSWINC_EL0:
case MISCREG_PMOVSSET_EL0:
case MISCREG_PMOVSSET:
- reg_pmovsr |= val;
+ setOverflowStatus(reg_pmovsr | val);
return;
default:
}
}
+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()
{
}
}
+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
{
*/
void raiseInterrupt();
+ /**
+ * Clear a PMU interrupt.
+ */
+ void clearInterrupt();
+
/**
* Get the value of a performance counter.
*
*/
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;