110037SARM gem5 Developers/*
212971Sandreas.sandberg@arm.com * Copyright (c) 2013, 2015, 2017-2018 ARM Limited
310037SARM gem5 Developers * All rights reserved.
410037SARM gem5 Developers *
510037SARM gem5 Developers * The license below extends only to copyright in the software and shall
610037SARM gem5 Developers * not be construed as granting a license to any other intellectual
710037SARM gem5 Developers * property including but not limited to intellectual property relating
810037SARM gem5 Developers * to a hardware implementation of the functionality of the software
910037SARM gem5 Developers * licensed hereunder.  You may use the software subject to the license
1010037SARM gem5 Developers * terms below provided that you ensure that this notice is replicated
1110037SARM gem5 Developers * unmodified and in its entirety in all distributions of the software,
1210037SARM gem5 Developers * modified or unmodified, in source code or in binary form.
1310037SARM gem5 Developers *
1410037SARM gem5 Developers * Redistribution and use in source and binary forms, with or without
1510037SARM gem5 Developers * modification, are permitted provided that the following conditions are
1610037SARM gem5 Developers * met: redistributions of source code must retain the above copyright
1710037SARM gem5 Developers * notice, this list of conditions and the following disclaimer;
1810037SARM gem5 Developers * redistributions in binary form must reproduce the above copyright
1910037SARM gem5 Developers * notice, this list of conditions and the following disclaimer in the
2010037SARM gem5 Developers * documentation and/or other materials provided with the distribution;
2110037SARM gem5 Developers * neither the name of the copyright holders nor the names of its
2210037SARM gem5 Developers * contributors may be used to endorse or promote products derived from
2310037SARM gem5 Developers * this software without specific prior written permission.
2410037SARM gem5 Developers *
2510037SARM gem5 Developers * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2610037SARM gem5 Developers * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2710037SARM gem5 Developers * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2810037SARM gem5 Developers * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2910037SARM gem5 Developers * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
3010037SARM gem5 Developers * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
3110037SARM gem5 Developers * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
3210037SARM gem5 Developers * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
3310037SARM gem5 Developers * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3410037SARM gem5 Developers * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
3510037SARM gem5 Developers * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3610037SARM gem5 Developers *
3710037SARM gem5 Developers * Authors: Giacomo Gabrielli
3810844Sandreas.sandberg@arm.com *          Andreas Sandberg
3910037SARM gem5 Developers */
4010037SARM gem5 Developers
4110844Sandreas.sandberg@arm.com#include "dev/arm/generic_timer.hh"
4210844Sandreas.sandberg@arm.com
4310037SARM gem5 Developers#include "arch/arm/system.hh"
4410037SARM gem5 Developers#include "debug/Timer.hh"
4510037SARM gem5 Developers#include "dev/arm/base_gic.hh"
4610847Sandreas.sandberg@arm.com#include "mem/packet_access.hh"
4710844Sandreas.sandberg@arm.com#include "params/GenericTimer.hh"
4810847Sandreas.sandberg@arm.com#include "params/GenericTimerMem.hh"
4910844Sandreas.sandberg@arm.com
5010844Sandreas.sandberg@arm.comSystemCounter::SystemCounter()
5110844Sandreas.sandberg@arm.com    : _freq(0), _period(0), _resetTick(0), _regCntkctl(0)
5210844Sandreas.sandberg@arm.com{
5310844Sandreas.sandberg@arm.com    setFreq(0x01800000);
5410844Sandreas.sandberg@arm.com}
5510037SARM gem5 Developers
5610037SARM gem5 Developersvoid
5710844Sandreas.sandberg@arm.comSystemCounter::setFreq(uint32_t freq)
5810037SARM gem5 Developers{
5910037SARM gem5 Developers    if (_freq != 0) {
6010037SARM gem5 Developers        // Altering the frequency after boot shouldn't be done in practice.
6110037SARM gem5 Developers        warn_once("The frequency of the system counter has already been set");
6210037SARM gem5 Developers    }
6310037SARM gem5 Developers    _freq = freq;
6410037SARM gem5 Developers    _period = (1.0 / freq) * SimClock::Frequency;
6510037SARM gem5 Developers    _resetTick = curTick();
6610037SARM gem5 Developers}
6710037SARM gem5 Developers
6810037SARM gem5 Developersvoid
6910905Sandreas.sandberg@arm.comSystemCounter::serialize(CheckpointOut &cp) const
7010037SARM gem5 Developers{
7110844Sandreas.sandberg@arm.com    SERIALIZE_SCALAR(_regCntkctl);
7212733Sandreas.sandberg@arm.com    SERIALIZE_SCALAR(_regCnthctl);
7310037SARM gem5 Developers    SERIALIZE_SCALAR(_freq);
7410037SARM gem5 Developers    SERIALIZE_SCALAR(_period);
7510037SARM gem5 Developers    SERIALIZE_SCALAR(_resetTick);
7610037SARM gem5 Developers}
7710037SARM gem5 Developers
7810037SARM gem5 Developersvoid
7910905Sandreas.sandberg@arm.comSystemCounter::unserialize(CheckpointIn &cp)
8010037SARM gem5 Developers{
8110844Sandreas.sandberg@arm.com    // We didn't handle CNTKCTL in this class before, assume it's zero
8210844Sandreas.sandberg@arm.com    // if it isn't present.
8310844Sandreas.sandberg@arm.com    if (!UNSERIALIZE_OPT_SCALAR(_regCntkctl))
8410844Sandreas.sandberg@arm.com        _regCntkctl = 0;
8512733Sandreas.sandberg@arm.com    if (!UNSERIALIZE_OPT_SCALAR(_regCnthctl))
8612733Sandreas.sandberg@arm.com        _regCnthctl = 0;
8710037SARM gem5 Developers    UNSERIALIZE_SCALAR(_freq);
8810037SARM gem5 Developers    UNSERIALIZE_SCALAR(_period);
8910037SARM gem5 Developers    UNSERIALIZE_SCALAR(_resetTick);
9010037SARM gem5 Developers}
9110037SARM gem5 Developers
9210844Sandreas.sandberg@arm.com
9310844Sandreas.sandberg@arm.com
9410844Sandreas.sandberg@arm.comArchTimer::ArchTimer(const std::string &name,
9510844Sandreas.sandberg@arm.com                     SimObject &parent,
9610844Sandreas.sandberg@arm.com                     SystemCounter &sysctr,
9712975Sgiacomo.travaglini@arm.com                     ArmInterruptPin *interrupt)
9810844Sandreas.sandberg@arm.com    : _name(name), _parent(parent), _systemCounter(sysctr),
9910844Sandreas.sandberg@arm.com      _interrupt(interrupt),
10010845Sandreas.sandberg@arm.com      _control(0), _counterLimit(0), _offset(0),
10112086Sspwilson2@wisc.edu      _counterLimitReachedEvent([this]{ counterLimitReached(); }, name)
10210844Sandreas.sandberg@arm.com{
10310844Sandreas.sandberg@arm.com}
10410844Sandreas.sandberg@arm.com
10510037SARM gem5 Developersvoid
10610844Sandreas.sandberg@arm.comArchTimer::counterLimitReached()
10710037SARM gem5 Developers{
10810037SARM gem5 Developers    _control.istatus = 1;
10910037SARM gem5 Developers
11010037SARM gem5 Developers    if (!_control.enable)
11110037SARM gem5 Developers        return;
11210037SARM gem5 Developers
11310844Sandreas.sandberg@arm.com    DPRINTF(Timer, "Counter limit reached\n");
11410037SARM gem5 Developers    if (!_control.imask) {
11512102SCurtis.Dunham@arm.com        if (scheduleEvents()) {
11612102SCurtis.Dunham@arm.com            DPRINTF(Timer, "Causing interrupt\n");
11712975Sgiacomo.travaglini@arm.com            _interrupt->raise();
11812102SCurtis.Dunham@arm.com        } else {
11912102SCurtis.Dunham@arm.com            DPRINTF(Timer, "Kvm mode; skipping simulated interrupt\n");
12012102SCurtis.Dunham@arm.com        }
12110037SARM gem5 Developers    }
12210037SARM gem5 Developers}
12310037SARM gem5 Developers
12410037SARM gem5 Developersvoid
12510844Sandreas.sandberg@arm.comArchTimer::updateCounter()
12610037SARM gem5 Developers{
12710037SARM gem5 Developers    if (_counterLimitReachedEvent.scheduled())
12810844Sandreas.sandberg@arm.com        _parent.deschedule(_counterLimitReachedEvent);
12910844Sandreas.sandberg@arm.com    if (value() >= _counterLimit) {
13010037SARM gem5 Developers        counterLimitReached();
13110037SARM gem5 Developers    } else {
13210037SARM gem5 Developers        _control.istatus = 0;
13312102SCurtis.Dunham@arm.com        if (scheduleEvents()) {
13412102SCurtis.Dunham@arm.com            const auto period(_systemCounter.period());
13512102SCurtis.Dunham@arm.com            _parent.schedule(_counterLimitReachedEvent,
13612102SCurtis.Dunham@arm.com                 curTick() + (_counterLimit - value()) * period);
13712102SCurtis.Dunham@arm.com        }
13810037SARM gem5 Developers    }
13910037SARM gem5 Developers}
14010037SARM gem5 Developers
14110037SARM gem5 Developersvoid
14210844Sandreas.sandberg@arm.comArchTimer::setCompareValue(uint64_t val)
14310037SARM gem5 Developers{
14410844Sandreas.sandberg@arm.com    _counterLimit = val;
14510844Sandreas.sandberg@arm.com    updateCounter();
14610037SARM gem5 Developers}
14710037SARM gem5 Developers
14810037SARM gem5 Developersvoid
14910844Sandreas.sandberg@arm.comArchTimer::setTimerValue(uint32_t val)
15010844Sandreas.sandberg@arm.com{
15110844Sandreas.sandberg@arm.com    setCompareValue(value() + sext<32>(val));
15210844Sandreas.sandberg@arm.com}
15310844Sandreas.sandberg@arm.com
15410844Sandreas.sandberg@arm.comvoid
15510844Sandreas.sandberg@arm.comArchTimer::setControl(uint32_t val)
15610037SARM gem5 Developers{
15710037SARM gem5 Developers    ArchTimerCtrl new_ctl = val;
15810037SARM gem5 Developers    if ((new_ctl.enable && !new_ctl.imask) &&
15910037SARM gem5 Developers        !(_control.enable && !_control.imask)) {
16010037SARM gem5 Developers        // Re-evalute the timer condition
16110844Sandreas.sandberg@arm.com        if (_counterLimit >= value()) {
16210037SARM gem5 Developers            _control.istatus = 1;
16310037SARM gem5 Developers
16410037SARM gem5 Developers            DPRINTF(Timer, "Causing interrupt in control\n");
16510844Sandreas.sandberg@arm.com            //_interrupt.send();
16610037SARM gem5 Developers        }
16710037SARM gem5 Developers    }
16810037SARM gem5 Developers    _control.enable = new_ctl.enable;
16910037SARM gem5 Developers    _control.imask = new_ctl.imask;
17010037SARM gem5 Developers}
17110037SARM gem5 Developers
17210845Sandreas.sandberg@arm.comvoid
17310845Sandreas.sandberg@arm.comArchTimer::setOffset(uint64_t val)
17410845Sandreas.sandberg@arm.com{
17510845Sandreas.sandberg@arm.com    _offset = val;
17610845Sandreas.sandberg@arm.com    updateCounter();
17710845Sandreas.sandberg@arm.com}
17810845Sandreas.sandberg@arm.com
17910844Sandreas.sandberg@arm.comuint64_t
18010844Sandreas.sandberg@arm.comArchTimer::value() const
18110844Sandreas.sandberg@arm.com{
18210845Sandreas.sandberg@arm.com    return _systemCounter.value() - _offset;
18310844Sandreas.sandberg@arm.com}
18410844Sandreas.sandberg@arm.com
18510037SARM gem5 Developersvoid
18610905Sandreas.sandberg@arm.comArchTimer::serialize(CheckpointOut &cp) const
18710037SARM gem5 Developers{
18810905Sandreas.sandberg@arm.com    paramOut(cp, "control_serial", _control);
18910037SARM gem5 Developers    SERIALIZE_SCALAR(_counterLimit);
19010845Sandreas.sandberg@arm.com    SERIALIZE_SCALAR(_offset);
19110037SARM gem5 Developers}
19210037SARM gem5 Developers
19310037SARM gem5 Developersvoid
19410905Sandreas.sandberg@arm.comArchTimer::unserialize(CheckpointIn &cp)
19510037SARM gem5 Developers{
19610905Sandreas.sandberg@arm.com    paramIn(cp, "control_serial", _control);
19710845Sandreas.sandberg@arm.com    // We didn't serialize an offset before we added support for the
19810845Sandreas.sandberg@arm.com    // virtual timer. Consider it optional to maintain backwards
19910845Sandreas.sandberg@arm.com    // compatibility.
20010845Sandreas.sandberg@arm.com    if (!UNSERIALIZE_OPT_SCALAR(_offset))
20110845Sandreas.sandberg@arm.com        _offset = 0;
20212101SCurtis.Dunham@arm.com
20312101SCurtis.Dunham@arm.com    // We no longer schedule an event here because we may enter KVM
20412101SCurtis.Dunham@arm.com    // emulation.  The event creation is delayed until drainResume().
20512101SCurtis.Dunham@arm.com}
20612101SCurtis.Dunham@arm.com
20712101SCurtis.Dunham@arm.comDrainState
20812101SCurtis.Dunham@arm.comArchTimer::drain()
20912101SCurtis.Dunham@arm.com{
21012101SCurtis.Dunham@arm.com    if (_counterLimitReachedEvent.scheduled())
21112101SCurtis.Dunham@arm.com        _parent.deschedule(_counterLimitReachedEvent);
21212101SCurtis.Dunham@arm.com
21312101SCurtis.Dunham@arm.com    return DrainState::Drained;
21412101SCurtis.Dunham@arm.com}
21512101SCurtis.Dunham@arm.com
21612101SCurtis.Dunham@arm.comvoid
21712101SCurtis.Dunham@arm.comArchTimer::drainResume()
21812101SCurtis.Dunham@arm.com{
21912101SCurtis.Dunham@arm.com    updateCounter();
22010037SARM gem5 Developers}
22110037SARM gem5 Developers
22210844Sandreas.sandberg@arm.comGenericTimer::GenericTimer(GenericTimerParams *p)
22312467SCurtis.Dunham@arm.com    : ClockedObject(p),
22412975Sgiacomo.travaglini@arm.com      system(*p->system)
22510844Sandreas.sandberg@arm.com{
22611668Sandreas.sandberg@arm.com    fatal_if(!p->system, "No system specified, can't instantiate timer.\n");
22712102SCurtis.Dunham@arm.com    system.setGenericTimer(this);
22810037SARM gem5 Developers}
22910037SARM gem5 Developers
23012975Sgiacomo.travaglini@arm.comconst GenericTimerParams *
23112975Sgiacomo.travaglini@arm.comGenericTimer::params() const
23212975Sgiacomo.travaglini@arm.com{
23312975Sgiacomo.travaglini@arm.com    return dynamic_cast<const GenericTimerParams *>(_params);
23412975Sgiacomo.travaglini@arm.com}
23512975Sgiacomo.travaglini@arm.com
23610037SARM gem5 Developersvoid
23710905Sandreas.sandberg@arm.comGenericTimer::serialize(CheckpointOut &cp) const
23810037SARM gem5 Developers{
23910905Sandreas.sandberg@arm.com    paramOut(cp, "cpu_count", timers.size());
24010844Sandreas.sandberg@arm.com
24110905Sandreas.sandberg@arm.com    systemCounter.serializeSection(cp, "sys_counter");
24210844Sandreas.sandberg@arm.com
24310844Sandreas.sandberg@arm.com    for (int i = 0; i < timers.size(); ++i) {
24410905Sandreas.sandberg@arm.com        const CoreTimers &core(*timers[i]);
24510844Sandreas.sandberg@arm.com
24610905Sandreas.sandberg@arm.com        // This should really be phys_timerN, but we are stuck with
24710905Sandreas.sandberg@arm.com        // arch_timer for backwards compatibility.
24812733Sandreas.sandberg@arm.com        core.physNS.serializeSection(cp, csprintf("arch_timer%d", i));
24912733Sandreas.sandberg@arm.com        core.physS.serializeSection(cp, csprintf("phys_s_timer%d", i));
25010905Sandreas.sandberg@arm.com        core.virt.serializeSection(cp, csprintf("virt_timer%d", i));
25112733Sandreas.sandberg@arm.com        core.hyp.serializeSection(cp, csprintf("hyp_timer%d", i));
25210037SARM gem5 Developers    }
25310037SARM gem5 Developers}
25410037SARM gem5 Developers
25510037SARM gem5 Developersvoid
25610905Sandreas.sandberg@arm.comGenericTimer::unserialize(CheckpointIn &cp)
25710037SARM gem5 Developers{
25810905Sandreas.sandberg@arm.com    systemCounter.unserializeSection(cp, "sys_counter");
25910844Sandreas.sandberg@arm.com
26010844Sandreas.sandberg@arm.com    // Try to unserialize the CPU count. Old versions of the timer
26110844Sandreas.sandberg@arm.com    // model assumed a 8 CPUs, so we fall back to that if the field
26210844Sandreas.sandberg@arm.com    // isn't present.
26310844Sandreas.sandberg@arm.com    static const unsigned OLD_CPU_MAX = 8;
26410844Sandreas.sandberg@arm.com    unsigned cpu_count;
26510844Sandreas.sandberg@arm.com    if (!UNSERIALIZE_OPT_SCALAR(cpu_count)) {
26610844Sandreas.sandberg@arm.com        warn("Checkpoint does not contain CPU count, assuming %i CPUs\n",
26710844Sandreas.sandberg@arm.com             OLD_CPU_MAX);
26810844Sandreas.sandberg@arm.com        cpu_count = OLD_CPU_MAX;
26910844Sandreas.sandberg@arm.com    }
27010844Sandreas.sandberg@arm.com
27110844Sandreas.sandberg@arm.com    for (int i = 0; i < cpu_count; ++i) {
27210844Sandreas.sandberg@arm.com        CoreTimers &core(getTimers(i));
27310844Sandreas.sandberg@arm.com        // This should really be phys_timerN, but we are stuck with
27410844Sandreas.sandberg@arm.com        // arch_timer for backwards compatibility.
27512733Sandreas.sandberg@arm.com        core.physNS.unserializeSection(cp, csprintf("arch_timer%d", i));
27612733Sandreas.sandberg@arm.com        core.physS.unserializeSection(cp, csprintf("phys_s_timer%d", i));
27710905Sandreas.sandberg@arm.com        core.virt.unserializeSection(cp, csprintf("virt_timer%d", i));
27812733Sandreas.sandberg@arm.com        core.hyp.unserializeSection(cp, csprintf("hyp_timer%d", i));
27910037SARM gem5 Developers    }
28010037SARM gem5 Developers}
28110037SARM gem5 Developers
28210844Sandreas.sandberg@arm.com
28310844Sandreas.sandberg@arm.comGenericTimer::CoreTimers &
28410844Sandreas.sandberg@arm.comGenericTimer::getTimers(int cpu_id)
28510844Sandreas.sandberg@arm.com{
28610844Sandreas.sandberg@arm.com    if (cpu_id >= timers.size())
28710844Sandreas.sandberg@arm.com        createTimers(cpu_id + 1);
28810844Sandreas.sandberg@arm.com
28910844Sandreas.sandberg@arm.com    return *timers[cpu_id];
29010844Sandreas.sandberg@arm.com}
29110844Sandreas.sandberg@arm.com
29210844Sandreas.sandberg@arm.comvoid
29310844Sandreas.sandberg@arm.comGenericTimer::createTimers(unsigned cpus)
29410844Sandreas.sandberg@arm.com{
29510844Sandreas.sandberg@arm.com    assert(timers.size() < cpus);
29612975Sgiacomo.travaglini@arm.com    auto p = static_cast<const GenericTimerParams *>(_params);
29710844Sandreas.sandberg@arm.com
29810844Sandreas.sandberg@arm.com    const unsigned old_cpu_count(timers.size());
29910844Sandreas.sandberg@arm.com    timers.resize(cpus);
30010844Sandreas.sandberg@arm.com    for (unsigned i = old_cpu_count; i < cpus; ++i) {
30112975Sgiacomo.travaglini@arm.com
30212975Sgiacomo.travaglini@arm.com        ThreadContext *tc = system.getThreadContext(i);
30312975Sgiacomo.travaglini@arm.com
30410844Sandreas.sandberg@arm.com        timers[i].reset(
30512733Sandreas.sandberg@arm.com            new CoreTimers(*this, system, i,
30612975Sgiacomo.travaglini@arm.com                           p->int_phys_s->get(tc),
30712975Sgiacomo.travaglini@arm.com                           p->int_phys_ns->get(tc),
30812975Sgiacomo.travaglini@arm.com                           p->int_virt->get(tc),
30912975Sgiacomo.travaglini@arm.com                           p->int_hyp->get(tc)));
31010844Sandreas.sandberg@arm.com    }
31110844Sandreas.sandberg@arm.com}
31210844Sandreas.sandberg@arm.com
31310844Sandreas.sandberg@arm.com
31410844Sandreas.sandberg@arm.comvoid
31513557Sgabeblack@google.comGenericTimer::setMiscReg(int reg, unsigned cpu, RegVal val)
31610844Sandreas.sandberg@arm.com{
31710844Sandreas.sandberg@arm.com    CoreTimers &core(getTimers(cpu));
31810844Sandreas.sandberg@arm.com
31910844Sandreas.sandberg@arm.com    switch (reg) {
32010844Sandreas.sandberg@arm.com      case MISCREG_CNTFRQ:
32110844Sandreas.sandberg@arm.com      case MISCREG_CNTFRQ_EL0:
32210844Sandreas.sandberg@arm.com        systemCounter.setFreq(val);
32310844Sandreas.sandberg@arm.com        return;
32410844Sandreas.sandberg@arm.com
32510844Sandreas.sandberg@arm.com      case MISCREG_CNTKCTL:
32610844Sandreas.sandberg@arm.com      case MISCREG_CNTKCTL_EL1:
32710844Sandreas.sandberg@arm.com        systemCounter.setKernelControl(val);
32810844Sandreas.sandberg@arm.com        return;
32910844Sandreas.sandberg@arm.com
33012733Sandreas.sandberg@arm.com      case MISCREG_CNTHCTL:
33112733Sandreas.sandberg@arm.com      case MISCREG_CNTHCTL_EL2:
33212733Sandreas.sandberg@arm.com        systemCounter.setHypControl(val);
33312733Sandreas.sandberg@arm.com        return;
33412733Sandreas.sandberg@arm.com
33512733Sandreas.sandberg@arm.com      // Physical timer (NS)
33610844Sandreas.sandberg@arm.com      case MISCREG_CNTP_CVAL_NS:
33710844Sandreas.sandberg@arm.com      case MISCREG_CNTP_CVAL_EL0:
33812733Sandreas.sandberg@arm.com        core.physNS.setCompareValue(val);
33910844Sandreas.sandberg@arm.com        return;
34010844Sandreas.sandberg@arm.com
34110844Sandreas.sandberg@arm.com      case MISCREG_CNTP_TVAL_NS:
34210844Sandreas.sandberg@arm.com      case MISCREG_CNTP_TVAL_EL0:
34312733Sandreas.sandberg@arm.com        core.physNS.setTimerValue(val);
34410844Sandreas.sandberg@arm.com        return;
34510844Sandreas.sandberg@arm.com
34610844Sandreas.sandberg@arm.com      case MISCREG_CNTP_CTL_NS:
34710844Sandreas.sandberg@arm.com      case MISCREG_CNTP_CTL_EL0:
34812733Sandreas.sandberg@arm.com        core.physNS.setControl(val);
34910844Sandreas.sandberg@arm.com        return;
35010844Sandreas.sandberg@arm.com
35110844Sandreas.sandberg@arm.com      // Count registers
35210844Sandreas.sandberg@arm.com      case MISCREG_CNTPCT:
35310844Sandreas.sandberg@arm.com      case MISCREG_CNTPCT_EL0:
35410844Sandreas.sandberg@arm.com      case MISCREG_CNTVCT:
35510844Sandreas.sandberg@arm.com      case MISCREG_CNTVCT_EL0:
35610844Sandreas.sandberg@arm.com        warn("Ignoring write to read only count register: %s\n",
35710844Sandreas.sandberg@arm.com             miscRegName[reg]);
35810844Sandreas.sandberg@arm.com        return;
35910844Sandreas.sandberg@arm.com
36010844Sandreas.sandberg@arm.com      // Virtual timer
36110844Sandreas.sandberg@arm.com      case MISCREG_CNTVOFF:
36210844Sandreas.sandberg@arm.com      case MISCREG_CNTVOFF_EL2:
36310845Sandreas.sandberg@arm.com        core.virt.setOffset(val);
36410845Sandreas.sandberg@arm.com        return;
36510845Sandreas.sandberg@arm.com
36610844Sandreas.sandberg@arm.com      case MISCREG_CNTV_CVAL:
36710844Sandreas.sandberg@arm.com      case MISCREG_CNTV_CVAL_EL0:
36810845Sandreas.sandberg@arm.com        core.virt.setCompareValue(val);
36910845Sandreas.sandberg@arm.com        return;
37010845Sandreas.sandberg@arm.com
37110844Sandreas.sandberg@arm.com      case MISCREG_CNTV_TVAL:
37210844Sandreas.sandberg@arm.com      case MISCREG_CNTV_TVAL_EL0:
37310845Sandreas.sandberg@arm.com        core.virt.setTimerValue(val);
37410845Sandreas.sandberg@arm.com        return;
37510845Sandreas.sandberg@arm.com
37610844Sandreas.sandberg@arm.com      case MISCREG_CNTV_CTL:
37710844Sandreas.sandberg@arm.com      case MISCREG_CNTV_CTL_EL0:
37810845Sandreas.sandberg@arm.com        core.virt.setControl(val);
37910845Sandreas.sandberg@arm.com        return;
38010844Sandreas.sandberg@arm.com
38112733Sandreas.sandberg@arm.com      // Physical timer (S)
38210844Sandreas.sandberg@arm.com      case MISCREG_CNTP_CTL_S:
38312733Sandreas.sandberg@arm.com      case MISCREG_CNTPS_CTL_EL1:
38412733Sandreas.sandberg@arm.com        core.physS.setControl(val);
38512733Sandreas.sandberg@arm.com        return;
38612733Sandreas.sandberg@arm.com
38712733Sandreas.sandberg@arm.com      case MISCREG_CNTP_CVAL_S:
38810844Sandreas.sandberg@arm.com      case MISCREG_CNTPS_CVAL_EL1:
38912733Sandreas.sandberg@arm.com        core.physS.setCompareValue(val);
39012733Sandreas.sandberg@arm.com        return;
39112733Sandreas.sandberg@arm.com
39212733Sandreas.sandberg@arm.com      case MISCREG_CNTP_TVAL_S:
39310844Sandreas.sandberg@arm.com      case MISCREG_CNTPS_TVAL_EL1:
39412733Sandreas.sandberg@arm.com        core.physS.setTimerValue(val);
39512733Sandreas.sandberg@arm.com        return;
39610844Sandreas.sandberg@arm.com
39712733Sandreas.sandberg@arm.com      // Hyp phys. timer, non-secure
39812733Sandreas.sandberg@arm.com      case MISCREG_CNTHP_CTL:
39912733Sandreas.sandberg@arm.com      case MISCREG_CNTHP_CTL_EL2:
40012733Sandreas.sandberg@arm.com        core.hyp.setControl(val);
40112733Sandreas.sandberg@arm.com        return;
40212733Sandreas.sandberg@arm.com
40310844Sandreas.sandberg@arm.com      case MISCREG_CNTHP_CVAL:
40410844Sandreas.sandberg@arm.com      case MISCREG_CNTHP_CVAL_EL2:
40512733Sandreas.sandberg@arm.com        core.hyp.setCompareValue(val);
40612733Sandreas.sandberg@arm.com        return;
40712733Sandreas.sandberg@arm.com
40810844Sandreas.sandberg@arm.com      case MISCREG_CNTHP_TVAL:
40910844Sandreas.sandberg@arm.com      case MISCREG_CNTHP_TVAL_EL2:
41012733Sandreas.sandberg@arm.com        core.hyp.setTimerValue(val);
41110844Sandreas.sandberg@arm.com        return;
41210844Sandreas.sandberg@arm.com
41310844Sandreas.sandberg@arm.com      default:
41410844Sandreas.sandberg@arm.com        warn("Writing to unknown register: %s\n", miscRegName[reg]);
41510844Sandreas.sandberg@arm.com        return;
41610844Sandreas.sandberg@arm.com    }
41710844Sandreas.sandberg@arm.com}
41810844Sandreas.sandberg@arm.com
41910844Sandreas.sandberg@arm.com
42013557Sgabeblack@google.comRegVal
42110844Sandreas.sandberg@arm.comGenericTimer::readMiscReg(int reg, unsigned cpu)
42210844Sandreas.sandberg@arm.com{
42310844Sandreas.sandberg@arm.com    CoreTimers &core(getTimers(cpu));
42410844Sandreas.sandberg@arm.com
42510844Sandreas.sandberg@arm.com    switch (reg) {
42610844Sandreas.sandberg@arm.com      case MISCREG_CNTFRQ:
42710844Sandreas.sandberg@arm.com      case MISCREG_CNTFRQ_EL0:
42810844Sandreas.sandberg@arm.com        return systemCounter.freq();
42910844Sandreas.sandberg@arm.com
43010844Sandreas.sandberg@arm.com      case MISCREG_CNTKCTL:
43110844Sandreas.sandberg@arm.com      case MISCREG_CNTKCTL_EL1:
43210844Sandreas.sandberg@arm.com        return systemCounter.getKernelControl();
43310844Sandreas.sandberg@arm.com
43412733Sandreas.sandberg@arm.com      case MISCREG_CNTHCTL:
43512733Sandreas.sandberg@arm.com      case MISCREG_CNTHCTL_EL2:
43612733Sandreas.sandberg@arm.com        return systemCounter.getHypControl();
43712733Sandreas.sandberg@arm.com
43810844Sandreas.sandberg@arm.com      // Physical timer
43912733Sandreas.sandberg@arm.com      case MISCREG_CNTP_CVAL_NS:
44010844Sandreas.sandberg@arm.com      case MISCREG_CNTP_CVAL_EL0:
44112733Sandreas.sandberg@arm.com        return core.physNS.compareValue();
44210844Sandreas.sandberg@arm.com
44312733Sandreas.sandberg@arm.com      case MISCREG_CNTP_TVAL_NS:
44410844Sandreas.sandberg@arm.com      case MISCREG_CNTP_TVAL_EL0:
44512733Sandreas.sandberg@arm.com        return core.physNS.timerValue();
44610844Sandreas.sandberg@arm.com
44710844Sandreas.sandberg@arm.com      case MISCREG_CNTP_CTL_EL0:
44810844Sandreas.sandberg@arm.com      case MISCREG_CNTP_CTL_NS:
44912733Sandreas.sandberg@arm.com        return core.physNS.control();
45010844Sandreas.sandberg@arm.com
45110844Sandreas.sandberg@arm.com      case MISCREG_CNTPCT:
45210844Sandreas.sandberg@arm.com      case MISCREG_CNTPCT_EL0:
45312733Sandreas.sandberg@arm.com        return core.physNS.value();
45410844Sandreas.sandberg@arm.com
45510844Sandreas.sandberg@arm.com
45610844Sandreas.sandberg@arm.com      // Virtual timer
45710844Sandreas.sandberg@arm.com      case MISCREG_CNTVCT:
45810844Sandreas.sandberg@arm.com      case MISCREG_CNTVCT_EL0:
45910845Sandreas.sandberg@arm.com        return core.virt.value();
46010844Sandreas.sandberg@arm.com
46110844Sandreas.sandberg@arm.com      case MISCREG_CNTVOFF:
46210844Sandreas.sandberg@arm.com      case MISCREG_CNTVOFF_EL2:
46310845Sandreas.sandberg@arm.com        return core.virt.offset();
46410845Sandreas.sandberg@arm.com
46510844Sandreas.sandberg@arm.com      case MISCREG_CNTV_CVAL:
46610844Sandreas.sandberg@arm.com      case MISCREG_CNTV_CVAL_EL0:
46710845Sandreas.sandberg@arm.com        return core.virt.compareValue();
46810845Sandreas.sandberg@arm.com
46910844Sandreas.sandberg@arm.com      case MISCREG_CNTV_TVAL:
47010844Sandreas.sandberg@arm.com      case MISCREG_CNTV_TVAL_EL0:
47110845Sandreas.sandberg@arm.com        return core.virt.timerValue();
47210845Sandreas.sandberg@arm.com
47310844Sandreas.sandberg@arm.com      case MISCREG_CNTV_CTL:
47410844Sandreas.sandberg@arm.com      case MISCREG_CNTV_CTL_EL0:
47510845Sandreas.sandberg@arm.com        return core.virt.control();
47610844Sandreas.sandberg@arm.com
47710844Sandreas.sandberg@arm.com      // PL1 phys. timer, secure
47810844Sandreas.sandberg@arm.com      case MISCREG_CNTP_CTL_S:
47912733Sandreas.sandberg@arm.com      case MISCREG_CNTPS_CTL_EL1:
48012733Sandreas.sandberg@arm.com        return core.physS.control();
48112733Sandreas.sandberg@arm.com
48212733Sandreas.sandberg@arm.com      case MISCREG_CNTP_CVAL_S:
48310844Sandreas.sandberg@arm.com      case MISCREG_CNTPS_CVAL_EL1:
48412733Sandreas.sandberg@arm.com        return core.physS.compareValue();
48512733Sandreas.sandberg@arm.com
48612733Sandreas.sandberg@arm.com      case MISCREG_CNTP_TVAL_S:
48710844Sandreas.sandberg@arm.com      case MISCREG_CNTPS_TVAL_EL1:
48812733Sandreas.sandberg@arm.com        return core.physS.timerValue();
48910844Sandreas.sandberg@arm.com
49012733Sandreas.sandberg@arm.com      // HYP phys. timer (NS)
49112733Sandreas.sandberg@arm.com      case MISCREG_CNTHP_CTL:
49212733Sandreas.sandberg@arm.com      case MISCREG_CNTHP_CTL_EL2:
49312733Sandreas.sandberg@arm.com        return core.hyp.control();
49412733Sandreas.sandberg@arm.com
49510844Sandreas.sandberg@arm.com      case MISCREG_CNTHP_CVAL:
49610844Sandreas.sandberg@arm.com      case MISCREG_CNTHP_CVAL_EL2:
49712733Sandreas.sandberg@arm.com        return core.hyp.compareValue();
49812733Sandreas.sandberg@arm.com
49910844Sandreas.sandberg@arm.com      case MISCREG_CNTHP_TVAL:
50010844Sandreas.sandberg@arm.com      case MISCREG_CNTHP_TVAL_EL2:
50112733Sandreas.sandberg@arm.com        return core.hyp.timerValue();
50210844Sandreas.sandberg@arm.com
50310844Sandreas.sandberg@arm.com      default:
50410844Sandreas.sandberg@arm.com        warn("Reading from unknown register: %s\n", miscRegName[reg]);
50510844Sandreas.sandberg@arm.com        return 0;
50610844Sandreas.sandberg@arm.com    }
50710844Sandreas.sandberg@arm.com}
50810844Sandreas.sandberg@arm.com
50910844Sandreas.sandberg@arm.com
51012971Sandreas.sandberg@arm.comvoid
51113557Sgabeblack@google.comGenericTimerISA::setMiscReg(int reg, RegVal val)
51212971Sandreas.sandberg@arm.com{
51312971Sandreas.sandberg@arm.com    DPRINTF(Timer, "Setting %s := 0x%x\n", miscRegName[reg], val);
51412971Sandreas.sandberg@arm.com    parent.setMiscReg(reg, cpu, val);
51512971Sandreas.sandberg@arm.com}
51612971Sandreas.sandberg@arm.com
51713557Sgabeblack@google.comRegVal
51812971Sandreas.sandberg@arm.comGenericTimerISA::readMiscReg(int reg)
51912971Sandreas.sandberg@arm.com{
52013557Sgabeblack@google.com    RegVal value = parent.readMiscReg(reg, cpu);
52112971Sandreas.sandberg@arm.com    DPRINTF(Timer, "Reading %s as 0x%x\n", miscRegName[reg], value);
52212971Sandreas.sandberg@arm.com    return value;
52312971Sandreas.sandberg@arm.com}
52410847Sandreas.sandberg@arm.com
52510847Sandreas.sandberg@arm.comGenericTimerMem::GenericTimerMem(GenericTimerMemParams *p)
52610847Sandreas.sandberg@arm.com    : PioDevice(p),
52710847Sandreas.sandberg@arm.com      ctrlRange(RangeSize(p->base, TheISA::PageBytes)),
52810847Sandreas.sandberg@arm.com      timerRange(RangeSize(p->base + TheISA::PageBytes, TheISA::PageBytes)),
52910847Sandreas.sandberg@arm.com      addrRanges{ctrlRange, timerRange},
53010847Sandreas.sandberg@arm.com      systemCounter(),
53110847Sandreas.sandberg@arm.com      physTimer(csprintf("%s.phys_timer0", name()),
53210847Sandreas.sandberg@arm.com                *this, systemCounter,
53312975Sgiacomo.travaglini@arm.com                p->int_phys->get()),
53410847Sandreas.sandberg@arm.com      virtTimer(csprintf("%s.virt_timer0", name()),
53510847Sandreas.sandberg@arm.com                *this, systemCounter,
53612975Sgiacomo.travaglini@arm.com                p->int_virt->get())
53710847Sandreas.sandberg@arm.com{
53810847Sandreas.sandberg@arm.com}
53910847Sandreas.sandberg@arm.com
54010847Sandreas.sandberg@arm.comvoid
54110905Sandreas.sandberg@arm.comGenericTimerMem::serialize(CheckpointOut &cp) const
54210847Sandreas.sandberg@arm.com{
54310905Sandreas.sandberg@arm.com    paramOut(cp, "timer_count", 1);
54410847Sandreas.sandberg@arm.com
54510905Sandreas.sandberg@arm.com    systemCounter.serializeSection(cp, "sys_counter");
54610847Sandreas.sandberg@arm.com
54710905Sandreas.sandberg@arm.com    physTimer.serializeSection(cp, "phys_timer0");
54810905Sandreas.sandberg@arm.com    virtTimer.serializeSection(cp, "virt_timer0");
54910847Sandreas.sandberg@arm.com}
55010847Sandreas.sandberg@arm.com
55110847Sandreas.sandberg@arm.comvoid
55210905Sandreas.sandberg@arm.comGenericTimerMem::unserialize(CheckpointIn &cp)
55310847Sandreas.sandberg@arm.com{
55410905Sandreas.sandberg@arm.com    systemCounter.unserializeSection(cp, "sys_counter");
55510847Sandreas.sandberg@arm.com
55610847Sandreas.sandberg@arm.com    unsigned timer_count;
55710847Sandreas.sandberg@arm.com    UNSERIALIZE_SCALAR(timer_count);
55810847Sandreas.sandberg@arm.com    // The timer count variable is just here for future versions where
55910847Sandreas.sandberg@arm.com    // we support more than one set of timers.
56010847Sandreas.sandberg@arm.com    if (timer_count != 1)
56110847Sandreas.sandberg@arm.com        panic("Incompatible checkpoint: Only one set of timers supported");
56210847Sandreas.sandberg@arm.com
56310905Sandreas.sandberg@arm.com    physTimer.unserializeSection(cp, "phys_timer0");
56410905Sandreas.sandberg@arm.com    virtTimer.unserializeSection(cp, "virt_timer0");
56510847Sandreas.sandberg@arm.com}
56610847Sandreas.sandberg@arm.com
56710847Sandreas.sandberg@arm.comTick
56810847Sandreas.sandberg@arm.comGenericTimerMem::read(PacketPtr pkt)
56910847Sandreas.sandberg@arm.com{
57010847Sandreas.sandberg@arm.com    const unsigned size(pkt->getSize());
57110847Sandreas.sandberg@arm.com    const Addr addr(pkt->getAddr());
57210847Sandreas.sandberg@arm.com    uint64_t value;
57310847Sandreas.sandberg@arm.com
57410847Sandreas.sandberg@arm.com    pkt->makeResponse();
57510847Sandreas.sandberg@arm.com    if (ctrlRange.contains(addr)) {
57610847Sandreas.sandberg@arm.com        value = ctrlRead(addr - ctrlRange.start(), size);
57710847Sandreas.sandberg@arm.com    } else if (timerRange.contains(addr)) {
57810847Sandreas.sandberg@arm.com        value = timerRead(addr - timerRange.start(), size);
57910847Sandreas.sandberg@arm.com    } else {
58010847Sandreas.sandberg@arm.com        panic("Invalid address: 0x%x\n", addr);
58110847Sandreas.sandberg@arm.com    }
58210847Sandreas.sandberg@arm.com
58310847Sandreas.sandberg@arm.com    DPRINTF(Timer, "Read 0x%x <- 0x%x(%i)\n", value, addr, size);
58410847Sandreas.sandberg@arm.com
58510847Sandreas.sandberg@arm.com    if (size == 8) {
58613230Sgabeblack@google.com        pkt->setLE<uint64_t>(value);
58710847Sandreas.sandberg@arm.com    } else if (size == 4) {
58813230Sgabeblack@google.com        pkt->setLE<uint32_t>(value);
58910847Sandreas.sandberg@arm.com    } else {
59010847Sandreas.sandberg@arm.com        panic("Unexpected access size: %i\n", size);
59110847Sandreas.sandberg@arm.com    }
59210847Sandreas.sandberg@arm.com
59310847Sandreas.sandberg@arm.com    return 0;
59410847Sandreas.sandberg@arm.com}
59510847Sandreas.sandberg@arm.com
59610847Sandreas.sandberg@arm.comTick
59710847Sandreas.sandberg@arm.comGenericTimerMem::write(PacketPtr pkt)
59810847Sandreas.sandberg@arm.com{
59910847Sandreas.sandberg@arm.com    const unsigned size(pkt->getSize());
60010847Sandreas.sandberg@arm.com    if (size != 8 && size != 4)
60110847Sandreas.sandberg@arm.com        panic("Unexpected access size\n");
60210847Sandreas.sandberg@arm.com
60310847Sandreas.sandberg@arm.com    const Addr addr(pkt->getAddr());
60410847Sandreas.sandberg@arm.com    const uint64_t value(size == 8 ?
60513230Sgabeblack@google.com                         pkt->getLE<uint64_t>() : pkt->getLE<uint32_t>());
60610847Sandreas.sandberg@arm.com
60710847Sandreas.sandberg@arm.com    DPRINTF(Timer, "Write 0x%x -> 0x%x(%i)\n", value, addr, size);
60810847Sandreas.sandberg@arm.com    if (ctrlRange.contains(addr)) {
60910847Sandreas.sandberg@arm.com        ctrlWrite(addr - ctrlRange.start(), size, value);
61010847Sandreas.sandberg@arm.com    } else if (timerRange.contains(addr)) {
61110847Sandreas.sandberg@arm.com        timerWrite(addr - timerRange.start(), size, value);
61210847Sandreas.sandberg@arm.com    } else {
61310847Sandreas.sandberg@arm.com        panic("Invalid address: 0x%x\n", addr);
61410847Sandreas.sandberg@arm.com    }
61510847Sandreas.sandberg@arm.com
61610847Sandreas.sandberg@arm.com    pkt->makeResponse();
61710847Sandreas.sandberg@arm.com    return 0;
61810847Sandreas.sandberg@arm.com}
61910847Sandreas.sandberg@arm.com
62010847Sandreas.sandberg@arm.comuint64_t
62110847Sandreas.sandberg@arm.comGenericTimerMem::ctrlRead(Addr addr, size_t size) const
62210847Sandreas.sandberg@arm.com{
62310847Sandreas.sandberg@arm.com    if (size == 4) {
62410847Sandreas.sandberg@arm.com        switch (addr) {
62510847Sandreas.sandberg@arm.com          case CTRL_CNTFRQ:
62610847Sandreas.sandberg@arm.com            return systemCounter.freq();
62710847Sandreas.sandberg@arm.com
62810847Sandreas.sandberg@arm.com          case CTRL_CNTTIDR:
62910847Sandreas.sandberg@arm.com            return 0x3; // Frame 0 implemented with virtual timers
63010847Sandreas.sandberg@arm.com
63110847Sandreas.sandberg@arm.com          case CTRL_CNTNSAR:
63210847Sandreas.sandberg@arm.com          case CTRL_CNTACR_BASE:
63310847Sandreas.sandberg@arm.com            warn("Reading from unimplemented control register (0x%x)\n", addr);
63410847Sandreas.sandberg@arm.com            return 0;
63510847Sandreas.sandberg@arm.com
63610847Sandreas.sandberg@arm.com          case CTRL_CNTVOFF_LO_BASE:
63710847Sandreas.sandberg@arm.com            return virtTimer.offset();
63810847Sandreas.sandberg@arm.com
63910847Sandreas.sandberg@arm.com          case CTRL_CNTVOFF_HI_BASE:
64010847Sandreas.sandberg@arm.com            return virtTimer.offset() >> 32;
64110847Sandreas.sandberg@arm.com
64210847Sandreas.sandberg@arm.com          default:
64310847Sandreas.sandberg@arm.com            warn("Unexpected address (0x%x:%i), assuming RAZ\n", addr, size);
64410847Sandreas.sandberg@arm.com            return 0;
64510847Sandreas.sandberg@arm.com        }
64610847Sandreas.sandberg@arm.com    } else if (size == 8) {
64710847Sandreas.sandberg@arm.com        switch (addr) {
64810847Sandreas.sandberg@arm.com          case CTRL_CNTVOFF_LO_BASE:
64910847Sandreas.sandberg@arm.com            return virtTimer.offset();
65010847Sandreas.sandberg@arm.com
65110847Sandreas.sandberg@arm.com          default:
65210847Sandreas.sandberg@arm.com            warn("Unexpected address (0x%x:%i), assuming RAZ\n", addr, size);
65310847Sandreas.sandberg@arm.com            return 0;
65410847Sandreas.sandberg@arm.com        }
65510847Sandreas.sandberg@arm.com    } else {
65610847Sandreas.sandberg@arm.com        panic("Invalid access size: %i\n", size);
65710847Sandreas.sandberg@arm.com    }
65810847Sandreas.sandberg@arm.com}
65910847Sandreas.sandberg@arm.com
66010847Sandreas.sandberg@arm.comvoid
66110847Sandreas.sandberg@arm.comGenericTimerMem::ctrlWrite(Addr addr, size_t size, uint64_t value)
66210847Sandreas.sandberg@arm.com{
66310847Sandreas.sandberg@arm.com    if (size == 4) {
66410847Sandreas.sandberg@arm.com        switch (addr) {
66510847Sandreas.sandberg@arm.com          case CTRL_CNTFRQ:
66610847Sandreas.sandberg@arm.com          case CTRL_CNTNSAR:
66710847Sandreas.sandberg@arm.com          case CTRL_CNTTIDR:
66810847Sandreas.sandberg@arm.com          case CTRL_CNTACR_BASE:
66910847Sandreas.sandberg@arm.com            warn("Write to unimplemented control register (0x%x)\n", addr);
67010847Sandreas.sandberg@arm.com            return;
67110847Sandreas.sandberg@arm.com
67210847Sandreas.sandberg@arm.com          case CTRL_CNTVOFF_LO_BASE:
67310847Sandreas.sandberg@arm.com            virtTimer.setOffset(
67410847Sandreas.sandberg@arm.com                insertBits(virtTimer.offset(), 31, 0, value));
67510847Sandreas.sandberg@arm.com            return;
67610847Sandreas.sandberg@arm.com
67710847Sandreas.sandberg@arm.com          case CTRL_CNTVOFF_HI_BASE:
67810847Sandreas.sandberg@arm.com            virtTimer.setOffset(
67910847Sandreas.sandberg@arm.com                insertBits(virtTimer.offset(), 63, 32, value));
68010847Sandreas.sandberg@arm.com            return;
68110847Sandreas.sandberg@arm.com
68210847Sandreas.sandberg@arm.com          default:
68310847Sandreas.sandberg@arm.com            warn("Ignoring write to unexpected address (0x%x:%i)\n",
68410847Sandreas.sandberg@arm.com                 addr, size);
68510847Sandreas.sandberg@arm.com            return;
68610847Sandreas.sandberg@arm.com        }
68710847Sandreas.sandberg@arm.com    } else if (size == 8) {
68810847Sandreas.sandberg@arm.com        switch (addr) {
68910847Sandreas.sandberg@arm.com          case CTRL_CNTVOFF_LO_BASE:
69010847Sandreas.sandberg@arm.com            virtTimer.setOffset(value);
69110847Sandreas.sandberg@arm.com            return;
69210847Sandreas.sandberg@arm.com
69310847Sandreas.sandberg@arm.com          default:
69410847Sandreas.sandberg@arm.com            warn("Ignoring write to unexpected address (0x%x:%i)\n",
69510847Sandreas.sandberg@arm.com                 addr, size);
69610847Sandreas.sandberg@arm.com            return;
69710847Sandreas.sandberg@arm.com        }
69810847Sandreas.sandberg@arm.com    } else {
69910847Sandreas.sandberg@arm.com        panic("Invalid access size: %i\n", size);
70010847Sandreas.sandberg@arm.com    }
70110847Sandreas.sandberg@arm.com}
70210847Sandreas.sandberg@arm.com
70310847Sandreas.sandberg@arm.comuint64_t
70410847Sandreas.sandberg@arm.comGenericTimerMem::timerRead(Addr addr, size_t size) const
70510847Sandreas.sandberg@arm.com{
70610847Sandreas.sandberg@arm.com    if (size == 4) {
70710847Sandreas.sandberg@arm.com        switch (addr) {
70810847Sandreas.sandberg@arm.com          case TIMER_CNTPCT_LO:
70910847Sandreas.sandberg@arm.com            return physTimer.value();
71010847Sandreas.sandberg@arm.com
71110847Sandreas.sandberg@arm.com          case TIMER_CNTPCT_HI:
71210847Sandreas.sandberg@arm.com            return physTimer.value() >> 32;
71310847Sandreas.sandberg@arm.com
71410847Sandreas.sandberg@arm.com          case TIMER_CNTVCT_LO:
71510847Sandreas.sandberg@arm.com            return virtTimer.value();
71610847Sandreas.sandberg@arm.com
71710847Sandreas.sandberg@arm.com          case TIMER_CNTVCT_HI:
71810847Sandreas.sandberg@arm.com            return virtTimer.value() >> 32;
71910847Sandreas.sandberg@arm.com
72010847Sandreas.sandberg@arm.com          case TIMER_CNTFRQ:
72110847Sandreas.sandberg@arm.com            return systemCounter.freq();
72210847Sandreas.sandberg@arm.com
72310847Sandreas.sandberg@arm.com          case TIMER_CNTEL0ACR:
72410847Sandreas.sandberg@arm.com            warn("Read from unimplemented timer register (0x%x)\n", addr);
72510847Sandreas.sandberg@arm.com            return 0;
72610847Sandreas.sandberg@arm.com
72710847Sandreas.sandberg@arm.com          case CTRL_CNTVOFF_LO_BASE:
72810847Sandreas.sandberg@arm.com            return virtTimer.offset();
72910847Sandreas.sandberg@arm.com
73010847Sandreas.sandberg@arm.com          case CTRL_CNTVOFF_HI_BASE:
73110847Sandreas.sandberg@arm.com            return virtTimer.offset() >> 32;
73210847Sandreas.sandberg@arm.com
73310847Sandreas.sandberg@arm.com          case TIMER_CNTP_CVAL_LO:
73410847Sandreas.sandberg@arm.com            return physTimer.compareValue();
73510847Sandreas.sandberg@arm.com
73610847Sandreas.sandberg@arm.com          case TIMER_CNTP_CVAL_HI:
73710847Sandreas.sandberg@arm.com            return physTimer.compareValue() >> 32;
73810847Sandreas.sandberg@arm.com
73910847Sandreas.sandberg@arm.com          case TIMER_CNTP_TVAL:
74010847Sandreas.sandberg@arm.com            return physTimer.timerValue();
74110847Sandreas.sandberg@arm.com
74210847Sandreas.sandberg@arm.com          case TIMER_CNTP_CTL:
74310847Sandreas.sandberg@arm.com            return physTimer.control();
74410847Sandreas.sandberg@arm.com
74510847Sandreas.sandberg@arm.com          case TIMER_CNTV_CVAL_LO:
74610847Sandreas.sandberg@arm.com            return virtTimer.compareValue();
74710847Sandreas.sandberg@arm.com
74810847Sandreas.sandberg@arm.com          case TIMER_CNTV_CVAL_HI:
74910847Sandreas.sandberg@arm.com            return virtTimer.compareValue() >> 32;
75010847Sandreas.sandberg@arm.com
75110847Sandreas.sandberg@arm.com          case TIMER_CNTV_TVAL:
75210847Sandreas.sandberg@arm.com            return virtTimer.timerValue();
75310847Sandreas.sandberg@arm.com
75410847Sandreas.sandberg@arm.com          case TIMER_CNTV_CTL:
75510847Sandreas.sandberg@arm.com            return virtTimer.control();
75610847Sandreas.sandberg@arm.com
75710847Sandreas.sandberg@arm.com          default:
75810847Sandreas.sandberg@arm.com            warn("Unexpected address (0x%x:%i), assuming RAZ\n", addr, size);
75910847Sandreas.sandberg@arm.com            return 0;
76010847Sandreas.sandberg@arm.com        }
76110847Sandreas.sandberg@arm.com    } else if (size == 8) {
76210847Sandreas.sandberg@arm.com        switch (addr) {
76310847Sandreas.sandberg@arm.com          case TIMER_CNTPCT_LO:
76410847Sandreas.sandberg@arm.com            return physTimer.value();
76510847Sandreas.sandberg@arm.com
76610847Sandreas.sandberg@arm.com          case TIMER_CNTVCT_LO:
76710847Sandreas.sandberg@arm.com            return virtTimer.value();
76810847Sandreas.sandberg@arm.com
76910847Sandreas.sandberg@arm.com          case CTRL_CNTVOFF_LO_BASE:
77010847Sandreas.sandberg@arm.com            return virtTimer.offset();
77110847Sandreas.sandberg@arm.com
77210847Sandreas.sandberg@arm.com          case TIMER_CNTP_CVAL_LO:
77310847Sandreas.sandberg@arm.com            return physTimer.compareValue();
77410847Sandreas.sandberg@arm.com
77510847Sandreas.sandberg@arm.com          case TIMER_CNTV_CVAL_LO:
77610847Sandreas.sandberg@arm.com            return virtTimer.compareValue();
77710847Sandreas.sandberg@arm.com
77810847Sandreas.sandberg@arm.com          default:
77910847Sandreas.sandberg@arm.com            warn("Unexpected address (0x%x:%i), assuming RAZ\n", addr, size);
78010847Sandreas.sandberg@arm.com            return 0;
78110847Sandreas.sandberg@arm.com        }
78210847Sandreas.sandberg@arm.com    } else {
78310847Sandreas.sandberg@arm.com        panic("Invalid access size: %i\n", size);
78410847Sandreas.sandberg@arm.com    }
78510847Sandreas.sandberg@arm.com}
78610847Sandreas.sandberg@arm.com
78710847Sandreas.sandberg@arm.comvoid
78810847Sandreas.sandberg@arm.comGenericTimerMem::timerWrite(Addr addr, size_t size, uint64_t value)
78910847Sandreas.sandberg@arm.com{
79010847Sandreas.sandberg@arm.com    if (size == 4) {
79110847Sandreas.sandberg@arm.com        switch (addr) {
79210847Sandreas.sandberg@arm.com          case TIMER_CNTEL0ACR:
79310847Sandreas.sandberg@arm.com            warn("Unimplemented timer register (0x%x)\n", addr);
79410847Sandreas.sandberg@arm.com            return;
79510847Sandreas.sandberg@arm.com
79610847Sandreas.sandberg@arm.com          case TIMER_CNTP_CVAL_LO:
79710847Sandreas.sandberg@arm.com            physTimer.setCompareValue(
79810847Sandreas.sandberg@arm.com                insertBits(physTimer.compareValue(), 31, 0, value));
79910847Sandreas.sandberg@arm.com            return;
80010847Sandreas.sandberg@arm.com
80110847Sandreas.sandberg@arm.com          case TIMER_CNTP_CVAL_HI:
80210847Sandreas.sandberg@arm.com            physTimer.setCompareValue(
80310847Sandreas.sandberg@arm.com                insertBits(physTimer.compareValue(), 63, 32, value));
80410847Sandreas.sandberg@arm.com            return;
80510847Sandreas.sandberg@arm.com
80610847Sandreas.sandberg@arm.com          case TIMER_CNTP_TVAL:
80710847Sandreas.sandberg@arm.com            physTimer.setTimerValue(value);
80810847Sandreas.sandberg@arm.com            return;
80910847Sandreas.sandberg@arm.com
81010847Sandreas.sandberg@arm.com          case TIMER_CNTP_CTL:
81110847Sandreas.sandberg@arm.com            physTimer.setControl(value);
81210847Sandreas.sandberg@arm.com            return;
81310847Sandreas.sandberg@arm.com
81410847Sandreas.sandberg@arm.com          case TIMER_CNTV_CVAL_LO:
81510847Sandreas.sandberg@arm.com            virtTimer.setCompareValue(
81610847Sandreas.sandberg@arm.com                insertBits(virtTimer.compareValue(), 31, 0, value));
81710847Sandreas.sandberg@arm.com            return;
81810847Sandreas.sandberg@arm.com
81910847Sandreas.sandberg@arm.com          case TIMER_CNTV_CVAL_HI:
82010847Sandreas.sandberg@arm.com            virtTimer.setCompareValue(
82110847Sandreas.sandberg@arm.com                insertBits(virtTimer.compareValue(), 63, 32, value));
82210847Sandreas.sandberg@arm.com            return;
82310847Sandreas.sandberg@arm.com
82410847Sandreas.sandberg@arm.com          case TIMER_CNTV_TVAL:
82510847Sandreas.sandberg@arm.com            virtTimer.setTimerValue(value);
82610847Sandreas.sandberg@arm.com            return;
82710847Sandreas.sandberg@arm.com
82810847Sandreas.sandberg@arm.com          case TIMER_CNTV_CTL:
82910847Sandreas.sandberg@arm.com            virtTimer.setControl(value);
83010847Sandreas.sandberg@arm.com            return;
83110847Sandreas.sandberg@arm.com
83210847Sandreas.sandberg@arm.com          default:
83310847Sandreas.sandberg@arm.com            warn("Unexpected address (0x%x:%i), ignoring write\n", addr, size);
83410847Sandreas.sandberg@arm.com            return;
83510847Sandreas.sandberg@arm.com        }
83610847Sandreas.sandberg@arm.com    } else if (size == 8) {
83710847Sandreas.sandberg@arm.com        switch (addr) {
83810847Sandreas.sandberg@arm.com          case TIMER_CNTP_CVAL_LO:
83910847Sandreas.sandberg@arm.com            return physTimer.setCompareValue(value);
84010847Sandreas.sandberg@arm.com
84110847Sandreas.sandberg@arm.com          case TIMER_CNTV_CVAL_LO:
84210847Sandreas.sandberg@arm.com            return virtTimer.setCompareValue(value);
84310847Sandreas.sandberg@arm.com
84410847Sandreas.sandberg@arm.com          default:
84510847Sandreas.sandberg@arm.com            warn("Unexpected address (0x%x:%i), ignoring write\n", addr, size);
84610847Sandreas.sandberg@arm.com            return;
84710847Sandreas.sandberg@arm.com        }
84810847Sandreas.sandberg@arm.com    } else {
84910847Sandreas.sandberg@arm.com        panic("Invalid access size: %i\n", size);
85010847Sandreas.sandberg@arm.com    }
85110847Sandreas.sandberg@arm.com}
85210847Sandreas.sandberg@arm.com
85310037SARM gem5 DevelopersGenericTimer *
85410037SARM gem5 DevelopersGenericTimerParams::create()
85510037SARM gem5 Developers{
85610037SARM gem5 Developers    return new GenericTimer(this);
85710037SARM gem5 Developers}
85810847Sandreas.sandberg@arm.com
85910847Sandreas.sandberg@arm.comGenericTimerMem *
86010847Sandreas.sandberg@arm.comGenericTimerMemParams::create()
86110847Sandreas.sandberg@arm.com{
86210847Sandreas.sandberg@arm.com    return new GenericTimerMem(this);
86310847Sandreas.sandberg@arm.com}
864