generic_timer.cc revision 11933
110037SARM gem5 Developers/* 211933Sandreas.sandberg@arm.com * Copyright (c) 2013, 2015, 2017 ARM Limited 310037SARM gem5 Developers * All rights reserved. 410037SARM gem5 Developers * 510037SARM gem5 Developers * The license below extends only to copyright in the software and shall 610037SARM gem5 Developers * not be construed as granting a license to any other intellectual 710037SARM gem5 Developers * property including but not limited to intellectual property relating 810037SARM gem5 Developers * to a hardware implementation of the functionality of the software 910037SARM gem5 Developers * licensed hereunder. You may use the software subject to the license 1010037SARM gem5 Developers * terms below provided that you ensure that this notice is replicated 1110037SARM gem5 Developers * unmodified and in its entirety in all distributions of the software, 1210037SARM gem5 Developers * modified or unmodified, in source code or in binary form. 1310037SARM gem5 Developers * 1410037SARM gem5 Developers * Redistribution and use in source and binary forms, with or without 1510037SARM gem5 Developers * modification, are permitted provided that the following conditions are 1610037SARM gem5 Developers * met: redistributions of source code must retain the above copyright 1710037SARM gem5 Developers * notice, this list of conditions and the following disclaimer; 1810037SARM gem5 Developers * redistributions in binary form must reproduce the above copyright 1910037SARM gem5 Developers * notice, this list of conditions and the following disclaimer in the 2010037SARM gem5 Developers * documentation and/or other materials provided with the distribution; 2110037SARM gem5 Developers * neither the name of the copyright holders nor the names of its 2210037SARM gem5 Developers * contributors may be used to endorse or promote products derived from 2310037SARM gem5 Developers * this software without specific prior written permission. 2410037SARM gem5 Developers * 2510037SARM gem5 Developers * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 2610037SARM gem5 Developers * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 2710037SARM gem5 Developers * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 2810037SARM gem5 Developers * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2910037SARM gem5 Developers * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 3010037SARM gem5 Developers * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 3110037SARM gem5 Developers * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 3210037SARM gem5 Developers * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 3310037SARM gem5 Developers * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 3410037SARM gem5 Developers * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 3510037SARM gem5 Developers * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 3610037SARM gem5 Developers * 3710037SARM gem5 Developers * Authors: Giacomo Gabrielli 3810844Sandreas.sandberg@arm.com * Andreas Sandberg 3910037SARM gem5 Developers */ 4010037SARM gem5 Developers 4110844Sandreas.sandberg@arm.com#include "dev/arm/generic_timer.hh" 4210844Sandreas.sandberg@arm.com 4310037SARM gem5 Developers#include "arch/arm/system.hh" 4410037SARM gem5 Developers#include "debug/Timer.hh" 4510037SARM gem5 Developers#include "dev/arm/base_gic.hh" 4610847Sandreas.sandberg@arm.com#include "mem/packet_access.hh" 4710844Sandreas.sandberg@arm.com#include "params/GenericTimer.hh" 4810847Sandreas.sandberg@arm.com#include "params/GenericTimerMem.hh" 4910844Sandreas.sandberg@arm.com 5010844Sandreas.sandberg@arm.comSystemCounter::SystemCounter() 5110844Sandreas.sandberg@arm.com : _freq(0), _period(0), _resetTick(0), _regCntkctl(0) 5210844Sandreas.sandberg@arm.com{ 5310844Sandreas.sandberg@arm.com setFreq(0x01800000); 5410844Sandreas.sandberg@arm.com} 5510037SARM gem5 Developers 5610037SARM gem5 Developersvoid 5710844Sandreas.sandberg@arm.comSystemCounter::setFreq(uint32_t freq) 5810037SARM gem5 Developers{ 5910037SARM gem5 Developers if (_freq != 0) { 6010037SARM gem5 Developers // Altering the frequency after boot shouldn't be done in practice. 6110037SARM gem5 Developers warn_once("The frequency of the system counter has already been set"); 6210037SARM gem5 Developers } 6310037SARM gem5 Developers _freq = freq; 6410037SARM gem5 Developers _period = (1.0 / freq) * SimClock::Frequency; 6510037SARM gem5 Developers _resetTick = curTick(); 6610037SARM gem5 Developers} 6710037SARM gem5 Developers 6810037SARM gem5 Developersvoid 6910905Sandreas.sandberg@arm.comSystemCounter::serialize(CheckpointOut &cp) const 7010037SARM gem5 Developers{ 7110844Sandreas.sandberg@arm.com SERIALIZE_SCALAR(_regCntkctl); 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 7810905Sandreas.sandberg@arm.comSystemCounter::unserialize(CheckpointIn &cp) 7910037SARM gem5 Developers{ 8010844Sandreas.sandberg@arm.com // We didn't handle CNTKCTL in this class before, assume it's zero 8110844Sandreas.sandberg@arm.com // if it isn't present. 8210844Sandreas.sandberg@arm.com if (!UNSERIALIZE_OPT_SCALAR(_regCntkctl)) 8310844Sandreas.sandberg@arm.com _regCntkctl = 0; 8410037SARM gem5 Developers UNSERIALIZE_SCALAR(_freq); 8510037SARM gem5 Developers UNSERIALIZE_SCALAR(_period); 8610037SARM gem5 Developers UNSERIALIZE_SCALAR(_resetTick); 8710037SARM gem5 Developers} 8810037SARM gem5 Developers 8910844Sandreas.sandberg@arm.com 9010844Sandreas.sandberg@arm.com 9110844Sandreas.sandberg@arm.comArchTimer::ArchTimer(const std::string &name, 9210844Sandreas.sandberg@arm.com SimObject &parent, 9310844Sandreas.sandberg@arm.com SystemCounter &sysctr, 9410844Sandreas.sandberg@arm.com const Interrupt &interrupt) 9510844Sandreas.sandberg@arm.com : _name(name), _parent(parent), _systemCounter(sysctr), 9610844Sandreas.sandberg@arm.com _interrupt(interrupt), 9710845Sandreas.sandberg@arm.com _control(0), _counterLimit(0), _offset(0), 9810844Sandreas.sandberg@arm.com _counterLimitReachedEvent(this) 9910844Sandreas.sandberg@arm.com{ 10010844Sandreas.sandberg@arm.com} 10110844Sandreas.sandberg@arm.com 10210037SARM gem5 Developersvoid 10310844Sandreas.sandberg@arm.comArchTimer::counterLimitReached() 10410037SARM gem5 Developers{ 10510037SARM gem5 Developers _control.istatus = 1; 10610037SARM gem5 Developers 10710037SARM gem5 Developers if (!_control.enable) 10810037SARM gem5 Developers return; 10910037SARM gem5 Developers 11010844Sandreas.sandberg@arm.com DPRINTF(Timer, "Counter limit reached\n"); 11110037SARM gem5 Developers if (!_control.imask) { 11210844Sandreas.sandberg@arm.com DPRINTF(Timer, "Causing interrupt\n"); 11310844Sandreas.sandberg@arm.com _interrupt.send(); 11410037SARM gem5 Developers } 11510037SARM gem5 Developers} 11610037SARM gem5 Developers 11710037SARM gem5 Developersvoid 11810844Sandreas.sandberg@arm.comArchTimer::updateCounter() 11910037SARM gem5 Developers{ 12010037SARM gem5 Developers if (_counterLimitReachedEvent.scheduled()) 12110844Sandreas.sandberg@arm.com _parent.deschedule(_counterLimitReachedEvent); 12210844Sandreas.sandberg@arm.com if (value() >= _counterLimit) { 12310037SARM gem5 Developers counterLimitReached(); 12410037SARM gem5 Developers } else { 12510844Sandreas.sandberg@arm.com const auto period(_systemCounter.period()); 12610037SARM gem5 Developers _control.istatus = 0; 12710844Sandreas.sandberg@arm.com _parent.schedule(_counterLimitReachedEvent, 12810844Sandreas.sandberg@arm.com curTick() + (_counterLimit - value()) * period); 12910037SARM gem5 Developers } 13010037SARM gem5 Developers} 13110037SARM gem5 Developers 13210037SARM gem5 Developersvoid 13310844Sandreas.sandberg@arm.comArchTimer::setCompareValue(uint64_t val) 13410037SARM gem5 Developers{ 13510844Sandreas.sandberg@arm.com _counterLimit = val; 13610844Sandreas.sandberg@arm.com updateCounter(); 13710037SARM gem5 Developers} 13810037SARM gem5 Developers 13910037SARM gem5 Developersvoid 14010844Sandreas.sandberg@arm.comArchTimer::setTimerValue(uint32_t val) 14110844Sandreas.sandberg@arm.com{ 14210844Sandreas.sandberg@arm.com setCompareValue(value() + sext<32>(val)); 14310844Sandreas.sandberg@arm.com} 14410844Sandreas.sandberg@arm.com 14510844Sandreas.sandberg@arm.comvoid 14610844Sandreas.sandberg@arm.comArchTimer::setControl(uint32_t val) 14710037SARM gem5 Developers{ 14810037SARM gem5 Developers ArchTimerCtrl new_ctl = val; 14910037SARM gem5 Developers if ((new_ctl.enable && !new_ctl.imask) && 15010037SARM gem5 Developers !(_control.enable && !_control.imask)) { 15110037SARM gem5 Developers // Re-evalute the timer condition 15210844Sandreas.sandberg@arm.com if (_counterLimit >= value()) { 15310037SARM gem5 Developers _control.istatus = 1; 15410037SARM gem5 Developers 15510037SARM gem5 Developers DPRINTF(Timer, "Causing interrupt in control\n"); 15610844Sandreas.sandberg@arm.com //_interrupt.send(); 15710037SARM gem5 Developers } 15810037SARM gem5 Developers } 15910037SARM gem5 Developers _control.enable = new_ctl.enable; 16010037SARM gem5 Developers _control.imask = new_ctl.imask; 16110037SARM gem5 Developers} 16210037SARM gem5 Developers 16310845Sandreas.sandberg@arm.comvoid 16410845Sandreas.sandberg@arm.comArchTimer::setOffset(uint64_t val) 16510845Sandreas.sandberg@arm.com{ 16610845Sandreas.sandberg@arm.com _offset = val; 16710845Sandreas.sandberg@arm.com updateCounter(); 16810845Sandreas.sandberg@arm.com} 16910845Sandreas.sandberg@arm.com 17010844Sandreas.sandberg@arm.comuint64_t 17110844Sandreas.sandberg@arm.comArchTimer::value() const 17210844Sandreas.sandberg@arm.com{ 17310845Sandreas.sandberg@arm.com return _systemCounter.value() - _offset; 17410844Sandreas.sandberg@arm.com} 17510844Sandreas.sandberg@arm.com 17610037SARM gem5 Developersvoid 17710905Sandreas.sandberg@arm.comArchTimer::serialize(CheckpointOut &cp) const 17810037SARM gem5 Developers{ 17910905Sandreas.sandberg@arm.com paramOut(cp, "control_serial", _control); 18010037SARM gem5 Developers SERIALIZE_SCALAR(_counterLimit); 18110845Sandreas.sandberg@arm.com SERIALIZE_SCALAR(_offset); 18210844Sandreas.sandberg@arm.com 18310844Sandreas.sandberg@arm.com const bool event_scheduled(_counterLimitReachedEvent.scheduled()); 18410037SARM gem5 Developers SERIALIZE_SCALAR(event_scheduled); 18510037SARM gem5 Developers if (event_scheduled) { 18610844Sandreas.sandberg@arm.com const Tick event_time(_counterLimitReachedEvent.when()); 18710037SARM gem5 Developers SERIALIZE_SCALAR(event_time); 18810037SARM gem5 Developers } 18910037SARM gem5 Developers} 19010037SARM gem5 Developers 19110037SARM gem5 Developersvoid 19210905Sandreas.sandberg@arm.comArchTimer::unserialize(CheckpointIn &cp) 19310037SARM gem5 Developers{ 19410905Sandreas.sandberg@arm.com paramIn(cp, "control_serial", _control); 19510845Sandreas.sandberg@arm.com // We didn't serialize an offset before we added support for the 19610845Sandreas.sandberg@arm.com // virtual timer. Consider it optional to maintain backwards 19710845Sandreas.sandberg@arm.com // compatibility. 19810845Sandreas.sandberg@arm.com if (!UNSERIALIZE_OPT_SCALAR(_offset)) 19910845Sandreas.sandberg@arm.com _offset = 0; 20010037SARM gem5 Developers bool event_scheduled; 20110037SARM gem5 Developers UNSERIALIZE_SCALAR(event_scheduled); 20210037SARM gem5 Developers if (event_scheduled) { 20310844Sandreas.sandberg@arm.com Tick event_time; 20410037SARM gem5 Developers UNSERIALIZE_SCALAR(event_time); 20510844Sandreas.sandberg@arm.com _parent.schedule(_counterLimitReachedEvent, event_time); 20610037SARM gem5 Developers } 20710037SARM gem5 Developers} 20810037SARM gem5 Developers 20910844Sandreas.sandberg@arm.comvoid 21010844Sandreas.sandberg@arm.comArchTimer::Interrupt::send() 21110037SARM gem5 Developers{ 21210844Sandreas.sandberg@arm.com if (_ppi) { 21310844Sandreas.sandberg@arm.com _gic.sendPPInt(_irq, _cpu); 21410844Sandreas.sandberg@arm.com } else { 21510844Sandreas.sandberg@arm.com _gic.sendInt(_irq); 21610844Sandreas.sandberg@arm.com } 21710844Sandreas.sandberg@arm.com} 21810037SARM gem5 Developers 21910844Sandreas.sandberg@arm.com 22010844Sandreas.sandberg@arm.comvoid 22110844Sandreas.sandberg@arm.comArchTimer::Interrupt::clear() 22210844Sandreas.sandberg@arm.com{ 22310844Sandreas.sandberg@arm.com if (_ppi) { 22410844Sandreas.sandberg@arm.com _gic.clearPPInt(_irq, _cpu); 22510844Sandreas.sandberg@arm.com } else { 22610844Sandreas.sandberg@arm.com _gic.clearInt(_irq); 22710844Sandreas.sandberg@arm.com } 22810844Sandreas.sandberg@arm.com} 22910844Sandreas.sandberg@arm.com 23010844Sandreas.sandberg@arm.com 23110844Sandreas.sandberg@arm.comGenericTimer::GenericTimer(GenericTimerParams *p) 23210844Sandreas.sandberg@arm.com : SimObject(p), 23310844Sandreas.sandberg@arm.com gic(p->gic), 23410845Sandreas.sandberg@arm.com irqPhys(p->int_phys), 23510845Sandreas.sandberg@arm.com irqVirt(p->int_virt) 23610844Sandreas.sandberg@arm.com{ 23711668Sandreas.sandberg@arm.com fatal_if(!p->system, "No system specified, can't instantiate timer.\n"); 23811668Sandreas.sandberg@arm.com p->system->setGenericTimer(this); 23910037SARM gem5 Developers} 24010037SARM gem5 Developers 24110037SARM gem5 Developersvoid 24210905Sandreas.sandberg@arm.comGenericTimer::serialize(CheckpointOut &cp) const 24310037SARM gem5 Developers{ 24410905Sandreas.sandberg@arm.com paramOut(cp, "cpu_count", timers.size()); 24510844Sandreas.sandberg@arm.com 24610905Sandreas.sandberg@arm.com systemCounter.serializeSection(cp, "sys_counter"); 24710844Sandreas.sandberg@arm.com 24810844Sandreas.sandberg@arm.com for (int i = 0; i < timers.size(); ++i) { 24910905Sandreas.sandberg@arm.com const CoreTimers &core(*timers[i]); 25010844Sandreas.sandberg@arm.com 25110905Sandreas.sandberg@arm.com // This should really be phys_timerN, but we are stuck with 25210905Sandreas.sandberg@arm.com // arch_timer for backwards compatibility. 25310905Sandreas.sandberg@arm.com core.phys.serializeSection(cp, csprintf("arch_timer%d", i)); 25410905Sandreas.sandberg@arm.com core.virt.serializeSection(cp, csprintf("virt_timer%d", i)); 25510037SARM gem5 Developers } 25610037SARM gem5 Developers} 25710037SARM gem5 Developers 25810037SARM gem5 Developersvoid 25910905Sandreas.sandberg@arm.comGenericTimer::unserialize(CheckpointIn &cp) 26010037SARM gem5 Developers{ 26110905Sandreas.sandberg@arm.com systemCounter.unserializeSection(cp, "sys_counter"); 26210844Sandreas.sandberg@arm.com 26310844Sandreas.sandberg@arm.com // Try to unserialize the CPU count. Old versions of the timer 26410844Sandreas.sandberg@arm.com // model assumed a 8 CPUs, so we fall back to that if the field 26510844Sandreas.sandberg@arm.com // isn't present. 26610844Sandreas.sandberg@arm.com static const unsigned OLD_CPU_MAX = 8; 26710844Sandreas.sandberg@arm.com unsigned cpu_count; 26810844Sandreas.sandberg@arm.com if (!UNSERIALIZE_OPT_SCALAR(cpu_count)) { 26910844Sandreas.sandberg@arm.com warn("Checkpoint does not contain CPU count, assuming %i CPUs\n", 27010844Sandreas.sandberg@arm.com OLD_CPU_MAX); 27110844Sandreas.sandberg@arm.com cpu_count = OLD_CPU_MAX; 27210844Sandreas.sandberg@arm.com } 27310844Sandreas.sandberg@arm.com 27410844Sandreas.sandberg@arm.com for (int i = 0; i < cpu_count; ++i) { 27510844Sandreas.sandberg@arm.com CoreTimers &core(getTimers(i)); 27610844Sandreas.sandberg@arm.com // This should really be phys_timerN, but we are stuck with 27710844Sandreas.sandberg@arm.com // arch_timer for backwards compatibility. 27810905Sandreas.sandberg@arm.com core.phys.unserializeSection(cp, csprintf("arch_timer%d", i)); 27910905Sandreas.sandberg@arm.com core.virt.unserializeSection(cp, csprintf("virt_timer%d", i)); 28010037SARM gem5 Developers } 28110037SARM gem5 Developers} 28210037SARM gem5 Developers 28310844Sandreas.sandberg@arm.com 28410844Sandreas.sandberg@arm.comGenericTimer::CoreTimers & 28510844Sandreas.sandberg@arm.comGenericTimer::getTimers(int cpu_id) 28610844Sandreas.sandberg@arm.com{ 28710844Sandreas.sandberg@arm.com if (cpu_id >= timers.size()) 28810844Sandreas.sandberg@arm.com createTimers(cpu_id + 1); 28910844Sandreas.sandberg@arm.com 29010844Sandreas.sandberg@arm.com return *timers[cpu_id]; 29110844Sandreas.sandberg@arm.com} 29210844Sandreas.sandberg@arm.com 29310844Sandreas.sandberg@arm.comvoid 29410844Sandreas.sandberg@arm.comGenericTimer::createTimers(unsigned cpus) 29510844Sandreas.sandberg@arm.com{ 29610844Sandreas.sandberg@arm.com assert(timers.size() < cpus); 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) { 30110844Sandreas.sandberg@arm.com timers[i].reset( 30210845Sandreas.sandberg@arm.com new CoreTimers(*this, i, irqPhys, irqVirt)); 30310844Sandreas.sandberg@arm.com } 30410844Sandreas.sandberg@arm.com} 30510844Sandreas.sandberg@arm.com 30610844Sandreas.sandberg@arm.com 30710844Sandreas.sandberg@arm.comvoid 30810844Sandreas.sandberg@arm.comGenericTimer::setMiscReg(int reg, unsigned cpu, MiscReg val) 30910844Sandreas.sandberg@arm.com{ 31011933Sandreas.sandberg@arm.com // This method might have been called from another context if we 31111933Sandreas.sandberg@arm.com // are running in multi-core KVM. Migrate to the SimObject's event 31211933Sandreas.sandberg@arm.com // queue to prevent surprising race conditions. 31311933Sandreas.sandberg@arm.com EventQueue::ScopedMigration migrate(eventQueue()); 31411933Sandreas.sandberg@arm.com 31510844Sandreas.sandberg@arm.com CoreTimers &core(getTimers(cpu)); 31610844Sandreas.sandberg@arm.com 31710844Sandreas.sandberg@arm.com switch (reg) { 31810844Sandreas.sandberg@arm.com case MISCREG_CNTFRQ: 31910844Sandreas.sandberg@arm.com case MISCREG_CNTFRQ_EL0: 32010844Sandreas.sandberg@arm.com systemCounter.setFreq(val); 32110844Sandreas.sandberg@arm.com return; 32210844Sandreas.sandberg@arm.com 32310844Sandreas.sandberg@arm.com case MISCREG_CNTKCTL: 32410844Sandreas.sandberg@arm.com case MISCREG_CNTKCTL_EL1: 32510844Sandreas.sandberg@arm.com systemCounter.setKernelControl(val); 32610844Sandreas.sandberg@arm.com return; 32710844Sandreas.sandberg@arm.com 32810844Sandreas.sandberg@arm.com // Physical timer 32910844Sandreas.sandberg@arm.com case MISCREG_CNTP_CVAL: 33010844Sandreas.sandberg@arm.com case MISCREG_CNTP_CVAL_NS: 33110844Sandreas.sandberg@arm.com case MISCREG_CNTP_CVAL_EL0: 33210844Sandreas.sandberg@arm.com core.phys.setCompareValue(val); 33310844Sandreas.sandberg@arm.com return; 33410844Sandreas.sandberg@arm.com 33510844Sandreas.sandberg@arm.com case MISCREG_CNTP_TVAL: 33610844Sandreas.sandberg@arm.com case MISCREG_CNTP_TVAL_NS: 33710844Sandreas.sandberg@arm.com case MISCREG_CNTP_TVAL_EL0: 33810844Sandreas.sandberg@arm.com core.phys.setTimerValue(val); 33910844Sandreas.sandberg@arm.com return; 34010844Sandreas.sandberg@arm.com 34110844Sandreas.sandberg@arm.com case MISCREG_CNTP_CTL: 34210844Sandreas.sandberg@arm.com case MISCREG_CNTP_CTL_NS: 34310844Sandreas.sandberg@arm.com case MISCREG_CNTP_CTL_EL0: 34410844Sandreas.sandberg@arm.com core.phys.setControl(val); 34510844Sandreas.sandberg@arm.com return; 34610844Sandreas.sandberg@arm.com 34710844Sandreas.sandberg@arm.com // Count registers 34810844Sandreas.sandberg@arm.com case MISCREG_CNTPCT: 34910844Sandreas.sandberg@arm.com case MISCREG_CNTPCT_EL0: 35010844Sandreas.sandberg@arm.com case MISCREG_CNTVCT: 35110844Sandreas.sandberg@arm.com case MISCREG_CNTVCT_EL0: 35210844Sandreas.sandberg@arm.com warn("Ignoring write to read only count register: %s\n", 35310844Sandreas.sandberg@arm.com miscRegName[reg]); 35410844Sandreas.sandberg@arm.com return; 35510844Sandreas.sandberg@arm.com 35610844Sandreas.sandberg@arm.com // Virtual timer 35710844Sandreas.sandberg@arm.com case MISCREG_CNTVOFF: 35810844Sandreas.sandberg@arm.com case MISCREG_CNTVOFF_EL2: 35910845Sandreas.sandberg@arm.com core.virt.setOffset(val); 36010845Sandreas.sandberg@arm.com return; 36110845Sandreas.sandberg@arm.com 36210844Sandreas.sandberg@arm.com case MISCREG_CNTV_CVAL: 36310844Sandreas.sandberg@arm.com case MISCREG_CNTV_CVAL_EL0: 36410845Sandreas.sandberg@arm.com core.virt.setCompareValue(val); 36510845Sandreas.sandberg@arm.com return; 36610845Sandreas.sandberg@arm.com 36710844Sandreas.sandberg@arm.com case MISCREG_CNTV_TVAL: 36810844Sandreas.sandberg@arm.com case MISCREG_CNTV_TVAL_EL0: 36910845Sandreas.sandberg@arm.com core.virt.setTimerValue(val); 37010845Sandreas.sandberg@arm.com return; 37110845Sandreas.sandberg@arm.com 37210844Sandreas.sandberg@arm.com case MISCREG_CNTV_CTL: 37310844Sandreas.sandberg@arm.com case MISCREG_CNTV_CTL_EL0: 37410845Sandreas.sandberg@arm.com core.virt.setControl(val); 37510845Sandreas.sandberg@arm.com return; 37610844Sandreas.sandberg@arm.com 37710844Sandreas.sandberg@arm.com // PL1 phys. timer, secure 37810844Sandreas.sandberg@arm.com case MISCREG_CNTP_CTL_S: 37910844Sandreas.sandberg@arm.com case MISCREG_CNTPS_CVAL_EL1: 38010844Sandreas.sandberg@arm.com case MISCREG_CNTPS_TVAL_EL1: 38110844Sandreas.sandberg@arm.com case MISCREG_CNTPS_CTL_EL1: 38210844Sandreas.sandberg@arm.com /* FALLTHROUGH */ 38310844Sandreas.sandberg@arm.com 38410844Sandreas.sandberg@arm.com // PL2 phys. timer, non-secure 38510844Sandreas.sandberg@arm.com case MISCREG_CNTHCTL: 38610844Sandreas.sandberg@arm.com case MISCREG_CNTHCTL_EL2: 38710844Sandreas.sandberg@arm.com case MISCREG_CNTHP_CVAL: 38810844Sandreas.sandberg@arm.com case MISCREG_CNTHP_CVAL_EL2: 38910844Sandreas.sandberg@arm.com case MISCREG_CNTHP_TVAL: 39010844Sandreas.sandberg@arm.com case MISCREG_CNTHP_TVAL_EL2: 39110844Sandreas.sandberg@arm.com case MISCREG_CNTHP_CTL: 39210844Sandreas.sandberg@arm.com case MISCREG_CNTHP_CTL_EL2: 39310844Sandreas.sandberg@arm.com warn("Writing to unimplemented register: %s\n", 39410844Sandreas.sandberg@arm.com miscRegName[reg]); 39510844Sandreas.sandberg@arm.com return; 39610844Sandreas.sandberg@arm.com 39710844Sandreas.sandberg@arm.com default: 39810844Sandreas.sandberg@arm.com warn("Writing to unknown register: %s\n", miscRegName[reg]); 39910844Sandreas.sandberg@arm.com return; 40010844Sandreas.sandberg@arm.com } 40110844Sandreas.sandberg@arm.com} 40210844Sandreas.sandberg@arm.com 40310844Sandreas.sandberg@arm.com 40410844Sandreas.sandberg@arm.comMiscReg 40510844Sandreas.sandberg@arm.comGenericTimer::readMiscReg(int reg, unsigned cpu) 40610844Sandreas.sandberg@arm.com{ 40711933Sandreas.sandberg@arm.com // This method might have been called from another context if we 40811933Sandreas.sandberg@arm.com // are running in multi-core KVM. Migrate to the SimObject's event 40911933Sandreas.sandberg@arm.com // queue to prevent surprising race conditions. 41011933Sandreas.sandberg@arm.com EventQueue::ScopedMigration migrate(eventQueue()); 41111933Sandreas.sandberg@arm.com 41210844Sandreas.sandberg@arm.com CoreTimers &core(getTimers(cpu)); 41310844Sandreas.sandberg@arm.com 41410844Sandreas.sandberg@arm.com switch (reg) { 41510844Sandreas.sandberg@arm.com case MISCREG_CNTFRQ: 41610844Sandreas.sandberg@arm.com case MISCREG_CNTFRQ_EL0: 41710844Sandreas.sandberg@arm.com return systemCounter.freq(); 41810844Sandreas.sandberg@arm.com 41910844Sandreas.sandberg@arm.com case MISCREG_CNTKCTL: 42010844Sandreas.sandberg@arm.com case MISCREG_CNTKCTL_EL1: 42110844Sandreas.sandberg@arm.com return systemCounter.getKernelControl(); 42210844Sandreas.sandberg@arm.com 42310844Sandreas.sandberg@arm.com // Physical timer 42410844Sandreas.sandberg@arm.com case MISCREG_CNTP_CVAL: 42510844Sandreas.sandberg@arm.com case MISCREG_CNTP_CVAL_EL0: 42610844Sandreas.sandberg@arm.com return core.phys.compareValue(); 42710844Sandreas.sandberg@arm.com 42810844Sandreas.sandberg@arm.com case MISCREG_CNTP_TVAL: 42910844Sandreas.sandberg@arm.com case MISCREG_CNTP_TVAL_EL0: 43010844Sandreas.sandberg@arm.com return core.phys.timerValue(); 43110844Sandreas.sandberg@arm.com 43210844Sandreas.sandberg@arm.com case MISCREG_CNTP_CTL: 43310844Sandreas.sandberg@arm.com case MISCREG_CNTP_CTL_EL0: 43410844Sandreas.sandberg@arm.com case MISCREG_CNTP_CTL_NS: 43510844Sandreas.sandberg@arm.com return core.phys.control(); 43610844Sandreas.sandberg@arm.com 43710844Sandreas.sandberg@arm.com case MISCREG_CNTPCT: 43810844Sandreas.sandberg@arm.com case MISCREG_CNTPCT_EL0: 43910844Sandreas.sandberg@arm.com return core.phys.value(); 44010844Sandreas.sandberg@arm.com 44110844Sandreas.sandberg@arm.com 44210844Sandreas.sandberg@arm.com // Virtual timer 44310844Sandreas.sandberg@arm.com case MISCREG_CNTVCT: 44410844Sandreas.sandberg@arm.com case MISCREG_CNTVCT_EL0: 44510845Sandreas.sandberg@arm.com return core.virt.value(); 44610844Sandreas.sandberg@arm.com 44710844Sandreas.sandberg@arm.com case MISCREG_CNTVOFF: 44810844Sandreas.sandberg@arm.com case MISCREG_CNTVOFF_EL2: 44910845Sandreas.sandberg@arm.com return core.virt.offset(); 45010845Sandreas.sandberg@arm.com 45110844Sandreas.sandberg@arm.com case MISCREG_CNTV_CVAL: 45210844Sandreas.sandberg@arm.com case MISCREG_CNTV_CVAL_EL0: 45310845Sandreas.sandberg@arm.com return core.virt.compareValue(); 45410845Sandreas.sandberg@arm.com 45510844Sandreas.sandberg@arm.com case MISCREG_CNTV_TVAL: 45610844Sandreas.sandberg@arm.com case MISCREG_CNTV_TVAL_EL0: 45710845Sandreas.sandberg@arm.com return core.virt.timerValue(); 45810845Sandreas.sandberg@arm.com 45910844Sandreas.sandberg@arm.com case MISCREG_CNTV_CTL: 46010844Sandreas.sandberg@arm.com case MISCREG_CNTV_CTL_EL0: 46110845Sandreas.sandberg@arm.com return core.virt.control(); 46210844Sandreas.sandberg@arm.com 46310844Sandreas.sandberg@arm.com // PL1 phys. timer, secure 46410844Sandreas.sandberg@arm.com case MISCREG_CNTP_CTL_S: 46510844Sandreas.sandberg@arm.com case MISCREG_CNTPS_CVAL_EL1: 46610844Sandreas.sandberg@arm.com case MISCREG_CNTPS_TVAL_EL1: 46710844Sandreas.sandberg@arm.com case MISCREG_CNTPS_CTL_EL1: 46810844Sandreas.sandberg@arm.com /* FALLTHROUGH */ 46910844Sandreas.sandberg@arm.com 47010844Sandreas.sandberg@arm.com // PL2 phys. timer, non-secure 47110844Sandreas.sandberg@arm.com case MISCREG_CNTHCTL: 47210844Sandreas.sandberg@arm.com case MISCREG_CNTHCTL_EL2: 47310844Sandreas.sandberg@arm.com case MISCREG_CNTHP_CVAL: 47410844Sandreas.sandberg@arm.com case MISCREG_CNTHP_CVAL_EL2: 47510844Sandreas.sandberg@arm.com case MISCREG_CNTHP_TVAL: 47610844Sandreas.sandberg@arm.com case MISCREG_CNTHP_TVAL_EL2: 47710844Sandreas.sandberg@arm.com case MISCREG_CNTHP_CTL: 47810844Sandreas.sandberg@arm.com case MISCREG_CNTHP_CTL_EL2: 47910844Sandreas.sandberg@arm.com warn("Reading from unimplemented register: %s\n", 48010844Sandreas.sandberg@arm.com miscRegName[reg]); 48110844Sandreas.sandberg@arm.com return 0; 48210844Sandreas.sandberg@arm.com 48310844Sandreas.sandberg@arm.com 48410844Sandreas.sandberg@arm.com default: 48510844Sandreas.sandberg@arm.com warn("Reading from unknown register: %s\n", miscRegName[reg]); 48610844Sandreas.sandberg@arm.com return 0; 48710844Sandreas.sandberg@arm.com } 48810844Sandreas.sandberg@arm.com} 48910844Sandreas.sandberg@arm.com 49010844Sandreas.sandberg@arm.com 49110847Sandreas.sandberg@arm.com 49210847Sandreas.sandberg@arm.comGenericTimerMem::GenericTimerMem(GenericTimerMemParams *p) 49310847Sandreas.sandberg@arm.com : PioDevice(p), 49410847Sandreas.sandberg@arm.com ctrlRange(RangeSize(p->base, TheISA::PageBytes)), 49510847Sandreas.sandberg@arm.com timerRange(RangeSize(p->base + TheISA::PageBytes, TheISA::PageBytes)), 49610847Sandreas.sandberg@arm.com addrRanges{ctrlRange, timerRange}, 49710847Sandreas.sandberg@arm.com systemCounter(), 49810847Sandreas.sandberg@arm.com physTimer(csprintf("%s.phys_timer0", name()), 49910847Sandreas.sandberg@arm.com *this, systemCounter, 50010847Sandreas.sandberg@arm.com ArchTimer::Interrupt(*p->gic, p->int_phys)), 50110847Sandreas.sandberg@arm.com virtTimer(csprintf("%s.virt_timer0", name()), 50210847Sandreas.sandberg@arm.com *this, systemCounter, 50310847Sandreas.sandberg@arm.com ArchTimer::Interrupt(*p->gic, p->int_virt)) 50410847Sandreas.sandberg@arm.com{ 50510847Sandreas.sandberg@arm.com} 50610847Sandreas.sandberg@arm.com 50710847Sandreas.sandberg@arm.comvoid 50810905Sandreas.sandberg@arm.comGenericTimerMem::serialize(CheckpointOut &cp) const 50910847Sandreas.sandberg@arm.com{ 51010905Sandreas.sandberg@arm.com paramOut(cp, "timer_count", 1); 51110847Sandreas.sandberg@arm.com 51210905Sandreas.sandberg@arm.com systemCounter.serializeSection(cp, "sys_counter"); 51310847Sandreas.sandberg@arm.com 51410905Sandreas.sandberg@arm.com physTimer.serializeSection(cp, "phys_timer0"); 51510905Sandreas.sandberg@arm.com virtTimer.serializeSection(cp, "virt_timer0"); 51610847Sandreas.sandberg@arm.com} 51710847Sandreas.sandberg@arm.com 51810847Sandreas.sandberg@arm.comvoid 51910905Sandreas.sandberg@arm.comGenericTimerMem::unserialize(CheckpointIn &cp) 52010847Sandreas.sandberg@arm.com{ 52110905Sandreas.sandberg@arm.com systemCounter.unserializeSection(cp, "sys_counter"); 52210847Sandreas.sandberg@arm.com 52310847Sandreas.sandberg@arm.com unsigned timer_count; 52410847Sandreas.sandberg@arm.com UNSERIALIZE_SCALAR(timer_count); 52510847Sandreas.sandberg@arm.com // The timer count variable is just here for future versions where 52610847Sandreas.sandberg@arm.com // we support more than one set of timers. 52710847Sandreas.sandberg@arm.com if (timer_count != 1) 52810847Sandreas.sandberg@arm.com panic("Incompatible checkpoint: Only one set of timers supported"); 52910847Sandreas.sandberg@arm.com 53010905Sandreas.sandberg@arm.com physTimer.unserializeSection(cp, "phys_timer0"); 53110905Sandreas.sandberg@arm.com virtTimer.unserializeSection(cp, "virt_timer0"); 53210847Sandreas.sandberg@arm.com} 53310847Sandreas.sandberg@arm.com 53410847Sandreas.sandberg@arm.comTick 53510847Sandreas.sandberg@arm.comGenericTimerMem::read(PacketPtr pkt) 53610847Sandreas.sandberg@arm.com{ 53710847Sandreas.sandberg@arm.com const unsigned size(pkt->getSize()); 53810847Sandreas.sandberg@arm.com const Addr addr(pkt->getAddr()); 53910847Sandreas.sandberg@arm.com uint64_t value; 54010847Sandreas.sandberg@arm.com 54110847Sandreas.sandberg@arm.com pkt->makeResponse(); 54210847Sandreas.sandberg@arm.com if (ctrlRange.contains(addr)) { 54310847Sandreas.sandberg@arm.com value = ctrlRead(addr - ctrlRange.start(), size); 54410847Sandreas.sandberg@arm.com } else if (timerRange.contains(addr)) { 54510847Sandreas.sandberg@arm.com value = timerRead(addr - timerRange.start(), size); 54610847Sandreas.sandberg@arm.com } else { 54710847Sandreas.sandberg@arm.com panic("Invalid address: 0x%x\n", addr); 54810847Sandreas.sandberg@arm.com } 54910847Sandreas.sandberg@arm.com 55010847Sandreas.sandberg@arm.com DPRINTF(Timer, "Read 0x%x <- 0x%x(%i)\n", value, addr, size); 55110847Sandreas.sandberg@arm.com 55210847Sandreas.sandberg@arm.com if (size == 8) { 55310847Sandreas.sandberg@arm.com pkt->set<uint64_t>(value); 55410847Sandreas.sandberg@arm.com } else if (size == 4) { 55510847Sandreas.sandberg@arm.com pkt->set<uint32_t>(value); 55610847Sandreas.sandberg@arm.com } else { 55710847Sandreas.sandberg@arm.com panic("Unexpected access size: %i\n", size); 55810847Sandreas.sandberg@arm.com } 55910847Sandreas.sandberg@arm.com 56010847Sandreas.sandberg@arm.com return 0; 56110847Sandreas.sandberg@arm.com} 56210847Sandreas.sandberg@arm.com 56310847Sandreas.sandberg@arm.comTick 56410847Sandreas.sandberg@arm.comGenericTimerMem::write(PacketPtr pkt) 56510847Sandreas.sandberg@arm.com{ 56610847Sandreas.sandberg@arm.com const unsigned size(pkt->getSize()); 56710847Sandreas.sandberg@arm.com if (size != 8 && size != 4) 56810847Sandreas.sandberg@arm.com panic("Unexpected access size\n"); 56910847Sandreas.sandberg@arm.com 57010847Sandreas.sandberg@arm.com const Addr addr(pkt->getAddr()); 57110847Sandreas.sandberg@arm.com const uint64_t value(size == 8 ? 57210847Sandreas.sandberg@arm.com pkt->get<uint64_t>() : pkt->get<uint32_t>()); 57310847Sandreas.sandberg@arm.com 57410847Sandreas.sandberg@arm.com DPRINTF(Timer, "Write 0x%x -> 0x%x(%i)\n", value, addr, size); 57510847Sandreas.sandberg@arm.com if (ctrlRange.contains(addr)) { 57610847Sandreas.sandberg@arm.com ctrlWrite(addr - ctrlRange.start(), size, value); 57710847Sandreas.sandberg@arm.com } else if (timerRange.contains(addr)) { 57810847Sandreas.sandberg@arm.com timerWrite(addr - timerRange.start(), size, value); 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 pkt->makeResponse(); 58410847Sandreas.sandberg@arm.com return 0; 58510847Sandreas.sandberg@arm.com} 58610847Sandreas.sandberg@arm.com 58710847Sandreas.sandberg@arm.comuint64_t 58810847Sandreas.sandberg@arm.comGenericTimerMem::ctrlRead(Addr addr, size_t size) const 58910847Sandreas.sandberg@arm.com{ 59010847Sandreas.sandberg@arm.com if (size == 4) { 59110847Sandreas.sandberg@arm.com switch (addr) { 59210847Sandreas.sandberg@arm.com case CTRL_CNTFRQ: 59310847Sandreas.sandberg@arm.com return systemCounter.freq(); 59410847Sandreas.sandberg@arm.com 59510847Sandreas.sandberg@arm.com case CTRL_CNTTIDR: 59610847Sandreas.sandberg@arm.com return 0x3; // Frame 0 implemented with virtual timers 59710847Sandreas.sandberg@arm.com 59810847Sandreas.sandberg@arm.com case CTRL_CNTNSAR: 59910847Sandreas.sandberg@arm.com case CTRL_CNTACR_BASE: 60010847Sandreas.sandberg@arm.com warn("Reading from unimplemented control register (0x%x)\n", addr); 60110847Sandreas.sandberg@arm.com return 0; 60210847Sandreas.sandberg@arm.com 60310847Sandreas.sandberg@arm.com case CTRL_CNTVOFF_LO_BASE: 60410847Sandreas.sandberg@arm.com return virtTimer.offset(); 60510847Sandreas.sandberg@arm.com 60610847Sandreas.sandberg@arm.com case CTRL_CNTVOFF_HI_BASE: 60710847Sandreas.sandberg@arm.com return virtTimer.offset() >> 32; 60810847Sandreas.sandberg@arm.com 60910847Sandreas.sandberg@arm.com default: 61010847Sandreas.sandberg@arm.com warn("Unexpected address (0x%x:%i), assuming RAZ\n", addr, size); 61110847Sandreas.sandberg@arm.com return 0; 61210847Sandreas.sandberg@arm.com } 61310847Sandreas.sandberg@arm.com } else if (size == 8) { 61410847Sandreas.sandberg@arm.com switch (addr) { 61510847Sandreas.sandberg@arm.com case CTRL_CNTVOFF_LO_BASE: 61610847Sandreas.sandberg@arm.com return virtTimer.offset(); 61710847Sandreas.sandberg@arm.com 61810847Sandreas.sandberg@arm.com default: 61910847Sandreas.sandberg@arm.com warn("Unexpected address (0x%x:%i), assuming RAZ\n", addr, size); 62010847Sandreas.sandberg@arm.com return 0; 62110847Sandreas.sandberg@arm.com } 62210847Sandreas.sandberg@arm.com } else { 62310847Sandreas.sandberg@arm.com panic("Invalid access size: %i\n", size); 62410847Sandreas.sandberg@arm.com } 62510847Sandreas.sandberg@arm.com} 62610847Sandreas.sandberg@arm.com 62710847Sandreas.sandberg@arm.comvoid 62810847Sandreas.sandberg@arm.comGenericTimerMem::ctrlWrite(Addr addr, size_t size, uint64_t value) 62910847Sandreas.sandberg@arm.com{ 63010847Sandreas.sandberg@arm.com if (size == 4) { 63110847Sandreas.sandberg@arm.com switch (addr) { 63210847Sandreas.sandberg@arm.com case CTRL_CNTFRQ: 63310847Sandreas.sandberg@arm.com case CTRL_CNTNSAR: 63410847Sandreas.sandberg@arm.com case CTRL_CNTTIDR: 63510847Sandreas.sandberg@arm.com case CTRL_CNTACR_BASE: 63610847Sandreas.sandberg@arm.com warn("Write to unimplemented control register (0x%x)\n", addr); 63710847Sandreas.sandberg@arm.com return; 63810847Sandreas.sandberg@arm.com 63910847Sandreas.sandberg@arm.com case CTRL_CNTVOFF_LO_BASE: 64010847Sandreas.sandberg@arm.com virtTimer.setOffset( 64110847Sandreas.sandberg@arm.com insertBits(virtTimer.offset(), 31, 0, value)); 64210847Sandreas.sandberg@arm.com return; 64310847Sandreas.sandberg@arm.com 64410847Sandreas.sandberg@arm.com case CTRL_CNTVOFF_HI_BASE: 64510847Sandreas.sandberg@arm.com virtTimer.setOffset( 64610847Sandreas.sandberg@arm.com insertBits(virtTimer.offset(), 63, 32, value)); 64710847Sandreas.sandberg@arm.com return; 64810847Sandreas.sandberg@arm.com 64910847Sandreas.sandberg@arm.com default: 65010847Sandreas.sandberg@arm.com warn("Ignoring write to unexpected address (0x%x:%i)\n", 65110847Sandreas.sandberg@arm.com addr, size); 65210847Sandreas.sandberg@arm.com return; 65310847Sandreas.sandberg@arm.com } 65410847Sandreas.sandberg@arm.com } else if (size == 8) { 65510847Sandreas.sandberg@arm.com switch (addr) { 65610847Sandreas.sandberg@arm.com case CTRL_CNTVOFF_LO_BASE: 65710847Sandreas.sandberg@arm.com virtTimer.setOffset(value); 65810847Sandreas.sandberg@arm.com return; 65910847Sandreas.sandberg@arm.com 66010847Sandreas.sandberg@arm.com default: 66110847Sandreas.sandberg@arm.com warn("Ignoring write to unexpected address (0x%x:%i)\n", 66210847Sandreas.sandberg@arm.com addr, size); 66310847Sandreas.sandberg@arm.com return; 66410847Sandreas.sandberg@arm.com } 66510847Sandreas.sandberg@arm.com } else { 66610847Sandreas.sandberg@arm.com panic("Invalid access size: %i\n", size); 66710847Sandreas.sandberg@arm.com } 66810847Sandreas.sandberg@arm.com} 66910847Sandreas.sandberg@arm.com 67010847Sandreas.sandberg@arm.comuint64_t 67110847Sandreas.sandberg@arm.comGenericTimerMem::timerRead(Addr addr, size_t size) const 67210847Sandreas.sandberg@arm.com{ 67310847Sandreas.sandberg@arm.com if (size == 4) { 67410847Sandreas.sandberg@arm.com switch (addr) { 67510847Sandreas.sandberg@arm.com case TIMER_CNTPCT_LO: 67610847Sandreas.sandberg@arm.com return physTimer.value(); 67710847Sandreas.sandberg@arm.com 67810847Sandreas.sandberg@arm.com case TIMER_CNTPCT_HI: 67910847Sandreas.sandberg@arm.com return physTimer.value() >> 32; 68010847Sandreas.sandberg@arm.com 68110847Sandreas.sandberg@arm.com case TIMER_CNTVCT_LO: 68210847Sandreas.sandberg@arm.com return virtTimer.value(); 68310847Sandreas.sandberg@arm.com 68410847Sandreas.sandberg@arm.com case TIMER_CNTVCT_HI: 68510847Sandreas.sandberg@arm.com return virtTimer.value() >> 32; 68610847Sandreas.sandberg@arm.com 68710847Sandreas.sandberg@arm.com case TIMER_CNTFRQ: 68810847Sandreas.sandberg@arm.com return systemCounter.freq(); 68910847Sandreas.sandberg@arm.com 69010847Sandreas.sandberg@arm.com case TIMER_CNTEL0ACR: 69110847Sandreas.sandberg@arm.com warn("Read from unimplemented timer register (0x%x)\n", addr); 69210847Sandreas.sandberg@arm.com return 0; 69310847Sandreas.sandberg@arm.com 69410847Sandreas.sandberg@arm.com case CTRL_CNTVOFF_LO_BASE: 69510847Sandreas.sandberg@arm.com return virtTimer.offset(); 69610847Sandreas.sandberg@arm.com 69710847Sandreas.sandberg@arm.com case CTRL_CNTVOFF_HI_BASE: 69810847Sandreas.sandberg@arm.com return virtTimer.offset() >> 32; 69910847Sandreas.sandberg@arm.com 70010847Sandreas.sandberg@arm.com case TIMER_CNTP_CVAL_LO: 70110847Sandreas.sandberg@arm.com return physTimer.compareValue(); 70210847Sandreas.sandberg@arm.com 70310847Sandreas.sandberg@arm.com case TIMER_CNTP_CVAL_HI: 70410847Sandreas.sandberg@arm.com return physTimer.compareValue() >> 32; 70510847Sandreas.sandberg@arm.com 70610847Sandreas.sandberg@arm.com case TIMER_CNTP_TVAL: 70710847Sandreas.sandberg@arm.com return physTimer.timerValue(); 70810847Sandreas.sandberg@arm.com 70910847Sandreas.sandberg@arm.com case TIMER_CNTP_CTL: 71010847Sandreas.sandberg@arm.com return physTimer.control(); 71110847Sandreas.sandberg@arm.com 71210847Sandreas.sandberg@arm.com case TIMER_CNTV_CVAL_LO: 71310847Sandreas.sandberg@arm.com return virtTimer.compareValue(); 71410847Sandreas.sandberg@arm.com 71510847Sandreas.sandberg@arm.com case TIMER_CNTV_CVAL_HI: 71610847Sandreas.sandberg@arm.com return virtTimer.compareValue() >> 32; 71710847Sandreas.sandberg@arm.com 71810847Sandreas.sandberg@arm.com case TIMER_CNTV_TVAL: 71910847Sandreas.sandberg@arm.com return virtTimer.timerValue(); 72010847Sandreas.sandberg@arm.com 72110847Sandreas.sandberg@arm.com case TIMER_CNTV_CTL: 72210847Sandreas.sandberg@arm.com return virtTimer.control(); 72310847Sandreas.sandberg@arm.com 72410847Sandreas.sandberg@arm.com default: 72510847Sandreas.sandberg@arm.com warn("Unexpected address (0x%x:%i), assuming RAZ\n", addr, size); 72610847Sandreas.sandberg@arm.com return 0; 72710847Sandreas.sandberg@arm.com } 72810847Sandreas.sandberg@arm.com } else if (size == 8) { 72910847Sandreas.sandberg@arm.com switch (addr) { 73010847Sandreas.sandberg@arm.com case TIMER_CNTPCT_LO: 73110847Sandreas.sandberg@arm.com return physTimer.value(); 73210847Sandreas.sandberg@arm.com 73310847Sandreas.sandberg@arm.com case TIMER_CNTVCT_LO: 73410847Sandreas.sandberg@arm.com return virtTimer.value(); 73510847Sandreas.sandberg@arm.com 73610847Sandreas.sandberg@arm.com case CTRL_CNTVOFF_LO_BASE: 73710847Sandreas.sandberg@arm.com return virtTimer.offset(); 73810847Sandreas.sandberg@arm.com 73910847Sandreas.sandberg@arm.com case TIMER_CNTP_CVAL_LO: 74010847Sandreas.sandberg@arm.com return physTimer.compareValue(); 74110847Sandreas.sandberg@arm.com 74210847Sandreas.sandberg@arm.com case TIMER_CNTV_CVAL_LO: 74310847Sandreas.sandberg@arm.com return virtTimer.compareValue(); 74410847Sandreas.sandberg@arm.com 74510847Sandreas.sandberg@arm.com default: 74610847Sandreas.sandberg@arm.com warn("Unexpected address (0x%x:%i), assuming RAZ\n", addr, size); 74710847Sandreas.sandberg@arm.com return 0; 74810847Sandreas.sandberg@arm.com } 74910847Sandreas.sandberg@arm.com } else { 75010847Sandreas.sandberg@arm.com panic("Invalid access size: %i\n", size); 75110847Sandreas.sandberg@arm.com } 75210847Sandreas.sandberg@arm.com} 75310847Sandreas.sandberg@arm.com 75410847Sandreas.sandberg@arm.comvoid 75510847Sandreas.sandberg@arm.comGenericTimerMem::timerWrite(Addr addr, size_t size, uint64_t value) 75610847Sandreas.sandberg@arm.com{ 75710847Sandreas.sandberg@arm.com if (size == 4) { 75810847Sandreas.sandberg@arm.com switch (addr) { 75910847Sandreas.sandberg@arm.com case TIMER_CNTEL0ACR: 76010847Sandreas.sandberg@arm.com warn("Unimplemented timer register (0x%x)\n", addr); 76110847Sandreas.sandberg@arm.com return; 76210847Sandreas.sandberg@arm.com 76310847Sandreas.sandberg@arm.com case TIMER_CNTP_CVAL_LO: 76410847Sandreas.sandberg@arm.com physTimer.setCompareValue( 76510847Sandreas.sandberg@arm.com insertBits(physTimer.compareValue(), 31, 0, value)); 76610847Sandreas.sandberg@arm.com return; 76710847Sandreas.sandberg@arm.com 76810847Sandreas.sandberg@arm.com case TIMER_CNTP_CVAL_HI: 76910847Sandreas.sandberg@arm.com physTimer.setCompareValue( 77010847Sandreas.sandberg@arm.com insertBits(physTimer.compareValue(), 63, 32, value)); 77110847Sandreas.sandberg@arm.com return; 77210847Sandreas.sandberg@arm.com 77310847Sandreas.sandberg@arm.com case TIMER_CNTP_TVAL: 77410847Sandreas.sandberg@arm.com physTimer.setTimerValue(value); 77510847Sandreas.sandberg@arm.com return; 77610847Sandreas.sandberg@arm.com 77710847Sandreas.sandberg@arm.com case TIMER_CNTP_CTL: 77810847Sandreas.sandberg@arm.com physTimer.setControl(value); 77910847Sandreas.sandberg@arm.com return; 78010847Sandreas.sandberg@arm.com 78110847Sandreas.sandberg@arm.com case TIMER_CNTV_CVAL_LO: 78210847Sandreas.sandberg@arm.com virtTimer.setCompareValue( 78310847Sandreas.sandberg@arm.com insertBits(virtTimer.compareValue(), 31, 0, value)); 78410847Sandreas.sandberg@arm.com return; 78510847Sandreas.sandberg@arm.com 78610847Sandreas.sandberg@arm.com case TIMER_CNTV_CVAL_HI: 78710847Sandreas.sandberg@arm.com virtTimer.setCompareValue( 78810847Sandreas.sandberg@arm.com insertBits(virtTimer.compareValue(), 63, 32, value)); 78910847Sandreas.sandberg@arm.com return; 79010847Sandreas.sandberg@arm.com 79110847Sandreas.sandberg@arm.com case TIMER_CNTV_TVAL: 79210847Sandreas.sandberg@arm.com virtTimer.setTimerValue(value); 79310847Sandreas.sandberg@arm.com return; 79410847Sandreas.sandberg@arm.com 79510847Sandreas.sandberg@arm.com case TIMER_CNTV_CTL: 79610847Sandreas.sandberg@arm.com virtTimer.setControl(value); 79710847Sandreas.sandberg@arm.com return; 79810847Sandreas.sandberg@arm.com 79910847Sandreas.sandberg@arm.com default: 80010847Sandreas.sandberg@arm.com warn("Unexpected address (0x%x:%i), ignoring write\n", addr, size); 80110847Sandreas.sandberg@arm.com return; 80210847Sandreas.sandberg@arm.com } 80310847Sandreas.sandberg@arm.com } else if (size == 8) { 80410847Sandreas.sandberg@arm.com switch (addr) { 80510847Sandreas.sandberg@arm.com case TIMER_CNTP_CVAL_LO: 80610847Sandreas.sandberg@arm.com return physTimer.setCompareValue(value); 80710847Sandreas.sandberg@arm.com 80810847Sandreas.sandberg@arm.com case TIMER_CNTV_CVAL_LO: 80910847Sandreas.sandberg@arm.com return virtTimer.setCompareValue(value); 81010847Sandreas.sandberg@arm.com 81110847Sandreas.sandberg@arm.com default: 81210847Sandreas.sandberg@arm.com warn("Unexpected address (0x%x:%i), ignoring write\n", addr, size); 81310847Sandreas.sandberg@arm.com return; 81410847Sandreas.sandberg@arm.com } 81510847Sandreas.sandberg@arm.com } else { 81610847Sandreas.sandberg@arm.com panic("Invalid access size: %i\n", size); 81710847Sandreas.sandberg@arm.com } 81810847Sandreas.sandberg@arm.com} 81910847Sandreas.sandberg@arm.com 82010037SARM gem5 DevelopersGenericTimer * 82110037SARM gem5 DevelopersGenericTimerParams::create() 82210037SARM gem5 Developers{ 82310037SARM gem5 Developers return new GenericTimer(this); 82410037SARM gem5 Developers} 82510847Sandreas.sandberg@arm.com 82610847Sandreas.sandberg@arm.comGenericTimerMem * 82710847Sandreas.sandberg@arm.comGenericTimerMemParams::create() 82810847Sandreas.sandberg@arm.com{ 82910847Sandreas.sandberg@arm.com return new GenericTimerMem(this); 83010847Sandreas.sandberg@arm.com} 831