/*
- * 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
#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"
ISA::ISA(Params *p)
: SimObject(p),
system(NULL),
+ _decoderFlavour(p->decoderFlavour),
pmu(p->pmu),
lookUpMiscReg(NUM_MISCREGS, {0,0})
{
pmu->setISA(this);
system = dynamic_cast<ArmSystem *>(p->system);
- DPRINTFN("ISA system set to: %p %p\n", system, p->system);
// Cache system-level properties
if (FullSystem && system) {
case MISCREG_DBGDSCRint:
return 0;
case MISCREG_ISR:
- return tc->getCpuPtr()->getInterruptController()->getISR(
+ return tc->getCpuPtr()->getInterruptController(tc->threadId())->getISR(
readMiscRegNoEffect(MISCREG_HCR),
readMiscRegNoEffect(MISCREG_CPSR),
readMiscRegNoEffect(MISCREG_SCR));
case MISCREG_ISR_EL1:
- return tc->getCpuPtr()->getInterruptController()->getISR(
+ return tc->getCpuPtr()->getInterruptController(tc->threadId())->getISR(
readMiscRegNoEffect(MISCREG_HCR_EL2),
readMiscRegNoEffect(MISCREG_CPSR),
readMiscRegNoEffect(MISCREG_SCR_EL3));
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;
miscRegs[sctlr_idx] = (MiscReg)new_sctlr;
tc->getITBPtr()->invalidateMiscReg();
tc->getDTBPtr()->invalidateMiscReg();
-
- if (new_sctlr.c)
- updateBootUncacheable(sctlr_idx, tc);
- return;
}
case MISCREG_MIDR:
case MISCREG_ID_PFR0:
oc = sys->getThreadContext(x);
assert(oc->getITBPtr() && oc->getDTBPtr());
asid = bits(newVal, 63, 48);
- if (haveLargeAsid64)
+ if (!haveLargeAsid64)
asid &= mask(8);
oc->getITBPtr()->flushAsid(asid, secure_lookup, target_el);
oc->getDTBPtr()->flushAsid(asid, secure_lookup, target_el);
case MISCREG_ATS1HR:
case MISCREG_ATS1HW:
{
- RequestPtr req = new Request;
unsigned flags = 0;
BaseTLB::Mode mode = BaseTLB::Read;
TLB::ArmTranslationType tranType = TLB::NormalTran;
// can't be an atomic translation because that causes problems
// with unexpected atomic snoop requests.
warn("Translating via MISCREG(%d) in functional mode! Fix Me!\n", misc_reg);
- req->setVirt(0, val, 1, flags, Request::funcMasterId,
- tc->pcState().pc());
- req->setThreadContext(tc->contextId(), tc->threadId());
- fault = tc->getDTBPtr()->translateFunctional(req, tc, mode, tranType);
+ Request req(0, val, 1, flags, Request::funcMasterId,
+ tc->pcState().pc(), tc->contextId(),
+ tc->threadId());
+ fault = tc->getDTBPtr()->translateFunctional(&req, tc, mode, tranType);
TTBCR ttbcr = readMiscRegNoEffect(MISCREG_TTBCR);
HCR hcr = readMiscRegNoEffect(MISCREG_HCR);
MiscReg newVal;
if (fault == NoFault) {
- Addr paddr = req->getPaddr();
+ Addr paddr = req.getPaddr();
if (haveLPAE && (ttbcr.eae || tranType & TLB::HypMode ||
((tranType & TLB::S1S2NsTran) && hcr.vm) )) {
newVal = (paddr & mask(39, 12)) |
"MISCREG: Translated addr 0x%08x fault fsr %#x: PAR: 0x%08x\n",
val, fsr, newVal);
}
- delete req;
setMiscRegNoEffect(MISCREG_PAR, newVal);
return;
}
{
tc->getITBPtr()->invalidateMiscReg();
tc->getDTBPtr()->invalidateMiscReg();
- SCTLR new_sctlr = newVal;
setMiscRegNoEffect(misc_reg, newVal);
- if (new_sctlr.c)
- updateBootUncacheable(misc_reg, tc);
- return;
}
case MISCREG_CONTEXTIDR:
case MISCREG_PRRR:
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;
}
}
}
void
-ISA::updateBootUncacheable(int sctlr_idx, ThreadContext *tc)
-{
- System *sys;
- ThreadContext *oc;
-
- // Check if all CPUs are booted with caches enabled
- // so we can stop enforcing coherency of some kernel
- // structures manually.
- sys = tc->getSystemPtr();
- for (int x = 0; x < sys->numContexts(); x++) {
- oc = sys->getThreadContext(x);
- // @todo: double check this for security
- SCTLR other_sctlr = oc->readMiscRegNoEffect(sctlr_idx);
- if (!other_sctlr.c && oc->status() != ThreadContext::Halted)
- return;
- }
-
- for (int x = 0; x < sys->numContexts(); x++) {
- oc = sys->getThreadContext(x);
- oc->getDTBPtr()->allCpusCaching();
- oc->getITBPtr()->allCpusCaching();
-
- // If CheckerCPU is connected, need to notify it.
- CheckerCPU *checker = oc->getCheckerCpuPtr();
- if (checker) {
- checker->getDTBPtr()->allCpusCaching();
- checker->getITBPtr()->allCpusCaching();
- }
- }
-}
-
-void
-ISA::tlbiVA(ThreadContext *tc, MiscReg newVal, uint8_t asid, bool secure_lookup,
- uint8_t target_el)
+ISA::tlbiVA(ThreadContext *tc, MiscReg newVal, uint16_t asid,
+ bool secure_lookup, uint8_t target_el)
{
- if (haveLargeAsid64)
+ if (!haveLargeAsid64)
asid &= mask(8);
Addr va = ((Addr) bits(newVal, 43, 0)) << 12;
System *sys = tc->getSystemPtr();
}
}
-::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");
+ // We only need to create an ISA interface the first time we try
+ // to access the timer.
+ if (timer)
+ return *timer.get();
+
+ 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 cnt;
-}
-::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");
- }
- return timer;
+ timer.reset(new GenericTimerISA(*generic_timer, tc->contextId()));
+ return *timer.get();
}
}