1/* 2 * Copyright (c) 2013, 2015 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: Giacomo Gabrielli 38 * Andreas Sandberg 39 */ 40 41#include "dev/arm/generic_timer.hh" 42 43#include "arch/arm/system.hh" 44#include "debug/Timer.hh" 45#include "dev/arm/base_gic.hh" 46#include "mem/packet_access.hh" 47#include "params/GenericTimer.hh" 48#include "params/GenericTimerMem.hh" 49 50SystemCounter::SystemCounter() 51 : _freq(0), _period(0), _resetTick(0), _regCntkctl(0) 52{ 53 setFreq(0x01800000); 54} 55 56void 57SystemCounter::setFreq(uint32_t freq) 58{ 59 if (_freq != 0) { 60 // Altering the frequency after boot shouldn't be done in practice. 61 warn_once("The frequency of the system counter has already been set"); 62 } 63 _freq = freq; 64 _period = (1.0 / freq) * SimClock::Frequency; 65 _resetTick = curTick(); 66} 67 68void
| 1/* 2 * Copyright (c) 2013, 2015 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: Giacomo Gabrielli 38 * Andreas Sandberg 39 */ 40 41#include "dev/arm/generic_timer.hh" 42 43#include "arch/arm/system.hh" 44#include "debug/Timer.hh" 45#include "dev/arm/base_gic.hh" 46#include "mem/packet_access.hh" 47#include "params/GenericTimer.hh" 48#include "params/GenericTimerMem.hh" 49 50SystemCounter::SystemCounter() 51 : _freq(0), _period(0), _resetTick(0), _regCntkctl(0) 52{ 53 setFreq(0x01800000); 54} 55 56void 57SystemCounter::setFreq(uint32_t freq) 58{ 59 if (_freq != 0) { 60 // Altering the frequency after boot shouldn't be done in practice. 61 warn_once("The frequency of the system counter has already been set"); 62 } 63 _freq = freq; 64 _period = (1.0 / freq) * SimClock::Frequency; 65 _resetTick = curTick(); 66} 67 68void
|
69SystemCounter::serialize(std::ostream &os) const
| 69SystemCounter::serialize(CheckpointOut &cp) const
|
70{ 71 SERIALIZE_SCALAR(_regCntkctl); 72 SERIALIZE_SCALAR(_freq); 73 SERIALIZE_SCALAR(_period); 74 SERIALIZE_SCALAR(_resetTick); 75} 76 77void
| 70{ 71 SERIALIZE_SCALAR(_regCntkctl); 72 SERIALIZE_SCALAR(_freq); 73 SERIALIZE_SCALAR(_period); 74 SERIALIZE_SCALAR(_resetTick); 75} 76 77void
|
78SystemCounter::unserialize(Checkpoint *cp, 79 const std::string §ion)
| 78SystemCounter::unserialize(CheckpointIn &cp)
|
80{ 81 // We didn't handle CNTKCTL in this class before, assume it's zero 82 // if it isn't present. 83 if (!UNSERIALIZE_OPT_SCALAR(_regCntkctl)) 84 _regCntkctl = 0; 85 UNSERIALIZE_SCALAR(_freq); 86 UNSERIALIZE_SCALAR(_period); 87 UNSERIALIZE_SCALAR(_resetTick); 88} 89 90 91 92ArchTimer::ArchTimer(const std::string &name, 93 SimObject &parent, 94 SystemCounter &sysctr, 95 const Interrupt &interrupt) 96 : _name(name), _parent(parent), _systemCounter(sysctr), 97 _interrupt(interrupt), 98 _control(0), _counterLimit(0), _offset(0), 99 _counterLimitReachedEvent(this) 100{ 101} 102 103void 104ArchTimer::counterLimitReached() 105{ 106 _control.istatus = 1; 107 108 if (!_control.enable) 109 return; 110 111 DPRINTF(Timer, "Counter limit reached\n"); 112 if (!_control.imask) { 113 DPRINTF(Timer, "Causing interrupt\n"); 114 _interrupt.send(); 115 } 116} 117 118void 119ArchTimer::updateCounter() 120{ 121 if (_counterLimitReachedEvent.scheduled()) 122 _parent.deschedule(_counterLimitReachedEvent); 123 if (value() >= _counterLimit) { 124 counterLimitReached(); 125 } else { 126 const auto period(_systemCounter.period()); 127 _control.istatus = 0; 128 _parent.schedule(_counterLimitReachedEvent, 129 curTick() + (_counterLimit - value()) * period); 130 } 131} 132 133void 134ArchTimer::setCompareValue(uint64_t val) 135{ 136 _counterLimit = val; 137 updateCounter(); 138} 139 140void 141ArchTimer::setTimerValue(uint32_t val) 142{ 143 setCompareValue(value() + sext<32>(val)); 144} 145 146void 147ArchTimer::setControl(uint32_t val) 148{ 149 ArchTimerCtrl new_ctl = val; 150 if ((new_ctl.enable && !new_ctl.imask) && 151 !(_control.enable && !_control.imask)) { 152 // Re-evalute the timer condition 153 if (_counterLimit >= value()) { 154 _control.istatus = 1; 155 156 DPRINTF(Timer, "Causing interrupt in control\n"); 157 //_interrupt.send(); 158 } 159 } 160 _control.enable = new_ctl.enable; 161 _control.imask = new_ctl.imask; 162} 163 164void 165ArchTimer::setOffset(uint64_t val) 166{ 167 _offset = val; 168 updateCounter(); 169} 170 171uint64_t 172ArchTimer::value() const 173{ 174 return _systemCounter.value() - _offset; 175} 176 177void
| 79{ 80 // We didn't handle CNTKCTL in this class before, assume it's zero 81 // if it isn't present. 82 if (!UNSERIALIZE_OPT_SCALAR(_regCntkctl)) 83 _regCntkctl = 0; 84 UNSERIALIZE_SCALAR(_freq); 85 UNSERIALIZE_SCALAR(_period); 86 UNSERIALIZE_SCALAR(_resetTick); 87} 88 89 90 91ArchTimer::ArchTimer(const std::string &name, 92 SimObject &parent, 93 SystemCounter &sysctr, 94 const Interrupt &interrupt) 95 : _name(name), _parent(parent), _systemCounter(sysctr), 96 _interrupt(interrupt), 97 _control(0), _counterLimit(0), _offset(0), 98 _counterLimitReachedEvent(this) 99{ 100} 101 102void 103ArchTimer::counterLimitReached() 104{ 105 _control.istatus = 1; 106 107 if (!_control.enable) 108 return; 109 110 DPRINTF(Timer, "Counter limit reached\n"); 111 if (!_control.imask) { 112 DPRINTF(Timer, "Causing interrupt\n"); 113 _interrupt.send(); 114 } 115} 116 117void 118ArchTimer::updateCounter() 119{ 120 if (_counterLimitReachedEvent.scheduled()) 121 _parent.deschedule(_counterLimitReachedEvent); 122 if (value() >= _counterLimit) { 123 counterLimitReached(); 124 } else { 125 const auto period(_systemCounter.period()); 126 _control.istatus = 0; 127 _parent.schedule(_counterLimitReachedEvent, 128 curTick() + (_counterLimit - value()) * period); 129 } 130} 131 132void 133ArchTimer::setCompareValue(uint64_t val) 134{ 135 _counterLimit = val; 136 updateCounter(); 137} 138 139void 140ArchTimer::setTimerValue(uint32_t val) 141{ 142 setCompareValue(value() + sext<32>(val)); 143} 144 145void 146ArchTimer::setControl(uint32_t val) 147{ 148 ArchTimerCtrl new_ctl = val; 149 if ((new_ctl.enable && !new_ctl.imask) && 150 !(_control.enable && !_control.imask)) { 151 // Re-evalute the timer condition 152 if (_counterLimit >= value()) { 153 _control.istatus = 1; 154 155 DPRINTF(Timer, "Causing interrupt in control\n"); 156 //_interrupt.send(); 157 } 158 } 159 _control.enable = new_ctl.enable; 160 _control.imask = new_ctl.imask; 161} 162 163void 164ArchTimer::setOffset(uint64_t val) 165{ 166 _offset = val; 167 updateCounter(); 168} 169 170uint64_t 171ArchTimer::value() const 172{ 173 return _systemCounter.value() - _offset; 174} 175 176void
|
178ArchTimer::serialize(std::ostream &os) const
| 177ArchTimer::serialize(CheckpointOut &cp) const
|
179{
| 178{
|
180 paramOut(os, "control_serial", _control);
| 179 paramOut(cp, "control_serial", _control);
|
181 SERIALIZE_SCALAR(_counterLimit); 182 SERIALIZE_SCALAR(_offset); 183 184 const bool event_scheduled(_counterLimitReachedEvent.scheduled()); 185 SERIALIZE_SCALAR(event_scheduled); 186 if (event_scheduled) { 187 const Tick event_time(_counterLimitReachedEvent.when()); 188 SERIALIZE_SCALAR(event_time); 189 } 190} 191 192void
| 180 SERIALIZE_SCALAR(_counterLimit); 181 SERIALIZE_SCALAR(_offset); 182 183 const bool event_scheduled(_counterLimitReachedEvent.scheduled()); 184 SERIALIZE_SCALAR(event_scheduled); 185 if (event_scheduled) { 186 const Tick event_time(_counterLimitReachedEvent.when()); 187 SERIALIZE_SCALAR(event_time); 188 } 189} 190 191void
|
193ArchTimer::unserialize(Checkpoint *cp, 194 const std::string §ion)
| 192ArchTimer::unserialize(CheckpointIn &cp)
|
195{
| 193{
|
196 paramIn(cp, section, "control_serial", _control);
| 194 paramIn(cp, "control_serial", _control);
|
197 // We didn't serialize an offset before we added support for the 198 // virtual timer. Consider it optional to maintain backwards 199 // compatibility. 200 if (!UNSERIALIZE_OPT_SCALAR(_offset)) 201 _offset = 0; 202 bool event_scheduled; 203 UNSERIALIZE_SCALAR(event_scheduled); 204 if (event_scheduled) { 205 Tick event_time; 206 UNSERIALIZE_SCALAR(event_time); 207 _parent.schedule(_counterLimitReachedEvent, event_time); 208 } 209} 210 211void 212ArchTimer::Interrupt::send() 213{ 214 if (_ppi) { 215 _gic.sendPPInt(_irq, _cpu); 216 } else { 217 _gic.sendInt(_irq); 218 } 219} 220 221 222void 223ArchTimer::Interrupt::clear() 224{ 225 if (_ppi) { 226 _gic.clearPPInt(_irq, _cpu); 227 } else { 228 _gic.clearInt(_irq); 229 } 230} 231 232 233GenericTimer::GenericTimer(GenericTimerParams *p) 234 : SimObject(p), 235 gic(p->gic), 236 irqPhys(p->int_phys), 237 irqVirt(p->int_virt) 238{ 239 dynamic_cast<ArmSystem &>(*p->system).setGenericTimer(this); 240} 241 242void
| 195 // We didn't serialize an offset before we added support for the 196 // virtual timer. Consider it optional to maintain backwards 197 // compatibility. 198 if (!UNSERIALIZE_OPT_SCALAR(_offset)) 199 _offset = 0; 200 bool event_scheduled; 201 UNSERIALIZE_SCALAR(event_scheduled); 202 if (event_scheduled) { 203 Tick event_time; 204 UNSERIALIZE_SCALAR(event_time); 205 _parent.schedule(_counterLimitReachedEvent, event_time); 206 } 207} 208 209void 210ArchTimer::Interrupt::send() 211{ 212 if (_ppi) { 213 _gic.sendPPInt(_irq, _cpu); 214 } else { 215 _gic.sendInt(_irq); 216 } 217} 218 219 220void 221ArchTimer::Interrupt::clear() 222{ 223 if (_ppi) { 224 _gic.clearPPInt(_irq, _cpu); 225 } else { 226 _gic.clearInt(_irq); 227 } 228} 229 230 231GenericTimer::GenericTimer(GenericTimerParams *p) 232 : SimObject(p), 233 gic(p->gic), 234 irqPhys(p->int_phys), 235 irqVirt(p->int_virt) 236{ 237 dynamic_cast<ArmSystem &>(*p->system).setGenericTimer(this); 238} 239 240void
|
243GenericTimer::serialize(std::ostream &os)
| 241GenericTimer::serialize(CheckpointOut &cp) const
|
244{
| 242{
|
245 paramOut(os, "cpu_count", timers.size());
| 243 paramOut(cp, "cpu_count", timers.size());
|
246
| 244
|
247 nameOut(os, csprintf("%s.sys_counter", name())); 248 systemCounter.serialize(os);
| 245 systemCounter.serializeSection(cp, "sys_counter");
|
249 250 for (int i = 0; i < timers.size(); ++i) {
| 246 247 for (int i = 0; i < timers.size(); ++i) {
|
251 CoreTimers &core(getTimers(i));
| 248 const CoreTimers &core(*timers[i]);
|
252
| 249
|
253 nameOut(os, core.phys.name()); 254 core.phys.serialize(os); 255 256 nameOut(os, core.virt.name()); 257 core.virt.serialize(os);
| 250 // This should really be phys_timerN, but we are stuck with 251 // arch_timer for backwards compatibility. 252 core.phys.serializeSection(cp, csprintf("arch_timer%d", i)); 253 core.virt.serializeSection(cp, csprintf("virt_timer%d", i));
|
258 } 259} 260 261void
| 254 } 255} 256 257void
|
262GenericTimer::unserialize(Checkpoint *cp, const std::string §ion)
| 258GenericTimer::unserialize(CheckpointIn &cp)
|
263{
| 259{
|
264 systemCounter.unserialize(cp, csprintf("%s.sys_counter", section));
| 260 systemCounter.unserializeSection(cp, "sys_counter");
|
265 266 // Try to unserialize the CPU count. Old versions of the timer 267 // model assumed a 8 CPUs, so we fall back to that if the field 268 // isn't present. 269 static const unsigned OLD_CPU_MAX = 8; 270 unsigned cpu_count; 271 if (!UNSERIALIZE_OPT_SCALAR(cpu_count)) { 272 warn("Checkpoint does not contain CPU count, assuming %i CPUs\n", 273 OLD_CPU_MAX); 274 cpu_count = OLD_CPU_MAX; 275 } 276 277 for (int i = 0; i < cpu_count; ++i) { 278 CoreTimers &core(getTimers(i)); 279 // This should really be phys_timerN, but we are stuck with 280 // arch_timer for backwards compatibility.
| 261 262 // Try to unserialize the CPU count. Old versions of the timer 263 // model assumed a 8 CPUs, so we fall back to that if the field 264 // isn't present. 265 static const unsigned OLD_CPU_MAX = 8; 266 unsigned cpu_count; 267 if (!UNSERIALIZE_OPT_SCALAR(cpu_count)) { 268 warn("Checkpoint does not contain CPU count, assuming %i CPUs\n", 269 OLD_CPU_MAX); 270 cpu_count = OLD_CPU_MAX; 271 } 272 273 for (int i = 0; i < cpu_count; ++i) { 274 CoreTimers &core(getTimers(i)); 275 // This should really be phys_timerN, but we are stuck with 276 // arch_timer for backwards compatibility.
|
281 core.phys.unserialize(cp, csprintf("%s.arch_timer%d", section, i)); 282 core.virt.unserialize(cp, csprintf("%s.virt_timer%d", section, i));
| 277 core.phys.unserializeSection(cp, csprintf("arch_timer%d", i)); 278 core.virt.unserializeSection(cp, csprintf("virt_timer%d", i));
|
283 } 284} 285 286 287GenericTimer::CoreTimers & 288GenericTimer::getTimers(int cpu_id) 289{ 290 if (cpu_id >= timers.size()) 291 createTimers(cpu_id + 1); 292 293 return *timers[cpu_id]; 294} 295 296void 297GenericTimer::createTimers(unsigned cpus) 298{ 299 assert(timers.size() < cpus); 300 301 const unsigned old_cpu_count(timers.size()); 302 timers.resize(cpus); 303 for (unsigned i = old_cpu_count; i < cpus; ++i) { 304 timers[i].reset( 305 new CoreTimers(*this, i, irqPhys, irqVirt)); 306 } 307} 308 309 310void 311GenericTimer::setMiscReg(int reg, unsigned cpu, MiscReg val) 312{ 313 CoreTimers &core(getTimers(cpu)); 314 315 switch (reg) { 316 case MISCREG_CNTFRQ: 317 case MISCREG_CNTFRQ_EL0: 318 systemCounter.setFreq(val); 319 return; 320 321 case MISCREG_CNTKCTL: 322 case MISCREG_CNTKCTL_EL1: 323 systemCounter.setKernelControl(val); 324 return; 325 326 // Physical timer 327 case MISCREG_CNTP_CVAL: 328 case MISCREG_CNTP_CVAL_NS: 329 case MISCREG_CNTP_CVAL_EL0: 330 core.phys.setCompareValue(val); 331 return; 332 333 case MISCREG_CNTP_TVAL: 334 case MISCREG_CNTP_TVAL_NS: 335 case MISCREG_CNTP_TVAL_EL0: 336 core.phys.setTimerValue(val); 337 return; 338 339 case MISCREG_CNTP_CTL: 340 case MISCREG_CNTP_CTL_NS: 341 case MISCREG_CNTP_CTL_EL0: 342 core.phys.setControl(val); 343 return; 344 345 // Count registers 346 case MISCREG_CNTPCT: 347 case MISCREG_CNTPCT_EL0: 348 case MISCREG_CNTVCT: 349 case MISCREG_CNTVCT_EL0: 350 warn("Ignoring write to read only count register: %s\n", 351 miscRegName[reg]); 352 return; 353 354 // Virtual timer 355 case MISCREG_CNTVOFF: 356 case MISCREG_CNTVOFF_EL2: 357 core.virt.setOffset(val); 358 return; 359 360 case MISCREG_CNTV_CVAL: 361 case MISCREG_CNTV_CVAL_EL0: 362 core.virt.setCompareValue(val); 363 return; 364 365 case MISCREG_CNTV_TVAL: 366 case MISCREG_CNTV_TVAL_EL0: 367 core.virt.setTimerValue(val); 368 return; 369 370 case MISCREG_CNTV_CTL: 371 case MISCREG_CNTV_CTL_EL0: 372 core.virt.setControl(val); 373 return; 374 375 // PL1 phys. timer, secure 376 case MISCREG_CNTP_CTL_S: 377 case MISCREG_CNTPS_CVAL_EL1: 378 case MISCREG_CNTPS_TVAL_EL1: 379 case MISCREG_CNTPS_CTL_EL1: 380 /* FALLTHROUGH */ 381 382 // PL2 phys. timer, non-secure 383 case MISCREG_CNTHCTL: 384 case MISCREG_CNTHCTL_EL2: 385 case MISCREG_CNTHP_CVAL: 386 case MISCREG_CNTHP_CVAL_EL2: 387 case MISCREG_CNTHP_TVAL: 388 case MISCREG_CNTHP_TVAL_EL2: 389 case MISCREG_CNTHP_CTL: 390 case MISCREG_CNTHP_CTL_EL2: 391 warn("Writing to unimplemented register: %s\n", 392 miscRegName[reg]); 393 return; 394 395 default: 396 warn("Writing to unknown register: %s\n", miscRegName[reg]); 397 return; 398 } 399} 400 401 402MiscReg 403GenericTimer::readMiscReg(int reg, unsigned cpu) 404{ 405 CoreTimers &core(getTimers(cpu)); 406 407 switch (reg) { 408 case MISCREG_CNTFRQ: 409 case MISCREG_CNTFRQ_EL0: 410 return systemCounter.freq(); 411 412 case MISCREG_CNTKCTL: 413 case MISCREG_CNTKCTL_EL1: 414 return systemCounter.getKernelControl(); 415 416 // Physical timer 417 case MISCREG_CNTP_CVAL: 418 case MISCREG_CNTP_CVAL_EL0: 419 return core.phys.compareValue(); 420 421 case MISCREG_CNTP_TVAL: 422 case MISCREG_CNTP_TVAL_EL0: 423 return core.phys.timerValue(); 424 425 case MISCREG_CNTP_CTL: 426 case MISCREG_CNTP_CTL_EL0: 427 case MISCREG_CNTP_CTL_NS: 428 return core.phys.control(); 429 430 case MISCREG_CNTPCT: 431 case MISCREG_CNTPCT_EL0: 432 return core.phys.value(); 433 434 435 // Virtual timer 436 case MISCREG_CNTVCT: 437 case MISCREG_CNTVCT_EL0: 438 return core.virt.value(); 439 440 case MISCREG_CNTVOFF: 441 case MISCREG_CNTVOFF_EL2: 442 return core.virt.offset(); 443 444 case MISCREG_CNTV_CVAL: 445 case MISCREG_CNTV_CVAL_EL0: 446 return core.virt.compareValue(); 447 448 case MISCREG_CNTV_TVAL: 449 case MISCREG_CNTV_TVAL_EL0: 450 return core.virt.timerValue(); 451 452 case MISCREG_CNTV_CTL: 453 case MISCREG_CNTV_CTL_EL0: 454 return core.virt.control(); 455 456 // PL1 phys. timer, secure 457 case MISCREG_CNTP_CTL_S: 458 case MISCREG_CNTPS_CVAL_EL1: 459 case MISCREG_CNTPS_TVAL_EL1: 460 case MISCREG_CNTPS_CTL_EL1: 461 /* FALLTHROUGH */ 462 463 // PL2 phys. timer, non-secure 464 case MISCREG_CNTHCTL: 465 case MISCREG_CNTHCTL_EL2: 466 case MISCREG_CNTHP_CVAL: 467 case MISCREG_CNTHP_CVAL_EL2: 468 case MISCREG_CNTHP_TVAL: 469 case MISCREG_CNTHP_TVAL_EL2: 470 case MISCREG_CNTHP_CTL: 471 case MISCREG_CNTHP_CTL_EL2: 472 warn("Reading from unimplemented register: %s\n", 473 miscRegName[reg]); 474 return 0; 475 476 477 default: 478 warn("Reading from unknown register: %s\n", miscRegName[reg]); 479 return 0; 480 } 481} 482 483 484 485GenericTimerMem::GenericTimerMem(GenericTimerMemParams *p) 486 : PioDevice(p), 487 ctrlRange(RangeSize(p->base, TheISA::PageBytes)), 488 timerRange(RangeSize(p->base + TheISA::PageBytes, TheISA::PageBytes)), 489 addrRanges{ctrlRange, timerRange}, 490 systemCounter(), 491 physTimer(csprintf("%s.phys_timer0", name()), 492 *this, systemCounter, 493 ArchTimer::Interrupt(*p->gic, p->int_phys)), 494 virtTimer(csprintf("%s.virt_timer0", name()), 495 *this, systemCounter, 496 ArchTimer::Interrupt(*p->gic, p->int_virt)) 497{ 498} 499 500void
| 279 } 280} 281 282 283GenericTimer::CoreTimers & 284GenericTimer::getTimers(int cpu_id) 285{ 286 if (cpu_id >= timers.size()) 287 createTimers(cpu_id + 1); 288 289 return *timers[cpu_id]; 290} 291 292void 293GenericTimer::createTimers(unsigned cpus) 294{ 295 assert(timers.size() < cpus); 296 297 const unsigned old_cpu_count(timers.size()); 298 timers.resize(cpus); 299 for (unsigned i = old_cpu_count; i < cpus; ++i) { 300 timers[i].reset( 301 new CoreTimers(*this, i, irqPhys, irqVirt)); 302 } 303} 304 305 306void 307GenericTimer::setMiscReg(int reg, unsigned cpu, MiscReg val) 308{ 309 CoreTimers &core(getTimers(cpu)); 310 311 switch (reg) { 312 case MISCREG_CNTFRQ: 313 case MISCREG_CNTFRQ_EL0: 314 systemCounter.setFreq(val); 315 return; 316 317 case MISCREG_CNTKCTL: 318 case MISCREG_CNTKCTL_EL1: 319 systemCounter.setKernelControl(val); 320 return; 321 322 // Physical timer 323 case MISCREG_CNTP_CVAL: 324 case MISCREG_CNTP_CVAL_NS: 325 case MISCREG_CNTP_CVAL_EL0: 326 core.phys.setCompareValue(val); 327 return; 328 329 case MISCREG_CNTP_TVAL: 330 case MISCREG_CNTP_TVAL_NS: 331 case MISCREG_CNTP_TVAL_EL0: 332 core.phys.setTimerValue(val); 333 return; 334 335 case MISCREG_CNTP_CTL: 336 case MISCREG_CNTP_CTL_NS: 337 case MISCREG_CNTP_CTL_EL0: 338 core.phys.setControl(val); 339 return; 340 341 // Count registers 342 case MISCREG_CNTPCT: 343 case MISCREG_CNTPCT_EL0: 344 case MISCREG_CNTVCT: 345 case MISCREG_CNTVCT_EL0: 346 warn("Ignoring write to read only count register: %s\n", 347 miscRegName[reg]); 348 return; 349 350 // Virtual timer 351 case MISCREG_CNTVOFF: 352 case MISCREG_CNTVOFF_EL2: 353 core.virt.setOffset(val); 354 return; 355 356 case MISCREG_CNTV_CVAL: 357 case MISCREG_CNTV_CVAL_EL0: 358 core.virt.setCompareValue(val); 359 return; 360 361 case MISCREG_CNTV_TVAL: 362 case MISCREG_CNTV_TVAL_EL0: 363 core.virt.setTimerValue(val); 364 return; 365 366 case MISCREG_CNTV_CTL: 367 case MISCREG_CNTV_CTL_EL0: 368 core.virt.setControl(val); 369 return; 370 371 // PL1 phys. timer, secure 372 case MISCREG_CNTP_CTL_S: 373 case MISCREG_CNTPS_CVAL_EL1: 374 case MISCREG_CNTPS_TVAL_EL1: 375 case MISCREG_CNTPS_CTL_EL1: 376 /* FALLTHROUGH */ 377 378 // PL2 phys. timer, non-secure 379 case MISCREG_CNTHCTL: 380 case MISCREG_CNTHCTL_EL2: 381 case MISCREG_CNTHP_CVAL: 382 case MISCREG_CNTHP_CVAL_EL2: 383 case MISCREG_CNTHP_TVAL: 384 case MISCREG_CNTHP_TVAL_EL2: 385 case MISCREG_CNTHP_CTL: 386 case MISCREG_CNTHP_CTL_EL2: 387 warn("Writing to unimplemented register: %s\n", 388 miscRegName[reg]); 389 return; 390 391 default: 392 warn("Writing to unknown register: %s\n", miscRegName[reg]); 393 return; 394 } 395} 396 397 398MiscReg 399GenericTimer::readMiscReg(int reg, unsigned cpu) 400{ 401 CoreTimers &core(getTimers(cpu)); 402 403 switch (reg) { 404 case MISCREG_CNTFRQ: 405 case MISCREG_CNTFRQ_EL0: 406 return systemCounter.freq(); 407 408 case MISCREG_CNTKCTL: 409 case MISCREG_CNTKCTL_EL1: 410 return systemCounter.getKernelControl(); 411 412 // Physical timer 413 case MISCREG_CNTP_CVAL: 414 case MISCREG_CNTP_CVAL_EL0: 415 return core.phys.compareValue(); 416 417 case MISCREG_CNTP_TVAL: 418 case MISCREG_CNTP_TVAL_EL0: 419 return core.phys.timerValue(); 420 421 case MISCREG_CNTP_CTL: 422 case MISCREG_CNTP_CTL_EL0: 423 case MISCREG_CNTP_CTL_NS: 424 return core.phys.control(); 425 426 case MISCREG_CNTPCT: 427 case MISCREG_CNTPCT_EL0: 428 return core.phys.value(); 429 430 431 // Virtual timer 432 case MISCREG_CNTVCT: 433 case MISCREG_CNTVCT_EL0: 434 return core.virt.value(); 435 436 case MISCREG_CNTVOFF: 437 case MISCREG_CNTVOFF_EL2: 438 return core.virt.offset(); 439 440 case MISCREG_CNTV_CVAL: 441 case MISCREG_CNTV_CVAL_EL0: 442 return core.virt.compareValue(); 443 444 case MISCREG_CNTV_TVAL: 445 case MISCREG_CNTV_TVAL_EL0: 446 return core.virt.timerValue(); 447 448 case MISCREG_CNTV_CTL: 449 case MISCREG_CNTV_CTL_EL0: 450 return core.virt.control(); 451 452 // PL1 phys. timer, secure 453 case MISCREG_CNTP_CTL_S: 454 case MISCREG_CNTPS_CVAL_EL1: 455 case MISCREG_CNTPS_TVAL_EL1: 456 case MISCREG_CNTPS_CTL_EL1: 457 /* FALLTHROUGH */ 458 459 // PL2 phys. timer, non-secure 460 case MISCREG_CNTHCTL: 461 case MISCREG_CNTHCTL_EL2: 462 case MISCREG_CNTHP_CVAL: 463 case MISCREG_CNTHP_CVAL_EL2: 464 case MISCREG_CNTHP_TVAL: 465 case MISCREG_CNTHP_TVAL_EL2: 466 case MISCREG_CNTHP_CTL: 467 case MISCREG_CNTHP_CTL_EL2: 468 warn("Reading from unimplemented register: %s\n", 469 miscRegName[reg]); 470 return 0; 471 472 473 default: 474 warn("Reading from unknown register: %s\n", miscRegName[reg]); 475 return 0; 476 } 477} 478 479 480 481GenericTimerMem::GenericTimerMem(GenericTimerMemParams *p) 482 : PioDevice(p), 483 ctrlRange(RangeSize(p->base, TheISA::PageBytes)), 484 timerRange(RangeSize(p->base + TheISA::PageBytes, TheISA::PageBytes)), 485 addrRanges{ctrlRange, timerRange}, 486 systemCounter(), 487 physTimer(csprintf("%s.phys_timer0", name()), 488 *this, systemCounter, 489 ArchTimer::Interrupt(*p->gic, p->int_phys)), 490 virtTimer(csprintf("%s.virt_timer0", name()), 491 *this, systemCounter, 492 ArchTimer::Interrupt(*p->gic, p->int_virt)) 493{ 494} 495 496void
|
501GenericTimerMem::serialize(std::ostream &os)
| 497GenericTimerMem::serialize(CheckpointOut &cp) const
|
502{
| 498{
|
503 paramOut(os, "timer_count", 1);
| 499 paramOut(cp, "timer_count", 1);
|
504
| 500
|
505 nameOut(os, csprintf("%s.sys_counter", name())); 506 systemCounter.serialize(os);
| 501 systemCounter.serializeSection(cp, "sys_counter");
|
507
| 502
|
508 nameOut(os, physTimer.name()); 509 physTimer.serialize(os); 510 511 nameOut(os, virtTimer.name()); 512 virtTimer.serialize(os);
| 503 physTimer.serializeSection(cp, "phys_timer0"); 504 virtTimer.serializeSection(cp, "virt_timer0");
|
513} 514 515void
| 505} 506 507void
|
516GenericTimerMem::unserialize(Checkpoint *cp, const std::string §ion)
| 508GenericTimerMem::unserialize(CheckpointIn &cp)
|
517{
| 509{
|
518 systemCounter.unserialize(cp, csprintf("%s.sys_counter", section));
| 510 systemCounter.unserializeSection(cp, "sys_counter");
|
519 520 unsigned timer_count; 521 UNSERIALIZE_SCALAR(timer_count); 522 // The timer count variable is just here for future versions where 523 // we support more than one set of timers. 524 if (timer_count != 1) 525 panic("Incompatible checkpoint: Only one set of timers supported"); 526
| 511 512 unsigned timer_count; 513 UNSERIALIZE_SCALAR(timer_count); 514 // The timer count variable is just here for future versions where 515 // we support more than one set of timers. 516 if (timer_count != 1) 517 panic("Incompatible checkpoint: Only one set of timers supported"); 518
|
527 physTimer.unserialize(cp, csprintf("%s.phys_timer0", section)); 528 virtTimer.unserialize(cp, csprintf("%s.virt_timer0", section));
| 519 physTimer.unserializeSection(cp, "phys_timer0"); 520 virtTimer.unserializeSection(cp, "virt_timer0");
|
529} 530 531Tick 532GenericTimerMem::read(PacketPtr pkt) 533{ 534 const unsigned size(pkt->getSize()); 535 const Addr addr(pkt->getAddr()); 536 uint64_t value; 537 538 pkt->makeResponse(); 539 if (ctrlRange.contains(addr)) { 540 value = ctrlRead(addr - ctrlRange.start(), size); 541 } else if (timerRange.contains(addr)) { 542 value = timerRead(addr - timerRange.start(), size); 543 } else { 544 panic("Invalid address: 0x%x\n", addr); 545 } 546 547 DPRINTF(Timer, "Read 0x%x <- 0x%x(%i)\n", value, addr, size); 548 549 if (size == 8) { 550 pkt->set<uint64_t>(value); 551 } else if (size == 4) { 552 pkt->set<uint32_t>(value); 553 } else { 554 panic("Unexpected access size: %i\n", size); 555 } 556 557 return 0; 558} 559 560Tick 561GenericTimerMem::write(PacketPtr pkt) 562{ 563 const unsigned size(pkt->getSize()); 564 if (size != 8 && size != 4) 565 panic("Unexpected access size\n"); 566 567 const Addr addr(pkt->getAddr()); 568 const uint64_t value(size == 8 ? 569 pkt->get<uint64_t>() : pkt->get<uint32_t>()); 570 571 DPRINTF(Timer, "Write 0x%x -> 0x%x(%i)\n", value, addr, size); 572 if (ctrlRange.contains(addr)) { 573 ctrlWrite(addr - ctrlRange.start(), size, value); 574 } else if (timerRange.contains(addr)) { 575 timerWrite(addr - timerRange.start(), size, value); 576 } else { 577 panic("Invalid address: 0x%x\n", addr); 578 } 579 580 pkt->makeResponse(); 581 return 0; 582} 583 584uint64_t 585GenericTimerMem::ctrlRead(Addr addr, size_t size) const 586{ 587 if (size == 4) { 588 switch (addr) { 589 case CTRL_CNTFRQ: 590 return systemCounter.freq(); 591 592 case CTRL_CNTTIDR: 593 return 0x3; // Frame 0 implemented with virtual timers 594 595 case CTRL_CNTNSAR: 596 case CTRL_CNTACR_BASE: 597 warn("Reading from unimplemented control register (0x%x)\n", addr); 598 return 0; 599 600 case CTRL_CNTVOFF_LO_BASE: 601 return virtTimer.offset(); 602 603 case CTRL_CNTVOFF_HI_BASE: 604 return virtTimer.offset() >> 32; 605 606 default: 607 warn("Unexpected address (0x%x:%i), assuming RAZ\n", addr, size); 608 return 0; 609 } 610 } else if (size == 8) { 611 switch (addr) { 612 case CTRL_CNTVOFF_LO_BASE: 613 return virtTimer.offset(); 614 615 default: 616 warn("Unexpected address (0x%x:%i), assuming RAZ\n", addr, size); 617 return 0; 618 } 619 } else { 620 panic("Invalid access size: %i\n", size); 621 } 622} 623 624void 625GenericTimerMem::ctrlWrite(Addr addr, size_t size, uint64_t value) 626{ 627 if (size == 4) { 628 switch (addr) { 629 case CTRL_CNTFRQ: 630 case CTRL_CNTNSAR: 631 case CTRL_CNTTIDR: 632 case CTRL_CNTACR_BASE: 633 warn("Write to unimplemented control register (0x%x)\n", addr); 634 return; 635 636 case CTRL_CNTVOFF_LO_BASE: 637 virtTimer.setOffset( 638 insertBits(virtTimer.offset(), 31, 0, value)); 639 return; 640 641 case CTRL_CNTVOFF_HI_BASE: 642 virtTimer.setOffset( 643 insertBits(virtTimer.offset(), 63, 32, value)); 644 return; 645 646 default: 647 warn("Ignoring write to unexpected address (0x%x:%i)\n", 648 addr, size); 649 return; 650 } 651 } else if (size == 8) { 652 switch (addr) { 653 case CTRL_CNTVOFF_LO_BASE: 654 virtTimer.setOffset(value); 655 return; 656 657 default: 658 warn("Ignoring write to unexpected address (0x%x:%i)\n", 659 addr, size); 660 return; 661 } 662 } else { 663 panic("Invalid access size: %i\n", size); 664 } 665} 666 667uint64_t 668GenericTimerMem::timerRead(Addr addr, size_t size) const 669{ 670 if (size == 4) { 671 switch (addr) { 672 case TIMER_CNTPCT_LO: 673 return physTimer.value(); 674 675 case TIMER_CNTPCT_HI: 676 return physTimer.value() >> 32; 677 678 case TIMER_CNTVCT_LO: 679 return virtTimer.value(); 680 681 case TIMER_CNTVCT_HI: 682 return virtTimer.value() >> 32; 683 684 case TIMER_CNTFRQ: 685 return systemCounter.freq(); 686 687 case TIMER_CNTEL0ACR: 688 warn("Read from unimplemented timer register (0x%x)\n", addr); 689 return 0; 690 691 case CTRL_CNTVOFF_LO_BASE: 692 return virtTimer.offset(); 693 694 case CTRL_CNTVOFF_HI_BASE: 695 return virtTimer.offset() >> 32; 696 697 case TIMER_CNTP_CVAL_LO: 698 return physTimer.compareValue(); 699 700 case TIMER_CNTP_CVAL_HI: 701 return physTimer.compareValue() >> 32; 702 703 case TIMER_CNTP_TVAL: 704 return physTimer.timerValue(); 705 706 case TIMER_CNTP_CTL: 707 return physTimer.control(); 708 709 case TIMER_CNTV_CVAL_LO: 710 return virtTimer.compareValue(); 711 712 case TIMER_CNTV_CVAL_HI: 713 return virtTimer.compareValue() >> 32; 714 715 case TIMER_CNTV_TVAL: 716 return virtTimer.timerValue(); 717 718 case TIMER_CNTV_CTL: 719 return virtTimer.control(); 720 721 default: 722 warn("Unexpected address (0x%x:%i), assuming RAZ\n", addr, size); 723 return 0; 724 } 725 } else if (size == 8) { 726 switch (addr) { 727 case TIMER_CNTPCT_LO: 728 return physTimer.value(); 729 730 case TIMER_CNTVCT_LO: 731 return virtTimer.value(); 732 733 case CTRL_CNTVOFF_LO_BASE: 734 return virtTimer.offset(); 735 736 case TIMER_CNTP_CVAL_LO: 737 return physTimer.compareValue(); 738 739 case TIMER_CNTV_CVAL_LO: 740 return virtTimer.compareValue(); 741 742 default: 743 warn("Unexpected address (0x%x:%i), assuming RAZ\n", addr, size); 744 return 0; 745 } 746 } else { 747 panic("Invalid access size: %i\n", size); 748 } 749} 750 751void 752GenericTimerMem::timerWrite(Addr addr, size_t size, uint64_t value) 753{ 754 if (size == 4) { 755 switch (addr) { 756 case TIMER_CNTEL0ACR: 757 warn("Unimplemented timer register (0x%x)\n", addr); 758 return; 759 760 case TIMER_CNTP_CVAL_LO: 761 physTimer.setCompareValue( 762 insertBits(physTimer.compareValue(), 31, 0, value)); 763 return; 764 765 case TIMER_CNTP_CVAL_HI: 766 physTimer.setCompareValue( 767 insertBits(physTimer.compareValue(), 63, 32, value)); 768 return; 769 770 case TIMER_CNTP_TVAL: 771 physTimer.setTimerValue(value); 772 return; 773 774 case TIMER_CNTP_CTL: 775 physTimer.setControl(value); 776 return; 777 778 case TIMER_CNTV_CVAL_LO: 779 virtTimer.setCompareValue( 780 insertBits(virtTimer.compareValue(), 31, 0, value)); 781 return; 782 783 case TIMER_CNTV_CVAL_HI: 784 virtTimer.setCompareValue( 785 insertBits(virtTimer.compareValue(), 63, 32, value)); 786 return; 787 788 case TIMER_CNTV_TVAL: 789 virtTimer.setTimerValue(value); 790 return; 791 792 case TIMER_CNTV_CTL: 793 virtTimer.setControl(value); 794 return; 795 796 default: 797 warn("Unexpected address (0x%x:%i), ignoring write\n", addr, size); 798 return; 799 } 800 } else if (size == 8) { 801 switch (addr) { 802 case TIMER_CNTP_CVAL_LO: 803 return physTimer.setCompareValue(value); 804 805 case TIMER_CNTV_CVAL_LO: 806 return virtTimer.setCompareValue(value); 807 808 default: 809 warn("Unexpected address (0x%x:%i), ignoring write\n", addr, size); 810 return; 811 } 812 } else { 813 panic("Invalid access size: %i\n", size); 814 } 815} 816 817GenericTimer * 818GenericTimerParams::create() 819{ 820 return new GenericTimer(this); 821} 822 823GenericTimerMem * 824GenericTimerMemParams::create() 825{ 826 return new GenericTimerMem(this); 827}
| 521} 522 523Tick 524GenericTimerMem::read(PacketPtr pkt) 525{ 526 const unsigned size(pkt->getSize()); 527 const Addr addr(pkt->getAddr()); 528 uint64_t value; 529 530 pkt->makeResponse(); 531 if (ctrlRange.contains(addr)) { 532 value = ctrlRead(addr - ctrlRange.start(), size); 533 } else if (timerRange.contains(addr)) { 534 value = timerRead(addr - timerRange.start(), size); 535 } else { 536 panic("Invalid address: 0x%x\n", addr); 537 } 538 539 DPRINTF(Timer, "Read 0x%x <- 0x%x(%i)\n", value, addr, size); 540 541 if (size == 8) { 542 pkt->set<uint64_t>(value); 543 } else if (size == 4) { 544 pkt->set<uint32_t>(value); 545 } else { 546 panic("Unexpected access size: %i\n", size); 547 } 548 549 return 0; 550} 551 552Tick 553GenericTimerMem::write(PacketPtr pkt) 554{ 555 const unsigned size(pkt->getSize()); 556 if (size != 8 && size != 4) 557 panic("Unexpected access size\n"); 558 559 const Addr addr(pkt->getAddr()); 560 const uint64_t value(size == 8 ? 561 pkt->get<uint64_t>() : pkt->get<uint32_t>()); 562 563 DPRINTF(Timer, "Write 0x%x -> 0x%x(%i)\n", value, addr, size); 564 if (ctrlRange.contains(addr)) { 565 ctrlWrite(addr - ctrlRange.start(), size, value); 566 } else if (timerRange.contains(addr)) { 567 timerWrite(addr - timerRange.start(), size, value); 568 } else { 569 panic("Invalid address: 0x%x\n", addr); 570 } 571 572 pkt->makeResponse(); 573 return 0; 574} 575 576uint64_t 577GenericTimerMem::ctrlRead(Addr addr, size_t size) const 578{ 579 if (size == 4) { 580 switch (addr) { 581 case CTRL_CNTFRQ: 582 return systemCounter.freq(); 583 584 case CTRL_CNTTIDR: 585 return 0x3; // Frame 0 implemented with virtual timers 586 587 case CTRL_CNTNSAR: 588 case CTRL_CNTACR_BASE: 589 warn("Reading from unimplemented control register (0x%x)\n", addr); 590 return 0; 591 592 case CTRL_CNTVOFF_LO_BASE: 593 return virtTimer.offset(); 594 595 case CTRL_CNTVOFF_HI_BASE: 596 return virtTimer.offset() >> 32; 597 598 default: 599 warn("Unexpected address (0x%x:%i), assuming RAZ\n", addr, size); 600 return 0; 601 } 602 } else if (size == 8) { 603 switch (addr) { 604 case CTRL_CNTVOFF_LO_BASE: 605 return virtTimer.offset(); 606 607 default: 608 warn("Unexpected address (0x%x:%i), assuming RAZ\n", addr, size); 609 return 0; 610 } 611 } else { 612 panic("Invalid access size: %i\n", size); 613 } 614} 615 616void 617GenericTimerMem::ctrlWrite(Addr addr, size_t size, uint64_t value) 618{ 619 if (size == 4) { 620 switch (addr) { 621 case CTRL_CNTFRQ: 622 case CTRL_CNTNSAR: 623 case CTRL_CNTTIDR: 624 case CTRL_CNTACR_BASE: 625 warn("Write to unimplemented control register (0x%x)\n", addr); 626 return; 627 628 case CTRL_CNTVOFF_LO_BASE: 629 virtTimer.setOffset( 630 insertBits(virtTimer.offset(), 31, 0, value)); 631 return; 632 633 case CTRL_CNTVOFF_HI_BASE: 634 virtTimer.setOffset( 635 insertBits(virtTimer.offset(), 63, 32, value)); 636 return; 637 638 default: 639 warn("Ignoring write to unexpected address (0x%x:%i)\n", 640 addr, size); 641 return; 642 } 643 } else if (size == 8) { 644 switch (addr) { 645 case CTRL_CNTVOFF_LO_BASE: 646 virtTimer.setOffset(value); 647 return; 648 649 default: 650 warn("Ignoring write to unexpected address (0x%x:%i)\n", 651 addr, size); 652 return; 653 } 654 } else { 655 panic("Invalid access size: %i\n", size); 656 } 657} 658 659uint64_t 660GenericTimerMem::timerRead(Addr addr, size_t size) const 661{ 662 if (size == 4) { 663 switch (addr) { 664 case TIMER_CNTPCT_LO: 665 return physTimer.value(); 666 667 case TIMER_CNTPCT_HI: 668 return physTimer.value() >> 32; 669 670 case TIMER_CNTVCT_LO: 671 return virtTimer.value(); 672 673 case TIMER_CNTVCT_HI: 674 return virtTimer.value() >> 32; 675 676 case TIMER_CNTFRQ: 677 return systemCounter.freq(); 678 679 case TIMER_CNTEL0ACR: 680 warn("Read from unimplemented timer register (0x%x)\n", addr); 681 return 0; 682 683 case CTRL_CNTVOFF_LO_BASE: 684 return virtTimer.offset(); 685 686 case CTRL_CNTVOFF_HI_BASE: 687 return virtTimer.offset() >> 32; 688 689 case TIMER_CNTP_CVAL_LO: 690 return physTimer.compareValue(); 691 692 case TIMER_CNTP_CVAL_HI: 693 return physTimer.compareValue() >> 32; 694 695 case TIMER_CNTP_TVAL: 696 return physTimer.timerValue(); 697 698 case TIMER_CNTP_CTL: 699 return physTimer.control(); 700 701 case TIMER_CNTV_CVAL_LO: 702 return virtTimer.compareValue(); 703 704 case TIMER_CNTV_CVAL_HI: 705 return virtTimer.compareValue() >> 32; 706 707 case TIMER_CNTV_TVAL: 708 return virtTimer.timerValue(); 709 710 case TIMER_CNTV_CTL: 711 return virtTimer.control(); 712 713 default: 714 warn("Unexpected address (0x%x:%i), assuming RAZ\n", addr, size); 715 return 0; 716 } 717 } else if (size == 8) { 718 switch (addr) { 719 case TIMER_CNTPCT_LO: 720 return physTimer.value(); 721 722 case TIMER_CNTVCT_LO: 723 return virtTimer.value(); 724 725 case CTRL_CNTVOFF_LO_BASE: 726 return virtTimer.offset(); 727 728 case TIMER_CNTP_CVAL_LO: 729 return physTimer.compareValue(); 730 731 case TIMER_CNTV_CVAL_LO: 732 return virtTimer.compareValue(); 733 734 default: 735 warn("Unexpected address (0x%x:%i), assuming RAZ\n", addr, size); 736 return 0; 737 } 738 } else { 739 panic("Invalid access size: %i\n", size); 740 } 741} 742 743void 744GenericTimerMem::timerWrite(Addr addr, size_t size, uint64_t value) 745{ 746 if (size == 4) { 747 switch (addr) { 748 case TIMER_CNTEL0ACR: 749 warn("Unimplemented timer register (0x%x)\n", addr); 750 return; 751 752 case TIMER_CNTP_CVAL_LO: 753 physTimer.setCompareValue( 754 insertBits(physTimer.compareValue(), 31, 0, value)); 755 return; 756 757 case TIMER_CNTP_CVAL_HI: 758 physTimer.setCompareValue( 759 insertBits(physTimer.compareValue(), 63, 32, value)); 760 return; 761 762 case TIMER_CNTP_TVAL: 763 physTimer.setTimerValue(value); 764 return; 765 766 case TIMER_CNTP_CTL: 767 physTimer.setControl(value); 768 return; 769 770 case TIMER_CNTV_CVAL_LO: 771 virtTimer.setCompareValue( 772 insertBits(virtTimer.compareValue(), 31, 0, value)); 773 return; 774 775 case TIMER_CNTV_CVAL_HI: 776 virtTimer.setCompareValue( 777 insertBits(virtTimer.compareValue(), 63, 32, value)); 778 return; 779 780 case TIMER_CNTV_TVAL: 781 virtTimer.setTimerValue(value); 782 return; 783 784 case TIMER_CNTV_CTL: 785 virtTimer.setControl(value); 786 return; 787 788 default: 789 warn("Unexpected address (0x%x:%i), ignoring write\n", addr, size); 790 return; 791 } 792 } else if (size == 8) { 793 switch (addr) { 794 case TIMER_CNTP_CVAL_LO: 795 return physTimer.setCompareValue(value); 796 797 case TIMER_CNTV_CVAL_LO: 798 return virtTimer.setCompareValue(value); 799 800 default: 801 warn("Unexpected address (0x%x:%i), ignoring write\n", addr, size); 802 return; 803 } 804 } else { 805 panic("Invalid access size: %i\n", size); 806 } 807} 808 809GenericTimer * 810GenericTimerParams::create() 811{ 812 return new GenericTimer(this); 813} 814 815GenericTimerMem * 816GenericTimerMemParams::create() 817{ 818 return new GenericTimerMem(this); 819}
|