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