summaryrefslogtreecommitdiff
path: root/src/arch/arm/pmu.cc
diff options
context:
space:
mode:
authorAndreas Sandberg <andreas.sandberg@arm.com>2014-12-23 09:31:17 -0500
committerAndreas Sandberg <andreas.sandberg@arm.com>2014-12-23 09:31:17 -0500
commit070b4a81dbf9cc040ecb771e128993ae519cf80f (patch)
treed3f7f059aafb0dff016a0486166d71c34bc8abc2 /src/arch/arm/pmu.cc
parent809134a2b151f82c29593e64086393b31bc110b7 (diff)
downloadgem5-070b4a81dbf9cc040ecb771e128993ae519cf80f.tar.xz
arm: Add support for filtering in the PMU
This patch adds support for filtering events in the PMU. In order to do so, it updates the ISADevice base class to forward an ISA pointer to ISA devices. This enables such devices to access the MiscReg file to determine the current execution level.
Diffstat (limited to 'src/arch/arm/pmu.cc')
-rw-r--r--src/arch/arm/pmu.cc49
1 files changed, 42 insertions, 7 deletions
diff --git a/src/arch/arm/pmu.cc b/src/arch/arm/pmu.cc
index 0fc903e9d..d20f4e27d 100644
--- a/src/arch/arm/pmu.cc
+++ b/src/arch/arm/pmu.cc
@@ -41,6 +41,8 @@
#include "arch/arm/pmu.hh"
+#include "arch/arm/isa.hh"
+#include "arch/arm/utility.hh"
#include "base/trace.hh"
#include "cpu/base.hh"
#include "debug/Checkpoint.hh"
@@ -350,12 +352,44 @@ PMU::updateAllCounters()
}
}
+bool
+PMU::isFiltered(const CounterState &ctr) const
+{
+ assert(isa);
+
+ const PMEVTYPER_t filter(ctr.filter);
+ const SCR scr(isa->readMiscRegNoEffect(MISCREG_SCR));
+ const CPSR cpsr(isa->readMiscRegNoEffect(MISCREG_CPSR));
+ const ExceptionLevel el(opModeToEL((OperatingMode)(uint8_t)cpsr.mode));
+ const bool secure(inSecureState(scr, cpsr));
+
+ switch (el) {
+ case EL0:
+ return secure ? filter.u : (filter.u != filter.nsu);
+
+ case EL1:
+ return secure ? filter.p : (filter.p != filter.nsk);
+
+ case EL2:
+ return !filter.nsh;
+
+ case EL3:
+ return filter.p != filter.m;
+
+ default:
+ panic("Unexpected execution level in PMU::isFiltered.\n");
+ }
+}
+
void
PMU::handleEvent(CounterId id, uint64_t delta)
{
CounterState &ctr(getCounter(id));
const bool overflowed(reg_pmovsr & (1 << id));
+ if (isFiltered(ctr))
+ return;
+
// Handle the "count every 64 cycles" mode
if (id == PMCCNTR && reg_pmcr.d) {
clock_remainder += delta;
@@ -434,9 +468,8 @@ PMU::getCounterTypeRegister(CounterId id) const
return 0;
const CounterState &cs(getCounter(id));
- PMEVTYPER_t type(0);
+ PMEVTYPER_t type(cs.filter);
- // TODO: Re-create filtering settings from counter state
type.evtCount = cs.eventId;
return type;
@@ -453,12 +486,14 @@ PMU::setCounterTypeRegister(CounterId id, PMEVTYPER_t val)
}
CounterState &ctr(getCounter(id));
- // TODO: Handle filtering (both for general purpose counters and
- // the cycle counter)
+ const EventTypeId old_event_id(ctr.eventId);
+
+ ctr.filter = val;
- // If PMCCNTR Register, do not change event type. PMCCNTR can count
- // processor cycles only.
- if (id != PMCCNTR) {
+ // If PMCCNTR Register, do not change event type. PMCCNTR can
+ // count processor cycles only. If we change the event type, we
+ // need to update the probes the counter is using.
+ if (id != PMCCNTR && old_event_id != val.evtCount) {
ctr.eventId = val.evtCount;
updateCounter(reg_pmselr.sel, ctr);
}