generic_timer.cc revision 13557
110037SARM gem5 Developers/* 212971Sandreas.sandberg@arm.com * Copyright (c) 2013, 2015, 2017-2018 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, 9712975Sgiacomo.travaglini@arm.com ArmInterruptPin *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"); 11712975Sgiacomo.travaglini@arm.com _interrupt->raise(); 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.comGenericTimer::GenericTimer(GenericTimerParams *p) 22312467SCurtis.Dunham@arm.com : ClockedObject(p), 22412975Sgiacomo.travaglini@arm.com system(*p->system) 22510844Sandreas.sandberg@arm.com{ 22611668Sandreas.sandberg@arm.com fatal_if(!p->system, "No system specified, can't instantiate timer.\n"); 22712102SCurtis.Dunham@arm.com system.setGenericTimer(this); 22810037SARM gem5 Developers} 22910037SARM gem5 Developers 23012975Sgiacomo.travaglini@arm.comconst GenericTimerParams * 23112975Sgiacomo.travaglini@arm.comGenericTimer::params() const 23212975Sgiacomo.travaglini@arm.com{ 23312975Sgiacomo.travaglini@arm.com return dynamic_cast<const GenericTimerParams *>(_params); 23412975Sgiacomo.travaglini@arm.com} 23512975Sgiacomo.travaglini@arm.com 23610037SARM gem5 Developersvoid 23710905Sandreas.sandberg@arm.comGenericTimer::serialize(CheckpointOut &cp) const 23810037SARM gem5 Developers{ 23910905Sandreas.sandberg@arm.com paramOut(cp, "cpu_count", timers.size()); 24010844Sandreas.sandberg@arm.com 24110905Sandreas.sandberg@arm.com systemCounter.serializeSection(cp, "sys_counter"); 24210844Sandreas.sandberg@arm.com 24310844Sandreas.sandberg@arm.com for (int i = 0; i < timers.size(); ++i) { 24410905Sandreas.sandberg@arm.com const CoreTimers &core(*timers[i]); 24510844Sandreas.sandberg@arm.com 24610905Sandreas.sandberg@arm.com // This should really be phys_timerN, but we are stuck with 24710905Sandreas.sandberg@arm.com // arch_timer for backwards compatibility. 24812733Sandreas.sandberg@arm.com core.physNS.serializeSection(cp, csprintf("arch_timer%d", i)); 24912733Sandreas.sandberg@arm.com core.physS.serializeSection(cp, csprintf("phys_s_timer%d", i)); 25010905Sandreas.sandberg@arm.com core.virt.serializeSection(cp, csprintf("virt_timer%d", i)); 25112733Sandreas.sandberg@arm.com core.hyp.serializeSection(cp, csprintf("hyp_timer%d", i)); 25210037SARM gem5 Developers } 25310037SARM gem5 Developers} 25410037SARM gem5 Developers 25510037SARM gem5 Developersvoid 25610905Sandreas.sandberg@arm.comGenericTimer::unserialize(CheckpointIn &cp) 25710037SARM gem5 Developers{ 25810905Sandreas.sandberg@arm.com systemCounter.unserializeSection(cp, "sys_counter"); 25910844Sandreas.sandberg@arm.com 26010844Sandreas.sandberg@arm.com // Try to unserialize the CPU count. Old versions of the timer 26110844Sandreas.sandberg@arm.com // model assumed a 8 CPUs, so we fall back to that if the field 26210844Sandreas.sandberg@arm.com // isn't present. 26310844Sandreas.sandberg@arm.com static const unsigned OLD_CPU_MAX = 8; 26410844Sandreas.sandberg@arm.com unsigned cpu_count; 26510844Sandreas.sandberg@arm.com if (!UNSERIALIZE_OPT_SCALAR(cpu_count)) { 26610844Sandreas.sandberg@arm.com warn("Checkpoint does not contain CPU count, assuming %i CPUs\n", 26710844Sandreas.sandberg@arm.com OLD_CPU_MAX); 26810844Sandreas.sandberg@arm.com cpu_count = OLD_CPU_MAX; 26910844Sandreas.sandberg@arm.com } 27010844Sandreas.sandberg@arm.com 27110844Sandreas.sandberg@arm.com for (int i = 0; i < cpu_count; ++i) { 27210844Sandreas.sandberg@arm.com CoreTimers &core(getTimers(i)); 27310844Sandreas.sandberg@arm.com // This should really be phys_timerN, but we are stuck with 27410844Sandreas.sandberg@arm.com // arch_timer for backwards compatibility. 27512733Sandreas.sandberg@arm.com core.physNS.unserializeSection(cp, csprintf("arch_timer%d", i)); 27612733Sandreas.sandberg@arm.com core.physS.unserializeSection(cp, csprintf("phys_s_timer%d", i)); 27710905Sandreas.sandberg@arm.com core.virt.unserializeSection(cp, csprintf("virt_timer%d", i)); 27812733Sandreas.sandberg@arm.com core.hyp.unserializeSection(cp, csprintf("hyp_timer%d", i)); 27910037SARM gem5 Developers } 28010037SARM gem5 Developers} 28110037SARM gem5 Developers 28210844Sandreas.sandberg@arm.com 28310844Sandreas.sandberg@arm.comGenericTimer::CoreTimers & 28410844Sandreas.sandberg@arm.comGenericTimer::getTimers(int cpu_id) 28510844Sandreas.sandberg@arm.com{ 28610844Sandreas.sandberg@arm.com if (cpu_id >= timers.size()) 28710844Sandreas.sandberg@arm.com createTimers(cpu_id + 1); 28810844Sandreas.sandberg@arm.com 28910844Sandreas.sandberg@arm.com return *timers[cpu_id]; 29010844Sandreas.sandberg@arm.com} 29110844Sandreas.sandberg@arm.com 29210844Sandreas.sandberg@arm.comvoid 29310844Sandreas.sandberg@arm.comGenericTimer::createTimers(unsigned cpus) 29410844Sandreas.sandberg@arm.com{ 29510844Sandreas.sandberg@arm.com assert(timers.size() < cpus); 29612975Sgiacomo.travaglini@arm.com auto p = static_cast<const GenericTimerParams *>(_params); 29710844Sandreas.sandberg@arm.com 29810844Sandreas.sandberg@arm.com const unsigned old_cpu_count(timers.size()); 29910844Sandreas.sandberg@arm.com timers.resize(cpus); 30010844Sandreas.sandberg@arm.com for (unsigned i = old_cpu_count; i < cpus; ++i) { 30112975Sgiacomo.travaglini@arm.com 30212975Sgiacomo.travaglini@arm.com ThreadContext *tc = system.getThreadContext(i); 30312975Sgiacomo.travaglini@arm.com 30410844Sandreas.sandberg@arm.com timers[i].reset( 30512733Sandreas.sandberg@arm.com new CoreTimers(*this, system, i, 30612975Sgiacomo.travaglini@arm.com p->int_phys_s->get(tc), 30712975Sgiacomo.travaglini@arm.com p->int_phys_ns->get(tc), 30812975Sgiacomo.travaglini@arm.com p->int_virt->get(tc), 30912975Sgiacomo.travaglini@arm.com p->int_hyp->get(tc))); 31010844Sandreas.sandberg@arm.com } 31110844Sandreas.sandberg@arm.com} 31210844Sandreas.sandberg@arm.com 31310844Sandreas.sandberg@arm.com 31410844Sandreas.sandberg@arm.comvoid 31513557Sgabeblack@google.comGenericTimer::setMiscReg(int reg, unsigned cpu, RegVal val) 31610844Sandreas.sandberg@arm.com{ 31710844Sandreas.sandberg@arm.com CoreTimers &core(getTimers(cpu)); 31810844Sandreas.sandberg@arm.com 31910844Sandreas.sandberg@arm.com switch (reg) { 32010844Sandreas.sandberg@arm.com case MISCREG_CNTFRQ: 32110844Sandreas.sandberg@arm.com case MISCREG_CNTFRQ_EL0: 32210844Sandreas.sandberg@arm.com systemCounter.setFreq(val); 32310844Sandreas.sandberg@arm.com return; 32410844Sandreas.sandberg@arm.com 32510844Sandreas.sandberg@arm.com case MISCREG_CNTKCTL: 32610844Sandreas.sandberg@arm.com case MISCREG_CNTKCTL_EL1: 32710844Sandreas.sandberg@arm.com systemCounter.setKernelControl(val); 32810844Sandreas.sandberg@arm.com return; 32910844Sandreas.sandberg@arm.com 33012733Sandreas.sandberg@arm.com case MISCREG_CNTHCTL: 33112733Sandreas.sandberg@arm.com case MISCREG_CNTHCTL_EL2: 33212733Sandreas.sandberg@arm.com systemCounter.setHypControl(val); 33312733Sandreas.sandberg@arm.com return; 33412733Sandreas.sandberg@arm.com 33512733Sandreas.sandberg@arm.com // Physical timer (NS) 33610844Sandreas.sandberg@arm.com case MISCREG_CNTP_CVAL_NS: 33710844Sandreas.sandberg@arm.com case MISCREG_CNTP_CVAL_EL0: 33812733Sandreas.sandberg@arm.com core.physNS.setCompareValue(val); 33910844Sandreas.sandberg@arm.com return; 34010844Sandreas.sandberg@arm.com 34110844Sandreas.sandberg@arm.com case MISCREG_CNTP_TVAL_NS: 34210844Sandreas.sandberg@arm.com case MISCREG_CNTP_TVAL_EL0: 34312733Sandreas.sandberg@arm.com core.physNS.setTimerValue(val); 34410844Sandreas.sandberg@arm.com return; 34510844Sandreas.sandberg@arm.com 34610844Sandreas.sandberg@arm.com case MISCREG_CNTP_CTL_NS: 34710844Sandreas.sandberg@arm.com case MISCREG_CNTP_CTL_EL0: 34812733Sandreas.sandberg@arm.com core.physNS.setControl(val); 34910844Sandreas.sandberg@arm.com return; 35010844Sandreas.sandberg@arm.com 35110844Sandreas.sandberg@arm.com // Count registers 35210844Sandreas.sandberg@arm.com case MISCREG_CNTPCT: 35310844Sandreas.sandberg@arm.com case MISCREG_CNTPCT_EL0: 35410844Sandreas.sandberg@arm.com case MISCREG_CNTVCT: 35510844Sandreas.sandberg@arm.com case MISCREG_CNTVCT_EL0: 35610844Sandreas.sandberg@arm.com warn("Ignoring write to read only count register: %s\n", 35710844Sandreas.sandberg@arm.com miscRegName[reg]); 35810844Sandreas.sandberg@arm.com return; 35910844Sandreas.sandberg@arm.com 36010844Sandreas.sandberg@arm.com // Virtual timer 36110844Sandreas.sandberg@arm.com case MISCREG_CNTVOFF: 36210844Sandreas.sandberg@arm.com case MISCREG_CNTVOFF_EL2: 36310845Sandreas.sandberg@arm.com core.virt.setOffset(val); 36410845Sandreas.sandberg@arm.com return; 36510845Sandreas.sandberg@arm.com 36610844Sandreas.sandberg@arm.com case MISCREG_CNTV_CVAL: 36710844Sandreas.sandberg@arm.com case MISCREG_CNTV_CVAL_EL0: 36810845Sandreas.sandberg@arm.com core.virt.setCompareValue(val); 36910845Sandreas.sandberg@arm.com return; 37010845Sandreas.sandberg@arm.com 37110844Sandreas.sandberg@arm.com case MISCREG_CNTV_TVAL: 37210844Sandreas.sandberg@arm.com case MISCREG_CNTV_TVAL_EL0: 37310845Sandreas.sandberg@arm.com core.virt.setTimerValue(val); 37410845Sandreas.sandberg@arm.com return; 37510845Sandreas.sandberg@arm.com 37610844Sandreas.sandberg@arm.com case MISCREG_CNTV_CTL: 37710844Sandreas.sandberg@arm.com case MISCREG_CNTV_CTL_EL0: 37810845Sandreas.sandberg@arm.com core.virt.setControl(val); 37910845Sandreas.sandberg@arm.com return; 38010844Sandreas.sandberg@arm.com 38112733Sandreas.sandberg@arm.com // Physical timer (S) 38210844Sandreas.sandberg@arm.com case MISCREG_CNTP_CTL_S: 38312733Sandreas.sandberg@arm.com case MISCREG_CNTPS_CTL_EL1: 38412733Sandreas.sandberg@arm.com core.physS.setControl(val); 38512733Sandreas.sandberg@arm.com return; 38612733Sandreas.sandberg@arm.com 38712733Sandreas.sandberg@arm.com case MISCREG_CNTP_CVAL_S: 38810844Sandreas.sandberg@arm.com case MISCREG_CNTPS_CVAL_EL1: 38912733Sandreas.sandberg@arm.com core.physS.setCompareValue(val); 39012733Sandreas.sandberg@arm.com return; 39112733Sandreas.sandberg@arm.com 39212733Sandreas.sandberg@arm.com case MISCREG_CNTP_TVAL_S: 39310844Sandreas.sandberg@arm.com case MISCREG_CNTPS_TVAL_EL1: 39412733Sandreas.sandberg@arm.com core.physS.setTimerValue(val); 39512733Sandreas.sandberg@arm.com return; 39610844Sandreas.sandberg@arm.com 39712733Sandreas.sandberg@arm.com // Hyp phys. timer, non-secure 39812733Sandreas.sandberg@arm.com case MISCREG_CNTHP_CTL: 39912733Sandreas.sandberg@arm.com case MISCREG_CNTHP_CTL_EL2: 40012733Sandreas.sandberg@arm.com core.hyp.setControl(val); 40112733Sandreas.sandberg@arm.com return; 40212733Sandreas.sandberg@arm.com 40310844Sandreas.sandberg@arm.com case MISCREG_CNTHP_CVAL: 40410844Sandreas.sandberg@arm.com case MISCREG_CNTHP_CVAL_EL2: 40512733Sandreas.sandberg@arm.com core.hyp.setCompareValue(val); 40612733Sandreas.sandberg@arm.com return; 40712733Sandreas.sandberg@arm.com 40810844Sandreas.sandberg@arm.com case MISCREG_CNTHP_TVAL: 40910844Sandreas.sandberg@arm.com case MISCREG_CNTHP_TVAL_EL2: 41012733Sandreas.sandberg@arm.com core.hyp.setTimerValue(val); 41110844Sandreas.sandberg@arm.com return; 41210844Sandreas.sandberg@arm.com 41310844Sandreas.sandberg@arm.com default: 41410844Sandreas.sandberg@arm.com warn("Writing to unknown register: %s\n", miscRegName[reg]); 41510844Sandreas.sandberg@arm.com return; 41610844Sandreas.sandberg@arm.com } 41710844Sandreas.sandberg@arm.com} 41810844Sandreas.sandberg@arm.com 41910844Sandreas.sandberg@arm.com 42013557Sgabeblack@google.comRegVal 42110844Sandreas.sandberg@arm.comGenericTimer::readMiscReg(int reg, unsigned cpu) 42210844Sandreas.sandberg@arm.com{ 42310844Sandreas.sandberg@arm.com CoreTimers &core(getTimers(cpu)); 42410844Sandreas.sandberg@arm.com 42510844Sandreas.sandberg@arm.com switch (reg) { 42610844Sandreas.sandberg@arm.com case MISCREG_CNTFRQ: 42710844Sandreas.sandberg@arm.com case MISCREG_CNTFRQ_EL0: 42810844Sandreas.sandberg@arm.com return systemCounter.freq(); 42910844Sandreas.sandberg@arm.com 43010844Sandreas.sandberg@arm.com case MISCREG_CNTKCTL: 43110844Sandreas.sandberg@arm.com case MISCREG_CNTKCTL_EL1: 43210844Sandreas.sandberg@arm.com return systemCounter.getKernelControl(); 43310844Sandreas.sandberg@arm.com 43412733Sandreas.sandberg@arm.com case MISCREG_CNTHCTL: 43512733Sandreas.sandberg@arm.com case MISCREG_CNTHCTL_EL2: 43612733Sandreas.sandberg@arm.com return systemCounter.getHypControl(); 43712733Sandreas.sandberg@arm.com 43810844Sandreas.sandberg@arm.com // Physical timer 43912733Sandreas.sandberg@arm.com case MISCREG_CNTP_CVAL_NS: 44010844Sandreas.sandberg@arm.com case MISCREG_CNTP_CVAL_EL0: 44112733Sandreas.sandberg@arm.com return core.physNS.compareValue(); 44210844Sandreas.sandberg@arm.com 44312733Sandreas.sandberg@arm.com case MISCREG_CNTP_TVAL_NS: 44410844Sandreas.sandberg@arm.com case MISCREG_CNTP_TVAL_EL0: 44512733Sandreas.sandberg@arm.com return core.physNS.timerValue(); 44610844Sandreas.sandberg@arm.com 44710844Sandreas.sandberg@arm.com case MISCREG_CNTP_CTL_EL0: 44810844Sandreas.sandberg@arm.com case MISCREG_CNTP_CTL_NS: 44912733Sandreas.sandberg@arm.com return core.physNS.control(); 45010844Sandreas.sandberg@arm.com 45110844Sandreas.sandberg@arm.com case MISCREG_CNTPCT: 45210844Sandreas.sandberg@arm.com case MISCREG_CNTPCT_EL0: 45312733Sandreas.sandberg@arm.com return core.physNS.value(); 45410844Sandreas.sandberg@arm.com 45510844Sandreas.sandberg@arm.com 45610844Sandreas.sandberg@arm.com // Virtual timer 45710844Sandreas.sandberg@arm.com case MISCREG_CNTVCT: 45810844Sandreas.sandberg@arm.com case MISCREG_CNTVCT_EL0: 45910845Sandreas.sandberg@arm.com return core.virt.value(); 46010844Sandreas.sandberg@arm.com 46110844Sandreas.sandberg@arm.com case MISCREG_CNTVOFF: 46210844Sandreas.sandberg@arm.com case MISCREG_CNTVOFF_EL2: 46310845Sandreas.sandberg@arm.com return core.virt.offset(); 46410845Sandreas.sandberg@arm.com 46510844Sandreas.sandberg@arm.com case MISCREG_CNTV_CVAL: 46610844Sandreas.sandberg@arm.com case MISCREG_CNTV_CVAL_EL0: 46710845Sandreas.sandberg@arm.com return core.virt.compareValue(); 46810845Sandreas.sandberg@arm.com 46910844Sandreas.sandberg@arm.com case MISCREG_CNTV_TVAL: 47010844Sandreas.sandberg@arm.com case MISCREG_CNTV_TVAL_EL0: 47110845Sandreas.sandberg@arm.com return core.virt.timerValue(); 47210845Sandreas.sandberg@arm.com 47310844Sandreas.sandberg@arm.com case MISCREG_CNTV_CTL: 47410844Sandreas.sandberg@arm.com case MISCREG_CNTV_CTL_EL0: 47510845Sandreas.sandberg@arm.com return core.virt.control(); 47610844Sandreas.sandberg@arm.com 47710844Sandreas.sandberg@arm.com // PL1 phys. timer, secure 47810844Sandreas.sandberg@arm.com case MISCREG_CNTP_CTL_S: 47912733Sandreas.sandberg@arm.com case MISCREG_CNTPS_CTL_EL1: 48012733Sandreas.sandberg@arm.com return core.physS.control(); 48112733Sandreas.sandberg@arm.com 48212733Sandreas.sandberg@arm.com case MISCREG_CNTP_CVAL_S: 48310844Sandreas.sandberg@arm.com case MISCREG_CNTPS_CVAL_EL1: 48412733Sandreas.sandberg@arm.com return core.physS.compareValue(); 48512733Sandreas.sandberg@arm.com 48612733Sandreas.sandberg@arm.com case MISCREG_CNTP_TVAL_S: 48710844Sandreas.sandberg@arm.com case MISCREG_CNTPS_TVAL_EL1: 48812733Sandreas.sandberg@arm.com return core.physS.timerValue(); 48910844Sandreas.sandberg@arm.com 49012733Sandreas.sandberg@arm.com // HYP phys. timer (NS) 49112733Sandreas.sandberg@arm.com case MISCREG_CNTHP_CTL: 49212733Sandreas.sandberg@arm.com case MISCREG_CNTHP_CTL_EL2: 49312733Sandreas.sandberg@arm.com return core.hyp.control(); 49412733Sandreas.sandberg@arm.com 49510844Sandreas.sandberg@arm.com case MISCREG_CNTHP_CVAL: 49610844Sandreas.sandberg@arm.com case MISCREG_CNTHP_CVAL_EL2: 49712733Sandreas.sandberg@arm.com return core.hyp.compareValue(); 49812733Sandreas.sandberg@arm.com 49910844Sandreas.sandberg@arm.com case MISCREG_CNTHP_TVAL: 50010844Sandreas.sandberg@arm.com case MISCREG_CNTHP_TVAL_EL2: 50112733Sandreas.sandberg@arm.com return core.hyp.timerValue(); 50210844Sandreas.sandberg@arm.com 50310844Sandreas.sandberg@arm.com default: 50410844Sandreas.sandberg@arm.com warn("Reading from unknown register: %s\n", miscRegName[reg]); 50510844Sandreas.sandberg@arm.com return 0; 50610844Sandreas.sandberg@arm.com } 50710844Sandreas.sandberg@arm.com} 50810844Sandreas.sandberg@arm.com 50910844Sandreas.sandberg@arm.com 51012971Sandreas.sandberg@arm.comvoid 51113557Sgabeblack@google.comGenericTimerISA::setMiscReg(int reg, RegVal val) 51212971Sandreas.sandberg@arm.com{ 51312971Sandreas.sandberg@arm.com DPRINTF(Timer, "Setting %s := 0x%x\n", miscRegName[reg], val); 51412971Sandreas.sandberg@arm.com parent.setMiscReg(reg, cpu, val); 51512971Sandreas.sandberg@arm.com} 51612971Sandreas.sandberg@arm.com 51713557Sgabeblack@google.comRegVal 51812971Sandreas.sandberg@arm.comGenericTimerISA::readMiscReg(int reg) 51912971Sandreas.sandberg@arm.com{ 52013557Sgabeblack@google.com RegVal value = parent.readMiscReg(reg, cpu); 52112971Sandreas.sandberg@arm.com DPRINTF(Timer, "Reading %s as 0x%x\n", miscRegName[reg], value); 52212971Sandreas.sandberg@arm.com return value; 52312971Sandreas.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, 53312975Sgiacomo.travaglini@arm.com p->int_phys->get()), 53410847Sandreas.sandberg@arm.com virtTimer(csprintf("%s.virt_timer0", name()), 53510847Sandreas.sandberg@arm.com *this, systemCounter, 53612975Sgiacomo.travaglini@arm.com p->int_virt->get()) 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) { 58613230Sgabeblack@google.com pkt->setLE<uint64_t>(value); 58710847Sandreas.sandberg@arm.com } else if (size == 4) { 58813230Sgabeblack@google.com pkt->setLE<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 ? 60513230Sgabeblack@google.com pkt->getLE<uint64_t>() : pkt->getLE<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