#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"
// Flag the event as available in the PMCEID register if it is an
// architected event.
if (id < 0x40)
- reg_pmceid |= (1 << id);
+ reg_pmceid |= (ULL(1) << id);
}
void
}
}
+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;
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;
}
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);
}
}
void
-PMU::serialize(std::ostream &os)
+PMU::serialize(CheckpointOut &cp) const
{
DPRINTF(Checkpoint, "Serializing Arm PMU\n");
SERIALIZE_SCALAR(reg_pmceid);
SERIALIZE_SCALAR(clock_remainder);
- for (size_t i = 0; i < counters.size(); ++i) {
- nameOut(os, csprintf("%s.counters.%i", name(), i));
- counters[i].serialize(os);
- }
+ for (size_t i = 0; i < counters.size(); ++i)
+ counters[i].serializeSection(cp, csprintf("counters.%i", i));
- nameOut(os, csprintf("%s.cycleCounter", name()));
- cycleCounter.serialize(os);
+ cycleCounter.serializeSection(cp, "cycleCounter");
}
void
-PMU::unserialize(Checkpoint *cp, const std::string §ion)
+PMU::unserialize(CheckpointIn &cp)
{
DPRINTF(Checkpoint, "Unserializing Arm PMU\n");
UNSERIALIZE_SCALAR(clock_remainder);
for (size_t i = 0; i < counters.size(); ++i)
- counters[i].unserialize(cp, csprintf("%s.counters.%i", section, i));
+ counters[i].unserializeSection(cp, csprintf("counters.%i", i));
- cycleCounter.unserialize(cp, csprintf("%s.cycleCounter", section));
+ cycleCounter.unserializeSection(cp, "cycleCounter");
}
void
-PMU::CounterState::serialize(std::ostream &os)
+PMU::CounterState::serialize(CheckpointOut &cp) const
{
SERIALIZE_SCALAR(eventId);
SERIALIZE_SCALAR(value);
}
void
-PMU::CounterState::unserialize(Checkpoint *cp, const std::string §ion)
+PMU::CounterState::unserialize(CheckpointIn &cp)
{
UNSERIALIZE_SCALAR(eventId);
UNSERIALIZE_SCALAR(value);