1b9625752977cecf477afaf556444034fcc635dc
[gem5.git] / src / dev / arm / generic_timer.cc
1 /*
2 * Copyright (c) 2013, 2015, 2017-2018,2020 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 <cmath>
41
42 #include "arch/arm/system.hh"
43 #include "arch/arm/utility.hh"
44 #include "cpu/base.hh"
45 #include "debug/Timer.hh"
46 #include "dev/arm/base_gic.hh"
47 #include "mem/packet_access.hh"
48 #include "params/GenericTimer.hh"
49 #include "params/GenericTimerFrame.hh"
50 #include "params/GenericTimerMem.hh"
51 #include "params/SystemCounter.hh"
52
53 SystemCounter::SystemCounter(SystemCounterParams *const p)
54 : SimObject(p),
55 _enabled(true),
56 _value(0),
57 _increment(1),
58 _freqTable(p->freqs),
59 _activeFreqEntry(0),
60 _updateTick(0),
61 _freqUpdateEvent([this]{ freqUpdateCallback(); }, name()),
62 _nextFreqEntry(0)
63 {
64 fatal_if(_freqTable.empty(), "SystemCounter::SystemCounter: Base "
65 "frequency not provided\n");
66 // Store the table end marker as a 32-bit zero word
67 _freqTable.push_back(0);
68 fatal_if(_freqTable.size() > MAX_FREQ_ENTRIES,
69 "SystemCounter::SystemCounter: Architecture states a maximum of 1004 "
70 "frequency table entries, limit surpassed\n");
71 // Set the active frequency to be the base
72 _freq = _freqTable.front();
73 _period = (1.0 / _freq) * SimClock::Frequency;
74 }
75
76 void
77 SystemCounter::validateCounterRef(SystemCounter *const sys_cnt)
78 {
79 fatal_if(!sys_cnt, "SystemCounter::validateCounterRef: No valid system "
80 "counter, can't instantiate system timers\n");
81 }
82
83 void
84 SystemCounter::enable()
85 {
86 DPRINTF(Timer, "SystemCounter::enable: Counter enabled\n");
87 _enabled = true;
88 updateTick();
89 }
90
91 void
92 SystemCounter::disable()
93 {
94 DPRINTF(Timer, "SystemCounter::disable: Counter disabled\n");
95 updateValue();
96 _enabled = false;
97 }
98
99 uint64_t
100 SystemCounter::value()
101 {
102 if (_enabled)
103 updateValue();
104 return _value;
105 }
106
107 void
108 SystemCounter::updateValue()
109 {
110 uint64_t new_value =
111 _value + ((curTick() - _updateTick) / _period) * _increment;
112 if (new_value > _value) {
113 _value = new_value;
114 updateTick();
115 }
116 }
117
118 void
119 SystemCounter::setValue(uint64_t new_value)
120 {
121 if (_enabled)
122 warn("Explicit value set with counter enabled, UNKNOWNN result\n");
123 _value = new_value;
124 updateTick();
125 notifyListeners();
126 }
127
128 Tick
129 SystemCounter::whenValue(uint64_t cur_val, uint64_t target_val) const
130 {
131 Tick when = curTick();
132 if (target_val > cur_val) {
133 uint64_t num_cycles =
134 std::ceil((target_val - cur_val) / ((double) _increment));
135 // Take into account current cycle remaining ticks
136 Tick rem_ticks = _period - (curTick() % _period);
137 if (rem_ticks < _period) {
138 when += rem_ticks;
139 num_cycles -= 1;
140 }
141 when += num_cycles * _period;
142 }
143 return when;
144 }
145
146 Tick
147 SystemCounter::whenValue(uint64_t target_val)
148 {
149 return whenValue(value(), target_val);
150 }
151
152 void
153 SystemCounter::updateTick()
154 {
155 _updateTick = curTick() - (curTick() % _period);
156 }
157
158 void
159 SystemCounter::freqUpdateSchedule(size_t new_freq_entry)
160 {
161 if (new_freq_entry < _freqTable.size()) {
162 auto &new_freq = _freqTable[new_freq_entry];
163 if (new_freq != _freq) {
164 _nextFreqEntry = new_freq_entry;
165 // Wait until the value for which the lowest frequency increment
166 // is a exact divisor. This covers both high to low and low to
167 // high transitions
168 uint64_t new_incr = _freqTable[0] / new_freq;
169 uint64_t target_val = value();
170 target_val += target_val % std::max(_increment, new_incr);
171 reschedule(_freqUpdateEvent, whenValue(target_val), true);
172 }
173 }
174 }
175
176 void
177 SystemCounter::freqUpdateCallback()
178 {
179 DPRINTF(Timer, "SystemCounter::freqUpdateCallback: Changing counter "
180 "frequency\n");
181 if (_enabled)
182 updateValue();
183 _activeFreqEntry = _nextFreqEntry;
184 _freq = _freqTable[_activeFreqEntry];
185 _increment = _freqTable[0] / _freq;
186 _period = (1.0 / _freq) * SimClock::Frequency;
187 notifyListeners();
188 }
189
190 void
191 SystemCounter::registerListener(SystemCounterListener *listener)
192 {
193 _listeners.push_back(listener);
194 }
195
196 void
197 SystemCounter::notifyListeners() const
198 {
199 for (auto &listener : _listeners)
200 listener->notify();
201 }
202
203 void
204 SystemCounter::serialize(CheckpointOut &cp) const
205 {
206 DPRINTF(Timer, "SystemCounter::serialize: Serializing\n");
207 SERIALIZE_SCALAR(_enabled);
208 SERIALIZE_SCALAR(_freq);
209 SERIALIZE_SCALAR(_value);
210 SERIALIZE_SCALAR(_increment);
211 SERIALIZE_CONTAINER(_freqTable);
212 SERIALIZE_SCALAR(_activeFreqEntry);
213 SERIALIZE_SCALAR(_updateTick);
214 bool pending_freq_update = _freqUpdateEvent.scheduled();
215 SERIALIZE_SCALAR(pending_freq_update);
216 if (pending_freq_update) {
217 Tick when_freq_update = _freqUpdateEvent.when();
218 SERIALIZE_SCALAR(when_freq_update);
219 }
220 SERIALIZE_SCALAR(_nextFreqEntry);
221 }
222
223 void
224 SystemCounter::unserialize(CheckpointIn &cp)
225 {
226 DPRINTF(Timer, "SystemCounter::unserialize: Unserializing\n");
227 UNSERIALIZE_SCALAR(_enabled);
228 UNSERIALIZE_SCALAR(_freq);
229 UNSERIALIZE_SCALAR(_value);
230 UNSERIALIZE_SCALAR(_increment);
231 UNSERIALIZE_CONTAINER(_freqTable);
232 UNSERIALIZE_SCALAR(_activeFreqEntry);
233 UNSERIALIZE_SCALAR(_updateTick);
234 bool pending_freq_update;
235 UNSERIALIZE_SCALAR(pending_freq_update);
236 if (pending_freq_update) {
237 Tick when_freq_update;
238 UNSERIALIZE_SCALAR(when_freq_update);
239 reschedule(_freqUpdateEvent, when_freq_update, true);
240 }
241 UNSERIALIZE_SCALAR(_nextFreqEntry);
242
243 _period = (1.0 / _freq) * SimClock::Frequency;
244 }
245
246 ArchTimer::ArchTimer(const std::string &name,
247 SimObject &parent,
248 SystemCounter &sysctr,
249 ArmInterruptPin *interrupt)
250 : _name(name), _parent(parent), _systemCounter(sysctr),
251 _interrupt(interrupt),
252 _control(0), _counterLimit(0), _offset(0),
253 _counterLimitReachedEvent([this]{ counterLimitReached(); }, name)
254 {
255 _systemCounter.registerListener(this);
256 }
257
258 void
259 ArchTimer::counterLimitReached()
260 {
261 if (!_control.enable)
262 return;
263
264 DPRINTF(Timer, "Counter limit reached\n");
265 _control.istatus = 1;
266 if (!_control.imask) {
267 if (scheduleEvents()) {
268 DPRINTF(Timer, "Causing interrupt\n");
269 _interrupt->raise();
270 } else {
271 DPRINTF(Timer, "Kvm mode; skipping simulated interrupt\n");
272 }
273 }
274 }
275
276 void
277 ArchTimer::updateCounter()
278 {
279 if (_counterLimitReachedEvent.scheduled())
280 _parent.deschedule(_counterLimitReachedEvent);
281 if (value() >= _counterLimit) {
282 counterLimitReached();
283 } else {
284 // Clear the interurpt when timers conditions are not met
285 if (_interrupt->active()) {
286 DPRINTF(Timer, "Clearing interrupt\n");
287 _interrupt->clear();
288 }
289
290 _control.istatus = 0;
291
292 if (scheduleEvents()) {
293 _parent.schedule(_counterLimitReachedEvent,
294 whenValue(_counterLimit));
295 }
296 }
297 }
298
299 void
300 ArchTimer::setCompareValue(uint64_t val)
301 {
302 _counterLimit = val;
303 updateCounter();
304 }
305
306 void
307 ArchTimer::setTimerValue(uint32_t val)
308 {
309 setCompareValue(value() + sext<32>(val));
310 }
311
312 void
313 ArchTimer::setControl(uint32_t val)
314 {
315 ArchTimerCtrl old_ctl = _control, new_ctl = val;
316 _control.enable = new_ctl.enable;
317 _control.imask = new_ctl.imask;
318 _control.istatus = old_ctl.istatus;
319 // Timer unmasked or enabled
320 if ((old_ctl.imask && !new_ctl.imask) ||
321 (!old_ctl.enable && new_ctl.enable))
322 updateCounter();
323 // Timer masked or disabled
324 else if ((!old_ctl.imask && new_ctl.imask) ||
325 (old_ctl.enable && !new_ctl.enable)) {
326
327 if (_interrupt->active()) {
328 DPRINTF(Timer, "Clearing interrupt\n");
329 // We are clearing the interrupt but we are not
330 // setting istatus to 0 as we are doing
331 // in the updateCounter.
332 // istatus signals that Timer conditions are met.
333 // It shouldn't depend on masking.
334 // if enable is zero. istatus is unknown.
335 _interrupt->clear();
336 }
337 }
338 }
339
340 void
341 ArchTimer::setOffset(uint64_t val)
342 {
343 _offset = val;
344 updateCounter();
345 }
346
347 uint64_t
348 ArchTimer::value() const
349 {
350 return _systemCounter.value() - _offset;
351 }
352
353 void
354 ArchTimer::notify()
355 {
356 updateCounter();
357 }
358
359 void
360 ArchTimer::serialize(CheckpointOut &cp) const
361 {
362 paramOut(cp, "control_serial", _control);
363 SERIALIZE_SCALAR(_counterLimit);
364 SERIALIZE_SCALAR(_offset);
365 }
366
367 void
368 ArchTimer::unserialize(CheckpointIn &cp)
369 {
370 paramIn(cp, "control_serial", _control);
371 // We didn't serialize an offset before we added support for the
372 // virtual timer. Consider it optional to maintain backwards
373 // compatibility.
374 if (!UNSERIALIZE_OPT_SCALAR(_offset))
375 _offset = 0;
376
377 // We no longer schedule an event here because we may enter KVM
378 // emulation. The event creation is delayed until drainResume().
379 }
380
381 DrainState
382 ArchTimer::drain()
383 {
384 if (_counterLimitReachedEvent.scheduled())
385 _parent.deschedule(_counterLimitReachedEvent);
386
387 return DrainState::Drained;
388 }
389
390 void
391 ArchTimer::drainResume()
392 {
393 updateCounter();
394 }
395
396 GenericTimer::GenericTimer(GenericTimerParams *const p)
397 : SimObject(p),
398 systemCounter(*p->counter),
399 system(*p->system)
400 {
401 SystemCounter::validateCounterRef(p->counter);
402 fatal_if(!p->system, "GenericTimer::GenericTimer: No system specified, "
403 "can't instantiate architected timers\n");
404 system.setGenericTimer(this);
405 }
406
407 const GenericTimerParams *
408 GenericTimer::params() const
409 {
410 return dynamic_cast<const GenericTimerParams *>(_params);
411 }
412
413 void
414 GenericTimer::serialize(CheckpointOut &cp) const
415 {
416 paramOut(cp, "cpu_count", timers.size());
417
418 for (int i = 0; i < timers.size(); ++i) {
419 const CoreTimers &core(*timers[i]);
420 core.serializeSection(cp, csprintf("pe_implementation%d", i));
421 }
422 }
423
424 void
425 GenericTimer::unserialize(CheckpointIn &cp)
426 {
427 // Try to unserialize the CPU count. Old versions of the timer
428 // model assumed a 8 CPUs, so we fall back to that if the field
429 // isn't present.
430 static const unsigned OLD_CPU_MAX = 8;
431 unsigned cpu_count;
432 if (!UNSERIALIZE_OPT_SCALAR(cpu_count)) {
433 warn("Checkpoint does not contain CPU count, assuming %i CPUs\n",
434 OLD_CPU_MAX);
435 cpu_count = OLD_CPU_MAX;
436 }
437
438 // We cannot assert for equality here because CPU timers are dynamically
439 // created on the first miscreg access. Therefore, if we take the checkpoint
440 // before any timer registers have been accessed, the number of counters
441 // is actually smaller than the total number of CPUs.
442 if (cpu_count > system.threads.size()) {
443 fatal("The simulated system has been initialized with %d CPUs, "
444 "but the Generic Timer checkpoint expects %d CPUs. Consider "
445 "restoring the checkpoint specifying %d CPUs.",
446 system.threads.size(), cpu_count, cpu_count);
447 }
448
449 for (int i = 0; i < cpu_count; ++i) {
450 CoreTimers &core(getTimers(i));
451 core.unserializeSection(cp, csprintf("pe_implementation%d", i));
452 }
453 }
454
455 GenericTimer::CoreTimers &
456 GenericTimer::getTimers(int cpu_id)
457 {
458 if (cpu_id >= timers.size())
459 createTimers(cpu_id + 1);
460
461 return *timers[cpu_id];
462 }
463
464 void
465 GenericTimer::createTimers(unsigned cpus)
466 {
467 assert(timers.size() < cpus);
468 auto p = static_cast<const GenericTimerParams *>(_params);
469
470 const unsigned old_cpu_count(timers.size());
471 timers.resize(cpus);
472 for (unsigned i = old_cpu_count; i < cpus; ++i) {
473
474 ThreadContext *tc = system.threads[i];
475
476 timers[i].reset(
477 new CoreTimers(*this, system, i,
478 p->int_phys_s->get(tc),
479 p->int_phys_ns->get(tc),
480 p->int_virt->get(tc),
481 p->int_hyp->get(tc)));
482 }
483 }
484
485 void
486 GenericTimer::handleStream(CoreTimers::EventStream *ev_stream,
487 ArchTimer *timer, RegVal old_cnt_ctl, RegVal cnt_ctl)
488 {
489 uint64_t evnten = bits(cnt_ctl, 2);
490 uint64_t old_evnten = bits(old_cnt_ctl, 2);
491 uint8_t old_trans_to = ev_stream->transitionTo;
492 uint8_t old_trans_bit = ev_stream->transitionBit;
493 ev_stream->transitionTo = !bits(cnt_ctl, 3);
494 ev_stream->transitionBit = bits(cnt_ctl, 7, 4);
495 // Reschedule the Event Stream if enabled and any change in
496 // configuration
497 if (evnten && ((old_evnten != evnten) ||
498 (old_trans_to != ev_stream->transitionTo) ||
499 (old_trans_bit != ev_stream->transitionBit))) {
500
501 Tick when = timer->whenValue(
502 ev_stream->eventTargetValue(timer->value()));
503 reschedule(ev_stream->event, when, true);
504 } else if (old_evnten && !evnten) {
505 // Event Stream generation disabled
506 if (ev_stream->event.scheduled())
507 deschedule(ev_stream->event);
508 }
509 }
510
511 void
512 GenericTimer::setMiscReg(int reg, unsigned cpu, RegVal val)
513 {
514 CoreTimers &core(getTimers(cpu));
515 ThreadContext *tc = system.threads[cpu];
516
517 switch (reg) {
518 case MISCREG_CNTFRQ:
519 case MISCREG_CNTFRQ_EL0:
520 core.cntfrq = val;
521 warn_if(core.cntfrq != systemCounter.freq(), "CNTFRQ configured freq "
522 "does not match the system counter freq\n");
523 return;
524 case MISCREG_CNTKCTL:
525 case MISCREG_CNTKCTL_EL1:
526 {
527 if (ELIsInHost(tc, currEL(tc))) {
528 tc->setMiscReg(MISCREG_CNTHCTL_EL2, val);
529 return;
530 }
531 RegVal old_cnt_ctl = core.cntkctl;
532 core.cntkctl = val;
533
534 ArchTimer *timer = &core.virt;
535 CoreTimers::EventStream *ev_stream = &core.virtEvStream;
536
537 handleStream(ev_stream, timer, old_cnt_ctl, val);
538 return;
539 }
540 case MISCREG_CNTHCTL:
541 case MISCREG_CNTHCTL_EL2:
542 {
543 RegVal old_cnt_ctl = core.cnthctl;
544 core.cnthctl = val;
545
546 ArchTimer *timer = &core.physNS;
547 CoreTimers::EventStream *ev_stream = &core.physEvStream;
548
549 handleStream(ev_stream, timer, old_cnt_ctl, val);
550 return;
551 }
552 // Physical timer (NS)
553 case MISCREG_CNTP_CVAL_NS:
554 case MISCREG_CNTP_CVAL_EL0:
555 core.physNS.setCompareValue(val);
556 return;
557
558 case MISCREG_CNTP_TVAL_NS:
559 case MISCREG_CNTP_TVAL_EL0:
560 core.physNS.setTimerValue(val);
561 return;
562
563 case MISCREG_CNTP_CTL_NS:
564 case MISCREG_CNTP_CTL_EL0:
565 core.physNS.setControl(val);
566 return;
567
568 // Count registers
569 case MISCREG_CNTPCT:
570 case MISCREG_CNTPCT_EL0:
571 case MISCREG_CNTVCT:
572 case MISCREG_CNTVCT_EL0:
573 warn("Ignoring write to read only count register: %s\n",
574 miscRegName[reg]);
575 return;
576
577 // Virtual timer
578 case MISCREG_CNTVOFF:
579 case MISCREG_CNTVOFF_EL2:
580 core.virt.setOffset(val);
581 return;
582
583 case MISCREG_CNTV_CVAL:
584 case MISCREG_CNTV_CVAL_EL0:
585 core.virt.setCompareValue(val);
586 return;
587
588 case MISCREG_CNTV_TVAL:
589 case MISCREG_CNTV_TVAL_EL0:
590 core.virt.setTimerValue(val);
591 return;
592
593 case MISCREG_CNTV_CTL:
594 case MISCREG_CNTV_CTL_EL0:
595 core.virt.setControl(val);
596 return;
597
598 // Physical timer (S)
599 case MISCREG_CNTP_CTL_S:
600 case MISCREG_CNTPS_CTL_EL1:
601 core.physS.setControl(val);
602 return;
603
604 case MISCREG_CNTP_CVAL_S:
605 case MISCREG_CNTPS_CVAL_EL1:
606 core.physS.setCompareValue(val);
607 return;
608
609 case MISCREG_CNTP_TVAL_S:
610 case MISCREG_CNTPS_TVAL_EL1:
611 core.physS.setTimerValue(val);
612 return;
613
614 // Hyp phys. timer, non-secure
615 case MISCREG_CNTHP_CTL:
616 case MISCREG_CNTHP_CTL_EL2:
617 core.hyp.setControl(val);
618 return;
619
620 case MISCREG_CNTHP_CVAL:
621 case MISCREG_CNTHP_CVAL_EL2:
622 core.hyp.setCompareValue(val);
623 return;
624
625 case MISCREG_CNTHP_TVAL:
626 case MISCREG_CNTHP_TVAL_EL2:
627 core.hyp.setTimerValue(val);
628 return;
629
630 default:
631 warn("Writing to unknown register: %s\n", miscRegName[reg]);
632 return;
633 }
634 }
635
636
637 RegVal
638 GenericTimer::readMiscReg(int reg, unsigned cpu)
639 {
640 CoreTimers &core(getTimers(cpu));
641
642 switch (reg) {
643 case MISCREG_CNTFRQ:
644 case MISCREG_CNTFRQ_EL0:
645 return core.cntfrq;
646 case MISCREG_CNTKCTL:
647 case MISCREG_CNTKCTL_EL1:
648 return core.cntkctl & 0x00000000ffffffff;
649 case MISCREG_CNTHCTL:
650 case MISCREG_CNTHCTL_EL2:
651 return core.cnthctl & 0x00000000ffffffff;
652 // Physical timer
653 case MISCREG_CNTP_CVAL_NS:
654 case MISCREG_CNTP_CVAL_EL0:
655 return core.physNS.compareValue();
656
657 case MISCREG_CNTP_TVAL_NS:
658 case MISCREG_CNTP_TVAL_EL0:
659 return core.physNS.timerValue();
660
661 case MISCREG_CNTP_CTL_EL0:
662 case MISCREG_CNTP_CTL_NS:
663 return core.physNS.control();
664
665 case MISCREG_CNTPCT:
666 case MISCREG_CNTPCT_EL0:
667 return core.physNS.value();
668
669
670 // Virtual timer
671 case MISCREG_CNTVCT:
672 case MISCREG_CNTVCT_EL0:
673 return core.virt.value();
674
675 case MISCREG_CNTVOFF:
676 case MISCREG_CNTVOFF_EL2:
677 return core.virt.offset();
678
679 case MISCREG_CNTV_CVAL:
680 case MISCREG_CNTV_CVAL_EL0:
681 return core.virt.compareValue();
682
683 case MISCREG_CNTV_TVAL:
684 case MISCREG_CNTV_TVAL_EL0:
685 return core.virt.timerValue();
686
687 case MISCREG_CNTV_CTL:
688 case MISCREG_CNTV_CTL_EL0:
689 return core.virt.control();
690
691 // PL1 phys. timer, secure
692 case MISCREG_CNTP_CTL_S:
693 case MISCREG_CNTPS_CTL_EL1:
694 return core.physS.control();
695
696 case MISCREG_CNTP_CVAL_S:
697 case MISCREG_CNTPS_CVAL_EL1:
698 return core.physS.compareValue();
699
700 case MISCREG_CNTP_TVAL_S:
701 case MISCREG_CNTPS_TVAL_EL1:
702 return core.physS.timerValue();
703
704 // HYP phys. timer (NS)
705 case MISCREG_CNTHP_CTL:
706 case MISCREG_CNTHP_CTL_EL2:
707 return core.hyp.control();
708
709 case MISCREG_CNTHP_CVAL:
710 case MISCREG_CNTHP_CVAL_EL2:
711 return core.hyp.compareValue();
712
713 case MISCREG_CNTHP_TVAL:
714 case MISCREG_CNTHP_TVAL_EL2:
715 return core.hyp.timerValue();
716
717 default:
718 warn("Reading from unknown register: %s\n", miscRegName[reg]);
719 return 0;
720 }
721 }
722
723 GenericTimer::CoreTimers::CoreTimers(GenericTimer &_parent,
724 ArmSystem &system, unsigned cpu,
725 ArmInterruptPin *_irqPhysS, ArmInterruptPin *_irqPhysNS,
726 ArmInterruptPin *_irqVirt, ArmInterruptPin *_irqHyp)
727 : parent(_parent),
728 cntfrq(parent.params()->cntfrq),
729 threadContext(system.threads[cpu]),
730 irqPhysS(_irqPhysS),
731 irqPhysNS(_irqPhysNS),
732 irqVirt(_irqVirt),
733 irqHyp(_irqHyp),
734 physS(csprintf("%s.phys_s_timer%d", parent.name(), cpu),
735 system, parent, parent.systemCounter,
736 _irqPhysS),
737 // This should really be phys_timerN, but we are stuck with
738 // arch_timer for backwards compatibility.
739 physNS(csprintf("%s.arch_timer%d", parent.name(), cpu),
740 system, parent, parent.systemCounter,
741 _irqPhysNS),
742 virt(csprintf("%s.virt_timer%d", parent.name(), cpu),
743 system, parent, parent.systemCounter,
744 _irqVirt),
745 hyp(csprintf("%s.hyp_timer%d", parent.name(), cpu),
746 system, parent, parent.systemCounter,
747 _irqHyp),
748 physEvStream{
749 EventFunctionWrapper([this]{ physEventStreamCallback(); },
750 csprintf("%s.phys_event_gen%d", parent.name(), cpu)), 0, 0
751 },
752 virtEvStream{
753 EventFunctionWrapper([this]{ virtEventStreamCallback(); },
754 csprintf("%s.virt_event_gen%d", parent.name(), cpu)), 0, 0
755 }
756 {
757 }
758
759 void
760 GenericTimer::CoreTimers::physEventStreamCallback()
761 {
762 eventStreamCallback();
763 schedNextEvent(physEvStream, physNS);
764 }
765
766 void
767 GenericTimer::CoreTimers::virtEventStreamCallback()
768 {
769 eventStreamCallback();
770 schedNextEvent(virtEvStream, virt);
771 }
772
773 void
774 GenericTimer::CoreTimers::eventStreamCallback() const
775 {
776 sendEvent(threadContext);
777 threadContext->getCpuPtr()->wakeup(threadContext->threadId());
778 }
779
780 void
781 GenericTimer::CoreTimers::schedNextEvent(EventStream &ev_stream,
782 ArchTimer &timer)
783 {
784 parent.reschedule(ev_stream.event, timer.whenValue(
785 ev_stream.eventTargetValue(timer.value())), true);
786 }
787
788 void
789 GenericTimer::CoreTimers::notify()
790 {
791 schedNextEvent(virtEvStream, virt);
792 schedNextEvent(physEvStream, physNS);
793 }
794
795 void
796 GenericTimer::CoreTimers::serialize(CheckpointOut &cp) const
797 {
798 SERIALIZE_SCALAR(cntfrq);
799 SERIALIZE_SCALAR(cntkctl);
800 SERIALIZE_SCALAR(cnthctl);
801
802 const bool phys_ev_scheduled = physEvStream.event.scheduled();
803 SERIALIZE_SCALAR(phys_ev_scheduled);
804 if (phys_ev_scheduled) {
805 const Tick phys_ev_when = physEvStream.event.when();
806 SERIALIZE_SCALAR(phys_ev_when);
807 }
808 SERIALIZE_SCALAR(physEvStream.transitionTo);
809 SERIALIZE_SCALAR(physEvStream.transitionBit);
810
811 const bool virt_ev_scheduled = virtEvStream.event.scheduled();
812 SERIALIZE_SCALAR(virt_ev_scheduled);
813 if (virt_ev_scheduled) {
814 const Tick virt_ev_when = virtEvStream.event.when();
815 SERIALIZE_SCALAR(virt_ev_when);
816 }
817 SERIALIZE_SCALAR(virtEvStream.transitionTo);
818 SERIALIZE_SCALAR(virtEvStream.transitionBit);
819
820 physS.serializeSection(cp, "phys_s_timer");
821 physNS.serializeSection(cp, "phys_ns_timer");
822 virt.serializeSection(cp, "virt_timer");
823 hyp.serializeSection(cp, "hyp_timer");
824 }
825
826 void
827 GenericTimer::CoreTimers::unserialize(CheckpointIn &cp)
828 {
829 UNSERIALIZE_SCALAR(cntfrq);
830 UNSERIALIZE_SCALAR(cntkctl);
831 UNSERIALIZE_SCALAR(cnthctl);
832
833 bool phys_ev_scheduled;
834 UNSERIALIZE_SCALAR(phys_ev_scheduled);
835 if (phys_ev_scheduled) {
836 Tick phys_ev_when;
837 UNSERIALIZE_SCALAR(phys_ev_when);
838 parent.reschedule(physEvStream.event, phys_ev_when, true);
839 }
840 UNSERIALIZE_SCALAR(physEvStream.transitionTo);
841 UNSERIALIZE_SCALAR(physEvStream.transitionBit);
842
843 bool virt_ev_scheduled;
844 UNSERIALIZE_SCALAR(virt_ev_scheduled);
845 if (virt_ev_scheduled) {
846 Tick virt_ev_when;
847 UNSERIALIZE_SCALAR(virt_ev_when);
848 parent.reschedule(virtEvStream.event, virt_ev_when, true);
849 }
850 UNSERIALIZE_SCALAR(virtEvStream.transitionTo);
851 UNSERIALIZE_SCALAR(virtEvStream.transitionBit);
852
853 physS.unserializeSection(cp, "phys_s_timer");
854 physNS.unserializeSection(cp, "phys_ns_timer");
855 virt.unserializeSection(cp, "virt_timer");
856 hyp.unserializeSection(cp, "hyp_timer");
857 }
858
859 void
860 GenericTimerISA::setMiscReg(int reg, RegVal val)
861 {
862 DPRINTF(Timer, "Setting %s := 0x%x\n", miscRegName[reg], val);
863 parent.setMiscReg(reg, cpu, val);
864 }
865
866 RegVal
867 GenericTimerISA::readMiscReg(int reg)
868 {
869 RegVal value = parent.readMiscReg(reg, cpu);
870 DPRINTF(Timer, "Reading %s as 0x%x\n", miscRegName[reg], value);
871 return value;
872 }
873
874 GenericTimerFrame::GenericTimerFrame(GenericTimerFrameParams *const p)
875 : PioDevice(p),
876 timerRange(RangeSize(p->cnt_base, ArmSystem::PageBytes)),
877 addrRanges({timerRange}),
878 systemCounter(*p->counter),
879 physTimer(csprintf("%s.phys_timer", name()),
880 *this, systemCounter, p->int_phys->get()),
881 virtTimer(csprintf("%s.virt_timer", name()),
882 *this, systemCounter,
883 p->int_virt->get()),
884 accessBits(0x3f),
885 system(*dynamic_cast<ArmSystem *>(sys))
886 {
887 SystemCounter::validateCounterRef(p->counter);
888 // Expose optional CNTEL0Base register frame
889 if (p->cnt_el0_base != MaxAddr) {
890 timerEl0Range = RangeSize(p->cnt_el0_base, ArmSystem::PageBytes);
891 accessBitsEl0 = 0x303;
892 addrRanges.push_back(timerEl0Range);
893 }
894 for (auto &range : addrRanges)
895 GenericTimerMem::validateFrameRange(range);
896 }
897
898 void
899 GenericTimerFrame::serialize(CheckpointOut &cp) const
900 {
901 SERIALIZE_SCALAR(accessBits);
902 if (hasEl0View())
903 SERIALIZE_SCALAR(accessBitsEl0);
904 SERIALIZE_SCALAR(nonSecureAccess);
905
906 physTimer.serializeSection(cp, "phys_timer");
907 virtTimer.serializeSection(cp, "virt_timer");
908 }
909
910 void
911 GenericTimerFrame::unserialize(CheckpointIn &cp)
912 {
913 UNSERIALIZE_SCALAR(accessBits);
914 if (hasEl0View())
915 UNSERIALIZE_SCALAR(accessBitsEl0);
916 UNSERIALIZE_SCALAR(nonSecureAccess);
917
918 physTimer.unserializeSection(cp, "phys_timer");
919 virtTimer.unserializeSection(cp, "virt_timer");
920 }
921
922 uint64_t
923 GenericTimerFrame::getVirtOffset() const
924 {
925 return virtTimer.offset();
926 }
927
928 void
929 GenericTimerFrame::setVirtOffset(uint64_t new_offset)
930 {
931 virtTimer.setOffset(new_offset);
932 }
933
934 bool
935 GenericTimerFrame::hasEl0View() const
936 {
937 return timerEl0Range.valid();
938 }
939
940 uint8_t
941 GenericTimerFrame::getAccessBits() const
942 {
943 return accessBits;
944 }
945
946 void
947 GenericTimerFrame::setAccessBits(uint8_t data)
948 {
949 accessBits = data & 0x3f;
950 }
951
952 bool
953 GenericTimerFrame::hasNonSecureAccess() const
954 {
955 return nonSecureAccess;
956 }
957
958 void
959 GenericTimerFrame::setNonSecureAccess()
960 {
961 nonSecureAccess = true;
962 }
963
964 bool
965 GenericTimerFrame::hasReadableVoff() const
966 {
967 return accessBits.rvoff;
968 }
969
970 AddrRangeList
971 GenericTimerFrame::getAddrRanges() const
972 {
973 return addrRanges;
974 }
975
976 Tick
977 GenericTimerFrame::read(PacketPtr pkt)
978 {
979 const Addr addr = pkt->getAddr();
980 const size_t size = pkt->getSize();
981 const bool is_sec = pkt->isSecure();
982 panic_if(size != 4 && size != 8,
983 "GenericTimerFrame::read: Invalid size %i\n", size);
984
985 bool to_el0 = false;
986 uint64_t resp = 0;
987 Addr offset = 0;
988 if (timerRange.contains(addr)) {
989 offset = addr - timerRange.start();
990 } else if (hasEl0View() && timerEl0Range.contains(addr)) {
991 offset = addr - timerEl0Range.start();
992 to_el0 = true;
993 } else {
994 panic("GenericTimerFrame::read: Invalid address: 0x%x\n", addr);
995 }
996
997 resp = timerRead(offset, size, is_sec, to_el0);
998
999 DPRINTF(Timer, "GenericTimerFrame::read: 0x%x<-0x%x(%i) [S = %u]\n", resp,
1000 addr, size, is_sec);
1001
1002 pkt->setUintX(resp, ByteOrder::little);
1003 pkt->makeResponse();
1004 return 0;
1005 }
1006
1007 Tick
1008 GenericTimerFrame::write(PacketPtr pkt)
1009 {
1010 const Addr addr = pkt->getAddr();
1011 const size_t size = pkt->getSize();
1012 const bool is_sec = pkt->isSecure();
1013 panic_if(size != 4 && size != 8,
1014 "GenericTimerFrame::write: Invalid size %i\n", size);
1015
1016 bool to_el0 = false;
1017 const uint64_t data = pkt->getUintX(ByteOrder::little);
1018 Addr offset = 0;
1019 if (timerRange.contains(addr)) {
1020 offset = addr - timerRange.start();
1021 } else if (hasEl0View() && timerEl0Range.contains(addr)) {
1022 offset = addr - timerEl0Range.start();
1023 to_el0 = true;
1024 } else {
1025 panic("GenericTimerFrame::write: Invalid address: 0x%x\n", addr);
1026 }
1027
1028 timerWrite(offset, size, data, is_sec, to_el0);
1029
1030 DPRINTF(Timer, "GenericTimerFrame::write: 0x%x->0x%x(%i) [S = %u]\n", data,
1031 addr, size, is_sec);
1032
1033 pkt->makeResponse();
1034 return 0;
1035 }
1036
1037 uint64_t
1038 GenericTimerFrame::timerRead(Addr addr, size_t size, bool is_sec,
1039 bool to_el0) const
1040 {
1041 if (!GenericTimerMem::validateAccessPerm(system, is_sec) &&
1042 !nonSecureAccess)
1043 return 0;
1044
1045 switch (addr) {
1046 case TIMER_CNTPCT_LO:
1047 if (!accessBits.rpct || (to_el0 && !accessBitsEl0.pcten))
1048 return 0;
1049 else
1050 return physTimer.value();
1051
1052 case TIMER_CNTPCT_HI:
1053 if (!accessBits.rpct || (to_el0 && !accessBitsEl0.pcten))
1054 return 0;
1055 else
1056 return physTimer.value() >> 32;
1057
1058 case TIMER_CNTFRQ:
1059 if ((!accessBits.rfrq) ||
1060 (to_el0 && (!accessBitsEl0.pcten && !accessBitsEl0.vcten)))
1061 return 0;
1062 else
1063 return systemCounter.freq();
1064
1065 case TIMER_CNTEL0ACR:
1066 if (!hasEl0View() || to_el0)
1067 return 0;
1068 else
1069 return accessBitsEl0;
1070
1071 case TIMER_CNTP_CVAL_LO:
1072 if (!accessBits.rwpt || (to_el0 && !accessBitsEl0.pten))
1073 return 0;
1074 else
1075 return physTimer.compareValue();
1076
1077 case TIMER_CNTP_CVAL_HI:
1078 if (!accessBits.rwpt || (to_el0 && !accessBitsEl0.pten))
1079 return 0;
1080 else
1081 return physTimer.compareValue() >> 32;
1082
1083 case TIMER_CNTP_TVAL:
1084 if (!accessBits.rwpt || (to_el0 && !accessBitsEl0.pten))
1085 return 0;
1086 else
1087 return physTimer.timerValue();
1088 case TIMER_CNTP_CTL:
1089 if (!accessBits.rwpt || (to_el0 && !accessBitsEl0.pten))
1090 return 0;
1091 else
1092 return physTimer.control();
1093
1094 case TIMER_CNTVCT_LO:
1095 if (!accessBits.rvct || (to_el0 && !accessBitsEl0.vcten))
1096 return 0;
1097 else
1098 return virtTimer.value();
1099
1100 case TIMER_CNTVCT_HI:
1101 if (!accessBits.rvct || (to_el0 && !accessBitsEl0.vcten))
1102 return 0;
1103 else
1104 return virtTimer.value() >> 32;
1105
1106 case TIMER_CNTVOFF_LO:
1107 if (!accessBits.rvoff || (to_el0))
1108 return 0;
1109 else
1110 return virtTimer.offset();
1111
1112 case TIMER_CNTVOFF_HI:
1113 if (!accessBits.rvoff || (to_el0))
1114 return 0;
1115 else
1116 return virtTimer.offset() >> 32;
1117
1118 case TIMER_CNTV_CVAL_LO:
1119 if (!accessBits.rwvt || (to_el0 && !accessBitsEl0.vten))
1120 return 0;
1121 else
1122 return virtTimer.compareValue();
1123
1124 case TIMER_CNTV_CVAL_HI:
1125 if (!accessBits.rwvt || (to_el0 && !accessBitsEl0.vten))
1126 return 0;
1127 else
1128 return virtTimer.compareValue() >> 32;
1129
1130 case TIMER_CNTV_TVAL:
1131 if (!accessBits.rwvt || (to_el0 && !accessBitsEl0.vten))
1132 return 0;
1133 else
1134 return virtTimer.timerValue();
1135
1136 case TIMER_CNTV_CTL:
1137 if (!accessBits.rwvt || (to_el0 && !accessBitsEl0.vten))
1138 return 0;
1139 else
1140 return virtTimer.control();
1141
1142 default:
1143 warn("GenericTimerFrame::timerRead: Unexpected address (0x%x:%i), "
1144 "assuming RAZ\n", addr, size);
1145 return 0;
1146 }
1147 }
1148
1149 void
1150 GenericTimerFrame::timerWrite(Addr addr, size_t size, uint64_t data,
1151 bool is_sec, bool to_el0)
1152 {
1153 if (!GenericTimerMem::validateAccessPerm(system, is_sec) &&
1154 !nonSecureAccess)
1155 return;
1156
1157 switch (addr) {
1158 case TIMER_CNTPCT_LO ... TIMER_CNTPCT_HI:
1159 warn("GenericTimerFrame::timerWrite: RO reg (0x%x) [CNTPCT]\n",
1160 addr);
1161 return;
1162
1163 case TIMER_CNTFRQ:
1164 warn("GenericTimerFrame::timerWrite: RO reg (0x%x) [CNTFRQ]\n",
1165 addr);
1166 return;
1167
1168 case TIMER_CNTEL0ACR:
1169 if (!hasEl0View() || to_el0)
1170 return;
1171
1172 insertBits(accessBitsEl0, 9, 8, data);
1173 insertBits(accessBitsEl0, 1, 0, data);
1174 return;
1175
1176 case TIMER_CNTP_CVAL_LO:
1177 if ((!accessBits.rwpt) || (to_el0 && !accessBitsEl0.pten))
1178 return;
1179 data = size == 4 ? insertBits(physTimer.compareValue(),
1180 31, 0, data) : data;
1181 physTimer.setCompareValue(data);
1182 return;
1183
1184 case TIMER_CNTP_CVAL_HI:
1185 if ((!accessBits.rwpt) || (to_el0 && !accessBitsEl0.pten))
1186 return;
1187 data = insertBits(physTimer.compareValue(), 63, 32, data);
1188 physTimer.setCompareValue(data);
1189 return;
1190
1191 case TIMER_CNTP_TVAL:
1192 if ((!accessBits.rwpt) || (to_el0 && !accessBitsEl0.pten))
1193 return;
1194 physTimer.setTimerValue(data);
1195 return;
1196
1197 case TIMER_CNTP_CTL:
1198 if ((!accessBits.rwpt) || (to_el0 && !accessBitsEl0.pten))
1199 return;
1200 physTimer.setControl(data);
1201 return;
1202
1203 case TIMER_CNTVCT_LO ... TIMER_CNTVCT_HI:
1204 warn("GenericTimerFrame::timerWrite: RO reg (0x%x) [CNTVCT]\n",
1205 addr);
1206 return;
1207 case TIMER_CNTVOFF_LO ... TIMER_CNTVOFF_HI:
1208 warn("GenericTimerFrame::timerWrite: RO reg (0x%x) [CNTVOFF]\n",
1209 addr);
1210 return;
1211
1212 case TIMER_CNTV_CVAL_LO:
1213 if ((!accessBits.rwvt) || (to_el0 && !accessBitsEl0.vten))
1214 return;
1215 data = size == 4 ? insertBits(virtTimer.compareValue(),
1216 31, 0, data) : data;
1217 virtTimer.setCompareValue(data);
1218 return;
1219
1220 case TIMER_CNTV_CVAL_HI:
1221 if ((!accessBits.rwvt) || (to_el0 && !accessBitsEl0.vten))
1222 return;
1223 data = insertBits(virtTimer.compareValue(), 63, 32, data);
1224 virtTimer.setCompareValue(data);
1225 return;
1226
1227 case TIMER_CNTV_TVAL:
1228 if ((!accessBits.rwvt) || (to_el0 && !accessBitsEl0.vten))
1229 return;
1230 virtTimer.setTimerValue(data);
1231 return;
1232
1233 case TIMER_CNTV_CTL:
1234 if ((!accessBits.rwvt) || (to_el0 && !accessBitsEl0.vten))
1235 return;
1236 virtTimer.setControl(data);
1237 return;
1238
1239 default:
1240 warn("GenericTimerFrame::timerWrite: Unexpected address (0x%x:%i), "
1241 "assuming WI\n", addr, size);
1242 }
1243 }
1244
1245 GenericTimerMem::GenericTimerMem(GenericTimerMemParams *const p)
1246 : PioDevice(p),
1247 counterCtrlRange(RangeSize(p->cnt_control_base, ArmSystem::PageBytes)),
1248 counterStatusRange(RangeSize(p->cnt_read_base, ArmSystem::PageBytes)),
1249 timerCtrlRange(RangeSize(p->cnt_ctl_base, ArmSystem::PageBytes)),
1250 cnttidr(0x0),
1251 addrRanges{counterCtrlRange, counterStatusRange, timerCtrlRange},
1252 systemCounter(*p->counter),
1253 frames(p->frames),
1254 system(*dynamic_cast<ArmSystem *>(sys))
1255 {
1256 SystemCounter::validateCounterRef(p->counter);
1257 for (auto &range : addrRanges)
1258 GenericTimerMem::validateFrameRange(range);
1259 fatal_if(frames.size() > MAX_TIMER_FRAMES,
1260 "GenericTimerMem::GenericTimerMem: Architecture states a maximum of "
1261 "8 memory-mapped timer frames, limit surpassed\n");
1262 // Initialize CNTTIDR with each frame's features
1263 for (int i = 0; i < frames.size(); i++) {
1264 uint32_t features = 0x1;
1265 features |= 0x2;
1266 if (frames[i]->hasEl0View())
1267 features |= 0x4;
1268 features <<= i * 4;
1269 replaceBits(cnttidr, (i + 1) * 4 - 1, i * 4, features);
1270 }
1271 }
1272
1273 void
1274 GenericTimerMem::validateFrameRange(const AddrRange &range)
1275 {
1276 fatal_if(range.start() % ArmSystem::PageBytes,
1277 "GenericTimerMem::validateFrameRange: Architecture states each "
1278 "register frame should be in a separate memory page, specified "
1279 "range base address [0x%x] is not compliant\n");
1280 }
1281
1282 bool
1283 GenericTimerMem::validateAccessPerm(ArmSystem &sys, bool is_sec)
1284 {
1285 return !sys.haveSecurity() || is_sec;
1286 }
1287
1288 AddrRangeList
1289 GenericTimerMem::getAddrRanges() const
1290 {
1291 return addrRanges;
1292 }
1293
1294 Tick
1295 GenericTimerMem::read(PacketPtr pkt)
1296 {
1297 const Addr addr = pkt->getAddr();
1298 const size_t size = pkt->getSize();
1299 const bool is_sec = pkt->isSecure();
1300 panic_if(size != 4 && size != 8,
1301 "GenericTimerMem::read: Invalid size %i\n", size);
1302
1303 uint64_t resp = 0;
1304 if (counterCtrlRange.contains(addr))
1305 resp = counterCtrlRead(addr - counterCtrlRange.start(), size, is_sec);
1306 else if (counterStatusRange.contains(addr))
1307 resp = counterStatusRead(addr - counterStatusRange.start(), size);
1308 else if (timerCtrlRange.contains(addr))
1309 resp = timerCtrlRead(addr - timerCtrlRange.start(), size, is_sec);
1310 else
1311 panic("GenericTimerMem::read: Invalid address: 0x%x\n", addr);
1312
1313 DPRINTF(Timer, "GenericTimerMem::read: 0x%x<-0x%x(%i) [S = %u]\n", resp,
1314 addr, size, is_sec);
1315
1316 pkt->setUintX(resp, ByteOrder::little);
1317 pkt->makeResponse();
1318 return 0;
1319 }
1320
1321 Tick
1322 GenericTimerMem::write(PacketPtr pkt)
1323 {
1324 const Addr addr = pkt->getAddr();
1325 const size_t size = pkt->getSize();
1326 const bool is_sec = pkt->isSecure();
1327 panic_if(size != 4 && size != 8,
1328 "GenericTimerMem::write: Invalid size %i\n", size);
1329
1330 const uint64_t data = pkt->getUintX(ByteOrder::little);
1331 if (counterCtrlRange.contains(addr))
1332 counterCtrlWrite(addr - counterCtrlRange.start(), size, data, is_sec);
1333 else if (counterStatusRange.contains(addr))
1334 counterStatusWrite(addr - counterStatusRange.start(), size, data);
1335 else if (timerCtrlRange.contains(addr))
1336 timerCtrlWrite(addr - timerCtrlRange.start(), size, data, is_sec);
1337 else
1338 panic("GenericTimerMem::write: Invalid address: 0x%x\n", addr);
1339
1340 DPRINTF(Timer, "GenericTimerMem::write: 0x%x->0x%x(%i) [S = %u]\n", data,
1341 addr, size, is_sec);
1342
1343 pkt->makeResponse();
1344 return 0;
1345 }
1346
1347 uint64_t
1348 GenericTimerMem::counterCtrlRead(Addr addr, size_t size, bool is_sec) const
1349 {
1350 if (!GenericTimerMem::validateAccessPerm(system, is_sec))
1351 return 0;
1352 switch (addr) {
1353 case COUNTER_CTRL_CNTCR:
1354 {
1355 CNTCR cntcr = 0;
1356 cntcr.en = systemCounter.enabled();
1357 cntcr.fcreq = systemCounter.activeFreqEntry();
1358 return cntcr;
1359 }
1360 case COUNTER_CTRL_CNTSR:
1361 {
1362 CNTSR cntsr = 0;
1363 cntsr.fcack = systemCounter.activeFreqEntry();
1364 return cntsr;
1365 }
1366 case COUNTER_CTRL_CNTCV_LO: return systemCounter.value();
1367 case COUNTER_CTRL_CNTCV_HI: return systemCounter.value() >> 32;
1368 case COUNTER_CTRL_CNTSCR: return 0;
1369 case COUNTER_CTRL_CNTID: return 0;
1370 default:
1371 {
1372 auto &freq_table = systemCounter.freqTable();
1373 for (int i = 0; i < (freq_table.size() - 1); i++) {
1374 Addr offset = COUNTER_CTRL_CNTFID + (i * 0x4);
1375 if (addr == offset)
1376 return freq_table[i];
1377 }
1378 warn("GenericTimerMem::counterCtrlRead: Unexpected address "
1379 "(0x%x:%i), assuming RAZ\n", addr, size);
1380 return 0;
1381 }
1382 }
1383 }
1384
1385 void
1386 GenericTimerMem::counterCtrlWrite(Addr addr, size_t size, uint64_t data,
1387 bool is_sec)
1388 {
1389 if (!GenericTimerMem::validateAccessPerm(system, is_sec))
1390 return;
1391
1392 switch (addr) {
1393 case COUNTER_CTRL_CNTCR:
1394 {
1395 CNTCR val = data;
1396 if (!systemCounter.enabled() && val.en)
1397 systemCounter.enable();
1398 else if (systemCounter.enabled() && !val.en)
1399 systemCounter.disable();
1400
1401 if (val.hdbg)
1402 warn("GenericTimerMem::counterCtrlWrite: Halt-on-debug is not "
1403 "supported\n");
1404 if (val.scen)
1405 warn("GenericTimerMem::counterCtrlWrite: Counter Scaling is not "
1406 "supported\n");
1407 if (val.fcreq != systemCounter.activeFreqEntry())
1408 systemCounter.freqUpdateSchedule(val.fcreq);
1409 return;
1410 }
1411
1412 case COUNTER_CTRL_CNTSR:
1413 warn("GenericTimerMem::counterCtrlWrite: RO reg (0x%x) [CNTSR]\n",
1414 addr);
1415 return;
1416
1417 case COUNTER_CTRL_CNTCV_LO:
1418 data = size == 4 ? insertBits(systemCounter.value(), 31, 0, data)
1419 : data;
1420 systemCounter.setValue(data);
1421 return;
1422
1423 case COUNTER_CTRL_CNTCV_HI:
1424 data = insertBits(systemCounter.value(), 63, 32, data);
1425 systemCounter.setValue(data);
1426 return;
1427
1428 case COUNTER_CTRL_CNTSCR:
1429 return;
1430
1431 case COUNTER_CTRL_CNTID:
1432 warn("GenericTimerMem::counterCtrlWrite: RO reg (0x%x) [CNTID]\n",
1433 addr);
1434 return;
1435
1436 default:
1437 {
1438 auto &freq_table = systemCounter.freqTable();
1439 for (int i = 0; i < (freq_table.size() - 1); i++) {
1440 Addr offset = COUNTER_CTRL_CNTFID + (i * 0x4);
1441 if (addr == offset) {
1442 freq_table[i] = data;
1443 // This is changing the currently selected frequency
1444 if (i == systemCounter.activeFreqEntry()) {
1445 // We've changed the frequency in the table entry,
1446 // however the counter will still work with the
1447 // current one until transition is completed
1448 systemCounter.freqUpdateSchedule(i);
1449 }
1450 return;
1451 }
1452 }
1453 warn("GenericTimerMem::counterCtrlWrite: Unexpected address "
1454 "(0x%x:%i), assuming WI\n", addr, size);
1455 }
1456 }
1457 }
1458
1459 uint64_t
1460 GenericTimerMem::counterStatusRead(Addr addr, size_t size) const
1461 {
1462 switch (addr) {
1463 case COUNTER_STATUS_CNTCV_LO: return systemCounter.value();
1464 case COUNTER_STATUS_CNTCV_HI: return systemCounter.value() >> 32;
1465 default:
1466 warn("GenericTimerMem::counterStatusRead: Unexpected address "
1467 "(0x%x:%i), assuming RAZ\n", addr, size);
1468 return 0;
1469 }
1470 }
1471
1472 void
1473 GenericTimerMem::counterStatusWrite(Addr addr, size_t size, uint64_t data)
1474 {
1475 switch (addr) {
1476 case COUNTER_STATUS_CNTCV_LO ... COUNTER_STATUS_CNTCV_HI:
1477 warn("GenericTimerMem::counterStatusWrite: RO reg (0x%x) [CNTCV]\n",
1478 addr);
1479 return;
1480 default:
1481 warn("GenericTimerMem::counterStatusWrite: Unexpected address "
1482 "(0x%x:%i), assuming WI\n", addr, size);
1483 }
1484 }
1485
1486 uint64_t
1487 GenericTimerMem::timerCtrlRead(Addr addr, size_t size, bool is_sec) const
1488 {
1489 switch (addr) {
1490 case TIMER_CTRL_CNTFRQ:
1491 if (!GenericTimerMem::validateAccessPerm(system, is_sec)) return 0;
1492 return systemCounter.freq();
1493 case TIMER_CTRL_CNTNSAR:
1494 {
1495 if (!GenericTimerMem::validateAccessPerm(system, is_sec)) return 0;
1496 uint32_t cntnsar = 0x0;
1497 for (int i = 0; i < frames.size(); i++) {
1498 if (frames[i]->hasNonSecureAccess())
1499 cntnsar |= 0x1 << i;
1500 }
1501 return cntnsar;
1502 }
1503 case TIMER_CTRL_CNTTIDR: return cnttidr;
1504 default:
1505 for (int i = 0; i < frames.size(); i++) {
1506 Addr cntacr_off = TIMER_CTRL_CNTACR + (i * 0x4);
1507 Addr cntvoff_lo_off = TIMER_CTRL_CNTVOFF_LO + (i * 0x4);
1508 Addr cntvoff_hi_off = TIMER_CTRL_CNTVOFF_HI + (i * 0x4);
1509 // CNTNSAR.NS determines if CNTACR/CNTVOFF are accessible from
1510 // normal world
1511 bool hit = addr == cntacr_off || addr == cntvoff_lo_off ||
1512 addr == cntvoff_hi_off;
1513 bool has_access =
1514 GenericTimerMem::validateAccessPerm(system, is_sec) ||
1515 frames[i]->hasNonSecureAccess();
1516 if (hit && !has_access) return 0;
1517 if (addr == cntacr_off)
1518 return frames[i]->getAccessBits();
1519 if (addr == cntvoff_lo_off || addr == cntvoff_hi_off) {
1520 return addr == cntvoff_lo_off ? frames[i]->getVirtOffset()
1521 : frames[i]->getVirtOffset() >> 32;
1522 }
1523 }
1524 warn("GenericTimerMem::timerCtrlRead: Unexpected address (0x%x:%i), "
1525 "assuming RAZ\n", addr, size);
1526 return 0;
1527 }
1528 }
1529
1530 void
1531 GenericTimerMem::timerCtrlWrite(Addr addr, size_t size, uint64_t data,
1532 bool is_sec)
1533 {
1534 switch (addr) {
1535 case TIMER_CTRL_CNTFRQ:
1536 if (!GenericTimerMem::validateAccessPerm(system, is_sec)) return;
1537 warn_if(data != systemCounter.freq(),
1538 "GenericTimerMem::timerCtrlWrite: CNTFRQ configured freq "
1539 "does not match the counter freq, ignoring\n");
1540 return;
1541 case TIMER_CTRL_CNTNSAR:
1542 if (!GenericTimerMem::validateAccessPerm(system, is_sec)) return;
1543 for (int i = 0; i < frames.size(); i++) {
1544 // Check if the CNTNSAR.NS bit is set for this frame
1545 if (data & (0x1 << i))
1546 frames[i]->setNonSecureAccess();
1547 }
1548 return;
1549 case TIMER_CTRL_CNTTIDR:
1550 warn("GenericTimerMem::timerCtrlWrite: RO reg (0x%x) [CNTTIDR]\n",
1551 addr);
1552 return;
1553 default:
1554 for (int i = 0; i < frames.size(); i++) {
1555 Addr cntacr_off = TIMER_CTRL_CNTACR + (i * 0x4);
1556 Addr cntvoff_lo_off = TIMER_CTRL_CNTVOFF_LO + (i * 0x4);
1557 Addr cntvoff_hi_off = TIMER_CTRL_CNTVOFF_HI + (i * 0x4);
1558 // CNTNSAR.NS determines if CNTACR/CNTVOFF are accessible from
1559 // normal world
1560 bool hit = addr == cntacr_off || addr == cntvoff_lo_off ||
1561 addr == cntvoff_hi_off;
1562 bool has_access =
1563 GenericTimerMem::validateAccessPerm(system, is_sec) ||
1564 frames[i]->hasNonSecureAccess();
1565 if (hit && !has_access) return;
1566 if (addr == cntacr_off) {
1567 frames[i]->setAccessBits(data);
1568 return;
1569 }
1570 if (addr == cntvoff_lo_off || addr == cntvoff_hi_off) {
1571 if (addr == cntvoff_lo_off)
1572 data = size == 4 ? insertBits(frames[i]->getVirtOffset(),
1573 31, 0, data) : data;
1574 else
1575 data = insertBits(frames[i]->getVirtOffset(),
1576 63, 32, data);
1577 frames[i]->setVirtOffset(data);
1578 return;
1579 }
1580 }
1581 warn("GenericTimerMem::timerCtrlWrite: Unexpected address "
1582 "(0x%x:%i), assuming WI\n", addr, size);
1583 }
1584 }
1585
1586 SystemCounter *
1587 SystemCounterParams::create()
1588 {
1589 return new SystemCounter(this);
1590 }
1591
1592 GenericTimer *
1593 GenericTimerParams::create()
1594 {
1595 return new GenericTimer(this);
1596 }
1597
1598 GenericTimerFrame *
1599 GenericTimerFrameParams::create()
1600 {
1601 return new GenericTimerFrame(this);
1602 }
1603
1604 GenericTimerMem *
1605 GenericTimerMemParams::create()
1606 {
1607 return new GenericTimerMem(this);
1608 }