2 * Copyright (c) 2013, 2015, 2017-2018 ARM Limited
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.
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.
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.
37 * Authors: Giacomo Gabrielli
41 #include "dev/arm/generic_timer.hh"
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"
50 SystemCounter::SystemCounter()
51 : _freq(0), _period(0), _resetTick(0), _regCntkctl(0)
57 SystemCounter::setFreq(uint32_t freq
)
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");
64 _period
= (1.0 / freq
) * SimClock::Frequency
;
65 _resetTick
= curTick();
69 SystemCounter::serialize(CheckpointOut
&cp
) const
71 SERIALIZE_SCALAR(_regCntkctl
);
72 SERIALIZE_SCALAR(_regCnthctl
);
73 SERIALIZE_SCALAR(_freq
);
74 SERIALIZE_SCALAR(_period
);
75 SERIALIZE_SCALAR(_resetTick
);
79 SystemCounter::unserialize(CheckpointIn
&cp
)
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
))
85 if (!UNSERIALIZE_OPT_SCALAR(_regCnthctl
))
87 UNSERIALIZE_SCALAR(_freq
);
88 UNSERIALIZE_SCALAR(_period
);
89 UNSERIALIZE_SCALAR(_resetTick
);
94 ArchTimer::ArchTimer(const std::string
&name
,
96 SystemCounter
&sysctr
,
97 ArmInterruptPin
*interrupt
)
98 : _name(name
), _parent(parent
), _systemCounter(sysctr
),
99 _interrupt(interrupt
),
100 _control(0), _counterLimit(0), _offset(0),
101 _counterLimitReachedEvent([this]{ counterLimitReached(); }, name
)
106 ArchTimer::counterLimitReached()
108 _control
.istatus
= 1;
110 if (!_control
.enable
)
113 DPRINTF(Timer
, "Counter limit reached\n");
114 if (!_control
.imask
) {
115 if (scheduleEvents()) {
116 DPRINTF(Timer
, "Causing interrupt\n");
119 DPRINTF(Timer
, "Kvm mode; skipping simulated interrupt\n");
125 ArchTimer::updateCounter()
127 if (_counterLimitReachedEvent
.scheduled())
128 _parent
.deschedule(_counterLimitReachedEvent
);
129 if (value() >= _counterLimit
) {
130 counterLimitReached();
132 _control
.istatus
= 0;
133 if (scheduleEvents()) {
134 const auto period(_systemCounter
.period());
135 _parent
.schedule(_counterLimitReachedEvent
,
136 curTick() + (_counterLimit
- value()) * period
);
142 ArchTimer::setCompareValue(uint64_t val
)
149 ArchTimer::setTimerValue(uint32_t val
)
151 setCompareValue(value() + sext
<32>(val
));
155 ArchTimer::setControl(uint32_t val
)
157 ArchTimerCtrl new_ctl
= val
;
158 if ((new_ctl
.enable
&& !new_ctl
.imask
) &&
159 !(_control
.enable
&& !_control
.imask
)) {
160 // Re-evalute the timer condition
161 if (_counterLimit
>= value()) {
162 _control
.istatus
= 1;
164 DPRINTF(Timer
, "Causing interrupt in control\n");
168 _control
.enable
= new_ctl
.enable
;
169 _control
.imask
= new_ctl
.imask
;
173 ArchTimer::setOffset(uint64_t val
)
180 ArchTimer::value() const
182 return _systemCounter
.value() - _offset
;
186 ArchTimer::serialize(CheckpointOut
&cp
) const
188 paramOut(cp
, "control_serial", _control
);
189 SERIALIZE_SCALAR(_counterLimit
);
190 SERIALIZE_SCALAR(_offset
);
194 ArchTimer::unserialize(CheckpointIn
&cp
)
196 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
200 if (!UNSERIALIZE_OPT_SCALAR(_offset
))
203 // We no longer schedule an event here because we may enter KVM
204 // emulation. The event creation is delayed until drainResume().
210 if (_counterLimitReachedEvent
.scheduled())
211 _parent
.deschedule(_counterLimitReachedEvent
);
213 return DrainState::Drained
;
217 ArchTimer::drainResume()
222 GenericTimer::GenericTimer(GenericTimerParams
*p
)
226 fatal_if(!p
->system
, "No system specified, can't instantiate timer.\n");
227 system
.setGenericTimer(this);
230 const GenericTimerParams
*
231 GenericTimer::params() const
233 return dynamic_cast<const GenericTimerParams
*>(_params
);
237 GenericTimer::serialize(CheckpointOut
&cp
) const
239 paramOut(cp
, "cpu_count", timers
.size());
241 systemCounter
.serializeSection(cp
, "sys_counter");
243 for (int i
= 0; i
< timers
.size(); ++i
) {
244 const CoreTimers
&core(*timers
[i
]);
246 // This should really be phys_timerN, but we are stuck with
247 // arch_timer for backwards compatibility.
248 core
.physNS
.serializeSection(cp
, csprintf("arch_timer%d", i
));
249 core
.physS
.serializeSection(cp
, csprintf("phys_s_timer%d", i
));
250 core
.virt
.serializeSection(cp
, csprintf("virt_timer%d", i
));
251 core
.hyp
.serializeSection(cp
, csprintf("hyp_timer%d", i
));
256 GenericTimer::unserialize(CheckpointIn
&cp
)
258 systemCounter
.unserializeSection(cp
, "sys_counter");
260 // Try to unserialize the CPU count. Old versions of the timer
261 // model assumed a 8 CPUs, so we fall back to that if the field
263 static const unsigned OLD_CPU_MAX
= 8;
265 if (!UNSERIALIZE_OPT_SCALAR(cpu_count
)) {
266 warn("Checkpoint does not contain CPU count, assuming %i CPUs\n",
268 cpu_count
= OLD_CPU_MAX
;
271 for (int i
= 0; i
< cpu_count
; ++i
) {
272 CoreTimers
&core(getTimers(i
));
273 // This should really be phys_timerN, but we are stuck with
274 // arch_timer for backwards compatibility.
275 core
.physNS
.unserializeSection(cp
, csprintf("arch_timer%d", i
));
276 core
.physS
.unserializeSection(cp
, csprintf("phys_s_timer%d", i
));
277 core
.virt
.unserializeSection(cp
, csprintf("virt_timer%d", i
));
278 core
.hyp
.unserializeSection(cp
, csprintf("hyp_timer%d", i
));
283 GenericTimer::CoreTimers
&
284 GenericTimer::getTimers(int cpu_id
)
286 if (cpu_id
>= timers
.size())
287 createTimers(cpu_id
+ 1);
289 return *timers
[cpu_id
];
293 GenericTimer::createTimers(unsigned cpus
)
295 assert(timers
.size() < cpus
);
296 auto p
= static_cast<const GenericTimerParams
*>(_params
);
298 const unsigned old_cpu_count(timers
.size());
300 for (unsigned i
= old_cpu_count
; i
< cpus
; ++i
) {
302 ThreadContext
*tc
= system
.getThreadContext(i
);
305 new CoreTimers(*this, system
, i
,
306 p
->int_phys_s
->get(tc
),
307 p
->int_phys_ns
->get(tc
),
308 p
->int_virt
->get(tc
),
309 p
->int_hyp
->get(tc
)));
315 GenericTimer::setMiscReg(int reg
, unsigned cpu
, MiscReg val
)
317 CoreTimers
&core(getTimers(cpu
));
321 case MISCREG_CNTFRQ_EL0
:
322 systemCounter
.setFreq(val
);
325 case MISCREG_CNTKCTL
:
326 case MISCREG_CNTKCTL_EL1
:
327 systemCounter
.setKernelControl(val
);
330 case MISCREG_CNTHCTL
:
331 case MISCREG_CNTHCTL_EL2
:
332 systemCounter
.setHypControl(val
);
335 // Physical timer (NS)
336 case MISCREG_CNTP_CVAL_NS
:
337 case MISCREG_CNTP_CVAL_EL0
:
338 core
.physNS
.setCompareValue(val
);
341 case MISCREG_CNTP_TVAL_NS
:
342 case MISCREG_CNTP_TVAL_EL0
:
343 core
.physNS
.setTimerValue(val
);
346 case MISCREG_CNTP_CTL_NS
:
347 case MISCREG_CNTP_CTL_EL0
:
348 core
.physNS
.setControl(val
);
353 case MISCREG_CNTPCT_EL0
:
355 case MISCREG_CNTVCT_EL0
:
356 warn("Ignoring write to read only count register: %s\n",
361 case MISCREG_CNTVOFF
:
362 case MISCREG_CNTVOFF_EL2
:
363 core
.virt
.setOffset(val
);
366 case MISCREG_CNTV_CVAL
:
367 case MISCREG_CNTV_CVAL_EL0
:
368 core
.virt
.setCompareValue(val
);
371 case MISCREG_CNTV_TVAL
:
372 case MISCREG_CNTV_TVAL_EL0
:
373 core
.virt
.setTimerValue(val
);
376 case MISCREG_CNTV_CTL
:
377 case MISCREG_CNTV_CTL_EL0
:
378 core
.virt
.setControl(val
);
381 // Physical timer (S)
382 case MISCREG_CNTP_CTL_S
:
383 case MISCREG_CNTPS_CTL_EL1
:
384 core
.physS
.setControl(val
);
387 case MISCREG_CNTP_CVAL_S
:
388 case MISCREG_CNTPS_CVAL_EL1
:
389 core
.physS
.setCompareValue(val
);
392 case MISCREG_CNTP_TVAL_S
:
393 case MISCREG_CNTPS_TVAL_EL1
:
394 core
.physS
.setTimerValue(val
);
397 // Hyp phys. timer, non-secure
398 case MISCREG_CNTHP_CTL
:
399 case MISCREG_CNTHP_CTL_EL2
:
400 core
.hyp
.setControl(val
);
403 case MISCREG_CNTHP_CVAL
:
404 case MISCREG_CNTHP_CVAL_EL2
:
405 core
.hyp
.setCompareValue(val
);
408 case MISCREG_CNTHP_TVAL
:
409 case MISCREG_CNTHP_TVAL_EL2
:
410 core
.hyp
.setTimerValue(val
);
414 warn("Writing to unknown register: %s\n", miscRegName
[reg
]);
421 GenericTimer::readMiscReg(int reg
, unsigned cpu
)
423 CoreTimers
&core(getTimers(cpu
));
427 case MISCREG_CNTFRQ_EL0
:
428 return systemCounter
.freq();
430 case MISCREG_CNTKCTL
:
431 case MISCREG_CNTKCTL_EL1
:
432 return systemCounter
.getKernelControl();
434 case MISCREG_CNTHCTL
:
435 case MISCREG_CNTHCTL_EL2
:
436 return systemCounter
.getHypControl();
439 case MISCREG_CNTP_CVAL_NS
:
440 case MISCREG_CNTP_CVAL_EL0
:
441 return core
.physNS
.compareValue();
443 case MISCREG_CNTP_TVAL_NS
:
444 case MISCREG_CNTP_TVAL_EL0
:
445 return core
.physNS
.timerValue();
447 case MISCREG_CNTP_CTL_EL0
:
448 case MISCREG_CNTP_CTL_NS
:
449 return core
.physNS
.control();
452 case MISCREG_CNTPCT_EL0
:
453 return core
.physNS
.value();
458 case MISCREG_CNTVCT_EL0
:
459 return core
.virt
.value();
461 case MISCREG_CNTVOFF
:
462 case MISCREG_CNTVOFF_EL2
:
463 return core
.virt
.offset();
465 case MISCREG_CNTV_CVAL
:
466 case MISCREG_CNTV_CVAL_EL0
:
467 return core
.virt
.compareValue();
469 case MISCREG_CNTV_TVAL
:
470 case MISCREG_CNTV_TVAL_EL0
:
471 return core
.virt
.timerValue();
473 case MISCREG_CNTV_CTL
:
474 case MISCREG_CNTV_CTL_EL0
:
475 return core
.virt
.control();
477 // PL1 phys. timer, secure
478 case MISCREG_CNTP_CTL_S
:
479 case MISCREG_CNTPS_CTL_EL1
:
480 return core
.physS
.control();
482 case MISCREG_CNTP_CVAL_S
:
483 case MISCREG_CNTPS_CVAL_EL1
:
484 return core
.physS
.compareValue();
486 case MISCREG_CNTP_TVAL_S
:
487 case MISCREG_CNTPS_TVAL_EL1
:
488 return core
.physS
.timerValue();
490 // HYP phys. timer (NS)
491 case MISCREG_CNTHP_CTL
:
492 case MISCREG_CNTHP_CTL_EL2
:
493 return core
.hyp
.control();
495 case MISCREG_CNTHP_CVAL
:
496 case MISCREG_CNTHP_CVAL_EL2
:
497 return core
.hyp
.compareValue();
499 case MISCREG_CNTHP_TVAL
:
500 case MISCREG_CNTHP_TVAL_EL2
:
501 return core
.hyp
.timerValue();
504 warn("Reading from unknown register: %s\n", miscRegName
[reg
]);
511 GenericTimerISA::setMiscReg(int reg
, MiscReg val
)
513 DPRINTF(Timer
, "Setting %s := 0x%x\n", miscRegName
[reg
], val
);
514 parent
.setMiscReg(reg
, cpu
, val
);
518 GenericTimerISA::readMiscReg(int reg
)
520 MiscReg value
= parent
.readMiscReg(reg
, cpu
);
521 DPRINTF(Timer
, "Reading %s as 0x%x\n", miscRegName
[reg
], value
);
525 GenericTimerMem::GenericTimerMem(GenericTimerMemParams
*p
)
527 ctrlRange(RangeSize(p
->base
, TheISA::PageBytes
)),
528 timerRange(RangeSize(p
->base
+ TheISA::PageBytes
, TheISA::PageBytes
)),
529 addrRanges
{ctrlRange
, timerRange
},
531 physTimer(csprintf("%s.phys_timer0", name()),
532 *this, systemCounter
,
534 virtTimer(csprintf("%s.virt_timer0", name()),
535 *this, systemCounter
,
541 GenericTimerMem::serialize(CheckpointOut
&cp
) const
543 paramOut(cp
, "timer_count", 1);
545 systemCounter
.serializeSection(cp
, "sys_counter");
547 physTimer
.serializeSection(cp
, "phys_timer0");
548 virtTimer
.serializeSection(cp
, "virt_timer0");
552 GenericTimerMem::unserialize(CheckpointIn
&cp
)
554 systemCounter
.unserializeSection(cp
, "sys_counter");
556 unsigned timer_count
;
557 UNSERIALIZE_SCALAR(timer_count
);
558 // The timer count variable is just here for future versions where
559 // we support more than one set of timers.
560 if (timer_count
!= 1)
561 panic("Incompatible checkpoint: Only one set of timers supported");
563 physTimer
.unserializeSection(cp
, "phys_timer0");
564 virtTimer
.unserializeSection(cp
, "virt_timer0");
568 GenericTimerMem::read(PacketPtr pkt
)
570 const unsigned size(pkt
->getSize());
571 const Addr
addr(pkt
->getAddr());
575 if (ctrlRange
.contains(addr
)) {
576 value
= ctrlRead(addr
- ctrlRange
.start(), size
);
577 } else if (timerRange
.contains(addr
)) {
578 value
= timerRead(addr
- timerRange
.start(), size
);
580 panic("Invalid address: 0x%x\n", addr
);
583 DPRINTF(Timer
, "Read 0x%x <- 0x%x(%i)\n", value
, addr
, size
);
586 pkt
->setLE
<uint64_t>(value
);
587 } else if (size
== 4) {
588 pkt
->setLE
<uint32_t>(value
);
590 panic("Unexpected access size: %i\n", size
);
597 GenericTimerMem::write(PacketPtr pkt
)
599 const unsigned size(pkt
->getSize());
600 if (size
!= 8 && size
!= 4)
601 panic("Unexpected access size\n");
603 const Addr
addr(pkt
->getAddr());
604 const uint64_t value(size
== 8 ?
605 pkt
->getLE
<uint64_t>() : pkt
->getLE
<uint32_t>());
607 DPRINTF(Timer
, "Write 0x%x -> 0x%x(%i)\n", value
, addr
, size
);
608 if (ctrlRange
.contains(addr
)) {
609 ctrlWrite(addr
- ctrlRange
.start(), size
, value
);
610 } else if (timerRange
.contains(addr
)) {
611 timerWrite(addr
- timerRange
.start(), size
, value
);
613 panic("Invalid address: 0x%x\n", addr
);
621 GenericTimerMem::ctrlRead(Addr addr
, size_t size
) const
626 return systemCounter
.freq();
629 return 0x3; // Frame 0 implemented with virtual timers
632 case CTRL_CNTACR_BASE
:
633 warn("Reading from unimplemented control register (0x%x)\n", addr
);
636 case CTRL_CNTVOFF_LO_BASE
:
637 return virtTimer
.offset();
639 case CTRL_CNTVOFF_HI_BASE
:
640 return virtTimer
.offset() >> 32;
643 warn("Unexpected address (0x%x:%i), assuming RAZ\n", addr
, size
);
646 } else if (size
== 8) {
648 case CTRL_CNTVOFF_LO_BASE
:
649 return virtTimer
.offset();
652 warn("Unexpected address (0x%x:%i), assuming RAZ\n", addr
, size
);
656 panic("Invalid access size: %i\n", size
);
661 GenericTimerMem::ctrlWrite(Addr addr
, size_t size
, uint64_t value
)
668 case CTRL_CNTACR_BASE
:
669 warn("Write to unimplemented control register (0x%x)\n", addr
);
672 case CTRL_CNTVOFF_LO_BASE
:
674 insertBits(virtTimer
.offset(), 31, 0, value
));
677 case CTRL_CNTVOFF_HI_BASE
:
679 insertBits(virtTimer
.offset(), 63, 32, value
));
683 warn("Ignoring write to unexpected address (0x%x:%i)\n",
687 } else if (size
== 8) {
689 case CTRL_CNTVOFF_LO_BASE
:
690 virtTimer
.setOffset(value
);
694 warn("Ignoring write to unexpected address (0x%x:%i)\n",
699 panic("Invalid access size: %i\n", size
);
704 GenericTimerMem::timerRead(Addr addr
, size_t size
) const
708 case TIMER_CNTPCT_LO
:
709 return physTimer
.value();
711 case TIMER_CNTPCT_HI
:
712 return physTimer
.value() >> 32;
714 case TIMER_CNTVCT_LO
:
715 return virtTimer
.value();
717 case TIMER_CNTVCT_HI
:
718 return virtTimer
.value() >> 32;
721 return systemCounter
.freq();
723 case TIMER_CNTEL0ACR
:
724 warn("Read from unimplemented timer register (0x%x)\n", addr
);
727 case CTRL_CNTVOFF_LO_BASE
:
728 return virtTimer
.offset();
730 case CTRL_CNTVOFF_HI_BASE
:
731 return virtTimer
.offset() >> 32;
733 case TIMER_CNTP_CVAL_LO
:
734 return physTimer
.compareValue();
736 case TIMER_CNTP_CVAL_HI
:
737 return physTimer
.compareValue() >> 32;
739 case TIMER_CNTP_TVAL
:
740 return physTimer
.timerValue();
743 return physTimer
.control();
745 case TIMER_CNTV_CVAL_LO
:
746 return virtTimer
.compareValue();
748 case TIMER_CNTV_CVAL_HI
:
749 return virtTimer
.compareValue() >> 32;
751 case TIMER_CNTV_TVAL
:
752 return virtTimer
.timerValue();
755 return virtTimer
.control();
758 warn("Unexpected address (0x%x:%i), assuming RAZ\n", addr
, size
);
761 } else if (size
== 8) {
763 case TIMER_CNTPCT_LO
:
764 return physTimer
.value();
766 case TIMER_CNTVCT_LO
:
767 return virtTimer
.value();
769 case CTRL_CNTVOFF_LO_BASE
:
770 return virtTimer
.offset();
772 case TIMER_CNTP_CVAL_LO
:
773 return physTimer
.compareValue();
775 case TIMER_CNTV_CVAL_LO
:
776 return virtTimer
.compareValue();
779 warn("Unexpected address (0x%x:%i), assuming RAZ\n", addr
, size
);
783 panic("Invalid access size: %i\n", size
);
788 GenericTimerMem::timerWrite(Addr addr
, size_t size
, uint64_t value
)
792 case TIMER_CNTEL0ACR
:
793 warn("Unimplemented timer register (0x%x)\n", addr
);
796 case TIMER_CNTP_CVAL_LO
:
797 physTimer
.setCompareValue(
798 insertBits(physTimer
.compareValue(), 31, 0, value
));
801 case TIMER_CNTP_CVAL_HI
:
802 physTimer
.setCompareValue(
803 insertBits(physTimer
.compareValue(), 63, 32, value
));
806 case TIMER_CNTP_TVAL
:
807 physTimer
.setTimerValue(value
);
811 physTimer
.setControl(value
);
814 case TIMER_CNTV_CVAL_LO
:
815 virtTimer
.setCompareValue(
816 insertBits(virtTimer
.compareValue(), 31, 0, value
));
819 case TIMER_CNTV_CVAL_HI
:
820 virtTimer
.setCompareValue(
821 insertBits(virtTimer
.compareValue(), 63, 32, value
));
824 case TIMER_CNTV_TVAL
:
825 virtTimer
.setTimerValue(value
);
829 virtTimer
.setControl(value
);
833 warn("Unexpected address (0x%x:%i), ignoring write\n", addr
, size
);
836 } else if (size
== 8) {
838 case TIMER_CNTP_CVAL_LO
:
839 return physTimer
.setCompareValue(value
);
841 case TIMER_CNTV_CVAL_LO
:
842 return virtTimer
.setCompareValue(value
);
845 warn("Unexpected address (0x%x:%i), ignoring write\n", addr
, size
);
849 panic("Invalid access size: %i\n", size
);
854 GenericTimerParams::create()
856 return new GenericTimer(this);
860 GenericTimerMemParams::create()
862 return new GenericTimerMem(this);