2 * Copyright (c) 2013, 2015, 2017 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(_freq
);
73 SERIALIZE_SCALAR(_period
);
74 SERIALIZE_SCALAR(_resetTick
);
78 SystemCounter::unserialize(CheckpointIn
&cp
)
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
))
84 UNSERIALIZE_SCALAR(_freq
);
85 UNSERIALIZE_SCALAR(_period
);
86 UNSERIALIZE_SCALAR(_resetTick
);
91 ArchTimer::ArchTimer(const std::string
&name
,
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)
103 ArchTimer::counterLimitReached()
105 _control
.istatus
= 1;
107 if (!_control
.enable
)
110 DPRINTF(Timer
, "Counter limit reached\n");
111 if (!_control
.imask
) {
112 DPRINTF(Timer
, "Causing interrupt\n");
118 ArchTimer::updateCounter()
120 if (_counterLimitReachedEvent
.scheduled())
121 _parent
.deschedule(_counterLimitReachedEvent
);
122 if (value() >= _counterLimit
) {
123 counterLimitReached();
125 const auto period(_systemCounter
.period());
126 _control
.istatus
= 0;
127 _parent
.schedule(_counterLimitReachedEvent
,
128 curTick() + (_counterLimit
- value()) * period
);
133 ArchTimer::setCompareValue(uint64_t val
)
140 ArchTimer::setTimerValue(uint32_t val
)
142 setCompareValue(value() + sext
<32>(val
));
146 ArchTimer::setControl(uint32_t val
)
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;
155 DPRINTF(Timer
, "Causing interrupt in control\n");
159 _control
.enable
= new_ctl
.enable
;
160 _control
.imask
= new_ctl
.imask
;
164 ArchTimer::setOffset(uint64_t val
)
171 ArchTimer::value() const
173 return _systemCounter
.value() - _offset
;
177 ArchTimer::serialize(CheckpointOut
&cp
) const
179 paramOut(cp
, "control_serial", _control
);
180 SERIALIZE_SCALAR(_counterLimit
);
181 SERIALIZE_SCALAR(_offset
);
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
);
192 ArchTimer::unserialize(CheckpointIn
&cp
)
194 paramIn(cp
, "control_serial", _control
);
195 // We didn't serialize an offset before we added support for the
196 // virtual timer. Consider it optional to maintain backwards
198 if (!UNSERIALIZE_OPT_SCALAR(_offset
))
200 bool event_scheduled
;
201 UNSERIALIZE_SCALAR(event_scheduled
);
202 if (event_scheduled
) {
204 UNSERIALIZE_SCALAR(event_time
);
205 _parent
.schedule(_counterLimitReachedEvent
, event_time
);
210 ArchTimer::Interrupt::send()
213 _gic
.sendPPInt(_irq
, _cpu
);
221 ArchTimer::Interrupt::clear()
224 _gic
.clearPPInt(_irq
, _cpu
);
231 GenericTimer::GenericTimer(GenericTimerParams
*p
)
234 irqPhys(p
->int_phys
),
237 fatal_if(!p
->system
, "No system specified, can't instantiate timer.\n");
238 p
->system
->setGenericTimer(this);
242 GenericTimer::serialize(CheckpointOut
&cp
) const
244 paramOut(cp
, "cpu_count", timers
.size());
246 systemCounter
.serializeSection(cp
, "sys_counter");
248 for (int i
= 0; i
< timers
.size(); ++i
) {
249 const CoreTimers
&core(*timers
[i
]);
251 // This should really be phys_timerN, but we are stuck with
252 // arch_timer for backwards compatibility.
253 core
.phys
.serializeSection(cp
, csprintf("arch_timer%d", i
));
254 core
.virt
.serializeSection(cp
, csprintf("virt_timer%d", i
));
259 GenericTimer::unserialize(CheckpointIn
&cp
)
261 systemCounter
.unserializeSection(cp
, "sys_counter");
263 // Try to unserialize the CPU count. Old versions of the timer
264 // model assumed a 8 CPUs, so we fall back to that if the field
266 static const unsigned OLD_CPU_MAX
= 8;
268 if (!UNSERIALIZE_OPT_SCALAR(cpu_count
)) {
269 warn("Checkpoint does not contain CPU count, assuming %i CPUs\n",
271 cpu_count
= OLD_CPU_MAX
;
274 for (int i
= 0; i
< cpu_count
; ++i
) {
275 CoreTimers
&core(getTimers(i
));
276 // This should really be phys_timerN, but we are stuck with
277 // arch_timer for backwards compatibility.
278 core
.phys
.unserializeSection(cp
, csprintf("arch_timer%d", i
));
279 core
.virt
.unserializeSection(cp
, csprintf("virt_timer%d", i
));
284 GenericTimer::CoreTimers
&
285 GenericTimer::getTimers(int cpu_id
)
287 if (cpu_id
>= timers
.size())
288 createTimers(cpu_id
+ 1);
290 return *timers
[cpu_id
];
294 GenericTimer::createTimers(unsigned cpus
)
296 assert(timers
.size() < cpus
);
298 const unsigned old_cpu_count(timers
.size());
300 for (unsigned i
= old_cpu_count
; i
< cpus
; ++i
) {
302 new CoreTimers(*this, i
, irqPhys
, irqVirt
));
308 GenericTimer::setMiscReg(int reg
, unsigned cpu
, MiscReg val
)
310 // This method might have been called from another context if we
311 // are running in multi-core KVM. Migrate to the SimObject's event
312 // queue to prevent surprising race conditions.
313 EventQueue::ScopedMigration
migrate(eventQueue());
315 CoreTimers
&core(getTimers(cpu
));
319 case MISCREG_CNTFRQ_EL0
:
320 systemCounter
.setFreq(val
);
323 case MISCREG_CNTKCTL
:
324 case MISCREG_CNTKCTL_EL1
:
325 systemCounter
.setKernelControl(val
);
329 case MISCREG_CNTP_CVAL
:
330 case MISCREG_CNTP_CVAL_NS
:
331 case MISCREG_CNTP_CVAL_EL0
:
332 core
.phys
.setCompareValue(val
);
335 case MISCREG_CNTP_TVAL
:
336 case MISCREG_CNTP_TVAL_NS
:
337 case MISCREG_CNTP_TVAL_EL0
:
338 core
.phys
.setTimerValue(val
);
341 case MISCREG_CNTP_CTL
:
342 case MISCREG_CNTP_CTL_NS
:
343 case MISCREG_CNTP_CTL_EL0
:
344 core
.phys
.setControl(val
);
349 case MISCREG_CNTPCT_EL0
:
351 case MISCREG_CNTVCT_EL0
:
352 warn("Ignoring write to read only count register: %s\n",
357 case MISCREG_CNTVOFF
:
358 case MISCREG_CNTVOFF_EL2
:
359 core
.virt
.setOffset(val
);
362 case MISCREG_CNTV_CVAL
:
363 case MISCREG_CNTV_CVAL_EL0
:
364 core
.virt
.setCompareValue(val
);
367 case MISCREG_CNTV_TVAL
:
368 case MISCREG_CNTV_TVAL_EL0
:
369 core
.virt
.setTimerValue(val
);
372 case MISCREG_CNTV_CTL
:
373 case MISCREG_CNTV_CTL_EL0
:
374 core
.virt
.setControl(val
);
377 // PL1 phys. timer, secure
378 case MISCREG_CNTP_CTL_S
:
379 case MISCREG_CNTPS_CVAL_EL1
:
380 case MISCREG_CNTPS_TVAL_EL1
:
381 case MISCREG_CNTPS_CTL_EL1
:
384 // PL2 phys. timer, non-secure
385 case MISCREG_CNTHCTL
:
386 case MISCREG_CNTHCTL_EL2
:
387 case MISCREG_CNTHP_CVAL
:
388 case MISCREG_CNTHP_CVAL_EL2
:
389 case MISCREG_CNTHP_TVAL
:
390 case MISCREG_CNTHP_TVAL_EL2
:
391 case MISCREG_CNTHP_CTL
:
392 case MISCREG_CNTHP_CTL_EL2
:
393 warn("Writing to unimplemented register: %s\n",
398 warn("Writing to unknown register: %s\n", miscRegName
[reg
]);
405 GenericTimer::readMiscReg(int reg
, unsigned cpu
)
407 // This method might have been called from another context if we
408 // are running in multi-core KVM. Migrate to the SimObject's event
409 // queue to prevent surprising race conditions.
410 EventQueue::ScopedMigration
migrate(eventQueue());
412 CoreTimers
&core(getTimers(cpu
));
416 case MISCREG_CNTFRQ_EL0
:
417 return systemCounter
.freq();
419 case MISCREG_CNTKCTL
:
420 case MISCREG_CNTKCTL_EL1
:
421 return systemCounter
.getKernelControl();
424 case MISCREG_CNTP_CVAL
:
425 case MISCREG_CNTP_CVAL_EL0
:
426 return core
.phys
.compareValue();
428 case MISCREG_CNTP_TVAL
:
429 case MISCREG_CNTP_TVAL_EL0
:
430 return core
.phys
.timerValue();
432 case MISCREG_CNTP_CTL
:
433 case MISCREG_CNTP_CTL_EL0
:
434 case MISCREG_CNTP_CTL_NS
:
435 return core
.phys
.control();
438 case MISCREG_CNTPCT_EL0
:
439 return core
.phys
.value();
444 case MISCREG_CNTVCT_EL0
:
445 return core
.virt
.value();
447 case MISCREG_CNTVOFF
:
448 case MISCREG_CNTVOFF_EL2
:
449 return core
.virt
.offset();
451 case MISCREG_CNTV_CVAL
:
452 case MISCREG_CNTV_CVAL_EL0
:
453 return core
.virt
.compareValue();
455 case MISCREG_CNTV_TVAL
:
456 case MISCREG_CNTV_TVAL_EL0
:
457 return core
.virt
.timerValue();
459 case MISCREG_CNTV_CTL
:
460 case MISCREG_CNTV_CTL_EL0
:
461 return core
.virt
.control();
463 // PL1 phys. timer, secure
464 case MISCREG_CNTP_CTL_S
:
465 case MISCREG_CNTPS_CVAL_EL1
:
466 case MISCREG_CNTPS_TVAL_EL1
:
467 case MISCREG_CNTPS_CTL_EL1
:
470 // PL2 phys. timer, non-secure
471 case MISCREG_CNTHCTL
:
472 case MISCREG_CNTHCTL_EL2
:
473 case MISCREG_CNTHP_CVAL
:
474 case MISCREG_CNTHP_CVAL_EL2
:
475 case MISCREG_CNTHP_TVAL
:
476 case MISCREG_CNTHP_TVAL_EL2
:
477 case MISCREG_CNTHP_CTL
:
478 case MISCREG_CNTHP_CTL_EL2
:
479 warn("Reading from unimplemented register: %s\n",
485 warn("Reading from unknown register: %s\n", miscRegName
[reg
]);
492 GenericTimerMem::GenericTimerMem(GenericTimerMemParams
*p
)
494 ctrlRange(RangeSize(p
->base
, TheISA::PageBytes
)),
495 timerRange(RangeSize(p
->base
+ TheISA::PageBytes
, TheISA::PageBytes
)),
496 addrRanges
{ctrlRange
, timerRange
},
498 physTimer(csprintf("%s.phys_timer0", name()),
499 *this, systemCounter
,
500 ArchTimer::Interrupt(*p
->gic
, p
->int_phys
)),
501 virtTimer(csprintf("%s.virt_timer0", name()),
502 *this, systemCounter
,
503 ArchTimer::Interrupt(*p
->gic
, p
->int_virt
))
508 GenericTimerMem::serialize(CheckpointOut
&cp
) const
510 paramOut(cp
, "timer_count", 1);
512 systemCounter
.serializeSection(cp
, "sys_counter");
514 physTimer
.serializeSection(cp
, "phys_timer0");
515 virtTimer
.serializeSection(cp
, "virt_timer0");
519 GenericTimerMem::unserialize(CheckpointIn
&cp
)
521 systemCounter
.unserializeSection(cp
, "sys_counter");
523 unsigned timer_count
;
524 UNSERIALIZE_SCALAR(timer_count
);
525 // The timer count variable is just here for future versions where
526 // we support more than one set of timers.
527 if (timer_count
!= 1)
528 panic("Incompatible checkpoint: Only one set of timers supported");
530 physTimer
.unserializeSection(cp
, "phys_timer0");
531 virtTimer
.unserializeSection(cp
, "virt_timer0");
535 GenericTimerMem::read(PacketPtr pkt
)
537 const unsigned size(pkt
->getSize());
538 const Addr
addr(pkt
->getAddr());
542 if (ctrlRange
.contains(addr
)) {
543 value
= ctrlRead(addr
- ctrlRange
.start(), size
);
544 } else if (timerRange
.contains(addr
)) {
545 value
= timerRead(addr
- timerRange
.start(), size
);
547 panic("Invalid address: 0x%x\n", addr
);
550 DPRINTF(Timer
, "Read 0x%x <- 0x%x(%i)\n", value
, addr
, size
);
553 pkt
->set
<uint64_t>(value
);
554 } else if (size
== 4) {
555 pkt
->set
<uint32_t>(value
);
557 panic("Unexpected access size: %i\n", size
);
564 GenericTimerMem::write(PacketPtr pkt
)
566 const unsigned size(pkt
->getSize());
567 if (size
!= 8 && size
!= 4)
568 panic("Unexpected access size\n");
570 const Addr
addr(pkt
->getAddr());
571 const uint64_t value(size
== 8 ?
572 pkt
->get
<uint64_t>() : pkt
->get
<uint32_t>());
574 DPRINTF(Timer
, "Write 0x%x -> 0x%x(%i)\n", value
, addr
, size
);
575 if (ctrlRange
.contains(addr
)) {
576 ctrlWrite(addr
- ctrlRange
.start(), size
, value
);
577 } else if (timerRange
.contains(addr
)) {
578 timerWrite(addr
- timerRange
.start(), size
, value
);
580 panic("Invalid address: 0x%x\n", addr
);
588 GenericTimerMem::ctrlRead(Addr addr
, size_t size
) const
593 return systemCounter
.freq();
596 return 0x3; // Frame 0 implemented with virtual timers
599 case CTRL_CNTACR_BASE
:
600 warn("Reading from unimplemented control register (0x%x)\n", addr
);
603 case CTRL_CNTVOFF_LO_BASE
:
604 return virtTimer
.offset();
606 case CTRL_CNTVOFF_HI_BASE
:
607 return virtTimer
.offset() >> 32;
610 warn("Unexpected address (0x%x:%i), assuming RAZ\n", addr
, size
);
613 } else if (size
== 8) {
615 case CTRL_CNTVOFF_LO_BASE
:
616 return virtTimer
.offset();
619 warn("Unexpected address (0x%x:%i), assuming RAZ\n", addr
, size
);
623 panic("Invalid access size: %i\n", size
);
628 GenericTimerMem::ctrlWrite(Addr addr
, size_t size
, uint64_t value
)
635 case CTRL_CNTACR_BASE
:
636 warn("Write to unimplemented control register (0x%x)\n", addr
);
639 case CTRL_CNTVOFF_LO_BASE
:
641 insertBits(virtTimer
.offset(), 31, 0, value
));
644 case CTRL_CNTVOFF_HI_BASE
:
646 insertBits(virtTimer
.offset(), 63, 32, value
));
650 warn("Ignoring write to unexpected address (0x%x:%i)\n",
654 } else if (size
== 8) {
656 case CTRL_CNTVOFF_LO_BASE
:
657 virtTimer
.setOffset(value
);
661 warn("Ignoring write to unexpected address (0x%x:%i)\n",
666 panic("Invalid access size: %i\n", size
);
671 GenericTimerMem::timerRead(Addr addr
, size_t size
) const
675 case TIMER_CNTPCT_LO
:
676 return physTimer
.value();
678 case TIMER_CNTPCT_HI
:
679 return physTimer
.value() >> 32;
681 case TIMER_CNTVCT_LO
:
682 return virtTimer
.value();
684 case TIMER_CNTVCT_HI
:
685 return virtTimer
.value() >> 32;
688 return systemCounter
.freq();
690 case TIMER_CNTEL0ACR
:
691 warn("Read from unimplemented timer register (0x%x)\n", addr
);
694 case CTRL_CNTVOFF_LO_BASE
:
695 return virtTimer
.offset();
697 case CTRL_CNTVOFF_HI_BASE
:
698 return virtTimer
.offset() >> 32;
700 case TIMER_CNTP_CVAL_LO
:
701 return physTimer
.compareValue();
703 case TIMER_CNTP_CVAL_HI
:
704 return physTimer
.compareValue() >> 32;
706 case TIMER_CNTP_TVAL
:
707 return physTimer
.timerValue();
710 return physTimer
.control();
712 case TIMER_CNTV_CVAL_LO
:
713 return virtTimer
.compareValue();
715 case TIMER_CNTV_CVAL_HI
:
716 return virtTimer
.compareValue() >> 32;
718 case TIMER_CNTV_TVAL
:
719 return virtTimer
.timerValue();
722 return virtTimer
.control();
725 warn("Unexpected address (0x%x:%i), assuming RAZ\n", addr
, size
);
728 } else if (size
== 8) {
730 case TIMER_CNTPCT_LO
:
731 return physTimer
.value();
733 case TIMER_CNTVCT_LO
:
734 return virtTimer
.value();
736 case CTRL_CNTVOFF_LO_BASE
:
737 return virtTimer
.offset();
739 case TIMER_CNTP_CVAL_LO
:
740 return physTimer
.compareValue();
742 case TIMER_CNTV_CVAL_LO
:
743 return virtTimer
.compareValue();
746 warn("Unexpected address (0x%x:%i), assuming RAZ\n", addr
, size
);
750 panic("Invalid access size: %i\n", size
);
755 GenericTimerMem::timerWrite(Addr addr
, size_t size
, uint64_t value
)
759 case TIMER_CNTEL0ACR
:
760 warn("Unimplemented timer register (0x%x)\n", addr
);
763 case TIMER_CNTP_CVAL_LO
:
764 physTimer
.setCompareValue(
765 insertBits(physTimer
.compareValue(), 31, 0, value
));
768 case TIMER_CNTP_CVAL_HI
:
769 physTimer
.setCompareValue(
770 insertBits(physTimer
.compareValue(), 63, 32, value
));
773 case TIMER_CNTP_TVAL
:
774 physTimer
.setTimerValue(value
);
778 physTimer
.setControl(value
);
781 case TIMER_CNTV_CVAL_LO
:
782 virtTimer
.setCompareValue(
783 insertBits(virtTimer
.compareValue(), 31, 0, value
));
786 case TIMER_CNTV_CVAL_HI
:
787 virtTimer
.setCompareValue(
788 insertBits(virtTimer
.compareValue(), 63, 32, value
));
791 case TIMER_CNTV_TVAL
:
792 virtTimer
.setTimerValue(value
);
796 virtTimer
.setControl(value
);
800 warn("Unexpected address (0x%x:%i), ignoring write\n", addr
, size
);
803 } else if (size
== 8) {
805 case TIMER_CNTP_CVAL_LO
:
806 return physTimer
.setCompareValue(value
);
808 case TIMER_CNTV_CVAL_LO
:
809 return virtTimer
.setCompareValue(value
);
812 warn("Unexpected address (0x%x:%i), ignoring write\n", addr
, size
);
816 panic("Invalid access size: %i\n", size
);
821 GenericTimerParams::create()
823 return new GenericTimer(this);
827 GenericTimerMemParams::create()
829 return new GenericTimerMem(this);