1/*
| 1/*
|
2 * Copyright (c) 2010-2013 ARM Limited
| 2 * Copyright (c) 2010-2013,2018 ARM Limited
|
3 * All rights reserved 4 * 5 * The license below extends only to copyright in the software and shall 6 * not be construed as granting a license to any other intellectual 7 * property including but not limited to intellectual property relating 8 * to a hardware implementation of the functionality of the software 9 * licensed hereunder. You may use the software subject to the license 10 * terms below provided that you ensure that this notice is replicated 11 * unmodified and in its entirety in all distributions of the software, 12 * modified or unmodified, in source code or in binary form. 13 * 14 * Redistribution and use in source and binary forms, with or without 15 * modification, are permitted provided that the following conditions are 16 * met: redistributions of source code must retain the above copyright 17 * notice, this list of conditions and the following disclaimer; 18 * redistributions in binary form must reproduce the above copyright 19 * notice, this list of conditions and the following disclaimer in the 20 * documentation and/or other materials provided with the distribution; 21 * neither the name of the copyright holders nor the names of its 22 * contributors may be used to endorse or promote products derived from 23 * this software without specific prior written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 26 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 27 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 28 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 29 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 30 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 31 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 35 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 36 * 37 * Authors: Ali Saidi 38 * Geoffrey Blake 39 */ 40 41#include "dev/arm/timer_cpulocal.hh" 42
| 3 * All rights reserved 4 * 5 * The license below extends only to copyright in the software and shall 6 * not be construed as granting a license to any other intellectual 7 * property including but not limited to intellectual property relating 8 * to a hardware implementation of the functionality of the software 9 * licensed hereunder. You may use the software subject to the license 10 * terms below provided that you ensure that this notice is replicated 11 * unmodified and in its entirety in all distributions of the software, 12 * modified or unmodified, in source code or in binary form. 13 * 14 * Redistribution and use in source and binary forms, with or without 15 * modification, are permitted provided that the following conditions are 16 * met: redistributions of source code must retain the above copyright 17 * notice, this list of conditions and the following disclaimer; 18 * redistributions in binary form must reproduce the above copyright 19 * notice, this list of conditions and the following disclaimer in the 20 * documentation and/or other materials provided with the distribution; 21 * neither the name of the copyright holders nor the names of its 22 * contributors may be used to endorse or promote products derived from 23 * this software without specific prior written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 26 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 27 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 28 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 29 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 30 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 31 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 35 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 36 * 37 * Authors: Ali Saidi 38 * Geoffrey Blake 39 */ 40 41#include "dev/arm/timer_cpulocal.hh" 42
|
| 43#include "arch/arm/system.hh"
|
43#include "base/intmath.hh" 44#include "base/trace.hh" 45#include "debug/Checkpoint.hh" 46#include "debug/Timer.hh" 47#include "dev/arm/base_gic.hh" 48#include "mem/packet.hh" 49#include "mem/packet_access.hh" 50 51CpuLocalTimer::CpuLocalTimer(Params *p)
| 44#include "base/intmath.hh" 45#include "base/trace.hh" 46#include "debug/Checkpoint.hh" 47#include "debug/Timer.hh" 48#include "dev/arm/base_gic.hh" 49#include "mem/packet.hh" 50#include "mem/packet_access.hh" 51 52CpuLocalTimer::CpuLocalTimer(Params *p)
|
52 : BasicPioDevice(p, 0x38), gic(p->gic)
| 53 : BasicPioDevice(p, 0x38)
|
53{
| 54{
|
| 55} 56 57void 58CpuLocalTimer::init() 59{ 60 auto p = params();
|
54 // Initialize the timer registers for each per cpu timer
| 61 // Initialize the timer registers for each per cpu timer
|
55 for (int i = 0; i < CPU_MAX; i++) {
| 62 for (int i = 0; i < sys->numContexts(); i++) { 63 ThreadContext* tc = sys->getThreadContext(i);
|
56 std::stringstream oss; 57 oss << name() << ".timer" << i;
| 64 std::stringstream oss; 65 oss << name() << ".timer" << i;
|
58 localTimer[i]._name = oss.str(); 59 localTimer[i].parent = this; 60 localTimer[i].intNumTimer = p->int_num_timer; 61 localTimer[i].intNumWatchdog = p->int_num_watchdog; 62 localTimer[i].cpuNum = i;
| 66 67 localTimer.emplace_back( 68 new Timer(oss.str(), this, 69 p->int_timer->get(tc), 70 p->int_watchdog->get(tc)));
|
63 }
| 71 }
|
| 72 73 BasicPioDevice::init();
|
64} 65
| 74} 75
|
66CpuLocalTimer::Timer::Timer() 67 : timerControl(0x0), watchdogControl(0x0), rawIntTimer(false), rawIntWatchdog(false), 68 rawResetWatchdog(false), watchdogDisableReg(0x0), pendingIntTimer(false), pendingIntWatchdog(false),
| 76CpuLocalTimer::Timer::Timer(const std::string &timer_name, 77 CpuLocalTimer* _parent, 78 ArmInterruptPin* int_timer, 79 ArmInterruptPin* int_watchdog) 80 : _name(timer_name), parent(_parent), intTimer(int_timer), 81 intWatchdog(int_watchdog), timerControl(0x0), watchdogControl(0x0), 82 rawIntTimer(false), rawIntWatchdog(false), 83 rawResetWatchdog(false), watchdogDisableReg(0x0), 84 pendingIntTimer(false), pendingIntWatchdog(false),
|
69 timerLoadValue(0x0), watchdogLoadValue(0x0), 70 timerZeroEvent([this]{ timerAtZero(); }, name()), 71 watchdogZeroEvent([this]{ watchdogAtZero(); }, name()) 72{ 73} 74 75Tick 76CpuLocalTimer::read(PacketPtr pkt) 77{ 78 assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize); 79 assert(pkt->getSize() == 4); 80 Addr daddr = pkt->getAddr() - pioAddr; 81 ContextID cpu_id = pkt->req->contextId(); 82 DPRINTF(Timer, "Reading from CpuLocalTimer at offset: %#x\n", daddr); 83 assert(cpu_id >= 0);
| 85 timerLoadValue(0x0), watchdogLoadValue(0x0), 86 timerZeroEvent([this]{ timerAtZero(); }, name()), 87 watchdogZeroEvent([this]{ watchdogAtZero(); }, name()) 88{ 89} 90 91Tick 92CpuLocalTimer::read(PacketPtr pkt) 93{ 94 assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize); 95 assert(pkt->getSize() == 4); 96 Addr daddr = pkt->getAddr() - pioAddr; 97 ContextID cpu_id = pkt->req->contextId(); 98 DPRINTF(Timer, "Reading from CpuLocalTimer at offset: %#x\n", daddr); 99 assert(cpu_id >= 0);
|
84 assert(cpu_id < CPU_MAX);
| 100 assert(cpu_id < localTimer.size());
|
85 86 if (daddr < Timer::Size)
| 101 102 if (daddr < Timer::Size)
|
87 localTimer[cpu_id].read(pkt, daddr);
| 103 localTimer[cpu_id]->read(pkt, daddr);
|
88 else 89 panic("Tried to read CpuLocalTimer at offset %#x that doesn't exist\n", daddr); 90 pkt->makeAtomicResponse(); 91 return pioDelay; 92} 93 94 95void 96CpuLocalTimer::Timer::read(PacketPtr pkt, Addr daddr) 97{ 98 DPRINTF(Timer, "Reading from CpuLocalTimer at offset: %#x\n", daddr); 99 Tick time; 100 101 switch(daddr) { 102 case TimerLoadReg: 103 pkt->set<uint32_t>(timerLoadValue); 104 break; 105 case TimerCounterReg: 106 DPRINTF(Timer, "Event schedule for timer %d, clock=%d, prescale=%d\n", 107 timerZeroEvent.when(), parent->clockPeriod(), 108 timerControl.prescalar); 109 time = timerZeroEvent.when() - curTick(); 110 time = time / parent->clockPeriod() / 111 power(16, timerControl.prescalar); 112 DPRINTF(Timer, "-- returning counter at %d\n", time); 113 pkt->set<uint32_t>(time); 114 break; 115 case TimerControlReg: 116 pkt->set<uint32_t>(timerControl); 117 break; 118 case TimerIntStatusReg: 119 pkt->set<uint32_t>(rawIntTimer); 120 break; 121 case WatchdogLoadReg: 122 pkt->set<uint32_t>(watchdogLoadValue); 123 break; 124 case WatchdogCounterReg: 125 DPRINTF(Timer, 126 "Event schedule for watchdog %d, clock=%d, prescale=%d\n", 127 watchdogZeroEvent.when(), parent->clockPeriod(), 128 watchdogControl.prescalar); 129 time = watchdogZeroEvent.when() - curTick(); 130 time = time / parent->clockPeriod() / 131 power(16, watchdogControl.prescalar); 132 DPRINTF(Timer, "-- returning counter at %d\n", time); 133 pkt->set<uint32_t>(time); 134 break; 135 case WatchdogControlReg: 136 pkt->set<uint32_t>(watchdogControl); 137 break; 138 case WatchdogIntStatusReg: 139 pkt->set<uint32_t>(rawIntWatchdog); 140 break; 141 case WatchdogResetStatusReg: 142 pkt->set<uint32_t>(rawResetWatchdog); 143 break; 144 case WatchdogDisableReg: 145 panic("Tried to read from WatchdogDisableRegister\n"); 146 break; 147 default: 148 panic("Tried to read CpuLocalTimer at offset %#x\n", daddr); 149 break; 150 } 151} 152 153Tick 154CpuLocalTimer::write(PacketPtr pkt) 155{ 156 assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize); 157 assert(pkt->getSize() == 4); 158 Addr daddr = pkt->getAddr() - pioAddr; 159 ContextID cpu_id = pkt->req->contextId(); 160 DPRINTF(Timer, "Writing to CpuLocalTimer at offset: %#x\n", daddr); 161 assert(cpu_id >= 0);
| 104 else 105 panic("Tried to read CpuLocalTimer at offset %#x that doesn't exist\n", daddr); 106 pkt->makeAtomicResponse(); 107 return pioDelay; 108} 109 110 111void 112CpuLocalTimer::Timer::read(PacketPtr pkt, Addr daddr) 113{ 114 DPRINTF(Timer, "Reading from CpuLocalTimer at offset: %#x\n", daddr); 115 Tick time; 116 117 switch(daddr) { 118 case TimerLoadReg: 119 pkt->set<uint32_t>(timerLoadValue); 120 break; 121 case TimerCounterReg: 122 DPRINTF(Timer, "Event schedule for timer %d, clock=%d, prescale=%d\n", 123 timerZeroEvent.when(), parent->clockPeriod(), 124 timerControl.prescalar); 125 time = timerZeroEvent.when() - curTick(); 126 time = time / parent->clockPeriod() / 127 power(16, timerControl.prescalar); 128 DPRINTF(Timer, "-- returning counter at %d\n", time); 129 pkt->set<uint32_t>(time); 130 break; 131 case TimerControlReg: 132 pkt->set<uint32_t>(timerControl); 133 break; 134 case TimerIntStatusReg: 135 pkt->set<uint32_t>(rawIntTimer); 136 break; 137 case WatchdogLoadReg: 138 pkt->set<uint32_t>(watchdogLoadValue); 139 break; 140 case WatchdogCounterReg: 141 DPRINTF(Timer, 142 "Event schedule for watchdog %d, clock=%d, prescale=%d\n", 143 watchdogZeroEvent.when(), parent->clockPeriod(), 144 watchdogControl.prescalar); 145 time = watchdogZeroEvent.when() - curTick(); 146 time = time / parent->clockPeriod() / 147 power(16, watchdogControl.prescalar); 148 DPRINTF(Timer, "-- returning counter at %d\n", time); 149 pkt->set<uint32_t>(time); 150 break; 151 case WatchdogControlReg: 152 pkt->set<uint32_t>(watchdogControl); 153 break; 154 case WatchdogIntStatusReg: 155 pkt->set<uint32_t>(rawIntWatchdog); 156 break; 157 case WatchdogResetStatusReg: 158 pkt->set<uint32_t>(rawResetWatchdog); 159 break; 160 case WatchdogDisableReg: 161 panic("Tried to read from WatchdogDisableRegister\n"); 162 break; 163 default: 164 panic("Tried to read CpuLocalTimer at offset %#x\n", daddr); 165 break; 166 } 167} 168 169Tick 170CpuLocalTimer::write(PacketPtr pkt) 171{ 172 assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize); 173 assert(pkt->getSize() == 4); 174 Addr daddr = pkt->getAddr() - pioAddr; 175 ContextID cpu_id = pkt->req->contextId(); 176 DPRINTF(Timer, "Writing to CpuLocalTimer at offset: %#x\n", daddr); 177 assert(cpu_id >= 0);
|
162 assert(cpu_id < CPU_MAX);
| 178 assert(cpu_id < localTimer.size());
|
163 164 if (daddr < Timer::Size)
| 179 180 if (daddr < Timer::Size)
|
165 localTimer[cpu_id].write(pkt, daddr);
| 181 localTimer[cpu_id]->write(pkt, daddr);
|
166 else 167 panic("Tried to write CpuLocalTimer at offset %#x that doesn't exist\n", daddr); 168 pkt->makeAtomicResponse(); 169 return pioDelay; 170} 171 172void 173CpuLocalTimer::Timer::write(PacketPtr pkt, Addr daddr) 174{ 175 DPRINTF(Timer, "Writing to CpuLocalTimer at offset: %#x\n", daddr); 176 bool old_enable; 177 bool old_wd_mode; 178 uint32_t old_val; 179 180 switch (daddr) { 181 case TimerLoadReg: 182 // Writing to this register also resets the counter register and 183 // starts decrementing if the counter is enabled. 184 timerLoadValue = pkt->get<uint32_t>(); 185 restartTimerCounter(timerLoadValue); 186 break; 187 case TimerCounterReg: 188 // Can be written, doesn't start counting unless the timer is enabled 189 restartTimerCounter(pkt->get<uint32_t>()); 190 break; 191 case TimerControlReg: 192 old_enable = timerControl.enable; 193 timerControl = pkt->get<uint32_t>(); 194 if ((old_enable == 0) && timerControl.enable) 195 restartTimerCounter(timerLoadValue); 196 break; 197 case TimerIntStatusReg: 198 rawIntTimer = false; 199 if (pendingIntTimer) { 200 pendingIntTimer = false; 201 DPRINTF(Timer, "Clearing interrupt\n"); 202 } 203 break; 204 case WatchdogLoadReg: 205 watchdogLoadValue = pkt->get<uint32_t>(); 206 restartWatchdogCounter(watchdogLoadValue); 207 break; 208 case WatchdogCounterReg: 209 // Can't be written when in watchdog mode, but can in timer mode 210 if (!watchdogControl.watchdogMode) { 211 restartWatchdogCounter(pkt->get<uint32_t>()); 212 } 213 break; 214 case WatchdogControlReg: 215 old_enable = watchdogControl.enable; 216 old_wd_mode = watchdogControl.watchdogMode; 217 watchdogControl = pkt->get<uint32_t>(); 218 if ((old_enable == 0) && watchdogControl.enable) 219 restartWatchdogCounter(watchdogLoadValue); 220 // cannot disable watchdog using control register 221 if ((old_wd_mode == 1) && watchdogControl.watchdogMode == 0) 222 watchdogControl.watchdogMode = 1; 223 break; 224 case WatchdogIntStatusReg: 225 rawIntWatchdog = false; 226 if (pendingIntWatchdog) { 227 pendingIntWatchdog = false; 228 DPRINTF(Timer, "Clearing watchdog interrupt\n"); 229 } 230 break; 231 case WatchdogResetStatusReg: 232 rawResetWatchdog = false; 233 DPRINTF(Timer, "Clearing watchdog reset flag\n"); 234 break; 235 case WatchdogDisableReg: 236 old_val = watchdogDisableReg; 237 watchdogDisableReg = pkt->get<uint32_t>(); 238 // if this sequence is observed, turn off watchdog mode 239 if (old_val == 0x12345678 && watchdogDisableReg == 0x87654321) 240 watchdogControl.watchdogMode = 0; 241 break; 242 default: 243 panic("Tried to write CpuLocalTimer timer at offset %#x\n", daddr); 244 break; 245 } 246} 247 248//XXX: Two functions are needed because the control registers are different types 249void 250CpuLocalTimer::Timer::restartTimerCounter(uint32_t val) 251{ 252 DPRINTF(Timer, "Resetting timer counter with value %#x\n", val); 253 if (!timerControl.enable) 254 return; 255 256 Tick time = parent->clockPeriod() * power(16, timerControl.prescalar); 257 time *= val; 258 259 if (timerZeroEvent.scheduled()) { 260 DPRINTF(Timer, "-- Event was already schedule, de-scheduling\n"); 261 parent->deschedule(timerZeroEvent); 262 } 263 parent->schedule(timerZeroEvent, curTick() + time); 264 DPRINTF(Timer, "-- Scheduling new event for: %d\n", curTick() + time); 265} 266 267void 268CpuLocalTimer::Timer::restartWatchdogCounter(uint32_t val) 269{ 270 DPRINTF(Timer, "Resetting watchdog counter with value %#x\n", val); 271 if (!watchdogControl.enable) 272 return; 273 274 Tick time = parent->clockPeriod() * power(16, watchdogControl.prescalar); 275 time *= val; 276 277 if (watchdogZeroEvent.scheduled()) { 278 DPRINTF(Timer, "-- Event was already schedule, de-scheduling\n"); 279 parent->deschedule(watchdogZeroEvent); 280 } 281 parent->schedule(watchdogZeroEvent, curTick() + time); 282 DPRINTF(Timer, "-- Scheduling new event for: %d\n", curTick() + time); 283} 284////// 285 286void 287CpuLocalTimer::Timer::timerAtZero() 288{ 289 if (!timerControl.enable) 290 return; 291 292 DPRINTF(Timer, "Timer Counter reached zero\n"); 293 294 rawIntTimer = true; 295 bool old_pending = pendingIntTimer; 296 if (timerControl.intEnable) 297 pendingIntTimer = true; 298 if (pendingIntTimer && !old_pending) { 299 DPRINTF(Timer, "-- Causing interrupt\n");
| 182 else 183 panic("Tried to write CpuLocalTimer at offset %#x that doesn't exist\n", daddr); 184 pkt->makeAtomicResponse(); 185 return pioDelay; 186} 187 188void 189CpuLocalTimer::Timer::write(PacketPtr pkt, Addr daddr) 190{ 191 DPRINTF(Timer, "Writing to CpuLocalTimer at offset: %#x\n", daddr); 192 bool old_enable; 193 bool old_wd_mode; 194 uint32_t old_val; 195 196 switch (daddr) { 197 case TimerLoadReg: 198 // Writing to this register also resets the counter register and 199 // starts decrementing if the counter is enabled. 200 timerLoadValue = pkt->get<uint32_t>(); 201 restartTimerCounter(timerLoadValue); 202 break; 203 case TimerCounterReg: 204 // Can be written, doesn't start counting unless the timer is enabled 205 restartTimerCounter(pkt->get<uint32_t>()); 206 break; 207 case TimerControlReg: 208 old_enable = timerControl.enable; 209 timerControl = pkt->get<uint32_t>(); 210 if ((old_enable == 0) && timerControl.enable) 211 restartTimerCounter(timerLoadValue); 212 break; 213 case TimerIntStatusReg: 214 rawIntTimer = false; 215 if (pendingIntTimer) { 216 pendingIntTimer = false; 217 DPRINTF(Timer, "Clearing interrupt\n"); 218 } 219 break; 220 case WatchdogLoadReg: 221 watchdogLoadValue = pkt->get<uint32_t>(); 222 restartWatchdogCounter(watchdogLoadValue); 223 break; 224 case WatchdogCounterReg: 225 // Can't be written when in watchdog mode, but can in timer mode 226 if (!watchdogControl.watchdogMode) { 227 restartWatchdogCounter(pkt->get<uint32_t>()); 228 } 229 break; 230 case WatchdogControlReg: 231 old_enable = watchdogControl.enable; 232 old_wd_mode = watchdogControl.watchdogMode; 233 watchdogControl = pkt->get<uint32_t>(); 234 if ((old_enable == 0) && watchdogControl.enable) 235 restartWatchdogCounter(watchdogLoadValue); 236 // cannot disable watchdog using control register 237 if ((old_wd_mode == 1) && watchdogControl.watchdogMode == 0) 238 watchdogControl.watchdogMode = 1; 239 break; 240 case WatchdogIntStatusReg: 241 rawIntWatchdog = false; 242 if (pendingIntWatchdog) { 243 pendingIntWatchdog = false; 244 DPRINTF(Timer, "Clearing watchdog interrupt\n"); 245 } 246 break; 247 case WatchdogResetStatusReg: 248 rawResetWatchdog = false; 249 DPRINTF(Timer, "Clearing watchdog reset flag\n"); 250 break; 251 case WatchdogDisableReg: 252 old_val = watchdogDisableReg; 253 watchdogDisableReg = pkt->get<uint32_t>(); 254 // if this sequence is observed, turn off watchdog mode 255 if (old_val == 0x12345678 && watchdogDisableReg == 0x87654321) 256 watchdogControl.watchdogMode = 0; 257 break; 258 default: 259 panic("Tried to write CpuLocalTimer timer at offset %#x\n", daddr); 260 break; 261 } 262} 263 264//XXX: Two functions are needed because the control registers are different types 265void 266CpuLocalTimer::Timer::restartTimerCounter(uint32_t val) 267{ 268 DPRINTF(Timer, "Resetting timer counter with value %#x\n", val); 269 if (!timerControl.enable) 270 return; 271 272 Tick time = parent->clockPeriod() * power(16, timerControl.prescalar); 273 time *= val; 274 275 if (timerZeroEvent.scheduled()) { 276 DPRINTF(Timer, "-- Event was already schedule, de-scheduling\n"); 277 parent->deschedule(timerZeroEvent); 278 } 279 parent->schedule(timerZeroEvent, curTick() + time); 280 DPRINTF(Timer, "-- Scheduling new event for: %d\n", curTick() + time); 281} 282 283void 284CpuLocalTimer::Timer::restartWatchdogCounter(uint32_t val) 285{ 286 DPRINTF(Timer, "Resetting watchdog counter with value %#x\n", val); 287 if (!watchdogControl.enable) 288 return; 289 290 Tick time = parent->clockPeriod() * power(16, watchdogControl.prescalar); 291 time *= val; 292 293 if (watchdogZeroEvent.scheduled()) { 294 DPRINTF(Timer, "-- Event was already schedule, de-scheduling\n"); 295 parent->deschedule(watchdogZeroEvent); 296 } 297 parent->schedule(watchdogZeroEvent, curTick() + time); 298 DPRINTF(Timer, "-- Scheduling new event for: %d\n", curTick() + time); 299} 300////// 301 302void 303CpuLocalTimer::Timer::timerAtZero() 304{ 305 if (!timerControl.enable) 306 return; 307 308 DPRINTF(Timer, "Timer Counter reached zero\n"); 309 310 rawIntTimer = true; 311 bool old_pending = pendingIntTimer; 312 if (timerControl.intEnable) 313 pendingIntTimer = true; 314 if (pendingIntTimer && !old_pending) { 315 DPRINTF(Timer, "-- Causing interrupt\n");
|
300 parent->gic->sendPPInt(intNumTimer, cpuNum);
| 316 intTimer->raise();
|
301 } 302 303 if (!timerControl.autoReload) 304 return; 305 else 306 restartTimerCounter(timerLoadValue); 307} 308 309void 310CpuLocalTimer::Timer::watchdogAtZero() 311{ 312 if (!watchdogControl.enable) 313 return; 314 315 DPRINTF(Timer, "Watchdog Counter reached zero\n"); 316 317 rawIntWatchdog = true; 318 bool old_pending = pendingIntWatchdog; 319 // generates an interrupt only if the watchdog is in timer 320 // mode. 321 if (watchdogControl.intEnable && !watchdogControl.watchdogMode) 322 pendingIntWatchdog = true; 323 else if (watchdogControl.watchdogMode) { 324 rawResetWatchdog = true; 325 fatal("gem5 ARM Model does not support true watchdog operation!\n"); 326 //XXX: Should we ever support a true watchdog reset? 327 } 328 329 if (pendingIntWatchdog && !old_pending) { 330 DPRINTF(Timer, "-- Causing interrupt\n");
| 317 } 318 319 if (!timerControl.autoReload) 320 return; 321 else 322 restartTimerCounter(timerLoadValue); 323} 324 325void 326CpuLocalTimer::Timer::watchdogAtZero() 327{ 328 if (!watchdogControl.enable) 329 return; 330 331 DPRINTF(Timer, "Watchdog Counter reached zero\n"); 332 333 rawIntWatchdog = true; 334 bool old_pending = pendingIntWatchdog; 335 // generates an interrupt only if the watchdog is in timer 336 // mode. 337 if (watchdogControl.intEnable && !watchdogControl.watchdogMode) 338 pendingIntWatchdog = true; 339 else if (watchdogControl.watchdogMode) { 340 rawResetWatchdog = true; 341 fatal("gem5 ARM Model does not support true watchdog operation!\n"); 342 //XXX: Should we ever support a true watchdog reset? 343 } 344 345 if (pendingIntWatchdog && !old_pending) { 346 DPRINTF(Timer, "-- Causing interrupt\n");
|
331 parent->gic->sendPPInt(intNumWatchdog, cpuNum);
| 347 intWatchdog->raise();
|
332 } 333 334 if (watchdogControl.watchdogMode) 335 return; 336 else if (watchdogControl.autoReload) 337 restartWatchdogCounter(watchdogLoadValue); 338} 339 340void 341CpuLocalTimer::Timer::serialize(CheckpointOut &cp) const 342{ 343 DPRINTF(Checkpoint, "Serializing Arm CpuLocalTimer\n");
| 348 } 349 350 if (watchdogControl.watchdogMode) 351 return; 352 else if (watchdogControl.autoReload) 353 restartWatchdogCounter(watchdogLoadValue); 354} 355 356void 357CpuLocalTimer::Timer::serialize(CheckpointOut &cp) const 358{ 359 DPRINTF(Checkpoint, "Serializing Arm CpuLocalTimer\n");
|
344 SERIALIZE_SCALAR(intNumTimer); 345 SERIALIZE_SCALAR(intNumWatchdog);
| |
346 347 uint32_t timer_control_serial = timerControl; 348 uint32_t watchdog_control_serial = watchdogControl; 349 SERIALIZE_SCALAR(timer_control_serial); 350 SERIALIZE_SCALAR(watchdog_control_serial); 351 352 SERIALIZE_SCALAR(rawIntTimer); 353 SERIALIZE_SCALAR(rawIntWatchdog); 354 SERIALIZE_SCALAR(rawResetWatchdog); 355 SERIALIZE_SCALAR(watchdogDisableReg); 356 SERIALIZE_SCALAR(pendingIntTimer); 357 SERIALIZE_SCALAR(pendingIntWatchdog); 358 SERIALIZE_SCALAR(timerLoadValue); 359 SERIALIZE_SCALAR(watchdogLoadValue); 360 361 bool timer_is_in_event = timerZeroEvent.scheduled(); 362 SERIALIZE_SCALAR(timer_is_in_event); 363 bool watchdog_is_in_event = watchdogZeroEvent.scheduled(); 364 SERIALIZE_SCALAR(watchdog_is_in_event); 365 366 Tick timer_event_time; 367 if (timer_is_in_event){ 368 timer_event_time = timerZeroEvent.when(); 369 SERIALIZE_SCALAR(timer_event_time); 370 } 371 Tick watchdog_event_time; 372 if (watchdog_is_in_event){ 373 watchdog_event_time = watchdogZeroEvent.when(); 374 SERIALIZE_SCALAR(watchdog_event_time); 375 } 376} 377 378void 379CpuLocalTimer::Timer::unserialize(CheckpointIn &cp) 380{ 381 DPRINTF(Checkpoint, "Unserializing Arm CpuLocalTimer\n"); 382
| 360 361 uint32_t timer_control_serial = timerControl; 362 uint32_t watchdog_control_serial = watchdogControl; 363 SERIALIZE_SCALAR(timer_control_serial); 364 SERIALIZE_SCALAR(watchdog_control_serial); 365 366 SERIALIZE_SCALAR(rawIntTimer); 367 SERIALIZE_SCALAR(rawIntWatchdog); 368 SERIALIZE_SCALAR(rawResetWatchdog); 369 SERIALIZE_SCALAR(watchdogDisableReg); 370 SERIALIZE_SCALAR(pendingIntTimer); 371 SERIALIZE_SCALAR(pendingIntWatchdog); 372 SERIALIZE_SCALAR(timerLoadValue); 373 SERIALIZE_SCALAR(watchdogLoadValue); 374 375 bool timer_is_in_event = timerZeroEvent.scheduled(); 376 SERIALIZE_SCALAR(timer_is_in_event); 377 bool watchdog_is_in_event = watchdogZeroEvent.scheduled(); 378 SERIALIZE_SCALAR(watchdog_is_in_event); 379 380 Tick timer_event_time; 381 if (timer_is_in_event){ 382 timer_event_time = timerZeroEvent.when(); 383 SERIALIZE_SCALAR(timer_event_time); 384 } 385 Tick watchdog_event_time; 386 if (watchdog_is_in_event){ 387 watchdog_event_time = watchdogZeroEvent.when(); 388 SERIALIZE_SCALAR(watchdog_event_time); 389 } 390} 391 392void 393CpuLocalTimer::Timer::unserialize(CheckpointIn &cp) 394{ 395 DPRINTF(Checkpoint, "Unserializing Arm CpuLocalTimer\n"); 396
|
383 UNSERIALIZE_SCALAR(intNumTimer); 384 UNSERIALIZE_SCALAR(intNumWatchdog); 385
| |
386 uint32_t timer_control_serial; 387 UNSERIALIZE_SCALAR(timer_control_serial); 388 timerControl = timer_control_serial; 389 uint32_t watchdog_control_serial; 390 UNSERIALIZE_SCALAR(watchdog_control_serial); 391 watchdogControl = watchdog_control_serial; 392 393 UNSERIALIZE_SCALAR(rawIntTimer); 394 UNSERIALIZE_SCALAR(rawIntWatchdog); 395 UNSERIALIZE_SCALAR(rawResetWatchdog); 396 UNSERIALIZE_SCALAR(watchdogDisableReg); 397 UNSERIALIZE_SCALAR(pendingIntTimer); 398 UNSERIALIZE_SCALAR(pendingIntWatchdog); 399 UNSERIALIZE_SCALAR(timerLoadValue); 400 UNSERIALIZE_SCALAR(watchdogLoadValue); 401 402 bool timer_is_in_event; 403 UNSERIALIZE_SCALAR(timer_is_in_event); 404 bool watchdog_is_in_event; 405 UNSERIALIZE_SCALAR(watchdog_is_in_event); 406 407 Tick timer_event_time; 408 if (timer_is_in_event){ 409 UNSERIALIZE_SCALAR(timer_event_time); 410 parent->schedule(timerZeroEvent, timer_event_time); 411 } 412 Tick watchdog_event_time; 413 if (watchdog_is_in_event) { 414 UNSERIALIZE_SCALAR(watchdog_event_time); 415 parent->schedule(watchdogZeroEvent, watchdog_event_time); 416 } 417} 418 419 420 421void 422CpuLocalTimer::serialize(CheckpointOut &cp) const 423{
| 397 uint32_t timer_control_serial; 398 UNSERIALIZE_SCALAR(timer_control_serial); 399 timerControl = timer_control_serial; 400 uint32_t watchdog_control_serial; 401 UNSERIALIZE_SCALAR(watchdog_control_serial); 402 watchdogControl = watchdog_control_serial; 403 404 UNSERIALIZE_SCALAR(rawIntTimer); 405 UNSERIALIZE_SCALAR(rawIntWatchdog); 406 UNSERIALIZE_SCALAR(rawResetWatchdog); 407 UNSERIALIZE_SCALAR(watchdogDisableReg); 408 UNSERIALIZE_SCALAR(pendingIntTimer); 409 UNSERIALIZE_SCALAR(pendingIntWatchdog); 410 UNSERIALIZE_SCALAR(timerLoadValue); 411 UNSERIALIZE_SCALAR(watchdogLoadValue); 412 413 bool timer_is_in_event; 414 UNSERIALIZE_SCALAR(timer_is_in_event); 415 bool watchdog_is_in_event; 416 UNSERIALIZE_SCALAR(watchdog_is_in_event); 417 418 Tick timer_event_time; 419 if (timer_is_in_event){ 420 UNSERIALIZE_SCALAR(timer_event_time); 421 parent->schedule(timerZeroEvent, timer_event_time); 422 } 423 Tick watchdog_event_time; 424 if (watchdog_is_in_event) { 425 UNSERIALIZE_SCALAR(watchdog_event_time); 426 parent->schedule(watchdogZeroEvent, watchdog_event_time); 427 } 428} 429 430 431 432void 433CpuLocalTimer::serialize(CheckpointOut &cp) const 434{
|
424 for (int i = 0; i < CPU_MAX; i++) 425 localTimer[i].serializeSection(cp, csprintf("timer%d", i));
| 435 for (int i = 0; i < sys->numContexts(); i++) 436 localTimer[i]->serializeSection(cp, csprintf("timer%d", i));
|
426} 427 428void 429CpuLocalTimer::unserialize(CheckpointIn &cp) 430{
| 437} 438 439void 440CpuLocalTimer::unserialize(CheckpointIn &cp) 441{
|
431 for (int i = 0; i < CPU_MAX; i++) 432 localTimer[i].unserializeSection(cp, csprintf("timer%d", i));
| 442 for (int i = 0; i < sys->numContexts(); i++) 443 localTimer[i]->unserializeSection(cp, csprintf("timer%d", i));
|
433} 434 435CpuLocalTimer * 436CpuLocalTimerParams::create() 437{ 438 return new CpuLocalTimer(this); 439}
| 444} 445 446CpuLocalTimer * 447CpuLocalTimerParams::create() 448{ 449 return new CpuLocalTimer(this); 450}
|