dev, arm: Refactor and clean up the generic timer model
This changeset cleans up the generic timer a bit and moves most of the register juggling from the ISA code into a separate class in the same source file as the rest of the generic timer. It also removes the assumption that there is always 8 or fewer CPUs in the system. Instead of having a fixed limit, we now instantiate per-core timers as they are requested. This is all in preparation for other patches that add support for virtual timers and a memory mapped interface.
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2014 ARM Limited
|
||||
* Copyright (c) 2010-2015 ARM Limited
|
||||
* All rights reserved
|
||||
*
|
||||
* The license below extends only to copyright in the software and shall
|
||||
@@ -45,6 +45,7 @@
|
||||
#include "cpu/base.hh"
|
||||
#include "debug/Arm.hh"
|
||||
#include "debug/MiscRegs.hh"
|
||||
#include "dev/arm/generic_timer.hh"
|
||||
#include "params/ArmISA.hh"
|
||||
#include "sim/faults.hh"
|
||||
#include "sim/stat_control.hh"
|
||||
@@ -730,52 +731,14 @@ ISA::readMiscReg(int misc_reg, ThreadContext *tc)
|
||||
return readMiscRegNoEffect(MISCREG_SCR_EL3);
|
||||
}
|
||||
}
|
||||
|
||||
// Generic Timer registers
|
||||
case MISCREG_CNTFRQ:
|
||||
case MISCREG_CNTFRQ_EL0:
|
||||
inform_once("Read CNTFREQ_EL0 frequency\n");
|
||||
return getSystemCounter(tc)->freq();
|
||||
case MISCREG_CNTPCT:
|
||||
case MISCREG_CNTPCT_EL0:
|
||||
return getSystemCounter(tc)->value();
|
||||
case MISCREG_CNTVCT:
|
||||
return getSystemCounter(tc)->value();
|
||||
case MISCREG_CNTVCT_EL0:
|
||||
return getSystemCounter(tc)->value();
|
||||
case MISCREG_CNTP_CVAL:
|
||||
case MISCREG_CNTP_CVAL_EL0:
|
||||
return getArchTimer(tc, tc->cpuId())->compareValue();
|
||||
case MISCREG_CNTP_TVAL:
|
||||
case MISCREG_CNTP_TVAL_EL0:
|
||||
return getArchTimer(tc, tc->cpuId())->timerValue();
|
||||
case MISCREG_CNTP_CTL:
|
||||
case MISCREG_CNTP_CTL_EL0:
|
||||
return getArchTimer(tc, tc->cpuId())->control();
|
||||
// PL1 phys. timer, secure
|
||||
// AArch64
|
||||
// case MISCREG_CNTPS_CVAL_EL1:
|
||||
// case MISCREG_CNTPS_TVAL_EL1:
|
||||
// case MISCREG_CNTPS_CTL_EL1:
|
||||
// PL2 phys. timer, non-secure
|
||||
// AArch32
|
||||
// case MISCREG_CNTHCTL:
|
||||
// case MISCREG_CNTHP_CVAL:
|
||||
// case MISCREG_CNTHP_TVAL:
|
||||
// case MISCREG_CNTHP_CTL:
|
||||
// AArch64
|
||||
// case MISCREG_CNTHCTL_EL2:
|
||||
// case MISCREG_CNTHP_CVAL_EL2:
|
||||
// case MISCREG_CNTHP_TVAL_EL2:
|
||||
// case MISCREG_CNTHP_CTL_EL2:
|
||||
// Virtual timer
|
||||
// AArch32
|
||||
// case MISCREG_CNTV_CVAL:
|
||||
// case MISCREG_CNTV_TVAL:
|
||||
// case MISCREG_CNTV_CTL:
|
||||
// AArch64
|
||||
// case MISCREG_CNTV_CVAL_EL2:
|
||||
// case MISCREG_CNTV_TVAL_EL2:
|
||||
// case MISCREG_CNTV_CTL_EL2:
|
||||
case MISCREG_CNTFRQ ... MISCREG_CNTHP_CTL:
|
||||
case MISCREG_CNTPCT ... MISCREG_CNTHP_CVAL:
|
||||
case MISCREG_CNTKCTL_EL1 ... MISCREG_CNTV_CVAL_EL0:
|
||||
case MISCREG_CNTVOFF_EL2 ... MISCREG_CNTPS_CVAL_EL1:
|
||||
return getGenericTimer(tc).readMiscReg(misc_reg);
|
||||
|
||||
default:
|
||||
break;
|
||||
|
||||
@@ -1853,47 +1816,11 @@ ISA::setMiscReg(int misc_reg, const MiscReg &val, ThreadContext *tc)
|
||||
break;
|
||||
|
||||
// Generic Timer registers
|
||||
case MISCREG_CNTFRQ:
|
||||
case MISCREG_CNTFRQ_EL0:
|
||||
getSystemCounter(tc)->setFreq(val);
|
||||
break;
|
||||
case MISCREG_CNTP_CVAL:
|
||||
case MISCREG_CNTP_CVAL_EL0:
|
||||
getArchTimer(tc, tc->cpuId())->setCompareValue(val);
|
||||
break;
|
||||
case MISCREG_CNTP_TVAL:
|
||||
case MISCREG_CNTP_TVAL_EL0:
|
||||
getArchTimer(tc, tc->cpuId())->setTimerValue(val);
|
||||
break;
|
||||
case MISCREG_CNTP_CTL:
|
||||
case MISCREG_CNTP_CTL_EL0:
|
||||
getArchTimer(tc, tc->cpuId())->setControl(val);
|
||||
break;
|
||||
// PL1 phys. timer, secure
|
||||
// AArch64
|
||||
case MISCREG_CNTPS_CVAL_EL1:
|
||||
case MISCREG_CNTPS_TVAL_EL1:
|
||||
case MISCREG_CNTPS_CTL_EL1:
|
||||
// PL2 phys. timer, non-secure
|
||||
// AArch32
|
||||
case MISCREG_CNTHCTL:
|
||||
case MISCREG_CNTHP_CVAL:
|
||||
case MISCREG_CNTHP_TVAL:
|
||||
case MISCREG_CNTHP_CTL:
|
||||
// AArch64
|
||||
case MISCREG_CNTHCTL_EL2:
|
||||
case MISCREG_CNTHP_CVAL_EL2:
|
||||
case MISCREG_CNTHP_TVAL_EL2:
|
||||
case MISCREG_CNTHP_CTL_EL2:
|
||||
// Virtual timer
|
||||
// AArch32
|
||||
case MISCREG_CNTV_CVAL:
|
||||
case MISCREG_CNTV_TVAL:
|
||||
case MISCREG_CNTV_CTL:
|
||||
// AArch64
|
||||
// case MISCREG_CNTV_CVAL_EL2:
|
||||
// case MISCREG_CNTV_TVAL_EL2:
|
||||
// case MISCREG_CNTV_CTL_EL2:
|
||||
case MISCREG_CNTFRQ ... MISCREG_CNTHP_CTL:
|
||||
case MISCREG_CNTPCT ... MISCREG_CNTHP_CVAL:
|
||||
case MISCREG_CNTKCTL_EL1 ... MISCREG_CNTV_CVAL_EL0:
|
||||
case MISCREG_CNTVOFF_EL2 ... MISCREG_CNTPS_CVAL_EL1:
|
||||
getGenericTimer(tc).setMiscReg(misc_reg, newVal);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1988,26 +1915,23 @@ ISA::tlbiMVA(ThreadContext *tc, MiscReg newVal, bool secure_lookup, bool hyp,
|
||||
}
|
||||
}
|
||||
|
||||
::GenericTimer::SystemCounter *
|
||||
ISA::getSystemCounter(ThreadContext *tc)
|
||||
BaseISADevice &
|
||||
ISA::getGenericTimer(ThreadContext *tc)
|
||||
{
|
||||
::GenericTimer::SystemCounter *cnt = ((ArmSystem *) tc->getSystemPtr())->
|
||||
getSystemCounter();
|
||||
if (cnt == NULL) {
|
||||
panic("System counter not available\n");
|
||||
}
|
||||
return cnt;
|
||||
}
|
||||
// We only need to create an ISA interface the first time we try
|
||||
// to access the timer.
|
||||
if (timer)
|
||||
return *timer.get();
|
||||
|
||||
::GenericTimer::ArchTimer *
|
||||
ISA::getArchTimer(ThreadContext *tc, int cpu_id)
|
||||
{
|
||||
::GenericTimer::ArchTimer *timer = ((ArmSystem *) tc->getSystemPtr())->
|
||||
getArchTimer(cpu_id);
|
||||
if (timer == NULL) {
|
||||
panic("Architected timer not available\n");
|
||||
assert(system);
|
||||
GenericTimer *generic_timer(system->getGenericTimer());
|
||||
if (!generic_timer) {
|
||||
panic("Trying to get a generic timer from a system that hasn't "
|
||||
"been configured to use a generic timer.\n");
|
||||
}
|
||||
return timer;
|
||||
|
||||
timer.reset(new GenericTimerISA(*generic_timer, tc->cpuId()));
|
||||
return *timer.get();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 2012-2014 ARM Limited
|
||||
* Copyright (c) 2010, 2012-2015 ARM Limited
|
||||
* All rights reserved
|
||||
*
|
||||
* The license below extends only to copyright in the software and shall
|
||||
@@ -49,7 +49,6 @@
|
||||
#include "arch/arm/tlb.hh"
|
||||
#include "arch/arm/types.hh"
|
||||
#include "debug/Checkpoint.hh"
|
||||
#include "dev/arm/generic_timer.hh"
|
||||
#include "sim/sim_object.hh"
|
||||
|
||||
struct ArmISAParams;
|
||||
@@ -139,6 +138,9 @@ namespace ArmISA
|
||||
// PMU belonging to this ISA
|
||||
BaseISADevice *pmu;
|
||||
|
||||
// Generic timer interface belonging to this ISA
|
||||
std::unique_ptr<BaseISADevice> timer;
|
||||
|
||||
// Cached copies of system-level properties
|
||||
bool haveSecurity;
|
||||
bool haveLPAE;
|
||||
@@ -205,9 +207,7 @@ namespace ArmISA
|
||||
}
|
||||
}
|
||||
|
||||
::GenericTimer::SystemCounter * getSystemCounter(ThreadContext *tc);
|
||||
::GenericTimer::ArchTimer * getArchTimer(ThreadContext *tc,
|
||||
int cpu_id);
|
||||
BaseISADevice &getGenericTimer(ThreadContext *tc);
|
||||
|
||||
|
||||
private:
|
||||
|
||||
@@ -151,24 +151,6 @@ ArmSystem::initState()
|
||||
}
|
||||
}
|
||||
|
||||
GenericTimer::ArchTimer *
|
||||
ArmSystem::getArchTimer(int cpu_id) const
|
||||
{
|
||||
if (_genericTimer) {
|
||||
return _genericTimer->getArchTimer(cpu_id);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GenericTimer::SystemCounter *
|
||||
ArmSystem::getSystemCounter() const
|
||||
{
|
||||
if (_genericTimer) {
|
||||
return _genericTimer->getSystemCounter();
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool
|
||||
ArmSystem::haveSecurity(ThreadContext *tc)
|
||||
{
|
||||
|
||||
@@ -46,13 +46,13 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "dev/arm/generic_timer.hh"
|
||||
#include "kern/linux/events.hh"
|
||||
#include "params/ArmSystem.hh"
|
||||
#include "params/GenericArmSystem.hh"
|
||||
#include "sim/sim_object.hh"
|
||||
#include "sim/system.hh"
|
||||
|
||||
class GenericTimer;
|
||||
class ThreadContext;
|
||||
|
||||
class ArmSystem : public System
|
||||
@@ -166,11 +166,8 @@ class ArmSystem : public System
|
||||
_genericTimer = generic_timer;
|
||||
}
|
||||
|
||||
/** Returns a pointer to the system counter. */
|
||||
GenericTimer::SystemCounter *getSystemCounter() const;
|
||||
|
||||
/** Returns a pointer to the appropriate architected timer. */
|
||||
GenericTimer::ArchTimer *getArchTimer(int cpu_id) const;
|
||||
/** Get a pointer to the system's generic timer model */
|
||||
GenericTimer *getGenericTimer() const { return _genericTimer; }
|
||||
|
||||
/** Returns true if the register width of the highest implemented exception
|
||||
* level is 64 bits (ARMv8) */
|
||||
|
||||
Reference in New Issue
Block a user