diff options
-rw-r--r-- | src/arch/arm/isa.cc | 3 | ||||
-rw-r--r-- | src/arch/arm/isa_device.cc | 13 | ||||
-rw-r--r-- | src/arch/arm/isa_device.hh | 9 | ||||
-rw-r--r-- | src/arch/arm/pmu.cc | 49 | ||||
-rw-r--r-- | src/arch/arm/pmu.hh | 13 |
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.. * |