changeset ae5582819481 in /z/repo/gem5
details: http://repo.gem5.org/gem5?cmd=changeset;node=ae5582819481
description:
        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:

 src/arch/arm/isa.cc        |   3 ++
 src/arch/arm/isa_device.cc |  13 ++++++++++++
 src/arch/arm/isa_device.hh |   9 +++++++-
 src/arch/arm/pmu.cc        |  49 +++++++++++++++++++++++++++++++++++++++------
 src/arch/arm/pmu.hh        |  13 +++++++++++-
 5 files changed, 78 insertions(+), 9 deletions(-)

diffs (196 lines):

diff -r 427f988fe6e5 -r ae5582819481 src/arch/arm/isa.cc
--- a/src/arch/arm/isa.cc       Tue Dec 23 09:31:17 2014 -0500
+++ b/src/arch/arm/isa.cc       Tue Dec 23 09:31:17 2014 -0500
@@ -139,6 +139,9 @@
     if (!pmu)
         pmu = &dummyDevice;
 
+    // Give all ISA devices a pointer to this ISA
+    pmu->setISA(this);
+
     system = dynamic_cast<ArmSystem *>(p->system);
     DPRINTFN("ISA system set to: %p %p\n", system, p->system);
 
diff -r 427f988fe6e5 -r ae5582819481 src/arch/arm/isa_device.cc
--- a/src/arch/arm/isa_device.cc        Tue Dec 23 09:31:17 2014 -0500
+++ b/src/arch/arm/isa_device.cc        Tue Dec 23 09:31:17 2014 -0500
@@ -44,6 +44,19 @@
 namespace ArmISA
 {
 
+BaseISADevice::BaseISADevice()
+    : isa(nullptr)
+{
+}
+
+void
+BaseISADevice::setISA(ISA *_isa)
+{
+    assert(_isa);
+
+    isa = _isa;
+}
+
 void
 DummyISADevice::setMiscReg(int misc_reg, MiscReg val)
 {
diff -r 427f988fe6e5 -r ae5582819481 src/arch/arm/isa_device.hh
--- a/src/arch/arm/isa_device.hh        Tue Dec 23 09:31:17 2014 -0500
+++ b/src/arch/arm/isa_device.hh        Tue Dec 23 09:31:17 2014 -0500
@@ -46,6 +46,8 @@
 namespace ArmISA
 {
 
+class ISA;
+
 /**
  * Base class for devices that use the MiscReg interfaces.
  *
@@ -56,9 +58,11 @@
 class BaseISADevice
 {
   public:
-    BaseISADevice() {}
+    BaseISADevice();
     virtual ~BaseISADevice() {}
 
+    virtual void setISA(ISA *isa);
+
     /**
      * Write to a system register belonging to this device.
      *
@@ -74,6 +78,9 @@
      * @return Register value.
      */
     virtual MiscReg readMiscReg(int misc_reg) = 0;
+
+  protected:
+    ISA *isa;
 };
 
 /**
diff -r 427f988fe6e5 -r ae5582819481 src/arch/arm/pmu.cc
--- a/src/arch/arm/pmu.cc       Tue Dec 23 09:31:17 2014 -0500
+++ b/src/arch/arm/pmu.cc       Tue Dec 23 09:31:17 2014 -0500
@@ -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 @@
     }
 }
 
+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 @@
         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 @@
     }
 
     CounterState &ctr(getCounter(id));
-    // TODO: Handle filtering (both for general purpose counters and
-    // the cycle counter)
+    const EventTypeId old_event_id(ctr.eventId);
 
-    // If PMCCNTR Register, do not change event type. PMCCNTR can count
-    // processor cycles only.
-    if (id != PMCCNTR) {
+    ctr.filter = val;
+
+    // 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);
     }
diff -r 427f988fe6e5 -r ae5582819481 src/arch/arm/pmu.hh
--- a/src/arch/arm/pmu.hh       Tue Dec 23 09:31:17 2014 -0500
+++ b/src/arch/arm/pmu.hh       Tue Dec 23 09:31:17 2014 -0500
@@ -323,7 +323,7 @@
     /** State of a counter within the PMU. */
     struct CounterState {
         CounterState()
-            : eventId(0), value(0), enabled(false),
+            : eventId(0), filter(0), value(0), enabled(false),
               overflow64(false) {
 
             listeners.reserve(4);
@@ -344,6 +344,9 @@
         /** Counter event ID */
         EventTypeId eventId;
 
+        /** Filtering settings (evtCount is unused) */
+        PMEVTYPER_t filter;
+
         /** Current value of the counter */
         uint64_t value;
 
@@ -422,6 +425,14 @@
     void updateCounter(CounterId id, CounterState &ctr);
 
     /**
+     * Check if a counter's settings allow it to be counted.
+     *
+     * @param ctr Counter state instance representing this counter.
+     * @return false if the counter is active, true otherwise.
+     */
+    bool isFiltered(const CounterState &ctr) const;
+
+    /**
      * Call updateCounter() for each counter in the PMU if the
      * counter's state has changed..
      *
_______________________________________________
gem5-dev mailing list
gem5-dev@gem5.org
http://m5sim.org/mailman/listinfo/gem5-dev

Reply via email to