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>
This commit is contained in:
Giacomo Travaglini
2018-09-04 13:17:15 +02:00
parent 7a6183aa61
commit 64b3a741f5
2 changed files with 45 additions and 2 deletions

View File

@@ -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
{

View File

@@ -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;