summaryrefslogtreecommitdiff
path: root/src/arch/arm/isa.cc
diff options
context:
space:
mode:
authorAndreas Sandberg <Andreas.Sandberg@ARM.com>2014-10-16 05:49:39 -0400
committerAndreas Sandberg <Andreas.Sandberg@ARM.com>2014-10-16 05:49:39 -0400
commit3697990c27243f0c454f2fab0f12ed06759c97b9 (patch)
treec7fe75d2cf328c26bc31cfe405d91afc2c4aa757 /src/arch/arm/isa.cc
parent132ea6319ab9292bef7c0ea87f396ef9de2db0fe (diff)
downloadgem5-3697990c27243f0c454f2fab0f12ed06759c97b9.tar.xz
arm: Add a model of an ARM PMUv3
This class implements a subset of the ARM PMU v3 specification as described in the ARMv8 reference manual. It supports most of the features of the PMU, however the following features are known to be missing: * Event filtering (e.g., from different privilege levels). * Access controls (the PMU currently ignores the execution level). * The chain counter (event no. 0x1E) is unimplemented. The PMU itself does not implement any events, it merely provides an interface for the configuration scripts to hook up probes that drive events. Configuration scripts should call addEventProbe() to configure custom events or high-level methods to configure architected events. The Python implementation of addEventProbe() automatically delays event type registration until after instantiation. In order to support CPU switching and some combined counters (e.g., memory references synthesized from loads and stores), the PMU allows multiple probes per event type. When creating a system that switches between CPU models that share the same PMU, PMU events for all of the CPU models can be registered with the PMU. Kudos to Matt Horsnell for the initial gem5 implementation of the PMU.
Diffstat (limited to 'src/arch/arm/isa.cc')
-rw-r--r--src/arch/arm/isa.cc67
1 files changed, 39 insertions, 28 deletions
diff --git a/src/arch/arm/isa.cc b/src/arch/arm/isa.cc
index e76ff452d..c2250e38a 100644
--- a/src/arch/arm/isa.cc
+++ b/src/arch/arm/isa.cc
@@ -39,8 +39,10 @@
*/
#include "arch/arm/isa.hh"
+#include "arch/arm/pmu.hh"
#include "arch/arm/system.hh"
#include "cpu/checker/cpu.hh"
+#include "cpu/base.hh"
#include "debug/Arm.hh"
#include "debug/MiscRegs.hh"
#include "params/ArmISA.hh"
@@ -122,12 +124,21 @@ const struct ISA::MiscRegInitializerEntry
ISA::ISA(Params *p)
- : SimObject(p), system(NULL), lookUpMiscReg(NUM_MISCREGS, {0,0})
+ : SimObject(p),
+ system(NULL),
+ pmu(p->pmu),
+ lookUpMiscReg(NUM_MISCREGS, {0,0})
{
SCTLR sctlr;
sctlr = 0;
miscRegs[MISCREG_SCTLR_RST] = sctlr;
+ // Hook up a dummy device if we haven't been configured with a
+ // real PMU. By using a dummy device, we don't need to check that
+ // the PMU exist every time we try to access a PMU register.
+ if (!pmu)
+ pmu = &dummyDevice;
+
system = dynamic_cast<ArmSystem *>(p->system);
DPRINTFN("ISA system set to: %p %p\n", system, p->system);
@@ -356,7 +367,10 @@ ISA::clear64(const ArmISAParams *p)
// Initialize configurable id registers
miscRegs[MISCREG_ID_AA64AFR0_EL1] = p->id_aa64afr0_el1;
miscRegs[MISCREG_ID_AA64AFR1_EL1] = p->id_aa64afr1_el1;
- miscRegs[MISCREG_ID_AA64DFR0_EL1] = p->id_aa64dfr0_el1;
+ miscRegs[MISCREG_ID_AA64DFR0_EL1] =
+ (p->id_aa64dfr0_el1 & 0xfffffffffffff0ffULL) |
+ (p->pmu ? 0x0000000000000100ULL : 0); // Enable PMUv3
+
miscRegs[MISCREG_ID_AA64DFR1_EL1] = p->id_aa64dfr1_el1;
miscRegs[MISCREG_ID_AA64ISAR0_EL1] = p->id_aa64isar0_el1;
miscRegs[MISCREG_ID_AA64ISAR1_EL1] = p->id_aa64isar1_el1;
@@ -365,6 +379,11 @@ ISA::clear64(const ArmISAParams *p)
miscRegs[MISCREG_ID_AA64PFR0_EL1] = p->id_aa64pfr0_el1;
miscRegs[MISCREG_ID_AA64PFR1_EL1] = p->id_aa64pfr1_el1;
+ miscRegs[MISCREG_ID_DFR0_EL1] =
+ (p->pmu ? 0x03000000ULL : 0); // Enable PMUv3
+
+ miscRegs[MISCREG_ID_DFR0] = miscRegs[MISCREG_ID_DFR0_EL1];
+
// Enforce consistency with system-level settings...
// EL3
@@ -491,7 +510,6 @@ ISA::readMiscReg(int misc_reg, ThreadContext *tc)
// top bit defined as RES1
return readMiscRegNoEffect(misc_reg) | 0x80000000;
case MISCREG_ID_AFR0: // not implemented, so alias MIDR
- case MISCREG_ID_DFR0: // not implemented, so alias MIDR
case MISCREG_REVIDR: // not implemented, so alias MIDR
case MISCREG_MIDR:
cpsr = readMiscRegNoEffect(MISCREG_CPSR);
@@ -549,12 +567,13 @@ ISA::readMiscReg(int misc_reg, ThreadContext *tc)
case MISCREG_ACTLR:
warn("Not doing anything for miscreg ACTLR\n");
break;
- case MISCREG_PMCR:
- case MISCREG_PMCCNTR:
- case MISCREG_PMSELR:
- warn("Not doing anything for read to miscreg %s\n",
- miscRegName[misc_reg]);
- break;
+
+ case MISCREG_PMXEVTYPER_PMCCFILTR:
+ case MISCREG_PMINTENSET_EL1 ... MISCREG_PMOVSSET_EL0:
+ case MISCREG_PMEVCNTR0_EL0 ... MISCREG_PMEVTYPER5_EL0:
+ case MISCREG_PMCR ... MISCREG_PMOVSSET:
+ return pmu->readMiscReg(misc_reg);
+
case MISCREG_CPSR_Q:
panic("shouldn't be reading this register seperately\n");
case MISCREG_FPSCR_QC:
@@ -640,9 +659,9 @@ ISA::readMiscReg(int misc_reg, ThreadContext *tc)
}
case MISCREG_DBGDIDR:
/* For now just implement the version number.
- * Return 0 as we don't support debug architecture yet.
+ * ARMv7, v7.1 Debug architecture (0b0101 --> 0x5)
*/
- return 0;
+ return 0x5 << 16;
case MISCREG_DBGDSCRint:
return 0;
case MISCREG_ISR:
@@ -1112,6 +1131,7 @@ ISA::setMiscReg(int misc_reg, const MiscReg &val, ThreadContext *tc)
case MISCREG_MIDR:
case MISCREG_ID_PFR0:
case MISCREG_ID_PFR1:
+ case MISCREG_ID_DFR0:
case MISCREG_ID_MMFR0:
case MISCREG_ID_MMFR1:
case MISCREG_ID_MMFR2:
@@ -1443,24 +1463,15 @@ ISA::setMiscReg(int misc_reg, const MiscReg &val, ThreadContext *tc)
case MISCREG_ACTLR:
warn("Not doing anything for write of miscreg ACTLR\n");
break;
- case MISCREG_PMCR:
- {
- // Performance counters not implemented. Instead, interpret
- // a reset command to this register to reset the simulator
- // statistics.
- // PMCR_E | PMCR_P | PMCR_C
- const int ResetAndEnableCounters = 0x7;
- if (newVal == ResetAndEnableCounters) {
- inform("Resetting all simobject stats\n");
- Stats::schedStatEvent(false, true);
- break;
- }
- }
- case MISCREG_PMCCNTR:
- case MISCREG_PMSELR:
- warn("Not doing anything for write to miscreg %s\n",
- miscRegName[misc_reg]);
+
+ case MISCREG_PMXEVTYPER_PMCCFILTR:
+ case MISCREG_PMINTENSET_EL1 ... MISCREG_PMOVSSET_EL0:
+ case MISCREG_PMEVCNTR0_EL0 ... MISCREG_PMEVTYPER5_EL0:
+ case MISCREG_PMCR ... MISCREG_PMOVSSET:
+ pmu->setMiscReg(misc_reg, newVal);
break;
+
+
case MISCREG_HSTR: // TJDBX, now redifined to be RES0
{
HSTR hstrMask = 0;