generic_timer.cc revision 12733
110037SARM gem5 Developers/* 211933Sandreas.sandberg@arm.com * Copyright (c) 2013, 2015, 2017 ARM Limited 310037SARM gem5 Developers * All rights reserved. 410037SARM gem5 Developers * 510037SARM gem5 Developers * The license below extends only to copyright in the software and shall 610037SARM gem5 Developers * not be construed as granting a license to any other intellectual 710037SARM gem5 Developers * property including but not limited to intellectual property relating 810037SARM gem5 Developers * to a hardware implementation of the functionality of the software 910037SARM gem5 Developers * licensed hereunder. You may use the software subject to the license 1010037SARM gem5 Developers * terms below provided that you ensure that this notice is replicated 1110037SARM gem5 Developers * unmodified and in its entirety in all distributions of the software, 1210037SARM gem5 Developers * modified or unmodified, in source code or in binary form. 1310037SARM gem5 Developers * 1410037SARM gem5 Developers * Redistribution and use in source and binary forms, with or without 1510037SARM gem5 Developers * modification, are permitted provided that the following conditions are 1610037SARM gem5 Developers * met: redistributions of source code must retain the above copyright 1710037SARM gem5 Developers * notice, this list of conditions and the following disclaimer; 1810037SARM gem5 Developers * redistributions in binary form must reproduce the above copyright 1910037SARM gem5 Developers * notice, this list of conditions and the following disclaimer in the 2010037SARM gem5 Developers * documentation and/or other materials provided with the distribution; 2110037SARM gem5 Developers * neither the name of the copyright holders nor the names of its 2210037SARM gem5 Developers * contributors may be used to endorse or promote products derived from 2310037SARM gem5 Developers * this software without specific prior written permission. 2410037SARM gem5 Developers * 2510037SARM gem5 Developers * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 2610037SARM gem5 Developers * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 2710037SARM gem5 Developers * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 2810037SARM gem5 Developers * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2910037SARM gem5 Developers * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 3010037SARM gem5 Developers * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 3110037SARM gem5 Developers * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 3210037SARM gem5 Developers * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 3310037SARM gem5 Developers * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 3410037SARM gem5 Developers * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 3510037SARM gem5 Developers * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 3610037SARM gem5 Developers * 3710037SARM gem5 Developers * Authors: Giacomo Gabrielli 3810844Sandreas.sandberg@arm.com * Andreas Sandberg 3910037SARM gem5 Developers */ 4010037SARM gem5 Developers 4110844Sandreas.sandberg@arm.com#include "dev/arm/generic_timer.hh" 4210844Sandreas.sandberg@arm.com 4310037SARM gem5 Developers#include "arch/arm/system.hh" 4410037SARM gem5 Developers#include "debug/Timer.hh" 4510037SARM gem5 Developers#include "dev/arm/base_gic.hh" 4610847Sandreas.sandberg@arm.com#include "mem/packet_access.hh" 4710844Sandreas.sandberg@arm.com#include "params/GenericTimer.hh" 4810847Sandreas.sandberg@arm.com#include "params/GenericTimerMem.hh" 4910844Sandreas.sandberg@arm.com 5010844Sandreas.sandberg@arm.comSystemCounter::SystemCounter() 5110844Sandreas.sandberg@arm.com : _freq(0), _period(0), _resetTick(0), _regCntkctl(0) 5210844Sandreas.sandberg@arm.com{ 5310844Sandreas.sandberg@arm.com setFreq(0x01800000); 5410844Sandreas.sandberg@arm.com} 5510037SARM gem5 Developers 5610037SARM gem5 Developersvoid 5710844Sandreas.sandberg@arm.comSystemCounter::setFreq(uint32_t freq) 5810037SARM gem5 Developers{ 5910037SARM gem5 Developers if (_freq != 0) { 6010037SARM gem5 Developers // Altering the frequency after boot shouldn't be done in practice. 6110037SARM gem5 Developers warn_once("The frequency of the system counter has already been set"); 6210037SARM gem5 Developers } 6310037SARM gem5 Developers _freq = freq; 6410037SARM gem5 Developers _period = (1.0 / freq) * SimClock::Frequency; 6510037SARM gem5 Developers _resetTick = curTick(); 6610037SARM gem5 Developers} 6710037SARM gem5 Developers 6810037SARM gem5 Developersvoid 6910905Sandreas.sandberg@arm.comSystemCounter::serialize(CheckpointOut &cp) const 7010037SARM gem5 Developers{ 7110844Sandreas.sandberg@arm.com SERIALIZE_SCALAR(_regCntkctl); 7212733Sandreas.sandberg@arm.com SERIALIZE_SCALAR(_regCnthctl); 7310037SARM gem5 Developers SERIALIZE_SCALAR(_freq); 7410037SARM gem5 Developers SERIALIZE_SCALAR(_period); 7510037SARM gem5 Developers SERIALIZE_SCALAR(_resetTick); 7610037SARM gem5 Developers} 7710037SARM gem5 Developers 7810037SARM gem5 Developersvoid 7910905Sandreas.sandberg@arm.comSystemCounter::unserialize(CheckpointIn &cp) 8010037SARM gem5 Developers{ 8110844Sandreas.sandberg@arm.com // We didn't handle CNTKCTL in this class before, assume it's zero 8210844Sandreas.sandberg@arm.com // if it isn't present. 8310844Sandreas.sandberg@arm.com if (!UNSERIALIZE_OPT_SCALAR(_regCntkctl)) 8410844Sandreas.sandberg@arm.com _regCntkctl = 0; 8512733Sandreas.sandberg@arm.com if (!UNSERIALIZE_OPT_SCALAR(_regCnthctl)) 8612733Sandreas.sandberg@arm.com _regCnthctl = 0; 8710037SARM gem5 Developers UNSERIALIZE_SCALAR(_freq); 8810037SARM gem5 Developers UNSERIALIZE_SCALAR(_period); 8910037SARM gem5 Developers UNSERIALIZE_SCALAR(_resetTick); 9010037SARM gem5 Developers} 9110037SARM gem5 Developers 9210844Sandreas.sandberg@arm.com 9310844Sandreas.sandberg@arm.com 9410844Sandreas.sandberg@arm.comArchTimer::ArchTimer(const std::string &name, 9510844Sandreas.sandberg@arm.com SimObject &parent, 9610844Sandreas.sandberg@arm.com SystemCounter &sysctr, 9710844Sandreas.sandberg@arm.com const Interrupt &interrupt) 9810844Sandreas.sandberg@arm.com : _name(name), _parent(parent), _systemCounter(sysctr), 9910844Sandreas.sandberg@arm.com _interrupt(interrupt), 10010845Sandreas.sandberg@arm.com _control(0), _counterLimit(0), _offset(0), 10112086Sspwilson2@wisc.edu _counterLimitReachedEvent([this]{ counterLimitReached(); }, name) 10210844Sandreas.sandberg@arm.com{ 10310844Sandreas.sandberg@arm.com} 10410844Sandreas.sandberg@arm.com 10510037SARM gem5 Developersvoid 10610844Sandreas.sandberg@arm.comArchTimer::counterLimitReached() 10710037SARM gem5 Developers{ 10810037SARM gem5 Developers _control.istatus = 1; 10910037SARM gem5 Developers 11010037SARM gem5 Developers if (!_control.enable) 11110037SARM gem5 Developers return; 11210037SARM gem5 Developers 11310844Sandreas.sandberg@arm.com DPRINTF(Timer, "Counter limit reached\n"); 11410037SARM gem5 Developers if (!_control.imask) { 11512102SCurtis.Dunham@arm.com if (scheduleEvents()) { 11612102SCurtis.Dunham@arm.com DPRINTF(Timer, "Causing interrupt\n"); 11712102SCurtis.Dunham@arm.com _interrupt.send(); 11812102SCurtis.Dunham@arm.com } else { 11912102SCurtis.Dunham@arm.com DPRINTF(Timer, "Kvm mode; skipping simulated interrupt\n"); 12012102SCurtis.Dunham@arm.com } 12110037SARM gem5 Developers } 12210037SARM gem5 Developers} 12310037SARM gem5 Developers 12410037SARM gem5 Developersvoid 12510844Sandreas.sandberg@arm.comArchTimer::updateCounter() 12610037SARM gem5 Developers{ 12710037SARM gem5 Developers if (_counterLimitReachedEvent.scheduled()) 12810844Sandreas.sandberg@arm.com _parent.deschedule(_counterLimitReachedEvent); 12910844Sandreas.sandberg@arm.com if (value() >= _counterLimit) { 13010037SARM gem5 Developers counterLimitReached(); 13110037SARM gem5 Developers } else { 13210037SARM gem5 Developers _control.istatus = 0; 13312102SCurtis.Dunham@arm.com if (scheduleEvents()) { 13412102SCurtis.Dunham@arm.com const auto period(_systemCounter.period()); 13512102SCurtis.Dunham@arm.com _parent.schedule(_counterLimitReachedEvent, 13612102SCurtis.Dunham@arm.com curTick() + (_counterLimit - value()) * period); 13712102SCurtis.Dunham@arm.com } 13810037SARM gem5 Developers } 13910037SARM gem5 Developers} 14010037SARM gem5 Developers 14110037SARM gem5 Developersvoid 14210844Sandreas.sandberg@arm.comArchTimer::setCompareValue(uint64_t val) 14310037SARM gem5 Developers{ 14410844Sandreas.sandberg@arm.com _counterLimit = val; 14510844Sandreas.sandberg@arm.com updateCounter(); 14610037SARM gem5 Developers} 14710037SARM gem5 Developers 14810037SARM gem5 Developersvoid 14910844Sandreas.sandberg@arm.comArchTimer::setTimerValue(uint32_t val) 15010844Sandreas.sandberg@arm.com{ 15110844Sandreas.sandberg@arm.com setCompareValue(value() + sext<32>(val)); 15210844Sandreas.sandberg@arm.com} 15310844Sandreas.sandberg@arm.com 15410844Sandreas.sandberg@arm.comvoid 15510844Sandreas.sandberg@arm.comArchTimer::setControl(uint32_t val) 15610037SARM gem5 Developers{ 15710037SARM gem5 Developers ArchTimerCtrl new_ctl = val; 15810037SARM gem5 Developers if ((new_ctl.enable && !new_ctl.imask) && 15910037SARM gem5 Developers !(_control.enable && !_control.imask)) { 16010037SARM gem5 Developers // Re-evalute the timer condition 16110844Sandreas.sandberg@arm.com if (_counterLimit >= value()) { 16210037SARM gem5 Developers _control.istatus = 1; 16310037SARM gem5 Developers 16410037SARM gem5 Developers DPRINTF(Timer, "Causing interrupt in control\n"); 16510844Sandreas.sandberg@arm.com //_interrupt.send(); 16610037SARM gem5 Developers } 16710037SARM gem5 Developers } 16810037SARM gem5 Developers _control.enable = new_ctl.enable; 16910037SARM gem5 Developers _control.imask = new_ctl.imask; 17010037SARM gem5 Developers} 17110037SARM gem5 Developers 17210845Sandreas.sandberg@arm.comvoid 17310845Sandreas.sandberg@arm.comArchTimer::setOffset(uint64_t val) 17410845Sandreas.sandberg@arm.com{ 17510845Sandreas.sandberg@arm.com _offset = val; 17610845Sandreas.sandberg@arm.com updateCounter(); 17710845Sandreas.sandberg@arm.com} 17810845Sandreas.sandberg@arm.com 17910844Sandreas.sandberg@arm.comuint64_t 18010844Sandreas.sandberg@arm.comArchTimer::value() const 18110844Sandreas.sandberg@arm.com{ 18210845Sandreas.sandberg@arm.com return _systemCounter.value() - _offset; 18310844Sandreas.sandberg@arm.com} 18410844Sandreas.sandberg@arm.com 18510037SARM gem5 Developersvoid 18610905Sandreas.sandberg@arm.comArchTimer::serialize(CheckpointOut &cp) const 18710037SARM gem5 Developers{ 18810905Sandreas.sandberg@arm.com paramOut(cp, "control_serial", _control); 18910037SARM gem5 Developers SERIALIZE_SCALAR(_counterLimit); 19010845Sandreas.sandberg@arm.com SERIALIZE_SCALAR(_offset); 19110037SARM gem5 Developers} 19210037SARM gem5 Developers 19310037SARM gem5 Developersvoid 19410905Sandreas.sandberg@arm.comArchTimer::unserialize(CheckpointIn &cp) 19510037SARM gem5 Developers{ 19610905Sandreas.sandberg@arm.com paramIn(cp, "control_serial", _control); 19710845Sandreas.sandberg@arm.com // We didn't serialize an offset before we added support for the 19810845Sandreas.sandberg@arm.com // virtual timer. Consider it optional to maintain backwards 19910845Sandreas.sandberg@arm.com // compatibility. 20010845Sandreas.sandberg@arm.com if (!UNSERIALIZE_OPT_SCALAR(_offset)) 20110845Sandreas.sandberg@arm.com _offset = 0; 20212101SCurtis.Dunham@arm.com 20312101SCurtis.Dunham@arm.com // We no longer schedule an event here because we may enter KVM 20412101SCurtis.Dunham@arm.com // emulation. The event creation is delayed until drainResume(). 20512101SCurtis.Dunham@arm.com} 20612101SCurtis.Dunham@arm.com 20712101SCurtis.Dunham@arm.comDrainState 20812101SCurtis.Dunham@arm.comArchTimer::drain() 20912101SCurtis.Dunham@arm.com{ 21012101SCurtis.Dunham@arm.com if (_counterLimitReachedEvent.scheduled()) 21112101SCurtis.Dunham@arm.com _parent.deschedule(_counterLimitReachedEvent); 21212101SCurtis.Dunham@arm.com 21312101SCurtis.Dunham@arm.com return DrainState::Drained; 21412101SCurtis.Dunham@arm.com} 21512101SCurtis.Dunham@arm.com 21612101SCurtis.Dunham@arm.comvoid 21712101SCurtis.Dunham@arm.comArchTimer::drainResume() 21812101SCurtis.Dunham@arm.com{ 21912101SCurtis.Dunham@arm.com updateCounter(); 22010037SARM gem5 Developers} 22110037SARM gem5 Developers 22210844Sandreas.sandberg@arm.comvoid 22310844Sandreas.sandberg@arm.comArchTimer::Interrupt::send() 22410037SARM gem5 Developers{ 22510844Sandreas.sandberg@arm.com if (_ppi) { 22610844Sandreas.sandberg@arm.com _gic.sendPPInt(_irq, _cpu); 22710844Sandreas.sandberg@arm.com } else { 22810844Sandreas.sandberg@arm.com _gic.sendInt(_irq); 22910844Sandreas.sandberg@arm.com } 23010844Sandreas.sandberg@arm.com} 23110037SARM gem5 Developers 23210844Sandreas.sandberg@arm.com 23310844Sandreas.sandberg@arm.comvoid 23410844Sandreas.sandberg@arm.comArchTimer::Interrupt::clear() 23510844Sandreas.sandberg@arm.com{ 23610844Sandreas.sandberg@arm.com if (_ppi) { 23710844Sandreas.sandberg@arm.com _gic.clearPPInt(_irq, _cpu); 23810844Sandreas.sandberg@arm.com } else { 23910844Sandreas.sandberg@arm.com _gic.clearInt(_irq); 24010844Sandreas.sandberg@arm.com } 24110844Sandreas.sandberg@arm.com} 24210844Sandreas.sandberg@arm.com 24310844Sandreas.sandberg@arm.com 24410844Sandreas.sandberg@arm.comGenericTimer::GenericTimer(GenericTimerParams *p) 24512467SCurtis.Dunham@arm.com : ClockedObject(p), 24612102SCurtis.Dunham@arm.com system(*p->system), 24710844Sandreas.sandberg@arm.com gic(p->gic), 24812733Sandreas.sandberg@arm.com irqPhysS(p->int_phys_s), 24912733Sandreas.sandberg@arm.com irqPhysNS(p->int_phys_ns), 25012733Sandreas.sandberg@arm.com irqVirt(p->int_virt), 25112733Sandreas.sandberg@arm.com irqHyp(p->int_hyp) 25210844Sandreas.sandberg@arm.com{ 25311668Sandreas.sandberg@arm.com fatal_if(!p->system, "No system specified, can't instantiate timer.\n"); 25412102SCurtis.Dunham@arm.com system.setGenericTimer(this); 25510037SARM gem5 Developers} 25610037SARM gem5 Developers 25710037SARM gem5 Developersvoid 25810905Sandreas.sandberg@arm.comGenericTimer::serialize(CheckpointOut &cp) const 25910037SARM gem5 Developers{ 26010905Sandreas.sandberg@arm.com paramOut(cp, "cpu_count", timers.size()); 26110844Sandreas.sandberg@arm.com 26210905Sandreas.sandberg@arm.com systemCounter.serializeSection(cp, "sys_counter"); 26310844Sandreas.sandberg@arm.com 26410844Sandreas.sandberg@arm.com for (int i = 0; i < timers.size(); ++i) { 26510905Sandreas.sandberg@arm.com const CoreTimers &core(*timers[i]); 26610844Sandreas.sandberg@arm.com 26710905Sandreas.sandberg@arm.com // This should really be phys_timerN, but we are stuck with 26810905Sandreas.sandberg@arm.com // arch_timer for backwards compatibility. 26912733Sandreas.sandberg@arm.com core.physNS.serializeSection(cp, csprintf("arch_timer%d", i)); 27012733Sandreas.sandberg@arm.com core.physS.serializeSection(cp, csprintf("phys_s_timer%d", i)); 27110905Sandreas.sandberg@arm.com core.virt.serializeSection(cp, csprintf("virt_timer%d", i)); 27212733Sandreas.sandberg@arm.com core.hyp.serializeSection(cp, csprintf("hyp_timer%d", i)); 27310037SARM gem5 Developers } 27410037SARM gem5 Developers} 27510037SARM gem5 Developers 27610037SARM gem5 Developersvoid 27710905Sandreas.sandberg@arm.comGenericTimer::unserialize(CheckpointIn &cp) 27810037SARM gem5 Developers{ 27910905Sandreas.sandberg@arm.com systemCounter.unserializeSection(cp, "sys_counter"); 28010844Sandreas.sandberg@arm.com 28110844Sandreas.sandberg@arm.com // Try to unserialize the CPU count. Old versions of the timer 28210844Sandreas.sandberg@arm.com // model assumed a 8 CPUs, so we fall back to that if the field 28310844Sandreas.sandberg@arm.com // isn't present. 28410844Sandreas.sandberg@arm.com static const unsigned OLD_CPU_MAX = 8; 28510844Sandreas.sandberg@arm.com unsigned cpu_count; 28610844Sandreas.sandberg@arm.com if (!UNSERIALIZE_OPT_SCALAR(cpu_count)) { 28710844Sandreas.sandberg@arm.com warn("Checkpoint does not contain CPU count, assuming %i CPUs\n", 28810844Sandreas.sandberg@arm.com OLD_CPU_MAX); 28910844Sandreas.sandberg@arm.com cpu_count = OLD_CPU_MAX; 29010844Sandreas.sandberg@arm.com } 29110844Sandreas.sandberg@arm.com 29210844Sandreas.sandberg@arm.com for (int i = 0; i < cpu_count; ++i) { 29310844Sandreas.sandberg@arm.com CoreTimers &core(getTimers(i)); 29410844Sandreas.sandberg@arm.com // This should really be phys_timerN, but we are stuck with 29510844Sandreas.sandberg@arm.com // arch_timer for backwards compatibility. 29612733Sandreas.sandberg@arm.com core.physNS.unserializeSection(cp, csprintf("arch_timer%d", i)); 29712733Sandreas.sandberg@arm.com core.physS.unserializeSection(cp, csprintf("phys_s_timer%d", i)); 29810905Sandreas.sandberg@arm.com core.virt.unserializeSection(cp, csprintf("virt_timer%d", i)); 29912733Sandreas.sandberg@arm.com core.hyp.unserializeSection(cp, csprintf("hyp_timer%d", i)); 30010037SARM gem5 Developers } 30110037SARM gem5 Developers} 30210037SARM gem5 Developers 30310844Sandreas.sandberg@arm.com 30410844Sandreas.sandberg@arm.comGenericTimer::CoreTimers & 30510844Sandreas.sandberg@arm.comGenericTimer::getTimers(int cpu_id) 30610844Sandreas.sandberg@arm.com{ 30710844Sandreas.sandberg@arm.com if (cpu_id >= timers.size()) 30810844Sandreas.sandberg@arm.com createTimers(cpu_id + 1); 30910844Sandreas.sandberg@arm.com 31010844Sandreas.sandberg@arm.com return *timers[cpu_id]; 31110844Sandreas.sandberg@arm.com} 31210844Sandreas.sandberg@arm.com 31310844Sandreas.sandberg@arm.comvoid 31410844Sandreas.sandberg@arm.comGenericTimer::createTimers(unsigned cpus) 31510844Sandreas.sandberg@arm.com{ 31610844Sandreas.sandberg@arm.com assert(timers.size() < cpus); 31710844Sandreas.sandberg@arm.com 31810844Sandreas.sandberg@arm.com const unsigned old_cpu_count(timers.size()); 31910844Sandreas.sandberg@arm.com timers.resize(cpus); 32010844Sandreas.sandberg@arm.com for (unsigned i = old_cpu_count; i < cpus; ++i) { 32110844Sandreas.sandberg@arm.com timers[i].reset( 32212733Sandreas.sandberg@arm.com new CoreTimers(*this, system, i, 32312733Sandreas.sandberg@arm.com irqPhysS, irqPhysNS, irqVirt, irqHyp)); 32410844Sandreas.sandberg@arm.com } 32510844Sandreas.sandberg@arm.com} 32610844Sandreas.sandberg@arm.com 32710844Sandreas.sandberg@arm.com 32810844Sandreas.sandberg@arm.comvoid 32910844Sandreas.sandberg@arm.comGenericTimer::setMiscReg(int reg, unsigned cpu, MiscReg val) 33010844Sandreas.sandberg@arm.com{ 33110844Sandreas.sandberg@arm.com CoreTimers &core(getTimers(cpu)); 33210844Sandreas.sandberg@arm.com 33310844Sandreas.sandberg@arm.com switch (reg) { 33410844Sandreas.sandberg@arm.com case MISCREG_CNTFRQ: 33510844Sandreas.sandberg@arm.com case MISCREG_CNTFRQ_EL0: 33610844Sandreas.sandberg@arm.com systemCounter.setFreq(val); 33710844Sandreas.sandberg@arm.com return; 33810844Sandreas.sandberg@arm.com 33910844Sandreas.sandberg@arm.com case MISCREG_CNTKCTL: 34010844Sandreas.sandberg@arm.com case MISCREG_CNTKCTL_EL1: 34110844Sandreas.sandberg@arm.com systemCounter.setKernelControl(val); 34210844Sandreas.sandberg@arm.com return; 34310844Sandreas.sandberg@arm.com 34412733Sandreas.sandberg@arm.com case MISCREG_CNTHCTL: 34512733Sandreas.sandberg@arm.com case MISCREG_CNTHCTL_EL2: 34612733Sandreas.sandberg@arm.com systemCounter.setHypControl(val); 34712733Sandreas.sandberg@arm.com return; 34812733Sandreas.sandberg@arm.com 34912733Sandreas.sandberg@arm.com // Physical timer (NS) 35010844Sandreas.sandberg@arm.com case MISCREG_CNTP_CVAL_NS: 35110844Sandreas.sandberg@arm.com case MISCREG_CNTP_CVAL_EL0: 35212733Sandreas.sandberg@arm.com core.physNS.setCompareValue(val); 35310844Sandreas.sandberg@arm.com return; 35410844Sandreas.sandberg@arm.com 35510844Sandreas.sandberg@arm.com case MISCREG_CNTP_TVAL_NS: 35610844Sandreas.sandberg@arm.com case MISCREG_CNTP_TVAL_EL0: 35712733Sandreas.sandberg@arm.com core.physNS.setTimerValue(val); 35810844Sandreas.sandberg@arm.com return; 35910844Sandreas.sandberg@arm.com 36010844Sandreas.sandberg@arm.com case MISCREG_CNTP_CTL_NS: 36110844Sandreas.sandberg@arm.com case MISCREG_CNTP_CTL_EL0: 36212733Sandreas.sandberg@arm.com core.physNS.setControl(val); 36310844Sandreas.sandberg@arm.com return; 36410844Sandreas.sandberg@arm.com 36510844Sandreas.sandberg@arm.com // Count registers 36610844Sandreas.sandberg@arm.com case MISCREG_CNTPCT: 36710844Sandreas.sandberg@arm.com case MISCREG_CNTPCT_EL0: 36810844Sandreas.sandberg@arm.com case MISCREG_CNTVCT: 36910844Sandreas.sandberg@arm.com case MISCREG_CNTVCT_EL0: 37010844Sandreas.sandberg@arm.com warn("Ignoring write to read only count register: %s\n", 37110844Sandreas.sandberg@arm.com miscRegName[reg]); 37210844Sandreas.sandberg@arm.com return; 37310844Sandreas.sandberg@arm.com 37410844Sandreas.sandberg@arm.com // Virtual timer 37510844Sandreas.sandberg@arm.com case MISCREG_CNTVOFF: 37610844Sandreas.sandberg@arm.com case MISCREG_CNTVOFF_EL2: 37710845Sandreas.sandberg@arm.com core.virt.setOffset(val); 37810845Sandreas.sandberg@arm.com return; 37910845Sandreas.sandberg@arm.com 38010844Sandreas.sandberg@arm.com case MISCREG_CNTV_CVAL: 38110844Sandreas.sandberg@arm.com case MISCREG_CNTV_CVAL_EL0: 38210845Sandreas.sandberg@arm.com core.virt.setCompareValue(val); 38310845Sandreas.sandberg@arm.com return; 38410845Sandreas.sandberg@arm.com 38510844Sandreas.sandberg@arm.com case MISCREG_CNTV_TVAL: 38610844Sandreas.sandberg@arm.com case MISCREG_CNTV_TVAL_EL0: 38710845Sandreas.sandberg@arm.com core.virt.setTimerValue(val); 38810845Sandreas.sandberg@arm.com return; 38910845Sandreas.sandberg@arm.com 39010844Sandreas.sandberg@arm.com case MISCREG_CNTV_CTL: 39110844Sandreas.sandberg@arm.com case MISCREG_CNTV_CTL_EL0: 39210845Sandreas.sandberg@arm.com core.virt.setControl(val); 39310845Sandreas.sandberg@arm.com return; 39410844Sandreas.sandberg@arm.com 39512733Sandreas.sandberg@arm.com // Physical timer (S) 39610844Sandreas.sandberg@arm.com case MISCREG_CNTP_CTL_S: 39712733Sandreas.sandberg@arm.com case MISCREG_CNTPS_CTL_EL1: 39812733Sandreas.sandberg@arm.com core.physS.setControl(val); 39912733Sandreas.sandberg@arm.com return; 40012733Sandreas.sandberg@arm.com 40112733Sandreas.sandberg@arm.com case MISCREG_CNTP_CVAL_S: 40210844Sandreas.sandberg@arm.com case MISCREG_CNTPS_CVAL_EL1: 40312733Sandreas.sandberg@arm.com core.physS.setCompareValue(val); 40412733Sandreas.sandberg@arm.com return; 40512733Sandreas.sandberg@arm.com 40612733Sandreas.sandberg@arm.com case MISCREG_CNTP_TVAL_S: 40710844Sandreas.sandberg@arm.com case MISCREG_CNTPS_TVAL_EL1: 40812733Sandreas.sandberg@arm.com core.physS.setTimerValue(val); 40912733Sandreas.sandberg@arm.com return; 41010844Sandreas.sandberg@arm.com 41112733Sandreas.sandberg@arm.com // Hyp phys. timer, non-secure 41212733Sandreas.sandberg@arm.com case MISCREG_CNTHP_CTL: 41312733Sandreas.sandberg@arm.com case MISCREG_CNTHP_CTL_EL2: 41412733Sandreas.sandberg@arm.com core.hyp.setControl(val); 41512733Sandreas.sandberg@arm.com return; 41612733Sandreas.sandberg@arm.com 41710844Sandreas.sandberg@arm.com case MISCREG_CNTHP_CVAL: 41810844Sandreas.sandberg@arm.com case MISCREG_CNTHP_CVAL_EL2: 41912733Sandreas.sandberg@arm.com core.hyp.setCompareValue(val); 42012733Sandreas.sandberg@arm.com return; 42112733Sandreas.sandberg@arm.com 42210844Sandreas.sandberg@arm.com case MISCREG_CNTHP_TVAL: 42310844Sandreas.sandberg@arm.com case MISCREG_CNTHP_TVAL_EL2: 42412733Sandreas.sandberg@arm.com core.hyp.setTimerValue(val); 42510844Sandreas.sandberg@arm.com return; 42610844Sandreas.sandberg@arm.com 42710844Sandreas.sandberg@arm.com default: 42810844Sandreas.sandberg@arm.com warn("Writing to unknown register: %s\n", miscRegName[reg]); 42910844Sandreas.sandberg@arm.com return; 43010844Sandreas.sandberg@arm.com } 43110844Sandreas.sandberg@arm.com} 43210844Sandreas.sandberg@arm.com 43310844Sandreas.sandberg@arm.com 43410844Sandreas.sandberg@arm.comMiscReg 43510844Sandreas.sandberg@arm.comGenericTimer::readMiscReg(int reg, unsigned cpu) 43610844Sandreas.sandberg@arm.com{ 43710844Sandreas.sandberg@arm.com CoreTimers &core(getTimers(cpu)); 43810844Sandreas.sandberg@arm.com 43910844Sandreas.sandberg@arm.com switch (reg) { 44010844Sandreas.sandberg@arm.com case MISCREG_CNTFRQ: 44110844Sandreas.sandberg@arm.com case MISCREG_CNTFRQ_EL0: 44210844Sandreas.sandberg@arm.com return systemCounter.freq(); 44310844Sandreas.sandberg@arm.com 44410844Sandreas.sandberg@arm.com case MISCREG_CNTKCTL: 44510844Sandreas.sandberg@arm.com case MISCREG_CNTKCTL_EL1: 44610844Sandreas.sandberg@arm.com return systemCounter.getKernelControl(); 44710844Sandreas.sandberg@arm.com 44812733Sandreas.sandberg@arm.com case MISCREG_CNTHCTL: 44912733Sandreas.sandberg@arm.com case MISCREG_CNTHCTL_EL2: 45012733Sandreas.sandberg@arm.com return systemCounter.getHypControl(); 45112733Sandreas.sandberg@arm.com 45210844Sandreas.sandberg@arm.com // Physical timer 45312733Sandreas.sandberg@arm.com case MISCREG_CNTP_CVAL_NS: 45410844Sandreas.sandberg@arm.com case MISCREG_CNTP_CVAL_EL0: 45512733Sandreas.sandberg@arm.com return core.physNS.compareValue(); 45610844Sandreas.sandberg@arm.com 45712733Sandreas.sandberg@arm.com case MISCREG_CNTP_TVAL_NS: 45810844Sandreas.sandberg@arm.com case MISCREG_CNTP_TVAL_EL0: 45912733Sandreas.sandberg@arm.com return core.physNS.timerValue(); 46010844Sandreas.sandberg@arm.com 46110844Sandreas.sandberg@arm.com case MISCREG_CNTP_CTL_EL0: 46210844Sandreas.sandberg@arm.com case MISCREG_CNTP_CTL_NS: 46312733Sandreas.sandberg@arm.com return core.physNS.control(); 46410844Sandreas.sandberg@arm.com 46510844Sandreas.sandberg@arm.com case MISCREG_CNTPCT: 46610844Sandreas.sandberg@arm.com case MISCREG_CNTPCT_EL0: 46712733Sandreas.sandberg@arm.com return core.physNS.value(); 46810844Sandreas.sandberg@arm.com 46910844Sandreas.sandberg@arm.com 47010844Sandreas.sandberg@arm.com // Virtual timer 47110844Sandreas.sandberg@arm.com case MISCREG_CNTVCT: 47210844Sandreas.sandberg@arm.com case MISCREG_CNTVCT_EL0: 47310845Sandreas.sandberg@arm.com return core.virt.value(); 47410844Sandreas.sandberg@arm.com 47510844Sandreas.sandberg@arm.com case MISCREG_CNTVOFF: 47610844Sandreas.sandberg@arm.com case MISCREG_CNTVOFF_EL2: 47710845Sandreas.sandberg@arm.com return core.virt.offset(); 47810845Sandreas.sandberg@arm.com 47910844Sandreas.sandberg@arm.com case MISCREG_CNTV_CVAL: 48010844Sandreas.sandberg@arm.com case MISCREG_CNTV_CVAL_EL0: 48110845Sandreas.sandberg@arm.com return core.virt.compareValue(); 48210845Sandreas.sandberg@arm.com 48310844Sandreas.sandberg@arm.com case MISCREG_CNTV_TVAL: 48410844Sandreas.sandberg@arm.com case MISCREG_CNTV_TVAL_EL0: 48510845Sandreas.sandberg@arm.com return core.virt.timerValue(); 48610845Sandreas.sandberg@arm.com 48710844Sandreas.sandberg@arm.com case MISCREG_CNTV_CTL: 48810844Sandreas.sandberg@arm.com case MISCREG_CNTV_CTL_EL0: 48910845Sandreas.sandberg@arm.com return core.virt.control(); 49010844Sandreas.sandberg@arm.com 49110844Sandreas.sandberg@arm.com // PL1 phys. timer, secure 49210844Sandreas.sandberg@arm.com case MISCREG_CNTP_CTL_S: 49312733Sandreas.sandberg@arm.com case MISCREG_CNTPS_CTL_EL1: 49412733Sandreas.sandberg@arm.com return core.physS.control(); 49512733Sandreas.sandberg@arm.com 49612733Sandreas.sandberg@arm.com case MISCREG_CNTP_CVAL_S: 49710844Sandreas.sandberg@arm.com case MISCREG_CNTPS_CVAL_EL1: 49812733Sandreas.sandberg@arm.com return core.physS.compareValue(); 49912733Sandreas.sandberg@arm.com 50012733Sandreas.sandberg@arm.com case MISCREG_CNTP_TVAL_S: 50110844Sandreas.sandberg@arm.com case MISCREG_CNTPS_TVAL_EL1: 50212733Sandreas.sandberg@arm.com return core.physS.timerValue(); 50310844Sandreas.sandberg@arm.com 50412733Sandreas.sandberg@arm.com // HYP phys. timer (NS) 50512733Sandreas.sandberg@arm.com case MISCREG_CNTHP_CTL: 50612733Sandreas.sandberg@arm.com case MISCREG_CNTHP_CTL_EL2: 50712733Sandreas.sandberg@arm.com return core.hyp.control(); 50812733Sandreas.sandberg@arm.com 50910844Sandreas.sandberg@arm.com case MISCREG_CNTHP_CVAL: 51010844Sandreas.sandberg@arm.com case MISCREG_CNTHP_CVAL_EL2: 51112733Sandreas.sandberg@arm.com return core.hyp.compareValue(); 51212733Sandreas.sandberg@arm.com 51310844Sandreas.sandberg@arm.com case MISCREG_CNTHP_TVAL: 51410844Sandreas.sandberg@arm.com case MISCREG_CNTHP_TVAL_EL2: 51512733Sandreas.sandberg@arm.com return core.hyp.timerValue(); 51610844Sandreas.sandberg@arm.com 51710844Sandreas.sandberg@arm.com default: 51810844Sandreas.sandberg@arm.com warn("Reading from unknown register: %s\n", miscRegName[reg]); 51910844Sandreas.sandberg@arm.com return 0; 52010844Sandreas.sandberg@arm.com } 52110844Sandreas.sandberg@arm.com} 52210844Sandreas.sandberg@arm.com 52310844Sandreas.sandberg@arm.com 52410847Sandreas.sandberg@arm.com 52510847Sandreas.sandberg@arm.comGenericTimerMem::GenericTimerMem(GenericTimerMemParams *p) 52610847Sandreas.sandberg@arm.com : PioDevice(p), 52710847Sandreas.sandberg@arm.com ctrlRange(RangeSize(p->base, TheISA::PageBytes)), 52810847Sandreas.sandberg@arm.com timerRange(RangeSize(p->base + TheISA::PageBytes, TheISA::PageBytes)), 52910847Sandreas.sandberg@arm.com addrRanges{ctrlRange, timerRange}, 53010847Sandreas.sandberg@arm.com systemCounter(), 53110847Sandreas.sandberg@arm.com physTimer(csprintf("%s.phys_timer0", name()), 53210847Sandreas.sandberg@arm.com *this, systemCounter, 53310847Sandreas.sandberg@arm.com ArchTimer::Interrupt(*p->gic, p->int_phys)), 53410847Sandreas.sandberg@arm.com virtTimer(csprintf("%s.virt_timer0", name()), 53510847Sandreas.sandberg@arm.com *this, systemCounter, 53610847Sandreas.sandberg@arm.com ArchTimer::Interrupt(*p->gic, p->int_virt)) 53710847Sandreas.sandberg@arm.com{ 53810847Sandreas.sandberg@arm.com} 53910847Sandreas.sandberg@arm.com 54010847Sandreas.sandberg@arm.comvoid 54110905Sandreas.sandberg@arm.comGenericTimerMem::serialize(CheckpointOut &cp) const 54210847Sandreas.sandberg@arm.com{ 54310905Sandreas.sandberg@arm.com paramOut(cp, "timer_count", 1); 54410847Sandreas.sandberg@arm.com 54510905Sandreas.sandberg@arm.com systemCounter.serializeSection(cp, "sys_counter"); 54610847Sandreas.sandberg@arm.com 54710905Sandreas.sandberg@arm.com physTimer.serializeSection(cp, "phys_timer0"); 54810905Sandreas.sandberg@arm.com virtTimer.serializeSection(cp, "virt_timer0"); 54910847Sandreas.sandberg@arm.com} 55010847Sandreas.sandberg@arm.com 55110847Sandreas.sandberg@arm.comvoid 55210905Sandreas.sandberg@arm.comGenericTimerMem::unserialize(CheckpointIn &cp) 55310847Sandreas.sandberg@arm.com{ 55410905Sandreas.sandberg@arm.com systemCounter.unserializeSection(cp, "sys_counter"); 55510847Sandreas.sandberg@arm.com 55610847Sandreas.sandberg@arm.com unsigned timer_count; 55710847Sandreas.sandberg@arm.com UNSERIALIZE_SCALAR(timer_count); 55810847Sandreas.sandberg@arm.com // The timer count variable is just here for future versions where 55910847Sandreas.sandberg@arm.com // we support more than one set of timers. 56010847Sandreas.sandberg@arm.com if (timer_count != 1) 56110847Sandreas.sandberg@arm.com panic("Incompatible checkpoint: Only one set of timers supported"); 56210847Sandreas.sandberg@arm.com 56310905Sandreas.sandberg@arm.com physTimer.unserializeSection(cp, "phys_timer0"); 56410905Sandreas.sandberg@arm.com virtTimer.unserializeSection(cp, "virt_timer0"); 56510847Sandreas.sandberg@arm.com} 56610847Sandreas.sandberg@arm.com 56710847Sandreas.sandberg@arm.comTick 56810847Sandreas.sandberg@arm.comGenericTimerMem::read(PacketPtr pkt) 56910847Sandreas.sandberg@arm.com{ 57010847Sandreas.sandberg@arm.com const unsigned size(pkt->getSize()); 57110847Sandreas.sandberg@arm.com const Addr addr(pkt->getAddr()); 57210847Sandreas.sandberg@arm.com uint64_t value; 57310847Sandreas.sandberg@arm.com 57410847Sandreas.sandberg@arm.com pkt->makeResponse(); 57510847Sandreas.sandberg@arm.com if (ctrlRange.contains(addr)) { 57610847Sandreas.sandberg@arm.com value = ctrlRead(addr - ctrlRange.start(), size); 57710847Sandreas.sandberg@arm.com } else if (timerRange.contains(addr)) { 57810847Sandreas.sandberg@arm.com value = timerRead(addr - timerRange.start(), size); 57910847Sandreas.sandberg@arm.com } else { 58010847Sandreas.sandberg@arm.com panic("Invalid address: 0x%x\n", addr); 58110847Sandreas.sandberg@arm.com } 58210847Sandreas.sandberg@arm.com 58310847Sandreas.sandberg@arm.com DPRINTF(Timer, "Read 0x%x <- 0x%x(%i)\n", value, addr, size); 58410847Sandreas.sandberg@arm.com 58510847Sandreas.sandberg@arm.com if (size == 8) { 58610847Sandreas.sandberg@arm.com pkt->set<uint64_t>(value); 58710847Sandreas.sandberg@arm.com } else if (size == 4) { 58810847Sandreas.sandberg@arm.com pkt->set<uint32_t>(value); 58910847Sandreas.sandberg@arm.com } else { 59010847Sandreas.sandberg@arm.com panic("Unexpected access size: %i\n", size); 59110847Sandreas.sandberg@arm.com } 59210847Sandreas.sandberg@arm.com 59310847Sandreas.sandberg@arm.com return 0; 59410847Sandreas.sandberg@arm.com} 59510847Sandreas.sandberg@arm.com 59610847Sandreas.sandberg@arm.comTick 59710847Sandreas.sandberg@arm.comGenericTimerMem::write(PacketPtr pkt) 59810847Sandreas.sandberg@arm.com{ 59910847Sandreas.sandberg@arm.com const unsigned size(pkt->getSize()); 60010847Sandreas.sandberg@arm.com if (size != 8 && size != 4) 60110847Sandreas.sandberg@arm.com panic("Unexpected access size\n"); 60210847Sandreas.sandberg@arm.com 60310847Sandreas.sandberg@arm.com const Addr addr(pkt->getAddr()); 60410847Sandreas.sandberg@arm.com const uint64_t value(size == 8 ? 60510847Sandreas.sandberg@arm.com pkt->get<uint64_t>() : pkt->get<uint32_t>()); 60610847Sandreas.sandberg@arm.com 60710847Sandreas.sandberg@arm.com DPRINTF(Timer, "Write 0x%x -> 0x%x(%i)\n", value, addr, size); 60810847Sandreas.sandberg@arm.com if (ctrlRange.contains(addr)) { 60910847Sandreas.sandberg@arm.com ctrlWrite(addr - ctrlRange.start(), size, value); 61010847Sandreas.sandberg@arm.com } else if (timerRange.contains(addr)) { 61110847Sandreas.sandberg@arm.com timerWrite(addr - timerRange.start(), size, value); 61210847Sandreas.sandberg@arm.com } else { 61310847Sandreas.sandberg@arm.com panic("Invalid address: 0x%x\n", addr); 61410847Sandreas.sandberg@arm.com } 61510847Sandreas.sandberg@arm.com 61610847Sandreas.sandberg@arm.com pkt->makeResponse(); 61710847Sandreas.sandberg@arm.com return 0; 61810847Sandreas.sandberg@arm.com} 61910847Sandreas.sandberg@arm.com 62010847Sandreas.sandberg@arm.comuint64_t 62110847Sandreas.sandberg@arm.comGenericTimerMem::ctrlRead(Addr addr, size_t size) const 62210847Sandreas.sandberg@arm.com{ 62310847Sandreas.sandberg@arm.com if (size == 4) { 62410847Sandreas.sandberg@arm.com switch (addr) { 62510847Sandreas.sandberg@arm.com case CTRL_CNTFRQ: 62610847Sandreas.sandberg@arm.com return systemCounter.freq(); 62710847Sandreas.sandberg@arm.com 62810847Sandreas.sandberg@arm.com case CTRL_CNTTIDR: 62910847Sandreas.sandberg@arm.com return 0x3; // Frame 0 implemented with virtual timers 63010847Sandreas.sandberg@arm.com 63110847Sandreas.sandberg@arm.com case CTRL_CNTNSAR: 63210847Sandreas.sandberg@arm.com case CTRL_CNTACR_BASE: 63310847Sandreas.sandberg@arm.com warn("Reading from unimplemented control register (0x%x)\n", addr); 63410847Sandreas.sandberg@arm.com return 0; 63510847Sandreas.sandberg@arm.com 63610847Sandreas.sandberg@arm.com case CTRL_CNTVOFF_LO_BASE: 63710847Sandreas.sandberg@arm.com return virtTimer.offset(); 63810847Sandreas.sandberg@arm.com 63910847Sandreas.sandberg@arm.com case CTRL_CNTVOFF_HI_BASE: 64010847Sandreas.sandberg@arm.com return virtTimer.offset() >> 32; 64110847Sandreas.sandberg@arm.com 64210847Sandreas.sandberg@arm.com default: 64310847Sandreas.sandberg@arm.com warn("Unexpected address (0x%x:%i), assuming RAZ\n", addr, size); 64410847Sandreas.sandberg@arm.com return 0; 64510847Sandreas.sandberg@arm.com } 64610847Sandreas.sandberg@arm.com } else if (size == 8) { 64710847Sandreas.sandberg@arm.com switch (addr) { 64810847Sandreas.sandberg@arm.com case CTRL_CNTVOFF_LO_BASE: 64910847Sandreas.sandberg@arm.com return virtTimer.offset(); 65010847Sandreas.sandberg@arm.com 65110847Sandreas.sandberg@arm.com default: 65210847Sandreas.sandberg@arm.com warn("Unexpected address (0x%x:%i), assuming RAZ\n", addr, size); 65310847Sandreas.sandberg@arm.com return 0; 65410847Sandreas.sandberg@arm.com } 65510847Sandreas.sandberg@arm.com } else { 65610847Sandreas.sandberg@arm.com panic("Invalid access size: %i\n", size); 65710847Sandreas.sandberg@arm.com } 65810847Sandreas.sandberg@arm.com} 65910847Sandreas.sandberg@arm.com 66010847Sandreas.sandberg@arm.comvoid 66110847Sandreas.sandberg@arm.comGenericTimerMem::ctrlWrite(Addr addr, size_t size, uint64_t value) 66210847Sandreas.sandberg@arm.com{ 66310847Sandreas.sandberg@arm.com if (size == 4) { 66410847Sandreas.sandberg@arm.com switch (addr) { 66510847Sandreas.sandberg@arm.com case CTRL_CNTFRQ: 66610847Sandreas.sandberg@arm.com case CTRL_CNTNSAR: 66710847Sandreas.sandberg@arm.com case CTRL_CNTTIDR: 66810847Sandreas.sandberg@arm.com case CTRL_CNTACR_BASE: 66910847Sandreas.sandberg@arm.com warn("Write to unimplemented control register (0x%x)\n", addr); 67010847Sandreas.sandberg@arm.com return; 67110847Sandreas.sandberg@arm.com 67210847Sandreas.sandberg@arm.com case CTRL_CNTVOFF_LO_BASE: 67310847Sandreas.sandberg@arm.com virtTimer.setOffset( 67410847Sandreas.sandberg@arm.com insertBits(virtTimer.offset(), 31, 0, value)); 67510847Sandreas.sandberg@arm.com return; 67610847Sandreas.sandberg@arm.com 67710847Sandreas.sandberg@arm.com case CTRL_CNTVOFF_HI_BASE: 67810847Sandreas.sandberg@arm.com virtTimer.setOffset( 67910847Sandreas.sandberg@arm.com insertBits(virtTimer.offset(), 63, 32, value)); 68010847Sandreas.sandberg@arm.com return; 68110847Sandreas.sandberg@arm.com 68210847Sandreas.sandberg@arm.com default: 68310847Sandreas.sandberg@arm.com warn("Ignoring write to unexpected address (0x%x:%i)\n", 68410847Sandreas.sandberg@arm.com addr, size); 68510847Sandreas.sandberg@arm.com return; 68610847Sandreas.sandberg@arm.com } 68710847Sandreas.sandberg@arm.com } else if (size == 8) { 68810847Sandreas.sandberg@arm.com switch (addr) { 68910847Sandreas.sandberg@arm.com case CTRL_CNTVOFF_LO_BASE: 69010847Sandreas.sandberg@arm.com virtTimer.setOffset(value); 69110847Sandreas.sandberg@arm.com return; 69210847Sandreas.sandberg@arm.com 69310847Sandreas.sandberg@arm.com default: 69410847Sandreas.sandberg@arm.com warn("Ignoring write to unexpected address (0x%x:%i)\n", 69510847Sandreas.sandberg@arm.com addr, size); 69610847Sandreas.sandberg@arm.com return; 69710847Sandreas.sandberg@arm.com } 69810847Sandreas.sandberg@arm.com } else { 69910847Sandreas.sandberg@arm.com panic("Invalid access size: %i\n", size); 70010847Sandreas.sandberg@arm.com } 70110847Sandreas.sandberg@arm.com} 70210847Sandreas.sandberg@arm.com 70310847Sandreas.sandberg@arm.comuint64_t 70410847Sandreas.sandberg@arm.comGenericTimerMem::timerRead(Addr addr, size_t size) const 70510847Sandreas.sandberg@arm.com{ 70610847Sandreas.sandberg@arm.com if (size == 4) { 70710847Sandreas.sandberg@arm.com switch (addr) { 70810847Sandreas.sandberg@arm.com case TIMER_CNTPCT_LO: 70910847Sandreas.sandberg@arm.com return physTimer.value(); 71010847Sandreas.sandberg@arm.com 71110847Sandreas.sandberg@arm.com case TIMER_CNTPCT_HI: 71210847Sandreas.sandberg@arm.com return physTimer.value() >> 32; 71310847Sandreas.sandberg@arm.com 71410847Sandreas.sandberg@arm.com case TIMER_CNTVCT_LO: 71510847Sandreas.sandberg@arm.com return virtTimer.value(); 71610847Sandreas.sandberg@arm.com 71710847Sandreas.sandberg@arm.com case TIMER_CNTVCT_HI: 71810847Sandreas.sandberg@arm.com return virtTimer.value() >> 32; 71910847Sandreas.sandberg@arm.com 72010847Sandreas.sandberg@arm.com case TIMER_CNTFRQ: 72110847Sandreas.sandberg@arm.com return systemCounter.freq(); 72210847Sandreas.sandberg@arm.com 72310847Sandreas.sandberg@arm.com case TIMER_CNTEL0ACR: 72410847Sandreas.sandberg@arm.com warn("Read from unimplemented timer register (0x%x)\n", addr); 72510847Sandreas.sandberg@arm.com return 0; 72610847Sandreas.sandberg@arm.com 72710847Sandreas.sandberg@arm.com case CTRL_CNTVOFF_LO_BASE: 72810847Sandreas.sandberg@arm.com return virtTimer.offset(); 72910847Sandreas.sandberg@arm.com 73010847Sandreas.sandberg@arm.com case CTRL_CNTVOFF_HI_BASE: 73110847Sandreas.sandberg@arm.com return virtTimer.offset() >> 32; 73210847Sandreas.sandberg@arm.com 73310847Sandreas.sandberg@arm.com case TIMER_CNTP_CVAL_LO: 73410847Sandreas.sandberg@arm.com return physTimer.compareValue(); 73510847Sandreas.sandberg@arm.com 73610847Sandreas.sandberg@arm.com case TIMER_CNTP_CVAL_HI: 73710847Sandreas.sandberg@arm.com return physTimer.compareValue() >> 32; 73810847Sandreas.sandberg@arm.com 73910847Sandreas.sandberg@arm.com case TIMER_CNTP_TVAL: 74010847Sandreas.sandberg@arm.com return physTimer.timerValue(); 74110847Sandreas.sandberg@arm.com 74210847Sandreas.sandberg@arm.com case TIMER_CNTP_CTL: 74310847Sandreas.sandberg@arm.com return physTimer.control(); 74410847Sandreas.sandberg@arm.com 74510847Sandreas.sandberg@arm.com case TIMER_CNTV_CVAL_LO: 74610847Sandreas.sandberg@arm.com return virtTimer.compareValue(); 74710847Sandreas.sandberg@arm.com 74810847Sandreas.sandberg@arm.com case TIMER_CNTV_CVAL_HI: 74910847Sandreas.sandberg@arm.com return virtTimer.compareValue() >> 32; 75010847Sandreas.sandberg@arm.com 75110847Sandreas.sandberg@arm.com case TIMER_CNTV_TVAL: 75210847Sandreas.sandberg@arm.com return virtTimer.timerValue(); 75310847Sandreas.sandberg@arm.com 75410847Sandreas.sandberg@arm.com case TIMER_CNTV_CTL: 75510847Sandreas.sandberg@arm.com return virtTimer.control(); 75610847Sandreas.sandberg@arm.com 75710847Sandreas.sandberg@arm.com default: 75810847Sandreas.sandberg@arm.com warn("Unexpected address (0x%x:%i), assuming RAZ\n", addr, size); 75910847Sandreas.sandberg@arm.com return 0; 76010847Sandreas.sandberg@arm.com } 76110847Sandreas.sandberg@arm.com } else if (size == 8) { 76210847Sandreas.sandberg@arm.com switch (addr) { 76310847Sandreas.sandberg@arm.com case TIMER_CNTPCT_LO: 76410847Sandreas.sandberg@arm.com return physTimer.value(); 76510847Sandreas.sandberg@arm.com 76610847Sandreas.sandberg@arm.com case TIMER_CNTVCT_LO: 76710847Sandreas.sandberg@arm.com return virtTimer.value(); 76810847Sandreas.sandberg@arm.com 76910847Sandreas.sandberg@arm.com case CTRL_CNTVOFF_LO_BASE: 77010847Sandreas.sandberg@arm.com return virtTimer.offset(); 77110847Sandreas.sandberg@arm.com 77210847Sandreas.sandberg@arm.com case TIMER_CNTP_CVAL_LO: 77310847Sandreas.sandberg@arm.com return physTimer.compareValue(); 77410847Sandreas.sandberg@arm.com 77510847Sandreas.sandberg@arm.com case TIMER_CNTV_CVAL_LO: 77610847Sandreas.sandberg@arm.com return virtTimer.compareValue(); 77710847Sandreas.sandberg@arm.com 77810847Sandreas.sandberg@arm.com default: 77910847Sandreas.sandberg@arm.com warn("Unexpected address (0x%x:%i), assuming RAZ\n", addr, size); 78010847Sandreas.sandberg@arm.com return 0; 78110847Sandreas.sandberg@arm.com } 78210847Sandreas.sandberg@arm.com } else { 78310847Sandreas.sandberg@arm.com panic("Invalid access size: %i\n", size); 78410847Sandreas.sandberg@arm.com } 78510847Sandreas.sandberg@arm.com} 78610847Sandreas.sandberg@arm.com 78710847Sandreas.sandberg@arm.comvoid 78810847Sandreas.sandberg@arm.comGenericTimerMem::timerWrite(Addr addr, size_t size, uint64_t value) 78910847Sandreas.sandberg@arm.com{ 79010847Sandreas.sandberg@arm.com if (size == 4) { 79110847Sandreas.sandberg@arm.com switch (addr) { 79210847Sandreas.sandberg@arm.com case TIMER_CNTEL0ACR: 79310847Sandreas.sandberg@arm.com warn("Unimplemented timer register (0x%x)\n", addr); 79410847Sandreas.sandberg@arm.com return; 79510847Sandreas.sandberg@arm.com 79610847Sandreas.sandberg@arm.com case TIMER_CNTP_CVAL_LO: 79710847Sandreas.sandberg@arm.com physTimer.setCompareValue( 79810847Sandreas.sandberg@arm.com insertBits(physTimer.compareValue(), 31, 0, value)); 79910847Sandreas.sandberg@arm.com return; 80010847Sandreas.sandberg@arm.com 80110847Sandreas.sandberg@arm.com case TIMER_CNTP_CVAL_HI: 80210847Sandreas.sandberg@arm.com physTimer.setCompareValue( 80310847Sandreas.sandberg@arm.com insertBits(physTimer.compareValue(), 63, 32, value)); 80410847Sandreas.sandberg@arm.com return; 80510847Sandreas.sandberg@arm.com 80610847Sandreas.sandberg@arm.com case TIMER_CNTP_TVAL: 80710847Sandreas.sandberg@arm.com physTimer.setTimerValue(value); 80810847Sandreas.sandberg@arm.com return; 80910847Sandreas.sandberg@arm.com 81010847Sandreas.sandberg@arm.com case TIMER_CNTP_CTL: 81110847Sandreas.sandberg@arm.com physTimer.setControl(value); 81210847Sandreas.sandberg@arm.com return; 81310847Sandreas.sandberg@arm.com 81410847Sandreas.sandberg@arm.com case TIMER_CNTV_CVAL_LO: 81510847Sandreas.sandberg@arm.com virtTimer.setCompareValue( 81610847Sandreas.sandberg@arm.com insertBits(virtTimer.compareValue(), 31, 0, value)); 81710847Sandreas.sandberg@arm.com return; 81810847Sandreas.sandberg@arm.com 81910847Sandreas.sandberg@arm.com case TIMER_CNTV_CVAL_HI: 82010847Sandreas.sandberg@arm.com virtTimer.setCompareValue( 82110847Sandreas.sandberg@arm.com insertBits(virtTimer.compareValue(), 63, 32, value)); 82210847Sandreas.sandberg@arm.com return; 82310847Sandreas.sandberg@arm.com 82410847Sandreas.sandberg@arm.com case TIMER_CNTV_TVAL: 82510847Sandreas.sandberg@arm.com virtTimer.setTimerValue(value); 82610847Sandreas.sandberg@arm.com return; 82710847Sandreas.sandberg@arm.com 82810847Sandreas.sandberg@arm.com case TIMER_CNTV_CTL: 82910847Sandreas.sandberg@arm.com virtTimer.setControl(value); 83010847Sandreas.sandberg@arm.com return; 83110847Sandreas.sandberg@arm.com 83210847Sandreas.sandberg@arm.com default: 83310847Sandreas.sandberg@arm.com warn("Unexpected address (0x%x:%i), ignoring write\n", addr, size); 83410847Sandreas.sandberg@arm.com return; 83510847Sandreas.sandberg@arm.com } 83610847Sandreas.sandberg@arm.com } else if (size == 8) { 83710847Sandreas.sandberg@arm.com switch (addr) { 83810847Sandreas.sandberg@arm.com case TIMER_CNTP_CVAL_LO: 83910847Sandreas.sandberg@arm.com return physTimer.setCompareValue(value); 84010847Sandreas.sandberg@arm.com 84110847Sandreas.sandberg@arm.com case TIMER_CNTV_CVAL_LO: 84210847Sandreas.sandberg@arm.com return virtTimer.setCompareValue(value); 84310847Sandreas.sandberg@arm.com 84410847Sandreas.sandberg@arm.com default: 84510847Sandreas.sandberg@arm.com warn("Unexpected address (0x%x:%i), ignoring write\n", addr, size); 84610847Sandreas.sandberg@arm.com return; 84710847Sandreas.sandberg@arm.com } 84810847Sandreas.sandberg@arm.com } else { 84910847Sandreas.sandberg@arm.com panic("Invalid access size: %i\n", size); 85010847Sandreas.sandberg@arm.com } 85110847Sandreas.sandberg@arm.com} 85210847Sandreas.sandberg@arm.com 85310037SARM gem5 DevelopersGenericTimer * 85410037SARM gem5 DevelopersGenericTimerParams::create() 85510037SARM gem5 Developers{ 85610037SARM gem5 Developers return new GenericTimer(this); 85710037SARM gem5 Developers} 85810847Sandreas.sandberg@arm.com 85910847Sandreas.sandberg@arm.comGenericTimerMem * 86010847Sandreas.sandberg@arm.comGenericTimerMemParams::create() 86110847Sandreas.sandberg@arm.com{ 86210847Sandreas.sandberg@arm.com return new GenericTimerMem(this); 86310847Sandreas.sandberg@arm.com} 864