stats: update stats for mmap() change.
[gem5.git] / src / arch / arm / pmu.cc
index 0fc903e9d656ea59db6ec37aa9debc7eec8a4e4d..6ea053e552de62b697eeee9c497dbd7f97e67b3a 100644 (file)
@@ -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);
     }
@@ -478,7 +513,7 @@ PMU::raiseInterrupt()
 }
 
 void
-PMU::serialize(std::ostream &os)
+PMU::serialize(CheckpointOut &cp) const
 {
     DPRINTF(Checkpoint, "Serializing Arm PMU\n");
 
@@ -490,17 +525,14 @@ PMU::serialize(std::ostream &os)
     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 &section)
+PMU::unserialize(CheckpointIn &cp)
 {
     DPRINTF(Checkpoint, "Unserializing Arm PMU\n");
 
@@ -513,13 +545,13 @@ PMU::unserialize(Checkpoint *cp, const std::string &section)
     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);
@@ -528,7 +560,7 @@ PMU::CounterState::serialize(std::ostream &os)
 }
 
 void
-PMU::CounterState::unserialize(Checkpoint *cp, const std::string &section)
+PMU::CounterState::unserialize(CheckpointIn &cp)
 {
     UNSERIALIZE_SCALAR(eventId);
     UNSERIALIZE_SCALAR(value);