timer_cpulocal.cc revision 9545
12810Srdreslin@umich.edu/* 212500Snikos.nikoleris@arm.com * Copyright (c) 2010-2013 ARM Limited 311051Sandreas.hansson@arm.com * All rights reserved 411051Sandreas.hansson@arm.com * 511051Sandreas.hansson@arm.com * The license below extends only to copyright in the software and shall 611051Sandreas.hansson@arm.com * not be construed as granting a license to any other intellectual 711051Sandreas.hansson@arm.com * property including but not limited to intellectual property relating 811051Sandreas.hansson@arm.com * to a hardware implementation of the functionality of the software 911051Sandreas.hansson@arm.com * licensed hereunder. You may use the software subject to the license 1011051Sandreas.hansson@arm.com * terms below provided that you ensure that this notice is replicated 1111051Sandreas.hansson@arm.com * unmodified and in its entirety in all distributions of the software, 1211051Sandreas.hansson@arm.com * modified or unmodified, in source code or in binary form. 1311051Sandreas.hansson@arm.com * 1411051Sandreas.hansson@arm.com * Redistribution and use in source and binary forms, with or without 1511051Sandreas.hansson@arm.com * modification, are permitted provided that the following conditions are 162810Srdreslin@umich.edu * met: redistributions of source code must retain the above copyright 172810Srdreslin@umich.edu * notice, this list of conditions and the following disclaimer; 182810Srdreslin@umich.edu * redistributions in binary form must reproduce the above copyright 192810Srdreslin@umich.edu * notice, this list of conditions and the following disclaimer in the 202810Srdreslin@umich.edu * documentation and/or other materials provided with the distribution; 212810Srdreslin@umich.edu * neither the name of the copyright holders nor the names of its 222810Srdreslin@umich.edu * contributors may be used to endorse or promote products derived from 232810Srdreslin@umich.edu * this software without specific prior written permission. 242810Srdreslin@umich.edu * 252810Srdreslin@umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 262810Srdreslin@umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 272810Srdreslin@umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 282810Srdreslin@umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 292810Srdreslin@umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 302810Srdreslin@umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 312810Srdreslin@umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 322810Srdreslin@umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 332810Srdreslin@umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 342810Srdreslin@umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 352810Srdreslin@umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 362810Srdreslin@umich.edu * 372810Srdreslin@umich.edu * Authors: Ali Saidi 382810Srdreslin@umich.edu * Geoffrey Blake 392810Srdreslin@umich.edu */ 402810Srdreslin@umich.edu 412810Srdreslin@umich.edu#include "base/intmath.hh" 4211051Sandreas.hansson@arm.com#include "base/trace.hh" 4311051Sandreas.hansson@arm.com#include "debug/Checkpoint.hh" 442810Srdreslin@umich.edu#include "debug/Timer.hh" 4511051Sandreas.hansson@arm.com#include "dev/arm/base_gic.hh" 4611051Sandreas.hansson@arm.com#include "dev/arm/timer_cpulocal.hh" 4712349Snikos.nikoleris@arm.com#include "mem/packet.hh" 482810Srdreslin@umich.edu#include "mem/packet_access.hh" 492810Srdreslin@umich.edu 502810Srdreslin@umich.eduCpuLocalTimer::CpuLocalTimer(Params *p) 512810Srdreslin@umich.edu : BasicPioDevice(p), gic(p->gic) 5211051Sandreas.hansson@arm.com{ 532810Srdreslin@umich.edu // Initialize the timer registers for each per cpu timer 542810Srdreslin@umich.edu for (int i = 0; i < CPU_MAX; i++) { 5511051Sandreas.hansson@arm.com std::stringstream oss; 562810Srdreslin@umich.edu oss << name() << ".timer" << i; 5712724Snikos.nikoleris@arm.com localTimer[i]._name = oss.str(); 5812724Snikos.nikoleris@arm.com localTimer[i].parent = this; 5912724Snikos.nikoleris@arm.com localTimer[i].intNumTimer = p->int_num_timer; 6012334Sgabeblack@google.com localTimer[i].intNumWatchdog = p->int_num_watchdog; 6112724Snikos.nikoleris@arm.com localTimer[i].cpuNum = i; 6211051Sandreas.hansson@arm.com } 6311051Sandreas.hansson@arm.com pioSize = 0x38; 6411051Sandreas.hansson@arm.com} 6511288Ssteve.reinhardt@amd.com 6612724Snikos.nikoleris@arm.comCpuLocalTimer::Timer::Timer() 6711051Sandreas.hansson@arm.com : timerControl(0x0), watchdogControl(0x0), rawIntTimer(false), rawIntWatchdog(false), 6811051Sandreas.hansson@arm.com rawResetWatchdog(false), watchdogDisableReg(0x0), pendingIntTimer(false), pendingIntWatchdog(false), 6912724Snikos.nikoleris@arm.com timerLoadValue(0x0), watchdogLoadValue(0x0), timerZeroEvent(this), watchdogZeroEvent(this) 7012724Snikos.nikoleris@arm.com{ 7112724Snikos.nikoleris@arm.com} 7212724Snikos.nikoleris@arm.com 7311051Sandreas.hansson@arm.comTick 7411053Sandreas.hansson@arm.comCpuLocalTimer::read(PacketPtr pkt) 7511053Sandreas.hansson@arm.com{ 7612724Snikos.nikoleris@arm.com assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize); 7711051Sandreas.hansson@arm.com assert(pkt->getSize() == 4); 7811051Sandreas.hansson@arm.com Addr daddr = pkt->getAddr() - pioAddr; 7911051Sandreas.hansson@arm.com pkt->allocate(); 8011051Sandreas.hansson@arm.com int cpu_id = pkt->req->contextId(); 8111601Sandreas.hansson@arm.com DPRINTF(Timer, "Reading from CpuLocalTimer at offset: %#x\n", daddr); 8211601Sandreas.hansson@arm.com assert(cpu_id >= 0); 8311051Sandreas.hansson@arm.com assert(cpu_id < CPU_MAX); 8412724Snikos.nikoleris@arm.com 8511051Sandreas.hansson@arm.com if (daddr < Timer::Size) 8612724Snikos.nikoleris@arm.com localTimer[cpu_id].read(pkt, daddr); 8711600Sandreas.hansson@arm.com else 8811600Sandreas.hansson@arm.com panic("Tried to read CpuLocalTimer at offset %#x that doesn't exist\n", daddr); 8911051Sandreas.hansson@arm.com pkt->makeAtomicResponse(); 9011051Sandreas.hansson@arm.com return pioDelay; 9111051Sandreas.hansson@arm.com} 9211284Sandreas.hansson@arm.com 9311051Sandreas.hansson@arm.com 9411051Sandreas.hansson@arm.comvoid 9511051Sandreas.hansson@arm.comCpuLocalTimer::Timer::read(PacketPtr pkt, Addr daddr) 9611602Sandreas.hansson@arm.com{ 9711051Sandreas.hansson@arm.com DPRINTF(Timer, "Reading from CpuLocalTimer at offset: %#x\n", daddr); 9811051Sandreas.hansson@arm.com Tick time; 9911284Sandreas.hansson@arm.com 10011051Sandreas.hansson@arm.com switch(daddr) { 10111284Sandreas.hansson@arm.com case TimerLoadReg: 10211602Sandreas.hansson@arm.com pkt->set<uint32_t>(timerLoadValue); 10311051Sandreas.hansson@arm.com break; 10411051Sandreas.hansson@arm.com case TimerCounterReg: 10511284Sandreas.hansson@arm.com DPRINTF(Timer, "Event schedule for timer %d, clock=%d, prescale=%d\n", 10611051Sandreas.hansson@arm.com timerZeroEvent.when(), parent->clockPeriod(), 10711284Sandreas.hansson@arm.com timerControl.prescalar); 10811284Sandreas.hansson@arm.com time = timerZeroEvent.when() - curTick(); 10911284Sandreas.hansson@arm.com time = time / parent->clockPeriod() / 11011051Sandreas.hansson@arm.com power(16, timerControl.prescalar); 11111051Sandreas.hansson@arm.com DPRINTF(Timer, "-- returning counter at %d\n", time); 11211051Sandreas.hansson@arm.com pkt->set<uint32_t>(time); 11311284Sandreas.hansson@arm.com break; 11411284Sandreas.hansson@arm.com case TimerControlReg: 11511284Sandreas.hansson@arm.com pkt->set<uint32_t>(timerControl); 11611284Sandreas.hansson@arm.com break; 11711051Sandreas.hansson@arm.com case TimerIntStatusReg: 11811051Sandreas.hansson@arm.com pkt->set<uint32_t>(rawIntTimer); 11911051Sandreas.hansson@arm.com break; 12011284Sandreas.hansson@arm.com case WatchdogLoadReg: 12111284Sandreas.hansson@arm.com pkt->set<uint32_t>(watchdogLoadValue); 12211284Sandreas.hansson@arm.com break; 12311197Sandreas.hansson@arm.com case WatchdogCounterReg: 12411601Sandreas.hansson@arm.com DPRINTF(Timer, 12511601Sandreas.hansson@arm.com "Event schedule for watchdog %d, clock=%d, prescale=%d\n", 12611601Sandreas.hansson@arm.com watchdogZeroEvent.when(), parent->clockPeriod(), 12711601Sandreas.hansson@arm.com watchdogControl.prescalar); 12811601Sandreas.hansson@arm.com time = watchdogZeroEvent.when() - curTick(); 12911601Sandreas.hansson@arm.com time = time / parent->clockPeriod() / 13011601Sandreas.hansson@arm.com power(16, watchdogControl.prescalar); 13111601Sandreas.hansson@arm.com DPRINTF(Timer, "-- returning counter at %d\n", time); 13211197Sandreas.hansson@arm.com pkt->set<uint32_t>(time); 13311601Sandreas.hansson@arm.com break; 13411601Sandreas.hansson@arm.com case WatchdogControlReg: 13511601Sandreas.hansson@arm.com pkt->set<uint32_t>(watchdogControl); 13611601Sandreas.hansson@arm.com break; 13711601Sandreas.hansson@arm.com case WatchdogIntStatusReg: 13811601Sandreas.hansson@arm.com pkt->set<uint32_t>(rawIntWatchdog); 13911601Sandreas.hansson@arm.com break; 14011051Sandreas.hansson@arm.com case WatchdogResetStatusReg: 14111051Sandreas.hansson@arm.com pkt->set<uint32_t>(rawResetWatchdog); 14211051Sandreas.hansson@arm.com break; 14311051Sandreas.hansson@arm.com case WatchdogDisableReg: 14411051Sandreas.hansson@arm.com panic("Tried to read from WatchdogDisableRegister\n"); 14511284Sandreas.hansson@arm.com break; 14611284Sandreas.hansson@arm.com default: 14711051Sandreas.hansson@arm.com panic("Tried to read CpuLocalTimer at offset %#x\n", daddr); 14811051Sandreas.hansson@arm.com break; 14911051Sandreas.hansson@arm.com } 15011051Sandreas.hansson@arm.com} 15111284Sandreas.hansson@arm.com 15211051Sandreas.hansson@arm.comTick 15311051Sandreas.hansson@arm.comCpuLocalTimer::write(PacketPtr pkt) 15411051Sandreas.hansson@arm.com{ 15511051Sandreas.hansson@arm.com assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize); 15611051Sandreas.hansson@arm.com assert(pkt->getSize() == 4); 15711051Sandreas.hansson@arm.com Addr daddr = pkt->getAddr() - pioAddr; 15811051Sandreas.hansson@arm.com pkt->allocate(); 15911051Sandreas.hansson@arm.com int cpu_id = pkt->req->contextId(); 16011051Sandreas.hansson@arm.com DPRINTF(Timer, "Writing to CpuLocalTimer at offset: %#x\n", daddr); 16111051Sandreas.hansson@arm.com assert(cpu_id >= 0); 16211051Sandreas.hansson@arm.com assert(cpu_id < CPU_MAX); 16311051Sandreas.hansson@arm.com 16411051Sandreas.hansson@arm.com if (daddr < Timer::Size) 16511051Sandreas.hansson@arm.com localTimer[cpu_id].write(pkt, daddr); 16611051Sandreas.hansson@arm.com else 16711051Sandreas.hansson@arm.com panic("Tried to write CpuLocalTimer at offset %#x that doesn't exist\n", daddr); 16811051Sandreas.hansson@arm.com pkt->makeAtomicResponse(); 16912724Snikos.nikoleris@arm.com return pioDelay; 17012724Snikos.nikoleris@arm.com} 17112724Snikos.nikoleris@arm.com 17212724Snikos.nikoleris@arm.comvoid 17312724Snikos.nikoleris@arm.comCpuLocalTimer::Timer::write(PacketPtr pkt, Addr daddr) 17412724Snikos.nikoleris@arm.com{ 17512724Snikos.nikoleris@arm.com DPRINTF(Timer, "Writing to CpuLocalTimer at offset: %#x\n", daddr); 17611051Sandreas.hansson@arm.com bool old_enable; 17711051Sandreas.hansson@arm.com bool old_wd_mode; 17811051Sandreas.hansson@arm.com uint32_t old_val; 17911051Sandreas.hansson@arm.com 18012723Snikos.nikoleris@arm.com switch (daddr) { 18111051Sandreas.hansson@arm.com case TimerLoadReg: 18211051Sandreas.hansson@arm.com // Writing to this register also resets the counter register and 18311484Snikos.nikoleris@arm.com // starts decrementing if the counter is enabled. 18411051Sandreas.hansson@arm.com timerLoadValue = pkt->get<uint32_t>(); 18511051Sandreas.hansson@arm.com restartTimerCounter(timerLoadValue); 18611051Sandreas.hansson@arm.com break; 18711051Sandreas.hansson@arm.com case TimerCounterReg: 18811051Sandreas.hansson@arm.com // Can be written, doesn't start counting unless the timer is enabled 18912724Snikos.nikoleris@arm.com restartTimerCounter(pkt->get<uint32_t>()); 19011601Sandreas.hansson@arm.com break; 19111601Sandreas.hansson@arm.com case TimerControlReg: 19211601Sandreas.hansson@arm.com old_enable = timerControl.enable; 19311051Sandreas.hansson@arm.com timerControl = pkt->get<uint32_t>(); 19411051Sandreas.hansson@arm.com if ((old_enable == 0) && timerControl.enable) 19511051Sandreas.hansson@arm.com restartTimerCounter(timerLoadValue); 19611051Sandreas.hansson@arm.com break; 19711051Sandreas.hansson@arm.com case TimerIntStatusReg: 19812345Snikos.nikoleris@arm.com rawIntTimer = false; 19912345Snikos.nikoleris@arm.com if (pendingIntTimer) { 20012345Snikos.nikoleris@arm.com pendingIntTimer = false; 20112345Snikos.nikoleris@arm.com DPRINTF(Timer, "Clearing interrupt\n"); 20211051Sandreas.hansson@arm.com } 20311051Sandreas.hansson@arm.com break; 20411051Sandreas.hansson@arm.com case WatchdogLoadReg: 20511051Sandreas.hansson@arm.com watchdogLoadValue = pkt->get<uint32_t>(); 20611051Sandreas.hansson@arm.com restartWatchdogCounter(watchdogLoadValue); 20711051Sandreas.hansson@arm.com break; 20811051Sandreas.hansson@arm.com case WatchdogCounterReg: 20911199Sandreas.hansson@arm.com // Can't be written when in watchdog mode, but can in timer mode 21011199Sandreas.hansson@arm.com if (!watchdogControl.watchdogMode) { 21111199Sandreas.hansson@arm.com restartWatchdogCounter(pkt->get<uint32_t>()); 21211199Sandreas.hansson@arm.com } 21311199Sandreas.hansson@arm.com break; 21411051Sandreas.hansson@arm.com case WatchdogControlReg: 21512345Snikos.nikoleris@arm.com old_enable = watchdogControl.enable; 21612345Snikos.nikoleris@arm.com old_wd_mode = watchdogControl.watchdogMode; 21711051Sandreas.hansson@arm.com watchdogControl = pkt->get<uint32_t>(); 21811051Sandreas.hansson@arm.com if ((old_enable == 0) && watchdogControl.enable) 21911051Sandreas.hansson@arm.com restartWatchdogCounter(watchdogLoadValue); 22011051Sandreas.hansson@arm.com // cannot disable watchdog using control register 22111051Sandreas.hansson@arm.com if ((old_wd_mode == 1) && watchdogControl.watchdogMode == 0) 22211051Sandreas.hansson@arm.com watchdogControl.watchdogMode = 1; 22311051Sandreas.hansson@arm.com break; 22411051Sandreas.hansson@arm.com case WatchdogIntStatusReg: 22511051Sandreas.hansson@arm.com rawIntWatchdog = false; 22611051Sandreas.hansson@arm.com if (pendingIntWatchdog) { 22711051Sandreas.hansson@arm.com pendingIntWatchdog = false; 22811051Sandreas.hansson@arm.com DPRINTF(Timer, "Clearing watchdog interrupt\n"); 22911051Sandreas.hansson@arm.com } 23011051Sandreas.hansson@arm.com break; 23111051Sandreas.hansson@arm.com case WatchdogResetStatusReg: 23211051Sandreas.hansson@arm.com rawResetWatchdog = false; 23311051Sandreas.hansson@arm.com DPRINTF(Timer, "Clearing watchdog reset flag\n"); 23411130Sali.jafri@arm.com break; 23511130Sali.jafri@arm.com case WatchdogDisableReg: 23611130Sali.jafri@arm.com old_val = watchdogDisableReg; 23711130Sali.jafri@arm.com watchdogDisableReg = pkt->get<uint32_t>(); 23811130Sali.jafri@arm.com // if this sequence is observed, turn off watchdog mode 23911130Sali.jafri@arm.com if (old_val == 0x12345678 && watchdogDisableReg == 0x87654321) 24011130Sali.jafri@arm.com watchdogControl.watchdogMode = 0; 24111130Sali.jafri@arm.com break; 24211130Sali.jafri@arm.com default: 24312345Snikos.nikoleris@arm.com panic("Tried to write CpuLocalTimer timer at offset %#x\n", daddr); 24412345Snikos.nikoleris@arm.com break; 24511130Sali.jafri@arm.com } 24611130Sali.jafri@arm.com} 24711130Sali.jafri@arm.com 24811130Sali.jafri@arm.com//XXX: Two functions are needed because the control registers are different types 24911130Sali.jafri@arm.comvoid 25011130Sali.jafri@arm.comCpuLocalTimer::Timer::restartTimerCounter(uint32_t val) 25112724Snikos.nikoleris@arm.com{ 25211130Sali.jafri@arm.com DPRINTF(Timer, "Resetting timer counter with value %#x\n", val); 25311130Sali.jafri@arm.com if (!timerControl.enable) 25411130Sali.jafri@arm.com return; 25511130Sali.jafri@arm.com 25611130Sali.jafri@arm.com Tick time = parent->clockPeriod() * power(16, timerControl.prescalar); 25711130Sali.jafri@arm.com time *= val; 25812724Snikos.nikoleris@arm.com 25911130Sali.jafri@arm.com if (timerZeroEvent.scheduled()) { 26011130Sali.jafri@arm.com DPRINTF(Timer, "-- Event was already schedule, de-scheduling\n"); 26111130Sali.jafri@arm.com parent->deschedule(timerZeroEvent); 26211130Sali.jafri@arm.com } 26311130Sali.jafri@arm.com parent->schedule(timerZeroEvent, curTick() + time); 26411130Sali.jafri@arm.com DPRINTF(Timer, "-- Scheduling new event for: %d\n", curTick() + time); 26511130Sali.jafri@arm.com} 26611130Sali.jafri@arm.com 26711130Sali.jafri@arm.comvoid 26811051Sandreas.hansson@arm.comCpuLocalTimer::Timer::restartWatchdogCounter(uint32_t val) 26911051Sandreas.hansson@arm.com{ 27011051Sandreas.hansson@arm.com DPRINTF(Timer, "Resetting watchdog counter with value %#x\n", val); 27111051Sandreas.hansson@arm.com if (!watchdogControl.enable) 27211744Snikos.nikoleris@arm.com return; 27311051Sandreas.hansson@arm.com 27411276Sandreas.hansson@arm.com Tick time = parent->clockPeriod() * power(16, watchdogControl.prescalar); 27511276Sandreas.hansson@arm.com time *= val; 27611276Sandreas.hansson@arm.com 27711276Sandreas.hansson@arm.com if (watchdogZeroEvent.scheduled()) { 27811276Sandreas.hansson@arm.com DPRINTF(Timer, "-- Event was already schedule, de-scheduling\n"); 27911276Sandreas.hansson@arm.com parent->deschedule(watchdogZeroEvent); 28011276Sandreas.hansson@arm.com } 28111276Sandreas.hansson@arm.com parent->schedule(watchdogZeroEvent, curTick() + time); 28211276Sandreas.hansson@arm.com DPRINTF(Timer, "-- Scheduling new event for: %d\n", curTick() + time); 28311051Sandreas.hansson@arm.com} 28411276Sandreas.hansson@arm.com////// 28511276Sandreas.hansson@arm.com 28611276Sandreas.hansson@arm.comvoid 28711276Sandreas.hansson@arm.comCpuLocalTimer::Timer::timerAtZero() 28811276Sandreas.hansson@arm.com{ 28911051Sandreas.hansson@arm.com if (!timerControl.enable) 29011051Sandreas.hansson@arm.com return; 29111051Sandreas.hansson@arm.com 29211051Sandreas.hansson@arm.com DPRINTF(Timer, "Timer Counter reached zero\n"); 29311051Sandreas.hansson@arm.com 29411051Sandreas.hansson@arm.com rawIntTimer = true; 29511051Sandreas.hansson@arm.com bool old_pending = pendingIntTimer; 29611051Sandreas.hansson@arm.com if (timerControl.intEnable) 29711051Sandreas.hansson@arm.com pendingIntTimer = true; 29811051Sandreas.hansson@arm.com if (pendingIntTimer && !old_pending) { 29911051Sandreas.hansson@arm.com DPRINTF(Timer, "-- Causing interrupt\n"); 30012724Snikos.nikoleris@arm.com parent->gic->sendPPInt(intNumTimer, cpuNum); 30111051Sandreas.hansson@arm.com } 30211051Sandreas.hansson@arm.com 30311051Sandreas.hansson@arm.com if (!timerControl.autoReload) 30411051Sandreas.hansson@arm.com return; 30511051Sandreas.hansson@arm.com else 30611051Sandreas.hansson@arm.com restartTimerCounter(timerLoadValue); 30711051Sandreas.hansson@arm.com} 30811051Sandreas.hansson@arm.com 30911051Sandreas.hansson@arm.comvoid 31011051Sandreas.hansson@arm.comCpuLocalTimer::Timer::watchdogAtZero() 31111051Sandreas.hansson@arm.com{ 31211051Sandreas.hansson@arm.com if (!watchdogControl.enable) 31311051Sandreas.hansson@arm.com return; 31412630Snikos.nikoleris@arm.com 31512720Snikos.nikoleris@arm.com DPRINTF(Timer, "Watchdog Counter reached zero\n"); 31612720Snikos.nikoleris@arm.com 31712720Snikos.nikoleris@arm.com rawIntWatchdog = true; 31812720Snikos.nikoleris@arm.com bool old_pending = pendingIntWatchdog; 31912720Snikos.nikoleris@arm.com // generates an interrupt only if the watchdog is in timer 32012720Snikos.nikoleris@arm.com // mode. 32112720Snikos.nikoleris@arm.com if (watchdogControl.intEnable && !watchdogControl.watchdogMode) 32212724Snikos.nikoleris@arm.com pendingIntWatchdog = true; 32312720Snikos.nikoleris@arm.com else if (watchdogControl.watchdogMode) { 32412720Snikos.nikoleris@arm.com rawResetWatchdog = true; 32512720Snikos.nikoleris@arm.com fatal("gem5 ARM Model does not support true watchdog operation!\n"); 32612720Snikos.nikoleris@arm.com //XXX: Should we ever support a true watchdog reset? 32712720Snikos.nikoleris@arm.com } 32812720Snikos.nikoleris@arm.com 32912724Snikos.nikoleris@arm.com if (pendingIntWatchdog && !old_pending) { 33012724Snikos.nikoleris@arm.com DPRINTF(Timer, "-- Causing interrupt\n"); 33112724Snikos.nikoleris@arm.com parent->gic->sendPPInt(intNumWatchdog, cpuNum); 33212724Snikos.nikoleris@arm.com } 33312724Snikos.nikoleris@arm.com 33412724Snikos.nikoleris@arm.com if (watchdogControl.watchdogMode) 33512724Snikos.nikoleris@arm.com return; 33612724Snikos.nikoleris@arm.com else if (watchdogControl.autoReload) 33712724Snikos.nikoleris@arm.com restartWatchdogCounter(watchdogLoadValue); 33812724Snikos.nikoleris@arm.com} 33912724Snikos.nikoleris@arm.com 34012724Snikos.nikoleris@arm.comvoid 34112724Snikos.nikoleris@arm.comCpuLocalTimer::Timer::serialize(std::ostream &os) 34212724Snikos.nikoleris@arm.com{ 34312724Snikos.nikoleris@arm.com DPRINTF(Checkpoint, "Serializing Arm CpuLocalTimer\n"); 34412724Snikos.nikoleris@arm.com SERIALIZE_SCALAR(intNumTimer); 34512724Snikos.nikoleris@arm.com SERIALIZE_SCALAR(intNumWatchdog); 34612724Snikos.nikoleris@arm.com 34712724Snikos.nikoleris@arm.com uint32_t timer_control_serial = timerControl; 34812724Snikos.nikoleris@arm.com uint32_t watchdog_control_serial = watchdogControl; 34912724Snikos.nikoleris@arm.com SERIALIZE_SCALAR(timer_control_serial); 35012724Snikos.nikoleris@arm.com SERIALIZE_SCALAR(watchdog_control_serial); 35112724Snikos.nikoleris@arm.com 35212724Snikos.nikoleris@arm.com SERIALIZE_SCALAR(rawIntTimer); 35312724Snikos.nikoleris@arm.com SERIALIZE_SCALAR(rawIntWatchdog); 35412720Snikos.nikoleris@arm.com SERIALIZE_SCALAR(rawResetWatchdog); 35512720Snikos.nikoleris@arm.com SERIALIZE_SCALAR(watchdogDisableReg); 35612724Snikos.nikoleris@arm.com SERIALIZE_SCALAR(pendingIntTimer); 35712720Snikos.nikoleris@arm.com SERIALIZE_SCALAR(pendingIntWatchdog); 35812720Snikos.nikoleris@arm.com SERIALIZE_SCALAR(timerLoadValue); 35912720Snikos.nikoleris@arm.com SERIALIZE_SCALAR(watchdogLoadValue); 36012720Snikos.nikoleris@arm.com 36112720Snikos.nikoleris@arm.com bool timer_is_in_event = timerZeroEvent.scheduled(); 36212720Snikos.nikoleris@arm.com SERIALIZE_SCALAR(timer_is_in_event); 36312720Snikos.nikoleris@arm.com bool watchdog_is_in_event = watchdogZeroEvent.scheduled(); 36412720Snikos.nikoleris@arm.com SERIALIZE_SCALAR(watchdog_is_in_event); 36512720Snikos.nikoleris@arm.com 36612720Snikos.nikoleris@arm.com Tick timer_event_time; 36712720Snikos.nikoleris@arm.com if (timer_is_in_event){ 36812720Snikos.nikoleris@arm.com timer_event_time = timerZeroEvent.when(); 36912720Snikos.nikoleris@arm.com SERIALIZE_SCALAR(timer_event_time); 37012720Snikos.nikoleris@arm.com } 37112720Snikos.nikoleris@arm.com Tick watchdog_event_time; 37212720Snikos.nikoleris@arm.com if (watchdog_is_in_event){ 37312720Snikos.nikoleris@arm.com watchdog_event_time = watchdogZeroEvent.when(); 37412720Snikos.nikoleris@arm.com SERIALIZE_SCALAR(watchdog_event_time); 37512720Snikos.nikoleris@arm.com } 37612720Snikos.nikoleris@arm.com} 37712720Snikos.nikoleris@arm.com 37812720Snikos.nikoleris@arm.comvoid 37912720Snikos.nikoleris@arm.comCpuLocalTimer::Timer::unserialize(Checkpoint *cp, const std::string §ion) 38012749Sgiacomo.travaglini@arm.com{ 38112749Sgiacomo.travaglini@arm.com DPRINTF(Checkpoint, "Unserializing Arm CpuLocalTimer\n"); 38212749Sgiacomo.travaglini@arm.com 38312749Sgiacomo.travaglini@arm.com UNSERIALIZE_SCALAR(intNumTimer); 38412720Snikos.nikoleris@arm.com UNSERIALIZE_SCALAR(intNumWatchdog); 38512720Snikos.nikoleris@arm.com 38612720Snikos.nikoleris@arm.com uint32_t timer_control_serial; 38712720Snikos.nikoleris@arm.com UNSERIALIZE_SCALAR(timer_control_serial); 38812720Snikos.nikoleris@arm.com timerControl = timer_control_serial; 38912720Snikos.nikoleris@arm.com uint32_t watchdog_control_serial; 39012720Snikos.nikoleris@arm.com UNSERIALIZE_SCALAR(watchdog_control_serial); 39112720Snikos.nikoleris@arm.com watchdogControl = watchdog_control_serial; 39212720Snikos.nikoleris@arm.com 39312720Snikos.nikoleris@arm.com UNSERIALIZE_SCALAR(rawIntTimer); 39412724Snikos.nikoleris@arm.com UNSERIALIZE_SCALAR(rawIntWatchdog); 39512720Snikos.nikoleris@arm.com UNSERIALIZE_SCALAR(rawResetWatchdog); 39612720Snikos.nikoleris@arm.com UNSERIALIZE_SCALAR(watchdogDisableReg); 39712720Snikos.nikoleris@arm.com UNSERIALIZE_SCALAR(pendingIntTimer); 39812720Snikos.nikoleris@arm.com UNSERIALIZE_SCALAR(pendingIntWatchdog); 39912720Snikos.nikoleris@arm.com UNSERIALIZE_SCALAR(timerLoadValue); 40012720Snikos.nikoleris@arm.com UNSERIALIZE_SCALAR(watchdogLoadValue); 40112724Snikos.nikoleris@arm.com 40212720Snikos.nikoleris@arm.com bool timer_is_in_event; 40312720Snikos.nikoleris@arm.com UNSERIALIZE_SCALAR(timer_is_in_event); 40412720Snikos.nikoleris@arm.com bool watchdog_is_in_event; 40511051Sandreas.hansson@arm.com UNSERIALIZE_SCALAR(watchdog_is_in_event); 40611051Sandreas.hansson@arm.com 40711830Sbaz21@cam.ac.uk Tick timer_event_time; 40811051Sandreas.hansson@arm.com if (timer_is_in_event){ 40911051Sandreas.hansson@arm.com UNSERIALIZE_SCALAR(timer_event_time); 41011051Sandreas.hansson@arm.com parent->schedule(timerZeroEvent, timer_event_time); 41111284Sandreas.hansson@arm.com } 41211051Sandreas.hansson@arm.com Tick watchdog_event_time; 41311284Sandreas.hansson@arm.com if (watchdog_is_in_event) { 41411284Sandreas.hansson@arm.com UNSERIALIZE_SCALAR(watchdog_event_time); 41511744Snikos.nikoleris@arm.com parent->schedule(watchdogZeroEvent, watchdog_event_time); 41611744Snikos.nikoleris@arm.com } 41711051Sandreas.hansson@arm.com} 41811284Sandreas.hansson@arm.com 41911284Sandreas.hansson@arm.com 42011284Sandreas.hansson@arm.com 42111284Sandreas.hansson@arm.comvoid 42211284Sandreas.hansson@arm.comCpuLocalTimer::serialize(std::ostream &os) 42311334Sandreas.hansson@arm.com{ 42411284Sandreas.hansson@arm.com for (int i = 0; i < CPU_MAX; i++) { 42511334Sandreas.hansson@arm.com nameOut(os, csprintf("%s.timer%d", name(), i)); 42611334Sandreas.hansson@arm.com localTimer[i].serialize(os); 42711334Sandreas.hansson@arm.com } 42811334Sandreas.hansson@arm.com} 42911284Sandreas.hansson@arm.com 43011334Sandreas.hansson@arm.comvoid 43111334Sandreas.hansson@arm.comCpuLocalTimer::unserialize(Checkpoint *cp, const std::string §ion) 43211334Sandreas.hansson@arm.com{ 43311334Sandreas.hansson@arm.com for (int i = 0; i < CPU_MAX; i++) { 43411334Sandreas.hansson@arm.com localTimer[i].unserialize(cp, csprintf("%s.timer%d", section, i)); 43511334Sandreas.hansson@arm.com } 43611051Sandreas.hansson@arm.com} 43711334Sandreas.hansson@arm.com 43811334Sandreas.hansson@arm.comCpuLocalTimer * 43911334Sandreas.hansson@arm.comCpuLocalTimerParams::create() 44011334Sandreas.hansson@arm.com{ 44111051Sandreas.hansson@arm.com return new CpuLocalTimer(this); 44211334Sandreas.hansson@arm.com} 44311334Sandreas.hansson@arm.com