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