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