generic_timer.cc revision 13557:fc33e6048b25
113996Sgiacomo.travaglini@arm.com/* 213996Sgiacomo.travaglini@arm.com * Copyright (c) 2013, 2015, 2017-2018 ARM Limited 313996Sgiacomo.travaglini@arm.com * All rights reserved. 413996Sgiacomo.travaglini@arm.com * 513996Sgiacomo.travaglini@arm.com * The license below extends only to copyright in the software and shall 613996Sgiacomo.travaglini@arm.com * not be construed as granting a license to any other intellectual 713996Sgiacomo.travaglini@arm.com * property including but not limited to intellectual property relating 813996Sgiacomo.travaglini@arm.com * to a hardware implementation of the functionality of the software 913996Sgiacomo.travaglini@arm.com * licensed hereunder. You may use the software subject to the license 1013996Sgiacomo.travaglini@arm.com * terms below provided that you ensure that this notice is replicated 1113996Sgiacomo.travaglini@arm.com * unmodified and in its entirety in all distributions of the software, 1213996Sgiacomo.travaglini@arm.com * modified or unmodified, in source code or in binary form. 1313996Sgiacomo.travaglini@arm.com * 1413996Sgiacomo.travaglini@arm.com * Redistribution and use in source and binary forms, with or without 1513996Sgiacomo.travaglini@arm.com * modification, are permitted provided that the following conditions are 1613996Sgiacomo.travaglini@arm.com * met: redistributions of source code must retain the above copyright 1713996Sgiacomo.travaglini@arm.com * notice, this list of conditions and the following disclaimer; 1813996Sgiacomo.travaglini@arm.com * redistributions in binary form must reproduce the above copyright 1913996Sgiacomo.travaglini@arm.com * notice, this list of conditions and the following disclaimer in the 2013996Sgiacomo.travaglini@arm.com * documentation and/or other materials provided with the distribution; 2113996Sgiacomo.travaglini@arm.com * neither the name of the copyright holders nor the names of its 2213996Sgiacomo.travaglini@arm.com * contributors may be used to endorse or promote products derived from 2313996Sgiacomo.travaglini@arm.com * this software without specific prior written permission. 2413996Sgiacomo.travaglini@arm.com * 2513996Sgiacomo.travaglini@arm.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 2613996Sgiacomo.travaglini@arm.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 2713996Sgiacomo.travaglini@arm.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 2813996Sgiacomo.travaglini@arm.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2913996Sgiacomo.travaglini@arm.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 3013996Sgiacomo.travaglini@arm.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 3113996Sgiacomo.travaglini@arm.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 3213996Sgiacomo.travaglini@arm.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 3313996Sgiacomo.travaglini@arm.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 3413996Sgiacomo.travaglini@arm.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 3513996Sgiacomo.travaglini@arm.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 3613996Sgiacomo.travaglini@arm.com * 3713996Sgiacomo.travaglini@arm.com * Authors: Giacomo Gabrielli 3813996Sgiacomo.travaglini@arm.com * Andreas Sandberg 3913996Sgiacomo.travaglini@arm.com */ 4013996Sgiacomo.travaglini@arm.com 4113996Sgiacomo.travaglini@arm.com#include "dev/arm/generic_timer.hh" 4213996Sgiacomo.travaglini@arm.com 4313996Sgiacomo.travaglini@arm.com#include "arch/arm/system.hh" 4413996Sgiacomo.travaglini@arm.com#include "debug/Timer.hh" 4513996Sgiacomo.travaglini@arm.com#include "dev/arm/base_gic.hh" 4613996Sgiacomo.travaglini@arm.com#include "mem/packet_access.hh" 4713996Sgiacomo.travaglini@arm.com#include "params/GenericTimer.hh" 4813996Sgiacomo.travaglini@arm.com#include "params/GenericTimerMem.hh" 4913996Sgiacomo.travaglini@arm.com 5013996Sgiacomo.travaglini@arm.comSystemCounter::SystemCounter() 5113996Sgiacomo.travaglini@arm.com : _freq(0), _period(0), _resetTick(0), _regCntkctl(0) 5213996Sgiacomo.travaglini@arm.com{ 5313996Sgiacomo.travaglini@arm.com setFreq(0x01800000); 5413996Sgiacomo.travaglini@arm.com} 5514181Sgiacomo.travaglini@arm.com 5614181Sgiacomo.travaglini@arm.comvoid 5713996Sgiacomo.travaglini@arm.comSystemCounter::setFreq(uint32_t freq) 5813996Sgiacomo.travaglini@arm.com{ 5913996Sgiacomo.travaglini@arm.com if (_freq != 0) { 6013996Sgiacomo.travaglini@arm.com // Altering the frequency after boot shouldn't be done in practice. 6113996Sgiacomo.travaglini@arm.com warn_once("The frequency of the system counter has already been set"); 6213996Sgiacomo.travaglini@arm.com } 6313996Sgiacomo.travaglini@arm.com _freq = freq; 6413996Sgiacomo.travaglini@arm.com _period = (1.0 / freq) * SimClock::Frequency; 6513996Sgiacomo.travaglini@arm.com _resetTick = curTick(); 6613996Sgiacomo.travaglini@arm.com} 6713996Sgiacomo.travaglini@arm.com 6813996Sgiacomo.travaglini@arm.comvoid 6913996Sgiacomo.travaglini@arm.comSystemCounter::serialize(CheckpointOut &cp) const 7013996Sgiacomo.travaglini@arm.com{ 7113996Sgiacomo.travaglini@arm.com SERIALIZE_SCALAR(_regCntkctl); 7213996Sgiacomo.travaglini@arm.com SERIALIZE_SCALAR(_regCnthctl); 7313996Sgiacomo.travaglini@arm.com SERIALIZE_SCALAR(_freq); 7413996Sgiacomo.travaglini@arm.com SERIALIZE_SCALAR(_period); 7513996Sgiacomo.travaglini@arm.com SERIALIZE_SCALAR(_resetTick); 7613996Sgiacomo.travaglini@arm.com} 7713996Sgiacomo.travaglini@arm.com 7813996Sgiacomo.travaglini@arm.comvoid 7913996Sgiacomo.travaglini@arm.comSystemCounter::unserialize(CheckpointIn &cp) 8013996Sgiacomo.travaglini@arm.com{ 8113996Sgiacomo.travaglini@arm.com // We didn't handle CNTKCTL in this class before, assume it's zero 8213996Sgiacomo.travaglini@arm.com // if it isn't present. 8313996Sgiacomo.travaglini@arm.com if (!UNSERIALIZE_OPT_SCALAR(_regCntkctl)) 8413996Sgiacomo.travaglini@arm.com _regCntkctl = 0; 8513996Sgiacomo.travaglini@arm.com if (!UNSERIALIZE_OPT_SCALAR(_regCnthctl)) 8613996Sgiacomo.travaglini@arm.com _regCnthctl = 0; 8713996Sgiacomo.travaglini@arm.com UNSERIALIZE_SCALAR(_freq); 8813996Sgiacomo.travaglini@arm.com UNSERIALIZE_SCALAR(_period); 8913996Sgiacomo.travaglini@arm.com UNSERIALIZE_SCALAR(_resetTick); 9013996Sgiacomo.travaglini@arm.com} 9113996Sgiacomo.travaglini@arm.com 9213996Sgiacomo.travaglini@arm.com 9313996Sgiacomo.travaglini@arm.com 9413996Sgiacomo.travaglini@arm.comArchTimer::ArchTimer(const std::string &name, 9513996Sgiacomo.travaglini@arm.com SimObject &parent, 9613996Sgiacomo.travaglini@arm.com SystemCounter &sysctr, 9713996Sgiacomo.travaglini@arm.com ArmInterruptPin *interrupt) 9813996Sgiacomo.travaglini@arm.com : _name(name), _parent(parent), _systemCounter(sysctr), 9913996Sgiacomo.travaglini@arm.com _interrupt(interrupt), 10013996Sgiacomo.travaglini@arm.com _control(0), _counterLimit(0), _offset(0), 10113996Sgiacomo.travaglini@arm.com _counterLimitReachedEvent([this]{ counterLimitReached(); }, name) 10213996Sgiacomo.travaglini@arm.com{ 10313996Sgiacomo.travaglini@arm.com} 10413996Sgiacomo.travaglini@arm.com 10513996Sgiacomo.travaglini@arm.comvoid 10613996Sgiacomo.travaglini@arm.comArchTimer::counterLimitReached() 10713996Sgiacomo.travaglini@arm.com{ 10813996Sgiacomo.travaglini@arm.com _control.istatus = 1; 10913996Sgiacomo.travaglini@arm.com 11013996Sgiacomo.travaglini@arm.com if (!_control.enable) 11113996Sgiacomo.travaglini@arm.com return; 11213996Sgiacomo.travaglini@arm.com 11313996Sgiacomo.travaglini@arm.com DPRINTF(Timer, "Counter limit reached\n"); 11413996Sgiacomo.travaglini@arm.com if (!_control.imask) { 11513996Sgiacomo.travaglini@arm.com if (scheduleEvents()) { 11613996Sgiacomo.travaglini@arm.com DPRINTF(Timer, "Causing interrupt\n"); 11713996Sgiacomo.travaglini@arm.com _interrupt->raise(); 11813996Sgiacomo.travaglini@arm.com } else { 11913996Sgiacomo.travaglini@arm.com DPRINTF(Timer, "Kvm mode; skipping simulated interrupt\n"); 12013996Sgiacomo.travaglini@arm.com } 12113996Sgiacomo.travaglini@arm.com } 12213996Sgiacomo.travaglini@arm.com} 12313996Sgiacomo.travaglini@arm.com 12413996Sgiacomo.travaglini@arm.comvoid 12513996Sgiacomo.travaglini@arm.comArchTimer::updateCounter() 12613996Sgiacomo.travaglini@arm.com{ 12713996Sgiacomo.travaglini@arm.com if (_counterLimitReachedEvent.scheduled()) 12813996Sgiacomo.travaglini@arm.com _parent.deschedule(_counterLimitReachedEvent); 12913996Sgiacomo.travaglini@arm.com if (value() >= _counterLimit) { 13013996Sgiacomo.travaglini@arm.com counterLimitReached(); 13113996Sgiacomo.travaglini@arm.com } else { 13213996Sgiacomo.travaglini@arm.com _control.istatus = 0; 13313996Sgiacomo.travaglini@arm.com if (scheduleEvents()) { 13413996Sgiacomo.travaglini@arm.com const auto period(_systemCounter.period()); 13513996Sgiacomo.travaglini@arm.com _parent.schedule(_counterLimitReachedEvent, 13613996Sgiacomo.travaglini@arm.com curTick() + (_counterLimit - value()) * period); 13713996Sgiacomo.travaglini@arm.com } 13813996Sgiacomo.travaglini@arm.com } 13913996Sgiacomo.travaglini@arm.com} 14013996Sgiacomo.travaglini@arm.com 14113996Sgiacomo.travaglini@arm.comvoid 14213996Sgiacomo.travaglini@arm.comArchTimer::setCompareValue(uint64_t val) 14313996Sgiacomo.travaglini@arm.com{ 14413996Sgiacomo.travaglini@arm.com _counterLimit = val; 14513996Sgiacomo.travaglini@arm.com updateCounter(); 14613996Sgiacomo.travaglini@arm.com} 14713996Sgiacomo.travaglini@arm.com 14813996Sgiacomo.travaglini@arm.comvoid 14914188Sgiacomo.travaglini@arm.comArchTimer::setTimerValue(uint32_t val) 15013996Sgiacomo.travaglini@arm.com{ 15113996Sgiacomo.travaglini@arm.com setCompareValue(value() + sext<32>(val)); 15213996Sgiacomo.travaglini@arm.com} 15313996Sgiacomo.travaglini@arm.com 15413996Sgiacomo.travaglini@arm.comvoid 15513996Sgiacomo.travaglini@arm.comArchTimer::setControl(uint32_t val) 15613996Sgiacomo.travaglini@arm.com{ 15713996Sgiacomo.travaglini@arm.com ArchTimerCtrl new_ctl = val; 15813996Sgiacomo.travaglini@arm.com if ((new_ctl.enable && !new_ctl.imask) && 15913996Sgiacomo.travaglini@arm.com !(_control.enable && !_control.imask)) { 16014188Sgiacomo.travaglini@arm.com // Re-evalute the timer condition 16113996Sgiacomo.travaglini@arm.com if (_counterLimit >= value()) { 16213996Sgiacomo.travaglini@arm.com _control.istatus = 1; 16313996Sgiacomo.travaglini@arm.com 16413996Sgiacomo.travaglini@arm.com DPRINTF(Timer, "Causing interrupt in control\n"); 16513996Sgiacomo.travaglini@arm.com //_interrupt.send(); 16613996Sgiacomo.travaglini@arm.com } 16713996Sgiacomo.travaglini@arm.com } 16813996Sgiacomo.travaglini@arm.com _control.enable = new_ctl.enable; 16913996Sgiacomo.travaglini@arm.com _control.imask = new_ctl.imask; 17013996Sgiacomo.travaglini@arm.com} 17113996Sgiacomo.travaglini@arm.com 17214188Sgiacomo.travaglini@arm.comvoid 17313996Sgiacomo.travaglini@arm.comArchTimer::setOffset(uint64_t val) 17413996Sgiacomo.travaglini@arm.com{ 17513996Sgiacomo.travaglini@arm.com _offset = val; 17613996Sgiacomo.travaglini@arm.com updateCounter(); 17713996Sgiacomo.travaglini@arm.com} 17813996Sgiacomo.travaglini@arm.com 17913996Sgiacomo.travaglini@arm.comuint64_t 18013996Sgiacomo.travaglini@arm.comArchTimer::value() const 18113996Sgiacomo.travaglini@arm.com{ 18214188Sgiacomo.travaglini@arm.com return _systemCounter.value() - _offset; 18313996Sgiacomo.travaglini@arm.com} 18414188Sgiacomo.travaglini@arm.com 18513996Sgiacomo.travaglini@arm.comvoid 18613996Sgiacomo.travaglini@arm.comArchTimer::serialize(CheckpointOut &cp) const 18713996Sgiacomo.travaglini@arm.com{ 18813996Sgiacomo.travaglini@arm.com paramOut(cp, "control_serial", _control); 18913996Sgiacomo.travaglini@arm.com SERIALIZE_SCALAR(_counterLimit); 19013996Sgiacomo.travaglini@arm.com SERIALIZE_SCALAR(_offset); 19113996Sgiacomo.travaglini@arm.com} 19213996Sgiacomo.travaglini@arm.com 19313996Sgiacomo.travaglini@arm.comvoid 19413996Sgiacomo.travaglini@arm.comArchTimer::unserialize(CheckpointIn &cp) 19513996Sgiacomo.travaglini@arm.com{ 19614188Sgiacomo.travaglini@arm.com paramIn(cp, "control_serial", _control); 19714188Sgiacomo.travaglini@arm.com // We didn't serialize an offset before we added support for the 19813996Sgiacomo.travaglini@arm.com // virtual timer. Consider it optional to maintain backwards 19913996Sgiacomo.travaglini@arm.com // compatibility. 20013996Sgiacomo.travaglini@arm.com if (!UNSERIALIZE_OPT_SCALAR(_offset)) 20113996Sgiacomo.travaglini@arm.com _offset = 0; 20213996Sgiacomo.travaglini@arm.com 20313996Sgiacomo.travaglini@arm.com // We no longer schedule an event here because we may enter KVM 20413996Sgiacomo.travaglini@arm.com // emulation. The event creation is delayed until drainResume(). 20513996Sgiacomo.travaglini@arm.com} 20613996Sgiacomo.travaglini@arm.com 20713996Sgiacomo.travaglini@arm.comDrainState 20814188Sgiacomo.travaglini@arm.comArchTimer::drain() 20913996Sgiacomo.travaglini@arm.com{ 21014188Sgiacomo.travaglini@arm.com if (_counterLimitReachedEvent.scheduled()) 21113996Sgiacomo.travaglini@arm.com _parent.deschedule(_counterLimitReachedEvent); 21213996Sgiacomo.travaglini@arm.com 21313996Sgiacomo.travaglini@arm.com return DrainState::Drained; 21413996Sgiacomo.travaglini@arm.com} 21513996Sgiacomo.travaglini@arm.com 21613996Sgiacomo.travaglini@arm.comvoid 21713996Sgiacomo.travaglini@arm.comArchTimer::drainResume() 21813996Sgiacomo.travaglini@arm.com{ 21913996Sgiacomo.travaglini@arm.com updateCounter(); 22013996Sgiacomo.travaglini@arm.com} 22113996Sgiacomo.travaglini@arm.com 22213996Sgiacomo.travaglini@arm.comGenericTimer::GenericTimer(GenericTimerParams *p) 22314181Sgiacomo.travaglini@arm.com : ClockedObject(p), 22413996Sgiacomo.travaglini@arm.com system(*p->system) 22513996Sgiacomo.travaglini@arm.com{ 22613996Sgiacomo.travaglini@arm.com fatal_if(!p->system, "No system specified, can't instantiate timer.\n"); 22713996Sgiacomo.travaglini@arm.com system.setGenericTimer(this); 22813996Sgiacomo.travaglini@arm.com} 22913996Sgiacomo.travaglini@arm.com 23014181Sgiacomo.travaglini@arm.comconst GenericTimerParams * 23114181Sgiacomo.travaglini@arm.comGenericTimer::params() const 23213996Sgiacomo.travaglini@arm.com{ 23313996Sgiacomo.travaglini@arm.com return dynamic_cast<const GenericTimerParams *>(_params); 23413996Sgiacomo.travaglini@arm.com} 23513996Sgiacomo.travaglini@arm.com 23613996Sgiacomo.travaglini@arm.comvoid 23713996Sgiacomo.travaglini@arm.comGenericTimer::serialize(CheckpointOut &cp) const 23813996Sgiacomo.travaglini@arm.com{ 23913996Sgiacomo.travaglini@arm.com paramOut(cp, "cpu_count", timers.size()); 24013996Sgiacomo.travaglini@arm.com 24113996Sgiacomo.travaglini@arm.com systemCounter.serializeSection(cp, "sys_counter"); 24213996Sgiacomo.travaglini@arm.com 24313996Sgiacomo.travaglini@arm.com for (int i = 0; i < timers.size(); ++i) { 24413996Sgiacomo.travaglini@arm.com const CoreTimers &core(*timers[i]); 24513996Sgiacomo.travaglini@arm.com 24613996Sgiacomo.travaglini@arm.com // This should really be phys_timerN, but we are stuck with 24713996Sgiacomo.travaglini@arm.com // arch_timer for backwards compatibility. 24813996Sgiacomo.travaglini@arm.com core.physNS.serializeSection(cp, csprintf("arch_timer%d", i)); 24913996Sgiacomo.travaglini@arm.com core.physS.serializeSection(cp, csprintf("phys_s_timer%d", i)); 25013996Sgiacomo.travaglini@arm.com core.virt.serializeSection(cp, csprintf("virt_timer%d", i)); 25113996Sgiacomo.travaglini@arm.com core.hyp.serializeSection(cp, csprintf("hyp_timer%d", i)); 25213996Sgiacomo.travaglini@arm.com } 25313996Sgiacomo.travaglini@arm.com} 25413996Sgiacomo.travaglini@arm.com 25513996Sgiacomo.travaglini@arm.comvoid 25613996Sgiacomo.travaglini@arm.comGenericTimer::unserialize(CheckpointIn &cp) 25713996Sgiacomo.travaglini@arm.com{ 25813996Sgiacomo.travaglini@arm.com systemCounter.unserializeSection(cp, "sys_counter"); 25913996Sgiacomo.travaglini@arm.com 26013996Sgiacomo.travaglini@arm.com // Try to unserialize the CPU count. Old versions of the timer 26113996Sgiacomo.travaglini@arm.com // model assumed a 8 CPUs, so we fall back to that if the field 26213996Sgiacomo.travaglini@arm.com // isn't present. 26313996Sgiacomo.travaglini@arm.com static const unsigned OLD_CPU_MAX = 8; 26413996Sgiacomo.travaglini@arm.com unsigned cpu_count; 26513996Sgiacomo.travaglini@arm.com if (!UNSERIALIZE_OPT_SCALAR(cpu_count)) { 26613996Sgiacomo.travaglini@arm.com warn("Checkpoint does not contain CPU count, assuming %i CPUs\n", 26713996Sgiacomo.travaglini@arm.com OLD_CPU_MAX); 26813996Sgiacomo.travaglini@arm.com cpu_count = OLD_CPU_MAX; 26913996Sgiacomo.travaglini@arm.com } 27013996Sgiacomo.travaglini@arm.com 27113996Sgiacomo.travaglini@arm.com for (int i = 0; i < cpu_count; ++i) { 27213996Sgiacomo.travaglini@arm.com CoreTimers &core(getTimers(i)); 27313996Sgiacomo.travaglini@arm.com // This should really be phys_timerN, but we are stuck with 27413996Sgiacomo.travaglini@arm.com // arch_timer for backwards compatibility. 27513996Sgiacomo.travaglini@arm.com core.physNS.unserializeSection(cp, csprintf("arch_timer%d", i)); 27613996Sgiacomo.travaglini@arm.com core.physS.unserializeSection(cp, csprintf("phys_s_timer%d", i)); 27713996Sgiacomo.travaglini@arm.com core.virt.unserializeSection(cp, csprintf("virt_timer%d", i)); 27813996Sgiacomo.travaglini@arm.com core.hyp.unserializeSection(cp, csprintf("hyp_timer%d", i)); 27913996Sgiacomo.travaglini@arm.com } 28013996Sgiacomo.travaglini@arm.com} 28113996Sgiacomo.travaglini@arm.com 28213996Sgiacomo.travaglini@arm.com 28313996Sgiacomo.travaglini@arm.comGenericTimer::CoreTimers & 28413996Sgiacomo.travaglini@arm.comGenericTimer::getTimers(int cpu_id) 28513996Sgiacomo.travaglini@arm.com{ 28613996Sgiacomo.travaglini@arm.com if (cpu_id >= timers.size()) 28713996Sgiacomo.travaglini@arm.com createTimers(cpu_id + 1); 28813996Sgiacomo.travaglini@arm.com 28913996Sgiacomo.travaglini@arm.com return *timers[cpu_id]; 29013996Sgiacomo.travaglini@arm.com} 29113996Sgiacomo.travaglini@arm.com 29213996Sgiacomo.travaglini@arm.comvoid 29313996Sgiacomo.travaglini@arm.comGenericTimer::createTimers(unsigned cpus) 29413996Sgiacomo.travaglini@arm.com{ 29513996Sgiacomo.travaglini@arm.com assert(timers.size() < cpus); 29613996Sgiacomo.travaglini@arm.com auto p = static_cast<const GenericTimerParams *>(_params); 29713996Sgiacomo.travaglini@arm.com 29813996Sgiacomo.travaglini@arm.com const unsigned old_cpu_count(timers.size()); 29913996Sgiacomo.travaglini@arm.com timers.resize(cpus); 30013996Sgiacomo.travaglini@arm.com for (unsigned i = old_cpu_count; i < cpus; ++i) { 30113996Sgiacomo.travaglini@arm.com 30213996Sgiacomo.travaglini@arm.com ThreadContext *tc = system.getThreadContext(i); 30313996Sgiacomo.travaglini@arm.com 30413996Sgiacomo.travaglini@arm.com timers[i].reset( 30513996Sgiacomo.travaglini@arm.com new CoreTimers(*this, system, i, 30613996Sgiacomo.travaglini@arm.com p->int_phys_s->get(tc), 30713996Sgiacomo.travaglini@arm.com p->int_phys_ns->get(tc), 30813996Sgiacomo.travaglini@arm.com p->int_virt->get(tc), 30913996Sgiacomo.travaglini@arm.com p->int_hyp->get(tc))); 31013996Sgiacomo.travaglini@arm.com } 31113996Sgiacomo.travaglini@arm.com} 31213996Sgiacomo.travaglini@arm.com 31313996Sgiacomo.travaglini@arm.com 31413996Sgiacomo.travaglini@arm.comvoid 31513996Sgiacomo.travaglini@arm.comGenericTimer::setMiscReg(int reg, unsigned cpu, RegVal val) 31613996Sgiacomo.travaglini@arm.com{ 31714181Sgiacomo.travaglini@arm.com CoreTimers &core(getTimers(cpu)); 31814181Sgiacomo.travaglini@arm.com 31913996Sgiacomo.travaglini@arm.com switch (reg) { 32013996Sgiacomo.travaglini@arm.com case MISCREG_CNTFRQ: 32113996Sgiacomo.travaglini@arm.com case MISCREG_CNTFRQ_EL0: 32213996Sgiacomo.travaglini@arm.com systemCounter.setFreq(val); 32313996Sgiacomo.travaglini@arm.com return; 32414181Sgiacomo.travaglini@arm.com 32514181Sgiacomo.travaglini@arm.com case MISCREG_CNTKCTL: 32614181Sgiacomo.travaglini@arm.com case MISCREG_CNTKCTL_EL1: 32713996Sgiacomo.travaglini@arm.com systemCounter.setKernelControl(val); 32813996Sgiacomo.travaglini@arm.com return; 32913996Sgiacomo.travaglini@arm.com 33013996Sgiacomo.travaglini@arm.com case MISCREG_CNTHCTL: 33113996Sgiacomo.travaglini@arm.com case MISCREG_CNTHCTL_EL2: 33213996Sgiacomo.travaglini@arm.com systemCounter.setHypControl(val); 33313996Sgiacomo.travaglini@arm.com return; 33413996Sgiacomo.travaglini@arm.com 33513996Sgiacomo.travaglini@arm.com // Physical timer (NS) 33613996Sgiacomo.travaglini@arm.com case MISCREG_CNTP_CVAL_NS: 33713996Sgiacomo.travaglini@arm.com case MISCREG_CNTP_CVAL_EL0: 33813996Sgiacomo.travaglini@arm.com core.physNS.setCompareValue(val); 33913996Sgiacomo.travaglini@arm.com return; 34013996Sgiacomo.travaglini@arm.com 34113996Sgiacomo.travaglini@arm.com case MISCREG_CNTP_TVAL_NS: 34213996Sgiacomo.travaglini@arm.com case MISCREG_CNTP_TVAL_EL0: 34313996Sgiacomo.travaglini@arm.com core.physNS.setTimerValue(val); 34413996Sgiacomo.travaglini@arm.com return; 34513996Sgiacomo.travaglini@arm.com 34613996Sgiacomo.travaglini@arm.com case MISCREG_CNTP_CTL_NS: 34713996Sgiacomo.travaglini@arm.com case MISCREG_CNTP_CTL_EL0: 34813996Sgiacomo.travaglini@arm.com core.physNS.setControl(val); 34913996Sgiacomo.travaglini@arm.com return; 35013996Sgiacomo.travaglini@arm.com 35113996Sgiacomo.travaglini@arm.com // Count registers 35213996Sgiacomo.travaglini@arm.com case MISCREG_CNTPCT: 35313996Sgiacomo.travaglini@arm.com case MISCREG_CNTPCT_EL0: 35413996Sgiacomo.travaglini@arm.com case MISCREG_CNTVCT: 35513996Sgiacomo.travaglini@arm.com case MISCREG_CNTVCT_EL0: 35613996Sgiacomo.travaglini@arm.com warn("Ignoring write to read only count register: %s\n", 35713996Sgiacomo.travaglini@arm.com miscRegName[reg]); 35813996Sgiacomo.travaglini@arm.com return; 35913996Sgiacomo.travaglini@arm.com 36013996Sgiacomo.travaglini@arm.com // Virtual timer 36113996Sgiacomo.travaglini@arm.com case MISCREG_CNTVOFF: 36213996Sgiacomo.travaglini@arm.com case MISCREG_CNTVOFF_EL2: 36313996Sgiacomo.travaglini@arm.com core.virt.setOffset(val); 36413996Sgiacomo.travaglini@arm.com return; 36513996Sgiacomo.travaglini@arm.com 36613996Sgiacomo.travaglini@arm.com case MISCREG_CNTV_CVAL: 36713996Sgiacomo.travaglini@arm.com case MISCREG_CNTV_CVAL_EL0: 36813996Sgiacomo.travaglini@arm.com core.virt.setCompareValue(val); 36913996Sgiacomo.travaglini@arm.com return; 37013996Sgiacomo.travaglini@arm.com 37113996Sgiacomo.travaglini@arm.com case MISCREG_CNTV_TVAL: 37213996Sgiacomo.travaglini@arm.com case MISCREG_CNTV_TVAL_EL0: 37313996Sgiacomo.travaglini@arm.com core.virt.setTimerValue(val); 37413996Sgiacomo.travaglini@arm.com return; 37513996Sgiacomo.travaglini@arm.com 37613996Sgiacomo.travaglini@arm.com case MISCREG_CNTV_CTL: 37713996Sgiacomo.travaglini@arm.com case MISCREG_CNTV_CTL_EL0: 37813996Sgiacomo.travaglini@arm.com core.virt.setControl(val); 37913996Sgiacomo.travaglini@arm.com return; 38013996Sgiacomo.travaglini@arm.com 38113996Sgiacomo.travaglini@arm.com // Physical timer (S) 38213996Sgiacomo.travaglini@arm.com case MISCREG_CNTP_CTL_S: 38313996Sgiacomo.travaglini@arm.com case MISCREG_CNTPS_CTL_EL1: 38413996Sgiacomo.travaglini@arm.com core.physS.setControl(val); 38513996Sgiacomo.travaglini@arm.com return; 38613996Sgiacomo.travaglini@arm.com 38713996Sgiacomo.travaglini@arm.com case MISCREG_CNTP_CVAL_S: 38813996Sgiacomo.travaglini@arm.com case MISCREG_CNTPS_CVAL_EL1: 38913996Sgiacomo.travaglini@arm.com core.physS.setCompareValue(val); 39013996Sgiacomo.travaglini@arm.com return; 39113996Sgiacomo.travaglini@arm.com 39213996Sgiacomo.travaglini@arm.com case MISCREG_CNTP_TVAL_S: 39313996Sgiacomo.travaglini@arm.com case MISCREG_CNTPS_TVAL_EL1: 39413996Sgiacomo.travaglini@arm.com core.physS.setTimerValue(val); 39513996Sgiacomo.travaglini@arm.com return; 39613996Sgiacomo.travaglini@arm.com 39713996Sgiacomo.travaglini@arm.com // Hyp phys. timer, non-secure 39813996Sgiacomo.travaglini@arm.com case MISCREG_CNTHP_CTL: 39913996Sgiacomo.travaglini@arm.com case MISCREG_CNTHP_CTL_EL2: 40013996Sgiacomo.travaglini@arm.com core.hyp.setControl(val); 40113996Sgiacomo.travaglini@arm.com return; 40213996Sgiacomo.travaglini@arm.com 40313996Sgiacomo.travaglini@arm.com case MISCREG_CNTHP_CVAL: 40413996Sgiacomo.travaglini@arm.com case MISCREG_CNTHP_CVAL_EL2: 40513996Sgiacomo.travaglini@arm.com core.hyp.setCompareValue(val); 40613996Sgiacomo.travaglini@arm.com return; 40713996Sgiacomo.travaglini@arm.com 40813996Sgiacomo.travaglini@arm.com case MISCREG_CNTHP_TVAL: 40913996Sgiacomo.travaglini@arm.com case MISCREG_CNTHP_TVAL_EL2: 41013996Sgiacomo.travaglini@arm.com core.hyp.setTimerValue(val); 41113996Sgiacomo.travaglini@arm.com return; 41213996Sgiacomo.travaglini@arm.com 41313996Sgiacomo.travaglini@arm.com default: 41413996Sgiacomo.travaglini@arm.com warn("Writing to unknown register: %s\n", miscRegName[reg]); 41513996Sgiacomo.travaglini@arm.com return; 41613996Sgiacomo.travaglini@arm.com } 41713996Sgiacomo.travaglini@arm.com} 41813996Sgiacomo.travaglini@arm.com 41913996Sgiacomo.travaglini@arm.com 42013996Sgiacomo.travaglini@arm.comRegVal 42113996Sgiacomo.travaglini@arm.comGenericTimer::readMiscReg(int reg, unsigned cpu) 42213996Sgiacomo.travaglini@arm.com{ 42313996Sgiacomo.travaglini@arm.com CoreTimers &core(getTimers(cpu)); 42413996Sgiacomo.travaglini@arm.com 42513996Sgiacomo.travaglini@arm.com switch (reg) { 42613996Sgiacomo.travaglini@arm.com case MISCREG_CNTFRQ: 42713996Sgiacomo.travaglini@arm.com case MISCREG_CNTFRQ_EL0: 42813996Sgiacomo.travaglini@arm.com return systemCounter.freq(); 42913996Sgiacomo.travaglini@arm.com 43013996Sgiacomo.travaglini@arm.com case MISCREG_CNTKCTL: 43113996Sgiacomo.travaglini@arm.com case MISCREG_CNTKCTL_EL1: 43213996Sgiacomo.travaglini@arm.com return systemCounter.getKernelControl(); 43313996Sgiacomo.travaglini@arm.com 43413996Sgiacomo.travaglini@arm.com case MISCREG_CNTHCTL: 43513996Sgiacomo.travaglini@arm.com case MISCREG_CNTHCTL_EL2: 43613996Sgiacomo.travaglini@arm.com return systemCounter.getHypControl(); 43713996Sgiacomo.travaglini@arm.com 43813996Sgiacomo.travaglini@arm.com // Physical timer 43913996Sgiacomo.travaglini@arm.com case MISCREG_CNTP_CVAL_NS: 44013996Sgiacomo.travaglini@arm.com case MISCREG_CNTP_CVAL_EL0: 44113996Sgiacomo.travaglini@arm.com return core.physNS.compareValue(); 44213996Sgiacomo.travaglini@arm.com 44313996Sgiacomo.travaglini@arm.com case MISCREG_CNTP_TVAL_NS: 44413996Sgiacomo.travaglini@arm.com case MISCREG_CNTP_TVAL_EL0: 44513996Sgiacomo.travaglini@arm.com return core.physNS.timerValue(); 44613996Sgiacomo.travaglini@arm.com 44713996Sgiacomo.travaglini@arm.com case MISCREG_CNTP_CTL_EL0: 44813996Sgiacomo.travaglini@arm.com case MISCREG_CNTP_CTL_NS: 44913996Sgiacomo.travaglini@arm.com return core.physNS.control(); 45013996Sgiacomo.travaglini@arm.com 45113996Sgiacomo.travaglini@arm.com case MISCREG_CNTPCT: 45213996Sgiacomo.travaglini@arm.com case MISCREG_CNTPCT_EL0: 45313996Sgiacomo.travaglini@arm.com return core.physNS.value(); 45413996Sgiacomo.travaglini@arm.com 45513996Sgiacomo.travaglini@arm.com 45613996Sgiacomo.travaglini@arm.com // Virtual timer 45713996Sgiacomo.travaglini@arm.com case MISCREG_CNTVCT: 45813996Sgiacomo.travaglini@arm.com case MISCREG_CNTVCT_EL0: 45913996Sgiacomo.travaglini@arm.com return core.virt.value(); 46013996Sgiacomo.travaglini@arm.com 46113996Sgiacomo.travaglini@arm.com case MISCREG_CNTVOFF: 46213996Sgiacomo.travaglini@arm.com case MISCREG_CNTVOFF_EL2: 46313996Sgiacomo.travaglini@arm.com return core.virt.offset(); 46413996Sgiacomo.travaglini@arm.com 46513996Sgiacomo.travaglini@arm.com case MISCREG_CNTV_CVAL: 46613996Sgiacomo.travaglini@arm.com case MISCREG_CNTV_CVAL_EL0: 46713996Sgiacomo.travaglini@arm.com return core.virt.compareValue(); 46813996Sgiacomo.travaglini@arm.com 46913996Sgiacomo.travaglini@arm.com case MISCREG_CNTV_TVAL: 47013996Sgiacomo.travaglini@arm.com case MISCREG_CNTV_TVAL_EL0: 47113996Sgiacomo.travaglini@arm.com return core.virt.timerValue(); 47213996Sgiacomo.travaglini@arm.com 47313996Sgiacomo.travaglini@arm.com case MISCREG_CNTV_CTL: 47413996Sgiacomo.travaglini@arm.com case MISCREG_CNTV_CTL_EL0: 47513996Sgiacomo.travaglini@arm.com return core.virt.control(); 47613996Sgiacomo.travaglini@arm.com 47713996Sgiacomo.travaglini@arm.com // PL1 phys. timer, secure 47813996Sgiacomo.travaglini@arm.com case MISCREG_CNTP_CTL_S: 47913996Sgiacomo.travaglini@arm.com case MISCREG_CNTPS_CTL_EL1: 48013996Sgiacomo.travaglini@arm.com return core.physS.control(); 48113996Sgiacomo.travaglini@arm.com 48213996Sgiacomo.travaglini@arm.com case MISCREG_CNTP_CVAL_S: 48313996Sgiacomo.travaglini@arm.com case MISCREG_CNTPS_CVAL_EL1: 48413996Sgiacomo.travaglini@arm.com return core.physS.compareValue(); 48513996Sgiacomo.travaglini@arm.com 48613996Sgiacomo.travaglini@arm.com case MISCREG_CNTP_TVAL_S: 48713996Sgiacomo.travaglini@arm.com case MISCREG_CNTPS_TVAL_EL1: 48813996Sgiacomo.travaglini@arm.com return core.physS.timerValue(); 48913996Sgiacomo.travaglini@arm.com 49013996Sgiacomo.travaglini@arm.com // HYP phys. timer (NS) 49113996Sgiacomo.travaglini@arm.com case MISCREG_CNTHP_CTL: 49213996Sgiacomo.travaglini@arm.com case MISCREG_CNTHP_CTL_EL2: 49313996Sgiacomo.travaglini@arm.com return core.hyp.control(); 49413996Sgiacomo.travaglini@arm.com 49513996Sgiacomo.travaglini@arm.com case MISCREG_CNTHP_CVAL: 49613996Sgiacomo.travaglini@arm.com case MISCREG_CNTHP_CVAL_EL2: 49713996Sgiacomo.travaglini@arm.com return core.hyp.compareValue(); 49813996Sgiacomo.travaglini@arm.com 49913996Sgiacomo.travaglini@arm.com case MISCREG_CNTHP_TVAL: 50013996Sgiacomo.travaglini@arm.com case MISCREG_CNTHP_TVAL_EL2: 50113996Sgiacomo.travaglini@arm.com return core.hyp.timerValue(); 50213996Sgiacomo.travaglini@arm.com 50313996Sgiacomo.travaglini@arm.com default: 50413996Sgiacomo.travaglini@arm.com warn("Reading from unknown register: %s\n", miscRegName[reg]); 50513996Sgiacomo.travaglini@arm.com return 0; 50613996Sgiacomo.travaglini@arm.com } 50713996Sgiacomo.travaglini@arm.com} 50813996Sgiacomo.travaglini@arm.com 50913996Sgiacomo.travaglini@arm.com 51013996Sgiacomo.travaglini@arm.comvoid 51113996Sgiacomo.travaglini@arm.comGenericTimerISA::setMiscReg(int reg, RegVal val) 51213996Sgiacomo.travaglini@arm.com{ 51313996Sgiacomo.travaglini@arm.com DPRINTF(Timer, "Setting %s := 0x%x\n", miscRegName[reg], val); 51413996Sgiacomo.travaglini@arm.com parent.setMiscReg(reg, cpu, val); 51513996Sgiacomo.travaglini@arm.com} 51613996Sgiacomo.travaglini@arm.com 51713996Sgiacomo.travaglini@arm.comRegVal 51813996Sgiacomo.travaglini@arm.comGenericTimerISA::readMiscReg(int reg) 51913996Sgiacomo.travaglini@arm.com{ 52013996Sgiacomo.travaglini@arm.com RegVal value = parent.readMiscReg(reg, cpu); 52113996Sgiacomo.travaglini@arm.com DPRINTF(Timer, "Reading %s as 0x%x\n", miscRegName[reg], value); 52213996Sgiacomo.travaglini@arm.com return value; 52313996Sgiacomo.travaglini@arm.com} 52413996Sgiacomo.travaglini@arm.com 52513996Sgiacomo.travaglini@arm.comGenericTimerMem::GenericTimerMem(GenericTimerMemParams *p) 52613996Sgiacomo.travaglini@arm.com : PioDevice(p), 52713996Sgiacomo.travaglini@arm.com ctrlRange(RangeSize(p->base, TheISA::PageBytes)), 52813996Sgiacomo.travaglini@arm.com timerRange(RangeSize(p->base + TheISA::PageBytes, TheISA::PageBytes)), 52913996Sgiacomo.travaglini@arm.com addrRanges{ctrlRange, timerRange}, 53013996Sgiacomo.travaglini@arm.com systemCounter(), 53113996Sgiacomo.travaglini@arm.com physTimer(csprintf("%s.phys_timer0", name()), 53213996Sgiacomo.travaglini@arm.com *this, systemCounter, 53313996Sgiacomo.travaglini@arm.com p->int_phys->get()), 53413996Sgiacomo.travaglini@arm.com virtTimer(csprintf("%s.virt_timer0", name()), 53513996Sgiacomo.travaglini@arm.com *this, systemCounter, 53613996Sgiacomo.travaglini@arm.com p->int_virt->get()) 53713996Sgiacomo.travaglini@arm.com{ 53813996Sgiacomo.travaglini@arm.com} 53913996Sgiacomo.travaglini@arm.com 54013996Sgiacomo.travaglini@arm.comvoid 54113996Sgiacomo.travaglini@arm.comGenericTimerMem::serialize(CheckpointOut &cp) const 54213996Sgiacomo.travaglini@arm.com{ 54313996Sgiacomo.travaglini@arm.com paramOut(cp, "timer_count", 1); 54413996Sgiacomo.travaglini@arm.com 54513996Sgiacomo.travaglini@arm.com systemCounter.serializeSection(cp, "sys_counter"); 54613996Sgiacomo.travaglini@arm.com 54713996Sgiacomo.travaglini@arm.com physTimer.serializeSection(cp, "phys_timer0"); 54813996Sgiacomo.travaglini@arm.com virtTimer.serializeSection(cp, "virt_timer0"); 54913996Sgiacomo.travaglini@arm.com} 55013996Sgiacomo.travaglini@arm.com 55113996Sgiacomo.travaglini@arm.comvoid 55213996Sgiacomo.travaglini@arm.comGenericTimerMem::unserialize(CheckpointIn &cp) 55313996Sgiacomo.travaglini@arm.com{ 55413996Sgiacomo.travaglini@arm.com systemCounter.unserializeSection(cp, "sys_counter"); 55513996Sgiacomo.travaglini@arm.com 55613996Sgiacomo.travaglini@arm.com unsigned timer_count; 55713996Sgiacomo.travaglini@arm.com UNSERIALIZE_SCALAR(timer_count); 55813996Sgiacomo.travaglini@arm.com // The timer count variable is just here for future versions where 55913996Sgiacomo.travaglini@arm.com // we support more than one set of timers. 56013996Sgiacomo.travaglini@arm.com if (timer_count != 1) 56113996Sgiacomo.travaglini@arm.com panic("Incompatible checkpoint: Only one set of timers supported"); 56213996Sgiacomo.travaglini@arm.com 56313996Sgiacomo.travaglini@arm.com physTimer.unserializeSection(cp, "phys_timer0"); 56413996Sgiacomo.travaglini@arm.com virtTimer.unserializeSection(cp, "virt_timer0"); 56513996Sgiacomo.travaglini@arm.com} 56613996Sgiacomo.travaglini@arm.com 56713996Sgiacomo.travaglini@arm.comTick 56813996Sgiacomo.travaglini@arm.comGenericTimerMem::read(PacketPtr pkt) 56913996Sgiacomo.travaglini@arm.com{ 57013996Sgiacomo.travaglini@arm.com const unsigned size(pkt->getSize()); 57113996Sgiacomo.travaglini@arm.com const Addr addr(pkt->getAddr()); 57213996Sgiacomo.travaglini@arm.com uint64_t value; 57313996Sgiacomo.travaglini@arm.com 57413996Sgiacomo.travaglini@arm.com pkt->makeResponse(); 57513996Sgiacomo.travaglini@arm.com if (ctrlRange.contains(addr)) { 57613996Sgiacomo.travaglini@arm.com value = ctrlRead(addr - ctrlRange.start(), size); 57713996Sgiacomo.travaglini@arm.com } else if (timerRange.contains(addr)) { 57813996Sgiacomo.travaglini@arm.com value = timerRead(addr - timerRange.start(), size); 57913996Sgiacomo.travaglini@arm.com } else { 58013996Sgiacomo.travaglini@arm.com panic("Invalid address: 0x%x\n", addr); 58113996Sgiacomo.travaglini@arm.com } 58213996Sgiacomo.travaglini@arm.com 58313996Sgiacomo.travaglini@arm.com DPRINTF(Timer, "Read 0x%x <- 0x%x(%i)\n", value, addr, size); 58413996Sgiacomo.travaglini@arm.com 58513996Sgiacomo.travaglini@arm.com if (size == 8) { 58613996Sgiacomo.travaglini@arm.com pkt->setLE<uint64_t>(value); 58713996Sgiacomo.travaglini@arm.com } else if (size == 4) { 58813996Sgiacomo.travaglini@arm.com pkt->setLE<uint32_t>(value); 58913996Sgiacomo.travaglini@arm.com } else { 59013996Sgiacomo.travaglini@arm.com panic("Unexpected access size: %i\n", size); 59113996Sgiacomo.travaglini@arm.com } 59213996Sgiacomo.travaglini@arm.com 59313996Sgiacomo.travaglini@arm.com return 0; 59413996Sgiacomo.travaglini@arm.com} 59513996Sgiacomo.travaglini@arm.com 59613996Sgiacomo.travaglini@arm.comTick 59713996Sgiacomo.travaglini@arm.comGenericTimerMem::write(PacketPtr pkt) 59813996Sgiacomo.travaglini@arm.com{ 59913996Sgiacomo.travaglini@arm.com const unsigned size(pkt->getSize()); 60013996Sgiacomo.travaglini@arm.com if (size != 8 && size != 4) 60113996Sgiacomo.travaglini@arm.com panic("Unexpected access size\n"); 60213996Sgiacomo.travaglini@arm.com 60313996Sgiacomo.travaglini@arm.com const Addr addr(pkt->getAddr()); 60413996Sgiacomo.travaglini@arm.com const uint64_t value(size == 8 ? 60513996Sgiacomo.travaglini@arm.com pkt->getLE<uint64_t>() : pkt->getLE<uint32_t>()); 60613996Sgiacomo.travaglini@arm.com 60713996Sgiacomo.travaglini@arm.com DPRINTF(Timer, "Write 0x%x -> 0x%x(%i)\n", value, addr, size); 60813996Sgiacomo.travaglini@arm.com if (ctrlRange.contains(addr)) { 60913996Sgiacomo.travaglini@arm.com ctrlWrite(addr - ctrlRange.start(), size, value); 61013996Sgiacomo.travaglini@arm.com } else if (timerRange.contains(addr)) { 61113996Sgiacomo.travaglini@arm.com timerWrite(addr - timerRange.start(), size, value); 61213996Sgiacomo.travaglini@arm.com } else { 61313996Sgiacomo.travaglini@arm.com panic("Invalid address: 0x%x\n", addr); 61413996Sgiacomo.travaglini@arm.com } 61513996Sgiacomo.travaglini@arm.com 61613996Sgiacomo.travaglini@arm.com pkt->makeResponse(); 61713996Sgiacomo.travaglini@arm.com return 0; 61813996Sgiacomo.travaglini@arm.com} 61913996Sgiacomo.travaglini@arm.com 62013996Sgiacomo.travaglini@arm.comuint64_t 62113996Sgiacomo.travaglini@arm.comGenericTimerMem::ctrlRead(Addr addr, size_t size) const 62213996Sgiacomo.travaglini@arm.com{ 62313996Sgiacomo.travaglini@arm.com if (size == 4) { 62413996Sgiacomo.travaglini@arm.com switch (addr) { 62513996Sgiacomo.travaglini@arm.com case CTRL_CNTFRQ: 62613996Sgiacomo.travaglini@arm.com return systemCounter.freq(); 62713996Sgiacomo.travaglini@arm.com 62813996Sgiacomo.travaglini@arm.com case CTRL_CNTTIDR: 62913996Sgiacomo.travaglini@arm.com return 0x3; // Frame 0 implemented with virtual timers 63013996Sgiacomo.travaglini@arm.com 63113996Sgiacomo.travaglini@arm.com case CTRL_CNTNSAR: 63213996Sgiacomo.travaglini@arm.com case CTRL_CNTACR_BASE: 63313996Sgiacomo.travaglini@arm.com warn("Reading from unimplemented control register (0x%x)\n", addr); 63413996Sgiacomo.travaglini@arm.com return 0; 63513996Sgiacomo.travaglini@arm.com 63613996Sgiacomo.travaglini@arm.com case CTRL_CNTVOFF_LO_BASE: 63713996Sgiacomo.travaglini@arm.com return virtTimer.offset(); 63813996Sgiacomo.travaglini@arm.com 63913996Sgiacomo.travaglini@arm.com case CTRL_CNTVOFF_HI_BASE: 64013996Sgiacomo.travaglini@arm.com return virtTimer.offset() >> 32; 64113996Sgiacomo.travaglini@arm.com 64213996Sgiacomo.travaglini@arm.com default: 64313996Sgiacomo.travaglini@arm.com warn("Unexpected address (0x%x:%i), assuming RAZ\n", addr, size); 64413996Sgiacomo.travaglini@arm.com return 0; 64513996Sgiacomo.travaglini@arm.com } 64613996Sgiacomo.travaglini@arm.com } else if (size == 8) { 64713996Sgiacomo.travaglini@arm.com switch (addr) { 64813996Sgiacomo.travaglini@arm.com case CTRL_CNTVOFF_LO_BASE: 64913996Sgiacomo.travaglini@arm.com return virtTimer.offset(); 65013996Sgiacomo.travaglini@arm.com 65113996Sgiacomo.travaglini@arm.com default: 65213996Sgiacomo.travaglini@arm.com warn("Unexpected address (0x%x:%i), assuming RAZ\n", addr, size); 65313996Sgiacomo.travaglini@arm.com return 0; 65413996Sgiacomo.travaglini@arm.com } 65513996Sgiacomo.travaglini@arm.com } else { 65613996Sgiacomo.travaglini@arm.com panic("Invalid access size: %i\n", size); 65713996Sgiacomo.travaglini@arm.com } 65813996Sgiacomo.travaglini@arm.com} 65913996Sgiacomo.travaglini@arm.com 66013996Sgiacomo.travaglini@arm.comvoid 66113996Sgiacomo.travaglini@arm.comGenericTimerMem::ctrlWrite(Addr addr, size_t size, uint64_t value) 66213996Sgiacomo.travaglini@arm.com{ 66313996Sgiacomo.travaglini@arm.com if (size == 4) { 66413996Sgiacomo.travaglini@arm.com switch (addr) { 66513996Sgiacomo.travaglini@arm.com case CTRL_CNTFRQ: 66613996Sgiacomo.travaglini@arm.com case CTRL_CNTNSAR: 66713996Sgiacomo.travaglini@arm.com case CTRL_CNTTIDR: 66813996Sgiacomo.travaglini@arm.com case CTRL_CNTACR_BASE: 66913996Sgiacomo.travaglini@arm.com warn("Write to unimplemented control register (0x%x)\n", addr); 67013996Sgiacomo.travaglini@arm.com return; 67113996Sgiacomo.travaglini@arm.com 67213996Sgiacomo.travaglini@arm.com case CTRL_CNTVOFF_LO_BASE: 67313996Sgiacomo.travaglini@arm.com virtTimer.setOffset( 67413996Sgiacomo.travaglini@arm.com insertBits(virtTimer.offset(), 31, 0, value)); 67513996Sgiacomo.travaglini@arm.com return; 67613996Sgiacomo.travaglini@arm.com 67713996Sgiacomo.travaglini@arm.com case CTRL_CNTVOFF_HI_BASE: 67813996Sgiacomo.travaglini@arm.com virtTimer.setOffset( 67913996Sgiacomo.travaglini@arm.com insertBits(virtTimer.offset(), 63, 32, value)); 68013996Sgiacomo.travaglini@arm.com return; 68113996Sgiacomo.travaglini@arm.com 68213996Sgiacomo.travaglini@arm.com default: 68313996Sgiacomo.travaglini@arm.com warn("Ignoring write to unexpected address (0x%x:%i)\n", 68413996Sgiacomo.travaglini@arm.com addr, size); 68513996Sgiacomo.travaglini@arm.com return; 68613996Sgiacomo.travaglini@arm.com } 68713996Sgiacomo.travaglini@arm.com } else if (size == 8) { 68813996Sgiacomo.travaglini@arm.com switch (addr) { 68913996Sgiacomo.travaglini@arm.com case CTRL_CNTVOFF_LO_BASE: 69013996Sgiacomo.travaglini@arm.com virtTimer.setOffset(value); 69113996Sgiacomo.travaglini@arm.com return; 69213996Sgiacomo.travaglini@arm.com 69313996Sgiacomo.travaglini@arm.com default: 69413996Sgiacomo.travaglini@arm.com warn("Ignoring write to unexpected address (0x%x:%i)\n", 69513996Sgiacomo.travaglini@arm.com addr, size); 69613996Sgiacomo.travaglini@arm.com return; 69713996Sgiacomo.travaglini@arm.com } 69813996Sgiacomo.travaglini@arm.com } else { 69913996Sgiacomo.travaglini@arm.com panic("Invalid access size: %i\n", size); 70013996Sgiacomo.travaglini@arm.com } 70113996Sgiacomo.travaglini@arm.com} 70213996Sgiacomo.travaglini@arm.com 70313996Sgiacomo.travaglini@arm.comuint64_t 70413996Sgiacomo.travaglini@arm.comGenericTimerMem::timerRead(Addr addr, size_t size) const 70513996Sgiacomo.travaglini@arm.com{ 70613996Sgiacomo.travaglini@arm.com if (size == 4) { 70713996Sgiacomo.travaglini@arm.com switch (addr) { 70813996Sgiacomo.travaglini@arm.com case TIMER_CNTPCT_LO: 70913996Sgiacomo.travaglini@arm.com return physTimer.value(); 71013996Sgiacomo.travaglini@arm.com 71113996Sgiacomo.travaglini@arm.com case TIMER_CNTPCT_HI: 71213996Sgiacomo.travaglini@arm.com return physTimer.value() >> 32; 71313996Sgiacomo.travaglini@arm.com 71413996Sgiacomo.travaglini@arm.com case TIMER_CNTVCT_LO: 71513996Sgiacomo.travaglini@arm.com return virtTimer.value(); 71613996Sgiacomo.travaglini@arm.com 71713996Sgiacomo.travaglini@arm.com case TIMER_CNTVCT_HI: 71813996Sgiacomo.travaglini@arm.com return virtTimer.value() >> 32; 71913996Sgiacomo.travaglini@arm.com 72013996Sgiacomo.travaglini@arm.com case TIMER_CNTFRQ: 72113996Sgiacomo.travaglini@arm.com return systemCounter.freq(); 72213996Sgiacomo.travaglini@arm.com 72313996Sgiacomo.travaglini@arm.com case TIMER_CNTEL0ACR: 72413996Sgiacomo.travaglini@arm.com warn("Read from unimplemented timer register (0x%x)\n", addr); 72513996Sgiacomo.travaglini@arm.com return 0; 72613996Sgiacomo.travaglini@arm.com 72713996Sgiacomo.travaglini@arm.com case CTRL_CNTVOFF_LO_BASE: 72813996Sgiacomo.travaglini@arm.com return virtTimer.offset(); 72913996Sgiacomo.travaglini@arm.com 73013996Sgiacomo.travaglini@arm.com case CTRL_CNTVOFF_HI_BASE: 73113996Sgiacomo.travaglini@arm.com return virtTimer.offset() >> 32; 73213996Sgiacomo.travaglini@arm.com 73313996Sgiacomo.travaglini@arm.com case TIMER_CNTP_CVAL_LO: 73413996Sgiacomo.travaglini@arm.com return physTimer.compareValue(); 73513996Sgiacomo.travaglini@arm.com 73613996Sgiacomo.travaglini@arm.com case TIMER_CNTP_CVAL_HI: 73713996Sgiacomo.travaglini@arm.com return physTimer.compareValue() >> 32; 73813996Sgiacomo.travaglini@arm.com 73913996Sgiacomo.travaglini@arm.com case TIMER_CNTP_TVAL: 74013996Sgiacomo.travaglini@arm.com return physTimer.timerValue(); 74113996Sgiacomo.travaglini@arm.com 74213996Sgiacomo.travaglini@arm.com case TIMER_CNTP_CTL: 74313996Sgiacomo.travaglini@arm.com return physTimer.control(); 74413996Sgiacomo.travaglini@arm.com 74513996Sgiacomo.travaglini@arm.com case TIMER_CNTV_CVAL_LO: 74613996Sgiacomo.travaglini@arm.com return virtTimer.compareValue(); 74713996Sgiacomo.travaglini@arm.com 74813996Sgiacomo.travaglini@arm.com case TIMER_CNTV_CVAL_HI: 74913996Sgiacomo.travaglini@arm.com return virtTimer.compareValue() >> 32; 75013996Sgiacomo.travaglini@arm.com 75113996Sgiacomo.travaglini@arm.com case TIMER_CNTV_TVAL: 75213996Sgiacomo.travaglini@arm.com return virtTimer.timerValue(); 75313996Sgiacomo.travaglini@arm.com 75413996Sgiacomo.travaglini@arm.com case TIMER_CNTV_CTL: 75513996Sgiacomo.travaglini@arm.com return virtTimer.control(); 75613996Sgiacomo.travaglini@arm.com 75713996Sgiacomo.travaglini@arm.com default: 75813996Sgiacomo.travaglini@arm.com warn("Unexpected address (0x%x:%i), assuming RAZ\n", addr, size); 75913996Sgiacomo.travaglini@arm.com return 0; 76013996Sgiacomo.travaglini@arm.com } 76113996Sgiacomo.travaglini@arm.com } else if (size == 8) { 76213996Sgiacomo.travaglini@arm.com switch (addr) { 76313996Sgiacomo.travaglini@arm.com case TIMER_CNTPCT_LO: 76413996Sgiacomo.travaglini@arm.com return physTimer.value(); 76513996Sgiacomo.travaglini@arm.com 76613996Sgiacomo.travaglini@arm.com case TIMER_CNTVCT_LO: 76713996Sgiacomo.travaglini@arm.com return virtTimer.value(); 76813996Sgiacomo.travaglini@arm.com 76913996Sgiacomo.travaglini@arm.com case CTRL_CNTVOFF_LO_BASE: 77013996Sgiacomo.travaglini@arm.com return virtTimer.offset(); 77113996Sgiacomo.travaglini@arm.com 77213996Sgiacomo.travaglini@arm.com case TIMER_CNTP_CVAL_LO: 77313996Sgiacomo.travaglini@arm.com return physTimer.compareValue(); 77413996Sgiacomo.travaglini@arm.com 77513996Sgiacomo.travaglini@arm.com case TIMER_CNTV_CVAL_LO: 77613996Sgiacomo.travaglini@arm.com return virtTimer.compareValue(); 77713996Sgiacomo.travaglini@arm.com 77813996Sgiacomo.travaglini@arm.com default: 77914181Sgiacomo.travaglini@arm.com warn("Unexpected address (0x%x:%i), assuming RAZ\n", addr, size); 78013996Sgiacomo.travaglini@arm.com return 0; 78113996Sgiacomo.travaglini@arm.com } 78213996Sgiacomo.travaglini@arm.com } else { 78314187Sgiacomo.travaglini@arm.com panic("Invalid access size: %i\n", size); 78413996Sgiacomo.travaglini@arm.com } 78513996Sgiacomo.travaglini@arm.com} 78613996Sgiacomo.travaglini@arm.com 78713996Sgiacomo.travaglini@arm.comvoid 78813996Sgiacomo.travaglini@arm.comGenericTimerMem::timerWrite(Addr addr, size_t size, uint64_t value) 78913996Sgiacomo.travaglini@arm.com{ 79014187Sgiacomo.travaglini@arm.com if (size == 4) { 79114187Sgiacomo.travaglini@arm.com switch (addr) { 79214187Sgiacomo.travaglini@arm.com case TIMER_CNTEL0ACR: 79314187Sgiacomo.travaglini@arm.com warn("Unimplemented timer register (0x%x)\n", addr); 79414187Sgiacomo.travaglini@arm.com return; 79514187Sgiacomo.travaglini@arm.com 79614187Sgiacomo.travaglini@arm.com case TIMER_CNTP_CVAL_LO: 79714187Sgiacomo.travaglini@arm.com physTimer.setCompareValue( 79814187Sgiacomo.travaglini@arm.com insertBits(physTimer.compareValue(), 31, 0, value)); 79913996Sgiacomo.travaglini@arm.com return; 80013996Sgiacomo.travaglini@arm.com 80113996Sgiacomo.travaglini@arm.com case TIMER_CNTP_CVAL_HI: 80213996Sgiacomo.travaglini@arm.com physTimer.setCompareValue( 80313996Sgiacomo.travaglini@arm.com insertBits(physTimer.compareValue(), 63, 32, value)); 80413996Sgiacomo.travaglini@arm.com return; 80513996Sgiacomo.travaglini@arm.com 80613996Sgiacomo.travaglini@arm.com case TIMER_CNTP_TVAL: 80713996Sgiacomo.travaglini@arm.com physTimer.setTimerValue(value); 80813996Sgiacomo.travaglini@arm.com return; 80913996Sgiacomo.travaglini@arm.com 81013996Sgiacomo.travaglini@arm.com case TIMER_CNTP_CTL: 81113996Sgiacomo.travaglini@arm.com physTimer.setControl(value); 81213996Sgiacomo.travaglini@arm.com return; 81313996Sgiacomo.travaglini@arm.com 81413996Sgiacomo.travaglini@arm.com case TIMER_CNTV_CVAL_LO: 81513996Sgiacomo.travaglini@arm.com virtTimer.setCompareValue( 81613996Sgiacomo.travaglini@arm.com insertBits(virtTimer.compareValue(), 31, 0, value)); 81713996Sgiacomo.travaglini@arm.com return; 81813996Sgiacomo.travaglini@arm.com 81913996Sgiacomo.travaglini@arm.com case TIMER_CNTV_CVAL_HI: 82013996Sgiacomo.travaglini@arm.com virtTimer.setCompareValue( 82113996Sgiacomo.travaglini@arm.com insertBits(virtTimer.compareValue(), 63, 32, value)); 82213996Sgiacomo.travaglini@arm.com return; 82313996Sgiacomo.travaglini@arm.com 82413996Sgiacomo.travaglini@arm.com case TIMER_CNTV_TVAL: 82513996Sgiacomo.travaglini@arm.com virtTimer.setTimerValue(value); 82613996Sgiacomo.travaglini@arm.com return; 82713996Sgiacomo.travaglini@arm.com 82813996Sgiacomo.travaglini@arm.com case TIMER_CNTV_CTL: 82913996Sgiacomo.travaglini@arm.com virtTimer.setControl(value); 83013996Sgiacomo.travaglini@arm.com return; 83113996Sgiacomo.travaglini@arm.com 83213996Sgiacomo.travaglini@arm.com default: 83313996Sgiacomo.travaglini@arm.com warn("Unexpected address (0x%x:%i), ignoring write\n", addr, size); 83413996Sgiacomo.travaglini@arm.com return; 83513996Sgiacomo.travaglini@arm.com } 83613996Sgiacomo.travaglini@arm.com } else if (size == 8) { 83713996Sgiacomo.travaglini@arm.com switch (addr) { 83813996Sgiacomo.travaglini@arm.com case TIMER_CNTP_CVAL_LO: 83913996Sgiacomo.travaglini@arm.com return physTimer.setCompareValue(value); 84013996Sgiacomo.travaglini@arm.com 84113996Sgiacomo.travaglini@arm.com case TIMER_CNTV_CVAL_LO: 84213996Sgiacomo.travaglini@arm.com return virtTimer.setCompareValue(value); 84314180Sgiacomo.travaglini@arm.com 84414180Sgiacomo.travaglini@arm.com default: 84514180Sgiacomo.travaglini@arm.com warn("Unexpected address (0x%x:%i), ignoring write\n", addr, size); 84614180Sgiacomo.travaglini@arm.com return; 84713996Sgiacomo.travaglini@arm.com } 84813996Sgiacomo.travaglini@arm.com } else { 84913996Sgiacomo.travaglini@arm.com panic("Invalid access size: %i\n", size); 85013996Sgiacomo.travaglini@arm.com } 85114180Sgiacomo.travaglini@arm.com} 85214180Sgiacomo.travaglini@arm.com 85314180Sgiacomo.travaglini@arm.comGenericTimer * 85414180Sgiacomo.travaglini@arm.comGenericTimerParams::create() 85513996Sgiacomo.travaglini@arm.com{ 85613996Sgiacomo.travaglini@arm.com return new GenericTimer(this); 85713996Sgiacomo.travaglini@arm.com} 85813996Sgiacomo.travaglini@arm.com 85914180Sgiacomo.travaglini@arm.comGenericTimerMem * 86014180Sgiacomo.travaglini@arm.comGenericTimerMemParams::create() 86114180Sgiacomo.travaglini@arm.com{ 86214180Sgiacomo.travaglini@arm.com return new GenericTimerMem(this); 86314168Sgiacomo.travaglini@arm.com} 86414168Sgiacomo.travaglini@arm.com