generic_timer.cc revision 10847
110037SARM gem5 Developers/* 210844Sandreas.sandberg@arm.com * Copyright (c) 2013, 2015 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 6910844Sandreas.sandberg@arm.comSystemCounter::serialize(std::ostream &os) const 7010037SARM gem5 Developers{ 7110844Sandreas.sandberg@arm.com SERIALIZE_SCALAR(_regCntkctl); 7210037SARM gem5 Developers SERIALIZE_SCALAR(_freq); 7310037SARM gem5 Developers SERIALIZE_SCALAR(_period); 7410037SARM gem5 Developers SERIALIZE_SCALAR(_resetTick); 7510037SARM gem5 Developers} 7610037SARM gem5 Developers 7710037SARM gem5 Developersvoid 7810844Sandreas.sandberg@arm.comSystemCounter::unserialize(Checkpoint *cp, 7910844Sandreas.sandberg@arm.com const std::string §ion) 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; 8510037SARM gem5 Developers UNSERIALIZE_SCALAR(_freq); 8610037SARM gem5 Developers UNSERIALIZE_SCALAR(_period); 8710037SARM gem5 Developers UNSERIALIZE_SCALAR(_resetTick); 8810037SARM gem5 Developers} 8910037SARM gem5 Developers 9010844Sandreas.sandberg@arm.com 9110844Sandreas.sandberg@arm.com 9210844Sandreas.sandberg@arm.comArchTimer::ArchTimer(const std::string &name, 9310844Sandreas.sandberg@arm.com SimObject &parent, 9410844Sandreas.sandberg@arm.com SystemCounter &sysctr, 9510844Sandreas.sandberg@arm.com const Interrupt &interrupt) 9610844Sandreas.sandberg@arm.com : _name(name), _parent(parent), _systemCounter(sysctr), 9710844Sandreas.sandberg@arm.com _interrupt(interrupt), 9810845Sandreas.sandberg@arm.com _control(0), _counterLimit(0), _offset(0), 9910844Sandreas.sandberg@arm.com _counterLimitReachedEvent(this) 10010844Sandreas.sandberg@arm.com{ 10110844Sandreas.sandberg@arm.com} 10210844Sandreas.sandberg@arm.com 10310037SARM gem5 Developersvoid 10410844Sandreas.sandberg@arm.comArchTimer::counterLimitReached() 10510037SARM gem5 Developers{ 10610037SARM gem5 Developers _control.istatus = 1; 10710037SARM gem5 Developers 10810037SARM gem5 Developers if (!_control.enable) 10910037SARM gem5 Developers return; 11010037SARM gem5 Developers 11110844Sandreas.sandberg@arm.com DPRINTF(Timer, "Counter limit reached\n"); 11210037SARM gem5 Developers if (!_control.imask) { 11310844Sandreas.sandberg@arm.com DPRINTF(Timer, "Causing interrupt\n"); 11410844Sandreas.sandberg@arm.com _interrupt.send(); 11510037SARM gem5 Developers } 11610037SARM gem5 Developers} 11710037SARM gem5 Developers 11810037SARM gem5 Developersvoid 11910844Sandreas.sandberg@arm.comArchTimer::updateCounter() 12010037SARM gem5 Developers{ 12110037SARM gem5 Developers if (_counterLimitReachedEvent.scheduled()) 12210844Sandreas.sandberg@arm.com _parent.deschedule(_counterLimitReachedEvent); 12310844Sandreas.sandberg@arm.com if (value() >= _counterLimit) { 12410037SARM gem5 Developers counterLimitReached(); 12510037SARM gem5 Developers } else { 12610844Sandreas.sandberg@arm.com const auto period(_systemCounter.period()); 12710037SARM gem5 Developers _control.istatus = 0; 12810844Sandreas.sandberg@arm.com _parent.schedule(_counterLimitReachedEvent, 12910844Sandreas.sandberg@arm.com curTick() + (_counterLimit - value()) * period); 13010037SARM gem5 Developers } 13110037SARM gem5 Developers} 13210037SARM gem5 Developers 13310037SARM gem5 Developersvoid 13410844Sandreas.sandberg@arm.comArchTimer::setCompareValue(uint64_t val) 13510037SARM gem5 Developers{ 13610844Sandreas.sandberg@arm.com _counterLimit = val; 13710844Sandreas.sandberg@arm.com updateCounter(); 13810037SARM gem5 Developers} 13910037SARM gem5 Developers 14010037SARM gem5 Developersvoid 14110844Sandreas.sandberg@arm.comArchTimer::setTimerValue(uint32_t val) 14210844Sandreas.sandberg@arm.com{ 14310844Sandreas.sandberg@arm.com setCompareValue(value() + sext<32>(val)); 14410844Sandreas.sandberg@arm.com} 14510844Sandreas.sandberg@arm.com 14610844Sandreas.sandberg@arm.comvoid 14710844Sandreas.sandberg@arm.comArchTimer::setControl(uint32_t val) 14810037SARM gem5 Developers{ 14910037SARM gem5 Developers ArchTimerCtrl new_ctl = val; 15010037SARM gem5 Developers if ((new_ctl.enable && !new_ctl.imask) && 15110037SARM gem5 Developers !(_control.enable && !_control.imask)) { 15210037SARM gem5 Developers // Re-evalute the timer condition 15310844Sandreas.sandberg@arm.com if (_counterLimit >= value()) { 15410037SARM gem5 Developers _control.istatus = 1; 15510037SARM gem5 Developers 15610037SARM gem5 Developers DPRINTF(Timer, "Causing interrupt in control\n"); 15710844Sandreas.sandberg@arm.com //_interrupt.send(); 15810037SARM gem5 Developers } 15910037SARM gem5 Developers } 16010037SARM gem5 Developers _control.enable = new_ctl.enable; 16110037SARM gem5 Developers _control.imask = new_ctl.imask; 16210037SARM gem5 Developers} 16310037SARM gem5 Developers 16410845Sandreas.sandberg@arm.comvoid 16510845Sandreas.sandberg@arm.comArchTimer::setOffset(uint64_t val) 16610845Sandreas.sandberg@arm.com{ 16710845Sandreas.sandberg@arm.com _offset = val; 16810845Sandreas.sandberg@arm.com updateCounter(); 16910845Sandreas.sandberg@arm.com} 17010845Sandreas.sandberg@arm.com 17110844Sandreas.sandberg@arm.comuint64_t 17210844Sandreas.sandberg@arm.comArchTimer::value() const 17310844Sandreas.sandberg@arm.com{ 17410845Sandreas.sandberg@arm.com return _systemCounter.value() - _offset; 17510844Sandreas.sandberg@arm.com} 17610844Sandreas.sandberg@arm.com 17710037SARM gem5 Developersvoid 17810844Sandreas.sandberg@arm.comArchTimer::serialize(std::ostream &os) const 17910037SARM gem5 Developers{ 18010844Sandreas.sandberg@arm.com paramOut(os, "control_serial", _control); 18110037SARM gem5 Developers SERIALIZE_SCALAR(_counterLimit); 18210845Sandreas.sandberg@arm.com SERIALIZE_SCALAR(_offset); 18310844Sandreas.sandberg@arm.com 18410844Sandreas.sandberg@arm.com const bool event_scheduled(_counterLimitReachedEvent.scheduled()); 18510037SARM gem5 Developers SERIALIZE_SCALAR(event_scheduled); 18610037SARM gem5 Developers if (event_scheduled) { 18710844Sandreas.sandberg@arm.com const Tick event_time(_counterLimitReachedEvent.when()); 18810037SARM gem5 Developers SERIALIZE_SCALAR(event_time); 18910037SARM gem5 Developers } 19010037SARM gem5 Developers} 19110037SARM gem5 Developers 19210037SARM gem5 Developersvoid 19310844Sandreas.sandberg@arm.comArchTimer::unserialize(Checkpoint *cp, 19410844Sandreas.sandberg@arm.com const std::string §ion) 19510037SARM gem5 Developers{ 19610844Sandreas.sandberg@arm.com paramIn(cp, section, "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; 20210037SARM gem5 Developers bool event_scheduled; 20310037SARM gem5 Developers UNSERIALIZE_SCALAR(event_scheduled); 20410037SARM gem5 Developers if (event_scheduled) { 20510844Sandreas.sandberg@arm.com Tick event_time; 20610037SARM gem5 Developers UNSERIALIZE_SCALAR(event_time); 20710844Sandreas.sandberg@arm.com _parent.schedule(_counterLimitReachedEvent, event_time); 20810037SARM gem5 Developers } 20910037SARM gem5 Developers} 21010037SARM gem5 Developers 21110844Sandreas.sandberg@arm.comvoid 21210844Sandreas.sandberg@arm.comArchTimer::Interrupt::send() 21310037SARM gem5 Developers{ 21410844Sandreas.sandberg@arm.com if (_ppi) { 21510844Sandreas.sandberg@arm.com _gic.sendPPInt(_irq, _cpu); 21610844Sandreas.sandberg@arm.com } else { 21710844Sandreas.sandberg@arm.com _gic.sendInt(_irq); 21810844Sandreas.sandberg@arm.com } 21910844Sandreas.sandberg@arm.com} 22010037SARM gem5 Developers 22110844Sandreas.sandberg@arm.com 22210844Sandreas.sandberg@arm.comvoid 22310844Sandreas.sandberg@arm.comArchTimer::Interrupt::clear() 22410844Sandreas.sandberg@arm.com{ 22510844Sandreas.sandberg@arm.com if (_ppi) { 22610844Sandreas.sandberg@arm.com _gic.clearPPInt(_irq, _cpu); 22710844Sandreas.sandberg@arm.com } else { 22810844Sandreas.sandberg@arm.com _gic.clearInt(_irq); 22910844Sandreas.sandberg@arm.com } 23010844Sandreas.sandberg@arm.com} 23110844Sandreas.sandberg@arm.com 23210844Sandreas.sandberg@arm.com 23310844Sandreas.sandberg@arm.comGenericTimer::GenericTimer(GenericTimerParams *p) 23410844Sandreas.sandberg@arm.com : SimObject(p), 23510844Sandreas.sandberg@arm.com gic(p->gic), 23610845Sandreas.sandberg@arm.com irqPhys(p->int_phys), 23710845Sandreas.sandberg@arm.com irqVirt(p->int_virt) 23810844Sandreas.sandberg@arm.com{ 23910844Sandreas.sandberg@arm.com dynamic_cast<ArmSystem &>(*p->system).setGenericTimer(this); 24010037SARM gem5 Developers} 24110037SARM gem5 Developers 24210037SARM gem5 Developersvoid 24310037SARM gem5 DevelopersGenericTimer::serialize(std::ostream &os) 24410037SARM gem5 Developers{ 24510844Sandreas.sandberg@arm.com paramOut(os, "cpu_count", timers.size()); 24610844Sandreas.sandberg@arm.com 24710037SARM gem5 Developers nameOut(os, csprintf("%s.sys_counter", name())); 24810844Sandreas.sandberg@arm.com systemCounter.serialize(os); 24910844Sandreas.sandberg@arm.com 25010844Sandreas.sandberg@arm.com for (int i = 0; i < timers.size(); ++i) { 25110844Sandreas.sandberg@arm.com CoreTimers &core(getTimers(i)); 25210844Sandreas.sandberg@arm.com 25310844Sandreas.sandberg@arm.com nameOut(os, core.phys.name()); 25410844Sandreas.sandberg@arm.com core.phys.serialize(os); 25510845Sandreas.sandberg@arm.com 25610845Sandreas.sandberg@arm.com nameOut(os, core.virt.name()); 25710845Sandreas.sandberg@arm.com core.virt.serialize(os); 25810037SARM gem5 Developers } 25910037SARM gem5 Developers} 26010037SARM gem5 Developers 26110037SARM gem5 Developersvoid 26210037SARM gem5 DevelopersGenericTimer::unserialize(Checkpoint *cp, const std::string §ion) 26310037SARM gem5 Developers{ 26410844Sandreas.sandberg@arm.com systemCounter.unserialize(cp, csprintf("%s.sys_counter", section)); 26510844Sandreas.sandberg@arm.com 26610844Sandreas.sandberg@arm.com // Try to unserialize the CPU count. Old versions of the timer 26710844Sandreas.sandberg@arm.com // model assumed a 8 CPUs, so we fall back to that if the field 26810844Sandreas.sandberg@arm.com // isn't present. 26910844Sandreas.sandberg@arm.com static const unsigned OLD_CPU_MAX = 8; 27010844Sandreas.sandberg@arm.com unsigned cpu_count; 27110844Sandreas.sandberg@arm.com if (!UNSERIALIZE_OPT_SCALAR(cpu_count)) { 27210844Sandreas.sandberg@arm.com warn("Checkpoint does not contain CPU count, assuming %i CPUs\n", 27310844Sandreas.sandberg@arm.com OLD_CPU_MAX); 27410844Sandreas.sandberg@arm.com cpu_count = OLD_CPU_MAX; 27510844Sandreas.sandberg@arm.com } 27610844Sandreas.sandberg@arm.com 27710844Sandreas.sandberg@arm.com for (int i = 0; i < cpu_count; ++i) { 27810844Sandreas.sandberg@arm.com CoreTimers &core(getTimers(i)); 27910844Sandreas.sandberg@arm.com // This should really be phys_timerN, but we are stuck with 28010844Sandreas.sandberg@arm.com // arch_timer for backwards compatibility. 28110844Sandreas.sandberg@arm.com core.phys.unserialize(cp, csprintf("%s.arch_timer%d", section, i)); 28210845Sandreas.sandberg@arm.com core.virt.unserialize(cp, csprintf("%s.virt_timer%d", section, i)); 28310037SARM gem5 Developers } 28410037SARM gem5 Developers} 28510037SARM gem5 Developers 28610844Sandreas.sandberg@arm.com 28710844Sandreas.sandberg@arm.comGenericTimer::CoreTimers & 28810844Sandreas.sandberg@arm.comGenericTimer::getTimers(int cpu_id) 28910844Sandreas.sandberg@arm.com{ 29010844Sandreas.sandberg@arm.com if (cpu_id >= timers.size()) 29110844Sandreas.sandberg@arm.com createTimers(cpu_id + 1); 29210844Sandreas.sandberg@arm.com 29310844Sandreas.sandberg@arm.com return *timers[cpu_id]; 29410844Sandreas.sandberg@arm.com} 29510844Sandreas.sandberg@arm.com 29610844Sandreas.sandberg@arm.comvoid 29710844Sandreas.sandberg@arm.comGenericTimer::createTimers(unsigned cpus) 29810844Sandreas.sandberg@arm.com{ 29910844Sandreas.sandberg@arm.com assert(timers.size() < cpus); 30010844Sandreas.sandberg@arm.com 30110844Sandreas.sandberg@arm.com const unsigned old_cpu_count(timers.size()); 30210844Sandreas.sandberg@arm.com timers.resize(cpus); 30310844Sandreas.sandberg@arm.com for (unsigned i = old_cpu_count; i < cpus; ++i) { 30410844Sandreas.sandberg@arm.com timers[i].reset( 30510845Sandreas.sandberg@arm.com new CoreTimers(*this, i, irqPhys, irqVirt)); 30610844Sandreas.sandberg@arm.com } 30710844Sandreas.sandberg@arm.com} 30810844Sandreas.sandberg@arm.com 30910844Sandreas.sandberg@arm.com 31010844Sandreas.sandberg@arm.comvoid 31110844Sandreas.sandberg@arm.comGenericTimer::setMiscReg(int reg, unsigned cpu, MiscReg val) 31210844Sandreas.sandberg@arm.com{ 31310844Sandreas.sandberg@arm.com CoreTimers &core(getTimers(cpu)); 31410844Sandreas.sandberg@arm.com 31510844Sandreas.sandberg@arm.com switch (reg) { 31610844Sandreas.sandberg@arm.com case MISCREG_CNTFRQ: 31710844Sandreas.sandberg@arm.com case MISCREG_CNTFRQ_EL0: 31810844Sandreas.sandberg@arm.com systemCounter.setFreq(val); 31910844Sandreas.sandberg@arm.com return; 32010844Sandreas.sandberg@arm.com 32110844Sandreas.sandberg@arm.com case MISCREG_CNTKCTL: 32210844Sandreas.sandberg@arm.com case MISCREG_CNTKCTL_EL1: 32310844Sandreas.sandberg@arm.com systemCounter.setKernelControl(val); 32410844Sandreas.sandberg@arm.com return; 32510844Sandreas.sandberg@arm.com 32610844Sandreas.sandberg@arm.com // Physical timer 32710844Sandreas.sandberg@arm.com case MISCREG_CNTP_CVAL: 32810844Sandreas.sandberg@arm.com case MISCREG_CNTP_CVAL_NS: 32910844Sandreas.sandberg@arm.com case MISCREG_CNTP_CVAL_EL0: 33010844Sandreas.sandberg@arm.com core.phys.setCompareValue(val); 33110844Sandreas.sandberg@arm.com return; 33210844Sandreas.sandberg@arm.com 33310844Sandreas.sandberg@arm.com case MISCREG_CNTP_TVAL: 33410844Sandreas.sandberg@arm.com case MISCREG_CNTP_TVAL_NS: 33510844Sandreas.sandberg@arm.com case MISCREG_CNTP_TVAL_EL0: 33610844Sandreas.sandberg@arm.com core.phys.setTimerValue(val); 33710844Sandreas.sandberg@arm.com return; 33810844Sandreas.sandberg@arm.com 33910844Sandreas.sandberg@arm.com case MISCREG_CNTP_CTL: 34010844Sandreas.sandberg@arm.com case MISCREG_CNTP_CTL_NS: 34110844Sandreas.sandberg@arm.com case MISCREG_CNTP_CTL_EL0: 34210844Sandreas.sandberg@arm.com core.phys.setControl(val); 34310844Sandreas.sandberg@arm.com return; 34410844Sandreas.sandberg@arm.com 34510844Sandreas.sandberg@arm.com // Count registers 34610844Sandreas.sandberg@arm.com case MISCREG_CNTPCT: 34710844Sandreas.sandberg@arm.com case MISCREG_CNTPCT_EL0: 34810844Sandreas.sandberg@arm.com case MISCREG_CNTVCT: 34910844Sandreas.sandberg@arm.com case MISCREG_CNTVCT_EL0: 35010844Sandreas.sandberg@arm.com warn("Ignoring write to read only count register: %s\n", 35110844Sandreas.sandberg@arm.com miscRegName[reg]); 35210844Sandreas.sandberg@arm.com return; 35310844Sandreas.sandberg@arm.com 35410844Sandreas.sandberg@arm.com // Virtual timer 35510844Sandreas.sandberg@arm.com case MISCREG_CNTVOFF: 35610844Sandreas.sandberg@arm.com case MISCREG_CNTVOFF_EL2: 35710845Sandreas.sandberg@arm.com core.virt.setOffset(val); 35810845Sandreas.sandberg@arm.com return; 35910845Sandreas.sandberg@arm.com 36010844Sandreas.sandberg@arm.com case MISCREG_CNTV_CVAL: 36110844Sandreas.sandberg@arm.com case MISCREG_CNTV_CVAL_EL0: 36210845Sandreas.sandberg@arm.com core.virt.setCompareValue(val); 36310845Sandreas.sandberg@arm.com return; 36410845Sandreas.sandberg@arm.com 36510844Sandreas.sandberg@arm.com case MISCREG_CNTV_TVAL: 36610844Sandreas.sandberg@arm.com case MISCREG_CNTV_TVAL_EL0: 36710845Sandreas.sandberg@arm.com core.virt.setTimerValue(val); 36810845Sandreas.sandberg@arm.com return; 36910845Sandreas.sandberg@arm.com 37010844Sandreas.sandberg@arm.com case MISCREG_CNTV_CTL: 37110844Sandreas.sandberg@arm.com case MISCREG_CNTV_CTL_EL0: 37210845Sandreas.sandberg@arm.com core.virt.setControl(val); 37310845Sandreas.sandberg@arm.com return; 37410844Sandreas.sandberg@arm.com 37510844Sandreas.sandberg@arm.com // PL1 phys. timer, secure 37610844Sandreas.sandberg@arm.com case MISCREG_CNTP_CTL_S: 37710844Sandreas.sandberg@arm.com case MISCREG_CNTPS_CVAL_EL1: 37810844Sandreas.sandberg@arm.com case MISCREG_CNTPS_TVAL_EL1: 37910844Sandreas.sandberg@arm.com case MISCREG_CNTPS_CTL_EL1: 38010844Sandreas.sandberg@arm.com /* FALLTHROUGH */ 38110844Sandreas.sandberg@arm.com 38210844Sandreas.sandberg@arm.com // PL2 phys. timer, non-secure 38310844Sandreas.sandberg@arm.com case MISCREG_CNTHCTL: 38410844Sandreas.sandberg@arm.com case MISCREG_CNTHCTL_EL2: 38510844Sandreas.sandberg@arm.com case MISCREG_CNTHP_CVAL: 38610844Sandreas.sandberg@arm.com case MISCREG_CNTHP_CVAL_EL2: 38710844Sandreas.sandberg@arm.com case MISCREG_CNTHP_TVAL: 38810844Sandreas.sandberg@arm.com case MISCREG_CNTHP_TVAL_EL2: 38910844Sandreas.sandberg@arm.com case MISCREG_CNTHP_CTL: 39010844Sandreas.sandberg@arm.com case MISCREG_CNTHP_CTL_EL2: 39110844Sandreas.sandberg@arm.com warn("Writing to unimplemented register: %s\n", 39210844Sandreas.sandberg@arm.com miscRegName[reg]); 39310844Sandreas.sandberg@arm.com return; 39410844Sandreas.sandberg@arm.com 39510844Sandreas.sandberg@arm.com default: 39610844Sandreas.sandberg@arm.com warn("Writing to unknown register: %s\n", miscRegName[reg]); 39710844Sandreas.sandberg@arm.com return; 39810844Sandreas.sandberg@arm.com } 39910844Sandreas.sandberg@arm.com} 40010844Sandreas.sandberg@arm.com 40110844Sandreas.sandberg@arm.com 40210844Sandreas.sandberg@arm.comMiscReg 40310844Sandreas.sandberg@arm.comGenericTimer::readMiscReg(int reg, unsigned cpu) 40410844Sandreas.sandberg@arm.com{ 40510844Sandreas.sandberg@arm.com CoreTimers &core(getTimers(cpu)); 40610844Sandreas.sandberg@arm.com 40710844Sandreas.sandberg@arm.com switch (reg) { 40810844Sandreas.sandberg@arm.com case MISCREG_CNTFRQ: 40910844Sandreas.sandberg@arm.com case MISCREG_CNTFRQ_EL0: 41010844Sandreas.sandberg@arm.com return systemCounter.freq(); 41110844Sandreas.sandberg@arm.com 41210844Sandreas.sandberg@arm.com case MISCREG_CNTKCTL: 41310844Sandreas.sandberg@arm.com case MISCREG_CNTKCTL_EL1: 41410844Sandreas.sandberg@arm.com return systemCounter.getKernelControl(); 41510844Sandreas.sandberg@arm.com 41610844Sandreas.sandberg@arm.com // Physical timer 41710844Sandreas.sandberg@arm.com case MISCREG_CNTP_CVAL: 41810844Sandreas.sandberg@arm.com case MISCREG_CNTP_CVAL_EL0: 41910844Sandreas.sandberg@arm.com return core.phys.compareValue(); 42010844Sandreas.sandberg@arm.com 42110844Sandreas.sandberg@arm.com case MISCREG_CNTP_TVAL: 42210844Sandreas.sandberg@arm.com case MISCREG_CNTP_TVAL_EL0: 42310844Sandreas.sandberg@arm.com return core.phys.timerValue(); 42410844Sandreas.sandberg@arm.com 42510844Sandreas.sandberg@arm.com case MISCREG_CNTP_CTL: 42610844Sandreas.sandberg@arm.com case MISCREG_CNTP_CTL_EL0: 42710844Sandreas.sandberg@arm.com case MISCREG_CNTP_CTL_NS: 42810844Sandreas.sandberg@arm.com return core.phys.control(); 42910844Sandreas.sandberg@arm.com 43010844Sandreas.sandberg@arm.com case MISCREG_CNTPCT: 43110844Sandreas.sandberg@arm.com case MISCREG_CNTPCT_EL0: 43210844Sandreas.sandberg@arm.com return core.phys.value(); 43310844Sandreas.sandberg@arm.com 43410844Sandreas.sandberg@arm.com 43510844Sandreas.sandberg@arm.com // Virtual timer 43610844Sandreas.sandberg@arm.com case MISCREG_CNTVCT: 43710844Sandreas.sandberg@arm.com case MISCREG_CNTVCT_EL0: 43810845Sandreas.sandberg@arm.com return core.virt.value(); 43910844Sandreas.sandberg@arm.com 44010844Sandreas.sandberg@arm.com case MISCREG_CNTVOFF: 44110844Sandreas.sandberg@arm.com case MISCREG_CNTVOFF_EL2: 44210845Sandreas.sandberg@arm.com return core.virt.offset(); 44310845Sandreas.sandberg@arm.com 44410844Sandreas.sandberg@arm.com case MISCREG_CNTV_CVAL: 44510844Sandreas.sandberg@arm.com case MISCREG_CNTV_CVAL_EL0: 44610845Sandreas.sandberg@arm.com return core.virt.compareValue(); 44710845Sandreas.sandberg@arm.com 44810844Sandreas.sandberg@arm.com case MISCREG_CNTV_TVAL: 44910844Sandreas.sandberg@arm.com case MISCREG_CNTV_TVAL_EL0: 45010845Sandreas.sandberg@arm.com return core.virt.timerValue(); 45110845Sandreas.sandberg@arm.com 45210844Sandreas.sandberg@arm.com case MISCREG_CNTV_CTL: 45310844Sandreas.sandberg@arm.com case MISCREG_CNTV_CTL_EL0: 45410845Sandreas.sandberg@arm.com return core.virt.control(); 45510844Sandreas.sandberg@arm.com 45610844Sandreas.sandberg@arm.com // PL1 phys. timer, secure 45710844Sandreas.sandberg@arm.com case MISCREG_CNTP_CTL_S: 45810844Sandreas.sandberg@arm.com case MISCREG_CNTPS_CVAL_EL1: 45910844Sandreas.sandberg@arm.com case MISCREG_CNTPS_TVAL_EL1: 46010844Sandreas.sandberg@arm.com case MISCREG_CNTPS_CTL_EL1: 46110844Sandreas.sandberg@arm.com /* FALLTHROUGH */ 46210844Sandreas.sandberg@arm.com 46310844Sandreas.sandberg@arm.com // PL2 phys. timer, non-secure 46410844Sandreas.sandberg@arm.com case MISCREG_CNTHCTL: 46510844Sandreas.sandberg@arm.com case MISCREG_CNTHCTL_EL2: 46610844Sandreas.sandberg@arm.com case MISCREG_CNTHP_CVAL: 46710844Sandreas.sandberg@arm.com case MISCREG_CNTHP_CVAL_EL2: 46810844Sandreas.sandberg@arm.com case MISCREG_CNTHP_TVAL: 46910844Sandreas.sandberg@arm.com case MISCREG_CNTHP_TVAL_EL2: 47010844Sandreas.sandberg@arm.com case MISCREG_CNTHP_CTL: 47110844Sandreas.sandberg@arm.com case MISCREG_CNTHP_CTL_EL2: 47210844Sandreas.sandberg@arm.com warn("Reading from unimplemented register: %s\n", 47310844Sandreas.sandberg@arm.com miscRegName[reg]); 47410844Sandreas.sandberg@arm.com return 0; 47510844Sandreas.sandberg@arm.com 47610844Sandreas.sandberg@arm.com 47710844Sandreas.sandberg@arm.com default: 47810844Sandreas.sandberg@arm.com warn("Reading from unknown register: %s\n", miscRegName[reg]); 47910844Sandreas.sandberg@arm.com return 0; 48010844Sandreas.sandberg@arm.com } 48110844Sandreas.sandberg@arm.com} 48210844Sandreas.sandberg@arm.com 48310844Sandreas.sandberg@arm.com 48410847Sandreas.sandberg@arm.com 48510847Sandreas.sandberg@arm.comGenericTimerMem::GenericTimerMem(GenericTimerMemParams *p) 48610847Sandreas.sandberg@arm.com : PioDevice(p), 48710847Sandreas.sandberg@arm.com ctrlRange(RangeSize(p->base, TheISA::PageBytes)), 48810847Sandreas.sandberg@arm.com timerRange(RangeSize(p->base + TheISA::PageBytes, TheISA::PageBytes)), 48910847Sandreas.sandberg@arm.com addrRanges{ctrlRange, timerRange}, 49010847Sandreas.sandberg@arm.com systemCounter(), 49110847Sandreas.sandberg@arm.com physTimer(csprintf("%s.phys_timer0", name()), 49210847Sandreas.sandberg@arm.com *this, systemCounter, 49310847Sandreas.sandberg@arm.com ArchTimer::Interrupt(*p->gic, p->int_phys)), 49410847Sandreas.sandberg@arm.com virtTimer(csprintf("%s.virt_timer0", name()), 49510847Sandreas.sandberg@arm.com *this, systemCounter, 49610847Sandreas.sandberg@arm.com ArchTimer::Interrupt(*p->gic, p->int_virt)) 49710847Sandreas.sandberg@arm.com{ 49810847Sandreas.sandberg@arm.com} 49910847Sandreas.sandberg@arm.com 50010847Sandreas.sandberg@arm.comvoid 50110847Sandreas.sandberg@arm.comGenericTimerMem::serialize(std::ostream &os) 50210847Sandreas.sandberg@arm.com{ 50310847Sandreas.sandberg@arm.com paramOut(os, "timer_count", 1); 50410847Sandreas.sandberg@arm.com 50510847Sandreas.sandberg@arm.com nameOut(os, csprintf("%s.sys_counter", name())); 50610847Sandreas.sandberg@arm.com systemCounter.serialize(os); 50710847Sandreas.sandberg@arm.com 50810847Sandreas.sandberg@arm.com nameOut(os, physTimer.name()); 50910847Sandreas.sandberg@arm.com physTimer.serialize(os); 51010847Sandreas.sandberg@arm.com 51110847Sandreas.sandberg@arm.com nameOut(os, virtTimer.name()); 51210847Sandreas.sandberg@arm.com virtTimer.serialize(os); 51310847Sandreas.sandberg@arm.com} 51410847Sandreas.sandberg@arm.com 51510847Sandreas.sandberg@arm.comvoid 51610847Sandreas.sandberg@arm.comGenericTimerMem::unserialize(Checkpoint *cp, const std::string §ion) 51710847Sandreas.sandberg@arm.com{ 51810847Sandreas.sandberg@arm.com systemCounter.unserialize(cp, csprintf("%s.sys_counter", section)); 51910847Sandreas.sandberg@arm.com 52010847Sandreas.sandberg@arm.com unsigned timer_count; 52110847Sandreas.sandberg@arm.com UNSERIALIZE_SCALAR(timer_count); 52210847Sandreas.sandberg@arm.com // The timer count variable is just here for future versions where 52310847Sandreas.sandberg@arm.com // we support more than one set of timers. 52410847Sandreas.sandberg@arm.com if (timer_count != 1) 52510847Sandreas.sandberg@arm.com panic("Incompatible checkpoint: Only one set of timers supported"); 52610847Sandreas.sandberg@arm.com 52710847Sandreas.sandberg@arm.com physTimer.unserialize(cp, csprintf("%s.phys_timer0", section)); 52810847Sandreas.sandberg@arm.com virtTimer.unserialize(cp, csprintf("%s.virt_timer0", section)); 52910847Sandreas.sandberg@arm.com} 53010847Sandreas.sandberg@arm.com 53110847Sandreas.sandberg@arm.comTick 53210847Sandreas.sandberg@arm.comGenericTimerMem::read(PacketPtr pkt) 53310847Sandreas.sandberg@arm.com{ 53410847Sandreas.sandberg@arm.com const unsigned size(pkt->getSize()); 53510847Sandreas.sandberg@arm.com const Addr addr(pkt->getAddr()); 53610847Sandreas.sandberg@arm.com uint64_t value; 53710847Sandreas.sandberg@arm.com 53810847Sandreas.sandberg@arm.com pkt->makeResponse(); 53910847Sandreas.sandberg@arm.com if (ctrlRange.contains(addr)) { 54010847Sandreas.sandberg@arm.com value = ctrlRead(addr - ctrlRange.start(), size); 54110847Sandreas.sandberg@arm.com } else if (timerRange.contains(addr)) { 54210847Sandreas.sandberg@arm.com value = timerRead(addr - timerRange.start(), size); 54310847Sandreas.sandberg@arm.com } else { 54410847Sandreas.sandberg@arm.com panic("Invalid address: 0x%x\n", addr); 54510847Sandreas.sandberg@arm.com } 54610847Sandreas.sandberg@arm.com 54710847Sandreas.sandberg@arm.com DPRINTF(Timer, "Read 0x%x <- 0x%x(%i)\n", value, addr, size); 54810847Sandreas.sandberg@arm.com 54910847Sandreas.sandberg@arm.com if (size == 8) { 55010847Sandreas.sandberg@arm.com pkt->set<uint64_t>(value); 55110847Sandreas.sandberg@arm.com } else if (size == 4) { 55210847Sandreas.sandberg@arm.com pkt->set<uint32_t>(value); 55310847Sandreas.sandberg@arm.com } else { 55410847Sandreas.sandberg@arm.com panic("Unexpected access size: %i\n", size); 55510847Sandreas.sandberg@arm.com } 55610847Sandreas.sandberg@arm.com 55710847Sandreas.sandberg@arm.com return 0; 55810847Sandreas.sandberg@arm.com} 55910847Sandreas.sandberg@arm.com 56010847Sandreas.sandberg@arm.comTick 56110847Sandreas.sandberg@arm.comGenericTimerMem::write(PacketPtr pkt) 56210847Sandreas.sandberg@arm.com{ 56310847Sandreas.sandberg@arm.com const unsigned size(pkt->getSize()); 56410847Sandreas.sandberg@arm.com if (size != 8 && size != 4) 56510847Sandreas.sandberg@arm.com panic("Unexpected access size\n"); 56610847Sandreas.sandberg@arm.com 56710847Sandreas.sandberg@arm.com const Addr addr(pkt->getAddr()); 56810847Sandreas.sandberg@arm.com const uint64_t value(size == 8 ? 56910847Sandreas.sandberg@arm.com pkt->get<uint64_t>() : pkt->get<uint32_t>()); 57010847Sandreas.sandberg@arm.com 57110847Sandreas.sandberg@arm.com DPRINTF(Timer, "Write 0x%x -> 0x%x(%i)\n", value, addr, size); 57210847Sandreas.sandberg@arm.com if (ctrlRange.contains(addr)) { 57310847Sandreas.sandberg@arm.com ctrlWrite(addr - ctrlRange.start(), size, value); 57410847Sandreas.sandberg@arm.com } else if (timerRange.contains(addr)) { 57510847Sandreas.sandberg@arm.com timerWrite(addr - timerRange.start(), size, value); 57610847Sandreas.sandberg@arm.com } else { 57710847Sandreas.sandberg@arm.com panic("Invalid address: 0x%x\n", addr); 57810847Sandreas.sandberg@arm.com } 57910847Sandreas.sandberg@arm.com 58010847Sandreas.sandberg@arm.com pkt->makeResponse(); 58110847Sandreas.sandberg@arm.com return 0; 58210847Sandreas.sandberg@arm.com} 58310847Sandreas.sandberg@arm.com 58410847Sandreas.sandberg@arm.comuint64_t 58510847Sandreas.sandberg@arm.comGenericTimerMem::ctrlRead(Addr addr, size_t size) const 58610847Sandreas.sandberg@arm.com{ 58710847Sandreas.sandberg@arm.com if (size == 4) { 58810847Sandreas.sandberg@arm.com switch (addr) { 58910847Sandreas.sandberg@arm.com case CTRL_CNTFRQ: 59010847Sandreas.sandberg@arm.com return systemCounter.freq(); 59110847Sandreas.sandberg@arm.com 59210847Sandreas.sandberg@arm.com case CTRL_CNTTIDR: 59310847Sandreas.sandberg@arm.com return 0x3; // Frame 0 implemented with virtual timers 59410847Sandreas.sandberg@arm.com 59510847Sandreas.sandberg@arm.com case CTRL_CNTNSAR: 59610847Sandreas.sandberg@arm.com case CTRL_CNTACR_BASE: 59710847Sandreas.sandberg@arm.com warn("Reading from unimplemented control register (0x%x)\n", addr); 59810847Sandreas.sandberg@arm.com return 0; 59910847Sandreas.sandberg@arm.com 60010847Sandreas.sandberg@arm.com case CTRL_CNTVOFF_LO_BASE: 60110847Sandreas.sandberg@arm.com return virtTimer.offset(); 60210847Sandreas.sandberg@arm.com 60310847Sandreas.sandberg@arm.com case CTRL_CNTVOFF_HI_BASE: 60410847Sandreas.sandberg@arm.com return virtTimer.offset() >> 32; 60510847Sandreas.sandberg@arm.com 60610847Sandreas.sandberg@arm.com default: 60710847Sandreas.sandberg@arm.com warn("Unexpected address (0x%x:%i), assuming RAZ\n", addr, size); 60810847Sandreas.sandberg@arm.com return 0; 60910847Sandreas.sandberg@arm.com } 61010847Sandreas.sandberg@arm.com } else if (size == 8) { 61110847Sandreas.sandberg@arm.com switch (addr) { 61210847Sandreas.sandberg@arm.com case CTRL_CNTVOFF_LO_BASE: 61310847Sandreas.sandberg@arm.com return virtTimer.offset(); 61410847Sandreas.sandberg@arm.com 61510847Sandreas.sandberg@arm.com default: 61610847Sandreas.sandberg@arm.com warn("Unexpected address (0x%x:%i), assuming RAZ\n", addr, size); 61710847Sandreas.sandberg@arm.com return 0; 61810847Sandreas.sandberg@arm.com } 61910847Sandreas.sandberg@arm.com } else { 62010847Sandreas.sandberg@arm.com panic("Invalid access size: %i\n", size); 62110847Sandreas.sandberg@arm.com } 62210847Sandreas.sandberg@arm.com} 62310847Sandreas.sandberg@arm.com 62410847Sandreas.sandberg@arm.comvoid 62510847Sandreas.sandberg@arm.comGenericTimerMem::ctrlWrite(Addr addr, size_t size, uint64_t value) 62610847Sandreas.sandberg@arm.com{ 62710847Sandreas.sandberg@arm.com if (size == 4) { 62810847Sandreas.sandberg@arm.com switch (addr) { 62910847Sandreas.sandberg@arm.com case CTRL_CNTFRQ: 63010847Sandreas.sandberg@arm.com case CTRL_CNTNSAR: 63110847Sandreas.sandberg@arm.com case CTRL_CNTTIDR: 63210847Sandreas.sandberg@arm.com case CTRL_CNTACR_BASE: 63310847Sandreas.sandberg@arm.com warn("Write to unimplemented control register (0x%x)\n", addr); 63410847Sandreas.sandberg@arm.com return; 63510847Sandreas.sandberg@arm.com 63610847Sandreas.sandberg@arm.com case CTRL_CNTVOFF_LO_BASE: 63710847Sandreas.sandberg@arm.com virtTimer.setOffset( 63810847Sandreas.sandberg@arm.com insertBits(virtTimer.offset(), 31, 0, value)); 63910847Sandreas.sandberg@arm.com return; 64010847Sandreas.sandberg@arm.com 64110847Sandreas.sandberg@arm.com case CTRL_CNTVOFF_HI_BASE: 64210847Sandreas.sandberg@arm.com virtTimer.setOffset( 64310847Sandreas.sandberg@arm.com insertBits(virtTimer.offset(), 63, 32, value)); 64410847Sandreas.sandberg@arm.com return; 64510847Sandreas.sandberg@arm.com 64610847Sandreas.sandberg@arm.com default: 64710847Sandreas.sandberg@arm.com warn("Ignoring write to unexpected address (0x%x:%i)\n", 64810847Sandreas.sandberg@arm.com addr, size); 64910847Sandreas.sandberg@arm.com return; 65010847Sandreas.sandberg@arm.com } 65110847Sandreas.sandberg@arm.com } else if (size == 8) { 65210847Sandreas.sandberg@arm.com switch (addr) { 65310847Sandreas.sandberg@arm.com case CTRL_CNTVOFF_LO_BASE: 65410847Sandreas.sandberg@arm.com virtTimer.setOffset(value); 65510847Sandreas.sandberg@arm.com return; 65610847Sandreas.sandberg@arm.com 65710847Sandreas.sandberg@arm.com default: 65810847Sandreas.sandberg@arm.com warn("Ignoring write to unexpected address (0x%x:%i)\n", 65910847Sandreas.sandberg@arm.com addr, size); 66010847Sandreas.sandberg@arm.com return; 66110847Sandreas.sandberg@arm.com } 66210847Sandreas.sandberg@arm.com } else { 66310847Sandreas.sandberg@arm.com panic("Invalid access size: %i\n", size); 66410847Sandreas.sandberg@arm.com } 66510847Sandreas.sandberg@arm.com} 66610847Sandreas.sandberg@arm.com 66710847Sandreas.sandberg@arm.comuint64_t 66810847Sandreas.sandberg@arm.comGenericTimerMem::timerRead(Addr addr, size_t size) const 66910847Sandreas.sandberg@arm.com{ 67010847Sandreas.sandberg@arm.com if (size == 4) { 67110847Sandreas.sandberg@arm.com switch (addr) { 67210847Sandreas.sandberg@arm.com case TIMER_CNTPCT_LO: 67310847Sandreas.sandberg@arm.com return physTimer.value(); 67410847Sandreas.sandberg@arm.com 67510847Sandreas.sandberg@arm.com case TIMER_CNTPCT_HI: 67610847Sandreas.sandberg@arm.com return physTimer.value() >> 32; 67710847Sandreas.sandberg@arm.com 67810847Sandreas.sandberg@arm.com case TIMER_CNTVCT_LO: 67910847Sandreas.sandberg@arm.com return virtTimer.value(); 68010847Sandreas.sandberg@arm.com 68110847Sandreas.sandberg@arm.com case TIMER_CNTVCT_HI: 68210847Sandreas.sandberg@arm.com return virtTimer.value() >> 32; 68310847Sandreas.sandberg@arm.com 68410847Sandreas.sandberg@arm.com case TIMER_CNTFRQ: 68510847Sandreas.sandberg@arm.com return systemCounter.freq(); 68610847Sandreas.sandberg@arm.com 68710847Sandreas.sandberg@arm.com case TIMER_CNTEL0ACR: 68810847Sandreas.sandberg@arm.com warn("Read from unimplemented timer register (0x%x)\n", addr); 68910847Sandreas.sandberg@arm.com return 0; 69010847Sandreas.sandberg@arm.com 69110847Sandreas.sandberg@arm.com case CTRL_CNTVOFF_LO_BASE: 69210847Sandreas.sandberg@arm.com return virtTimer.offset(); 69310847Sandreas.sandberg@arm.com 69410847Sandreas.sandberg@arm.com case CTRL_CNTVOFF_HI_BASE: 69510847Sandreas.sandberg@arm.com return virtTimer.offset() >> 32; 69610847Sandreas.sandberg@arm.com 69710847Sandreas.sandberg@arm.com case TIMER_CNTP_CVAL_LO: 69810847Sandreas.sandberg@arm.com return physTimer.compareValue(); 69910847Sandreas.sandberg@arm.com 70010847Sandreas.sandberg@arm.com case TIMER_CNTP_CVAL_HI: 70110847Sandreas.sandberg@arm.com return physTimer.compareValue() >> 32; 70210847Sandreas.sandberg@arm.com 70310847Sandreas.sandberg@arm.com case TIMER_CNTP_TVAL: 70410847Sandreas.sandberg@arm.com return physTimer.timerValue(); 70510847Sandreas.sandberg@arm.com 70610847Sandreas.sandberg@arm.com case TIMER_CNTP_CTL: 70710847Sandreas.sandberg@arm.com return physTimer.control(); 70810847Sandreas.sandberg@arm.com 70910847Sandreas.sandberg@arm.com case TIMER_CNTV_CVAL_LO: 71010847Sandreas.sandberg@arm.com return virtTimer.compareValue(); 71110847Sandreas.sandberg@arm.com 71210847Sandreas.sandberg@arm.com case TIMER_CNTV_CVAL_HI: 71310847Sandreas.sandberg@arm.com return virtTimer.compareValue() >> 32; 71410847Sandreas.sandberg@arm.com 71510847Sandreas.sandberg@arm.com case TIMER_CNTV_TVAL: 71610847Sandreas.sandberg@arm.com return virtTimer.timerValue(); 71710847Sandreas.sandberg@arm.com 71810847Sandreas.sandberg@arm.com case TIMER_CNTV_CTL: 71910847Sandreas.sandberg@arm.com return virtTimer.control(); 72010847Sandreas.sandberg@arm.com 72110847Sandreas.sandberg@arm.com default: 72210847Sandreas.sandberg@arm.com warn("Unexpected address (0x%x:%i), assuming RAZ\n", addr, size); 72310847Sandreas.sandberg@arm.com return 0; 72410847Sandreas.sandberg@arm.com } 72510847Sandreas.sandberg@arm.com } else if (size == 8) { 72610847Sandreas.sandberg@arm.com switch (addr) { 72710847Sandreas.sandberg@arm.com case TIMER_CNTPCT_LO: 72810847Sandreas.sandberg@arm.com return physTimer.value(); 72910847Sandreas.sandberg@arm.com 73010847Sandreas.sandberg@arm.com case TIMER_CNTVCT_LO: 73110847Sandreas.sandberg@arm.com return virtTimer.value(); 73210847Sandreas.sandberg@arm.com 73310847Sandreas.sandberg@arm.com case CTRL_CNTVOFF_LO_BASE: 73410847Sandreas.sandberg@arm.com return virtTimer.offset(); 73510847Sandreas.sandberg@arm.com 73610847Sandreas.sandberg@arm.com case TIMER_CNTP_CVAL_LO: 73710847Sandreas.sandberg@arm.com return physTimer.compareValue(); 73810847Sandreas.sandberg@arm.com 73910847Sandreas.sandberg@arm.com case TIMER_CNTV_CVAL_LO: 74010847Sandreas.sandberg@arm.com return virtTimer.compareValue(); 74110847Sandreas.sandberg@arm.com 74210847Sandreas.sandberg@arm.com default: 74310847Sandreas.sandberg@arm.com warn("Unexpected address (0x%x:%i), assuming RAZ\n", addr, size); 74410847Sandreas.sandberg@arm.com return 0; 74510847Sandreas.sandberg@arm.com } 74610847Sandreas.sandberg@arm.com } else { 74710847Sandreas.sandberg@arm.com panic("Invalid access size: %i\n", size); 74810847Sandreas.sandberg@arm.com } 74910847Sandreas.sandberg@arm.com} 75010847Sandreas.sandberg@arm.com 75110847Sandreas.sandberg@arm.comvoid 75210847Sandreas.sandberg@arm.comGenericTimerMem::timerWrite(Addr addr, size_t size, uint64_t value) 75310847Sandreas.sandberg@arm.com{ 75410847Sandreas.sandberg@arm.com if (size == 4) { 75510847Sandreas.sandberg@arm.com switch (addr) { 75610847Sandreas.sandberg@arm.com case TIMER_CNTEL0ACR: 75710847Sandreas.sandberg@arm.com warn("Unimplemented timer register (0x%x)\n", addr); 75810847Sandreas.sandberg@arm.com return; 75910847Sandreas.sandberg@arm.com 76010847Sandreas.sandberg@arm.com case TIMER_CNTP_CVAL_LO: 76110847Sandreas.sandberg@arm.com physTimer.setCompareValue( 76210847Sandreas.sandberg@arm.com insertBits(physTimer.compareValue(), 31, 0, value)); 76310847Sandreas.sandberg@arm.com return; 76410847Sandreas.sandberg@arm.com 76510847Sandreas.sandberg@arm.com case TIMER_CNTP_CVAL_HI: 76610847Sandreas.sandberg@arm.com physTimer.setCompareValue( 76710847Sandreas.sandberg@arm.com insertBits(physTimer.compareValue(), 63, 32, value)); 76810847Sandreas.sandberg@arm.com return; 76910847Sandreas.sandberg@arm.com 77010847Sandreas.sandberg@arm.com case TIMER_CNTP_TVAL: 77110847Sandreas.sandberg@arm.com physTimer.setTimerValue(value); 77210847Sandreas.sandberg@arm.com return; 77310847Sandreas.sandberg@arm.com 77410847Sandreas.sandberg@arm.com case TIMER_CNTP_CTL: 77510847Sandreas.sandberg@arm.com physTimer.setControl(value); 77610847Sandreas.sandberg@arm.com return; 77710847Sandreas.sandberg@arm.com 77810847Sandreas.sandberg@arm.com case TIMER_CNTV_CVAL_LO: 77910847Sandreas.sandberg@arm.com virtTimer.setCompareValue( 78010847Sandreas.sandberg@arm.com insertBits(virtTimer.compareValue(), 31, 0, value)); 78110847Sandreas.sandberg@arm.com return; 78210847Sandreas.sandberg@arm.com 78310847Sandreas.sandberg@arm.com case TIMER_CNTV_CVAL_HI: 78410847Sandreas.sandberg@arm.com virtTimer.setCompareValue( 78510847Sandreas.sandberg@arm.com insertBits(virtTimer.compareValue(), 63, 32, value)); 78610847Sandreas.sandberg@arm.com return; 78710847Sandreas.sandberg@arm.com 78810847Sandreas.sandberg@arm.com case TIMER_CNTV_TVAL: 78910847Sandreas.sandberg@arm.com virtTimer.setTimerValue(value); 79010847Sandreas.sandberg@arm.com return; 79110847Sandreas.sandberg@arm.com 79210847Sandreas.sandberg@arm.com case TIMER_CNTV_CTL: 79310847Sandreas.sandberg@arm.com virtTimer.setControl(value); 79410847Sandreas.sandberg@arm.com return; 79510847Sandreas.sandberg@arm.com 79610847Sandreas.sandberg@arm.com default: 79710847Sandreas.sandberg@arm.com warn("Unexpected address (0x%x:%i), ignoring write\n", addr, size); 79810847Sandreas.sandberg@arm.com return; 79910847Sandreas.sandberg@arm.com } 80010847Sandreas.sandberg@arm.com } else if (size == 8) { 80110847Sandreas.sandberg@arm.com switch (addr) { 80210847Sandreas.sandberg@arm.com case TIMER_CNTP_CVAL_LO: 80310847Sandreas.sandberg@arm.com return physTimer.setCompareValue(value); 80410847Sandreas.sandberg@arm.com 80510847Sandreas.sandberg@arm.com case TIMER_CNTV_CVAL_LO: 80610847Sandreas.sandberg@arm.com return virtTimer.setCompareValue(value); 80710847Sandreas.sandberg@arm.com 80810847Sandreas.sandberg@arm.com default: 80910847Sandreas.sandberg@arm.com warn("Unexpected address (0x%x:%i), ignoring write\n", addr, size); 81010847Sandreas.sandberg@arm.com return; 81110847Sandreas.sandberg@arm.com } 81210847Sandreas.sandberg@arm.com } else { 81310847Sandreas.sandberg@arm.com panic("Invalid access size: %i\n", size); 81410847Sandreas.sandberg@arm.com } 81510847Sandreas.sandberg@arm.com} 81610847Sandreas.sandberg@arm.com 81710037SARM gem5 DevelopersGenericTimer * 81810037SARM gem5 DevelopersGenericTimerParams::create() 81910037SARM gem5 Developers{ 82010037SARM gem5 Developers return new GenericTimer(this); 82110037SARM gem5 Developers} 82210847Sandreas.sandberg@arm.com 82310847Sandreas.sandberg@arm.comGenericTimerMem * 82410847Sandreas.sandberg@arm.comGenericTimerMemParams::create() 82510847Sandreas.sandberg@arm.com{ 82610847Sandreas.sandberg@arm.com return new GenericTimerMem(this); 82710847Sandreas.sandberg@arm.com} 828