2 * Copyright (c) 2013, 2015 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 "params/GenericTimer.hh"
48 SystemCounter::SystemCounter()
49 : _freq(0), _period(0), _resetTick(0), _regCntkctl(0)
55 SystemCounter::setFreq(uint32_t freq
)
58 // Altering the frequency after boot shouldn't be done in practice.
59 warn_once("The frequency of the system counter has already been set");
62 _period
= (1.0 / freq
) * SimClock::Frequency
;
63 _resetTick
= curTick();
67 SystemCounter::serialize(std::ostream
&os
) const
69 SERIALIZE_SCALAR(_regCntkctl
);
70 SERIALIZE_SCALAR(_freq
);
71 SERIALIZE_SCALAR(_period
);
72 SERIALIZE_SCALAR(_resetTick
);
76 SystemCounter::unserialize(Checkpoint
*cp
,
77 const std::string
§ion
)
79 // We didn't handle CNTKCTL in this class before, assume it's zero
80 // if it isn't present.
81 if (!UNSERIALIZE_OPT_SCALAR(_regCntkctl
))
83 UNSERIALIZE_SCALAR(_freq
);
84 UNSERIALIZE_SCALAR(_period
);
85 UNSERIALIZE_SCALAR(_resetTick
);
90 ArchTimer::ArchTimer(const std::string
&name
,
92 SystemCounter
&sysctr
,
93 const Interrupt
&interrupt
)
94 : _name(name
), _parent(parent
), _systemCounter(sysctr
),
95 _interrupt(interrupt
),
96 _control(0), _counterLimit(0), _offset(0),
97 _counterLimitReachedEvent(this)
102 ArchTimer::counterLimitReached()
104 _control
.istatus
= 1;
106 if (!_control
.enable
)
109 DPRINTF(Timer
, "Counter limit reached\n");
110 if (!_control
.imask
) {
111 DPRINTF(Timer
, "Causing interrupt\n");
117 ArchTimer::updateCounter()
119 if (_counterLimitReachedEvent
.scheduled())
120 _parent
.deschedule(_counterLimitReachedEvent
);
121 if (value() >= _counterLimit
) {
122 counterLimitReached();
124 const auto period(_systemCounter
.period());
125 _control
.istatus
= 0;
126 _parent
.schedule(_counterLimitReachedEvent
,
127 curTick() + (_counterLimit
- value()) * period
);
132 ArchTimer::setCompareValue(uint64_t val
)
139 ArchTimer::setTimerValue(uint32_t val
)
141 setCompareValue(value() + sext
<32>(val
));
145 ArchTimer::setControl(uint32_t val
)
147 ArchTimerCtrl new_ctl
= val
;
148 if ((new_ctl
.enable
&& !new_ctl
.imask
) &&
149 !(_control
.enable
&& !_control
.imask
)) {
150 // Re-evalute the timer condition
151 if (_counterLimit
>= value()) {
152 _control
.istatus
= 1;
154 DPRINTF(Timer
, "Causing interrupt in control\n");
158 _control
.enable
= new_ctl
.enable
;
159 _control
.imask
= new_ctl
.imask
;
163 ArchTimer::setOffset(uint64_t val
)
170 ArchTimer::value() const
172 return _systemCounter
.value() - _offset
;
176 ArchTimer::serialize(std::ostream
&os
) const
178 paramOut(os
, "control_serial", _control
);
179 SERIALIZE_SCALAR(_counterLimit
);
180 SERIALIZE_SCALAR(_offset
);
182 const bool event_scheduled(_counterLimitReachedEvent
.scheduled());
183 SERIALIZE_SCALAR(event_scheduled
);
184 if (event_scheduled
) {
185 const Tick
event_time(_counterLimitReachedEvent
.when());
186 SERIALIZE_SCALAR(event_time
);
191 ArchTimer::unserialize(Checkpoint
*cp
,
192 const std::string
§ion
)
194 paramIn(cp
, section
, "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 dynamic_cast<ArmSystem
&>(*p
->system
).setGenericTimer(this);
241 GenericTimer::serialize(std::ostream
&os
)
243 paramOut(os
, "cpu_count", timers
.size());
245 nameOut(os
, csprintf("%s.sys_counter", name()));
246 systemCounter
.serialize(os
);
248 for (int i
= 0; i
< timers
.size(); ++i
) {
249 CoreTimers
&core(getTimers(i
));
251 nameOut(os
, core
.phys
.name());
252 core
.phys
.serialize(os
);
254 nameOut(os
, core
.virt
.name());
255 core
.virt
.serialize(os
);
260 GenericTimer::unserialize(Checkpoint
*cp
, const std::string
§ion
)
262 systemCounter
.unserialize(cp
, csprintf("%s.sys_counter", section
));
264 // Try to unserialize the CPU count. Old versions of the timer
265 // model assumed a 8 CPUs, so we fall back to that if the field
267 static const unsigned OLD_CPU_MAX
= 8;
269 if (!UNSERIALIZE_OPT_SCALAR(cpu_count
)) {
270 warn("Checkpoint does not contain CPU count, assuming %i CPUs\n",
272 cpu_count
= OLD_CPU_MAX
;
275 for (int i
= 0; i
< cpu_count
; ++i
) {
276 CoreTimers
&core(getTimers(i
));
277 // This should really be phys_timerN, but we are stuck with
278 // arch_timer for backwards compatibility.
279 core
.phys
.unserialize(cp
, csprintf("%s.arch_timer%d", section
, i
));
280 core
.virt
.unserialize(cp
, csprintf("%s.virt_timer%d", section
, i
));
285 GenericTimer::CoreTimers
&
286 GenericTimer::getTimers(int cpu_id
)
288 if (cpu_id
>= timers
.size())
289 createTimers(cpu_id
+ 1);
291 return *timers
[cpu_id
];
295 GenericTimer::createTimers(unsigned cpus
)
297 assert(timers
.size() < cpus
);
299 const unsigned old_cpu_count(timers
.size());
301 for (unsigned i
= old_cpu_count
; i
< cpus
; ++i
) {
303 new CoreTimers(*this, i
, irqPhys
, irqVirt
));
309 GenericTimer::setMiscReg(int reg
, unsigned cpu
, MiscReg val
)
311 CoreTimers
&core(getTimers(cpu
));
315 case MISCREG_CNTFRQ_EL0
:
316 systemCounter
.setFreq(val
);
319 case MISCREG_CNTKCTL
:
320 case MISCREG_CNTKCTL_EL1
:
321 systemCounter
.setKernelControl(val
);
325 case MISCREG_CNTP_CVAL
:
326 case MISCREG_CNTP_CVAL_NS
:
327 case MISCREG_CNTP_CVAL_EL0
:
328 core
.phys
.setCompareValue(val
);
331 case MISCREG_CNTP_TVAL
:
332 case MISCREG_CNTP_TVAL_NS
:
333 case MISCREG_CNTP_TVAL_EL0
:
334 core
.phys
.setTimerValue(val
);
337 case MISCREG_CNTP_CTL
:
338 case MISCREG_CNTP_CTL_NS
:
339 case MISCREG_CNTP_CTL_EL0
:
340 core
.phys
.setControl(val
);
345 case MISCREG_CNTPCT_EL0
:
347 case MISCREG_CNTVCT_EL0
:
348 warn("Ignoring write to read only count register: %s\n",
353 case MISCREG_CNTVOFF
:
354 case MISCREG_CNTVOFF_EL2
:
355 core
.virt
.setOffset(val
);
358 case MISCREG_CNTV_CVAL
:
359 case MISCREG_CNTV_CVAL_EL0
:
360 core
.virt
.setCompareValue(val
);
363 case MISCREG_CNTV_TVAL
:
364 case MISCREG_CNTV_TVAL_EL0
:
365 core
.virt
.setTimerValue(val
);
368 case MISCREG_CNTV_CTL
:
369 case MISCREG_CNTV_CTL_EL0
:
370 core
.virt
.setControl(val
);
373 // PL1 phys. timer, secure
374 case MISCREG_CNTP_CTL_S
:
375 case MISCREG_CNTPS_CVAL_EL1
:
376 case MISCREG_CNTPS_TVAL_EL1
:
377 case MISCREG_CNTPS_CTL_EL1
:
380 // PL2 phys. timer, non-secure
381 case MISCREG_CNTHCTL
:
382 case MISCREG_CNTHCTL_EL2
:
383 case MISCREG_CNTHP_CVAL
:
384 case MISCREG_CNTHP_CVAL_EL2
:
385 case MISCREG_CNTHP_TVAL
:
386 case MISCREG_CNTHP_TVAL_EL2
:
387 case MISCREG_CNTHP_CTL
:
388 case MISCREG_CNTHP_CTL_EL2
:
389 warn("Writing to unimplemented register: %s\n",
394 warn("Writing to unknown register: %s\n", miscRegName
[reg
]);
401 GenericTimer::readMiscReg(int reg
, unsigned cpu
)
403 CoreTimers
&core(getTimers(cpu
));
407 case MISCREG_CNTFRQ_EL0
:
408 return systemCounter
.freq();
410 case MISCREG_CNTKCTL
:
411 case MISCREG_CNTKCTL_EL1
:
412 return systemCounter
.getKernelControl();
415 case MISCREG_CNTP_CVAL
:
416 case MISCREG_CNTP_CVAL_EL0
:
417 return core
.phys
.compareValue();
419 case MISCREG_CNTP_TVAL
:
420 case MISCREG_CNTP_TVAL_EL0
:
421 return core
.phys
.timerValue();
423 case MISCREG_CNTP_CTL
:
424 case MISCREG_CNTP_CTL_EL0
:
425 case MISCREG_CNTP_CTL_NS
:
426 return core
.phys
.control();
429 case MISCREG_CNTPCT_EL0
:
430 return core
.phys
.value();
435 case MISCREG_CNTVCT_EL0
:
436 return core
.virt
.value();
438 case MISCREG_CNTVOFF
:
439 case MISCREG_CNTVOFF_EL2
:
440 return core
.virt
.offset();
442 case MISCREG_CNTV_CVAL
:
443 case MISCREG_CNTV_CVAL_EL0
:
444 return core
.virt
.compareValue();
446 case MISCREG_CNTV_TVAL
:
447 case MISCREG_CNTV_TVAL_EL0
:
448 return core
.virt
.timerValue();
450 case MISCREG_CNTV_CTL
:
451 case MISCREG_CNTV_CTL_EL0
:
452 return core
.virt
.control();
454 // PL1 phys. timer, secure
455 case MISCREG_CNTP_CTL_S
:
456 case MISCREG_CNTPS_CVAL_EL1
:
457 case MISCREG_CNTPS_TVAL_EL1
:
458 case MISCREG_CNTPS_CTL_EL1
:
461 // PL2 phys. timer, non-secure
462 case MISCREG_CNTHCTL
:
463 case MISCREG_CNTHCTL_EL2
:
464 case MISCREG_CNTHP_CVAL
:
465 case MISCREG_CNTHP_CVAL_EL2
:
466 case MISCREG_CNTHP_TVAL
:
467 case MISCREG_CNTHP_TVAL_EL2
:
468 case MISCREG_CNTHP_CTL
:
469 case MISCREG_CNTHP_CTL_EL2
:
470 warn("Reading from unimplemented register: %s\n",
476 warn("Reading from unknown register: %s\n", miscRegName
[reg
]);
483 GenericTimerParams::create()
485 return new GenericTimer(this);