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