summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/arch/arm/isa.cc3
-rw-r--r--src/arch/arm/isa_device.cc13
-rw-r--r--src/arch/arm/isa_device.hh9
-rw-r--r--src/arch/arm/pmu.cc49
-rw-r--r--src/arch/arm/pmu.hh13
5 files changed, 78 insertions, 9 deletions
diff --git a/src/arch/arm/isa.cc b/src/arch/arm/isa.cc
index d97c03db5..6bbd55195 100644
--- a/src/arch/arm/isa.cc
+++ b/src/arch/arm/isa.cc
@@ -139,6 +139,9 @@ ISA::ISA(Params *p)
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 --git a/src/arch/arm/isa_device.cc b/src/arch/arm/isa_device.cc
index 6fb58c6e1..0bb488dac 100644
--- a/src/arch/arm/isa_device.cc
+++ b/src/arch/arm/isa_device.cc
@@ -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 --git a/src/arch/arm/isa_device.hh b/src/arch/arm/isa_device.hh
index edf43f1cb..8b12fa502 100644
--- a/src/arch/arm/isa_device.hh
+++ b/src/arch/arm/isa_device.hh
@@ -46,6 +46,8 @@
namespace ArmISA
{
+class ISA;
+
/**
* Base class for devices that use the MiscReg interfaces.
*
@@ -56,9 +58,11 @@ namespace ArmISA
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 @@ class BaseISADevice
* @return Register value.
*/
virtual MiscReg readMiscReg(int misc_reg) = 0;
+
+ protected:
+ ISA *isa;
};
/**
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);
}
diff --git a/src/arch/arm/pmu.hh b/src/arch/arm/pmu.hh
index 989ad76c6..94f8c2397 100644
--- a/src/arch/arm/pmu.hh
+++ b/src/arch/arm/pmu.hh
@@ -323,7 +323,7 @@ class PMU : public SimObject, public ArmISA::BaseISADevice {
/** 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 @@ class PMU : public SimObject, public ArmISA::BaseISADevice {
/** 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 @@ class PMU : public SimObject, public ArmISA::BaseISADevice {
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..
*