gem5  [DEVELOP-FOR-23.0]
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
generic_timer.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2013, 2015, 2017-2018,2020,2022 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 #include <string_view>
42 
43 #include "arch/arm/page_size.hh"
44 #include "arch/arm/system.hh"
45 #include "arch/arm/utility.hh"
46 #include "base/logging.hh"
47 #include "base/trace.hh"
48 #include "config/kvm_isa.hh"
49 #include "config/use_kvm.hh"
50 #include "cpu/base.hh"
51 #include "cpu/kvm/vm.hh"
52 #include "debug/Timer.hh"
53 #include "dev/arm/base_gic.hh"
54 #include "mem/packet_access.hh"
55 #include "params/GenericTimer.hh"
56 #include "params/GenericTimerFrame.hh"
57 #include "params/GenericTimerMem.hh"
58 #include "params/SystemCounter.hh"
59 #include "sim/core.hh"
60 #include "sim/cur_tick.hh"
61 
62 namespace gem5
63 {
64 
65 using namespace ArmISA;
66 
67 SystemCounter::SystemCounter(const SystemCounterParams &p)
68  : SimObject(p),
69  _enabled(true),
70  _value(0),
71  _increment(1),
72  _freqTable(p.freqs),
73  _activeFreqEntry(0),
74  _updateTick(0),
75  _freqUpdateEvent([this]{ freqUpdateCallback(); }, name()),
76  _nextFreqEntry(0)
77 {
78  fatal_if(_freqTable.empty(), "SystemCounter::SystemCounter: Base "
79  "frequency not provided\n");
80  // Store the table end marker as a 32-bit zero word
81  _freqTable.push_back(0);
83  "SystemCounter::SystemCounter: Architecture states a maximum of 1004 "
84  "frequency table entries, limit surpassed\n");
85  // Set the active frequency to be the base
86  _freq = _freqTable.front();
88 }
89 
90 void
92 {
93  fatal_if(!sys_cnt, "SystemCounter::validateCounterRef: No valid system "
94  "counter, can't instantiate system timers\n");
95 }
96 
97 void
99 {
100  DPRINTF(Timer, "SystemCounter::enable: Counter enabled\n");
101  _enabled = true;
102  updateTick();
103 }
104 
105 void
107 {
108  DPRINTF(Timer, "SystemCounter::disable: Counter disabled\n");
109  updateValue();
110  _enabled = false;
111 }
112 
113 uint64_t
115 {
116  if (_enabled)
117  updateValue();
118  return _value;
119 }
120 
121 void
123 {
124  uint64_t new_value =
126  if (new_value > _value) {
127  _value = new_value;
128  updateTick();
129  }
130 }
131 
132 void
133 SystemCounter::setValue(uint64_t new_value)
134 {
135  if (_enabled)
136  warn("Explicit value set with counter enabled, UNKNOWNN result\n");
137  _value = new_value;
138  updateTick();
139  notifyListeners();
140 }
141 
142 Tick
143 SystemCounter::whenValue(uint64_t cur_val, uint64_t target_val) const
144 {
145  Tick when = curTick();
146  if (target_val > cur_val) {
147  uint64_t num_cycles =
148  std::ceil((target_val - cur_val) / ((double) _increment));
149  // Take into account current cycle remaining ticks
150  Tick rem_ticks = _period - (curTick() % _period);
151  if (rem_ticks < _period) {
152  when += rem_ticks;
153  num_cycles -= 1;
154  }
155  when += num_cycles * _period;
156  }
157  return when;
158 }
159 
160 Tick
161 SystemCounter::whenValue(uint64_t target_val)
162 {
163  return whenValue(value(), target_val);
164 }
165 
166 void
168 {
169  _updateTick = curTick() - (curTick() % _period);
170 }
171 
172 void
173 SystemCounter::freqUpdateSchedule(size_t new_freq_entry)
174 {
175  if (new_freq_entry < _freqTable.size()) {
176  auto &new_freq = _freqTable[new_freq_entry];
177  if (new_freq != _freq) {
178  _nextFreqEntry = new_freq_entry;
179  // Wait until the value for which the lowest frequency increment
180  // is a exact divisor. This covers both high to low and low to
181  // high transitions
182  uint64_t new_incr = _freqTable[0] / new_freq;
183  uint64_t target_val = value();
184  target_val += target_val % std::max(_increment, new_incr);
185  reschedule(_freqUpdateEvent, whenValue(target_val), true);
186  }
187  }
188 }
189 
190 void
192 {
193  DPRINTF(Timer, "SystemCounter::freqUpdateCallback: Changing counter "
194  "frequency\n");
195  if (_enabled)
196  updateValue();
199  _increment = _freqTable[0] / _freq;
200  _period = (1.0 / _freq) * sim_clock::Frequency;
201  notifyListeners();
202 }
203 
204 void
206 {
207  _listeners.push_back(listener);
208 }
209 
210 void
212 {
213  for (auto &listener : _listeners)
214  listener->notify();
215 }
216 
217 void
219 {
220  DPRINTF(Timer, "SystemCounter::serialize: Serializing\n");
228  bool pending_freq_update = _freqUpdateEvent.scheduled();
229  SERIALIZE_SCALAR(pending_freq_update);
230  if (pending_freq_update) {
231  Tick when_freq_update = _freqUpdateEvent.when();
232  SERIALIZE_SCALAR(when_freq_update);
233  }
235 }
236 
237 void
239 {
240  DPRINTF(Timer, "SystemCounter::unserialize: Unserializing\n");
248  bool pending_freq_update;
249  UNSERIALIZE_SCALAR(pending_freq_update);
250  if (pending_freq_update) {
251  Tick when_freq_update;
252  UNSERIALIZE_SCALAR(when_freq_update);
253  reschedule(_freqUpdateEvent, when_freq_update, true);
254  }
256 
257  _period = (1.0 / _freq) * sim_clock::Frequency;
258 }
259 
260 ArchTimer::ArchTimer(const std::string &name,
261  SimObject &parent,
262  SystemCounter &sysctr,
263  ArmInterruptPin *interrupt)
264  : _name(name), _parent(parent), _systemCounter(sysctr),
265  _interrupt(interrupt),
266  _control(0), _counterLimit(0), _offset(0),
267  _counterLimitReachedEvent([this]{ counterLimitReached(); }, name)
268 {
269  _systemCounter.registerListener(this);
270 }
271 
272 void
274 {
275  if (!_control.enable)
276  return;
277 
278  DPRINTF(Timer, "Counter limit reached\n");
279  _control.istatus = 1;
280  if (!_control.imask) {
281  if (scheduleEvents()) {
282  DPRINTF(Timer, "Causing interrupt\n");
283  _interrupt->raise();
284  } else {
285  DPRINTF(Timer, "Kvm mode; skipping simulated interrupt\n");
286  }
287  }
288 }
289 
290 void
292 {
295  if (value() >= _counterLimit) {
297  } else {
298  // Clear the interurpt when timers conditions are not met
299  if (_interrupt->active()) {
300  DPRINTF(Timer, "Clearing interrupt\n");
301  _interrupt->clear();
302  }
303 
304  _control.istatus = 0;
305 
306  if (scheduleEvents()) {
309  }
310  }
311 }
312 
313 void
315 {
316  _counterLimit = val;
317  updateCounter();
318 }
319 
320 void
322 {
323  setCompareValue(value() + sext<32>(val));
324 }
325 
326 void
328 {
329  ArchTimerCtrl old_ctl = _control, new_ctl = val;
330  _control.enable = new_ctl.enable;
331  _control.imask = new_ctl.imask;
332  _control.istatus = old_ctl.istatus;
333  // Timer unmasked or enabled
334  if ((old_ctl.imask && !new_ctl.imask) ||
335  (!old_ctl.enable && new_ctl.enable))
336  updateCounter();
337  // Timer masked or disabled
338  else if ((!old_ctl.imask && new_ctl.imask) ||
339  (old_ctl.enable && !new_ctl.enable)) {
340 
341  if (_interrupt->active()) {
342  DPRINTF(Timer, "Clearing interrupt\n");
343  // We are clearing the interrupt but we are not
344  // setting istatus to 0 as we are doing
345  // in the updateCounter.
346  // istatus signals that Timer conditions are met.
347  // It shouldn't depend on masking.
348  // if enable is zero. istatus is unknown.
349  _interrupt->clear();
350  }
351  }
352 }
353 
354 void
356 {
357  _offset = val;
358  updateCounter();
359 }
360 
361 uint64_t
363 {
364  return _systemCounter.value() - _offset;
365 }
366 
367 void
369 {
370  updateCounter();
371 }
372 
373 void
375 {
376  paramOut(cp, "control_serial", _control);
379 }
380 
381 void
383 {
384  paramIn(cp, "control_serial", _control);
385  // We didn't serialize an offset before we added support for the
386  // virtual timer. Consider it optional to maintain backwards
387  // compatibility.
389  _offset = 0;
390 
391  // We no longer schedule an event here because we may enter KVM
392  // emulation. The event creation is delayed until drainResume().
393 }
394 
397 {
400 
401  return DrainState::Drained;
402 }
403 
404 void
406 {
407  updateCounter();
408 }
409 
410 bool
412 {
413  if constexpr (USE_KVM &&
414  std::string_view(KVM_ISA) == std::string_view("arm")) {
415  auto *vm = system.getKvmVM();
416  return !vm || !vm->validEnvironment();
417  } else {
418  return true;
419  }
420 }
421 
422 GenericTimer::GenericTimer(const GenericTimerParams &p)
423  : SimObject(p),
424  systemCounter(*p.counter),
425  system(*p.system)
426 {
428  fatal_if(!p.system, "GenericTimer::GenericTimer: No system specified, "
429  "can't instantiate architected timers\n");
430  system.setGenericTimer(this);
431 }
432 
433 void
435 {
436  paramOut(cp, "cpu_count", timers.size());
437 
438  for (int i = 0; i < timers.size(); ++i) {
439  const CoreTimers &core(*timers[i]);
440  core.serializeSection(cp, csprintf("pe_implementation%d", i));
441  }
442 }
443 
444 void
446 {
447  // Try to unserialize the CPU count. Old versions of the timer
448  // model assumed a 8 CPUs, so we fall back to that if the field
449  // isn't present.
450  static const unsigned OLD_CPU_MAX = 8;
451  unsigned cpu_count;
452  if (!UNSERIALIZE_OPT_SCALAR(cpu_count)) {
453  warn("Checkpoint does not contain CPU count, assuming %i CPUs\n",
454  OLD_CPU_MAX);
455  cpu_count = OLD_CPU_MAX;
456  }
457 
458  // We cannot assert for equality here because CPU timers are dynamically
459  // created on the first miscreg access. Therefore, if we take the checkpoint
460  // before any timer registers have been accessed, the number of counters
461  // is actually smaller than the total number of CPUs.
462  if (cpu_count > system.threads.size()) {
463  fatal("The simulated system has been initialized with %d CPUs, "
464  "but the Generic Timer checkpoint expects %d CPUs. Consider "
465  "restoring the checkpoint specifying %d CPUs.",
466  system.threads.size(), cpu_count, cpu_count);
467  }
468 
469  for (int i = 0; i < cpu_count; ++i) {
470  CoreTimers &core(getTimers(i));
471  core.unserializeSection(cp, csprintf("pe_implementation%d", i));
472  }
473 }
474 
477 {
478  if (cpu_id >= timers.size())
479  createTimers(cpu_id + 1);
480 
481  return *timers[cpu_id];
482 }
483 
484 void
486 {
487  assert(timers.size() < cpus);
488  auto &p = params();
489 
490  const unsigned old_cpu_count(timers.size());
491  timers.resize(cpus);
492  for (unsigned i = old_cpu_count; i < cpus; ++i) {
493 
494  ThreadContext *tc = system.threads[i];
495 
496  timers[i].reset(
497  new CoreTimers(*this, system, i,
498  p.int_el3_phys->get(tc),
499  p.int_el1_phys->get(tc),
500  p.int_el1_virt->get(tc),
501  p.int_el2_ns_phys->get(tc),
502  p.int_el2_ns_virt->get(tc),
503  p.int_el2_s_phys->get(tc),
504  p.int_el2_s_virt->get(tc)));
505  }
506 }
507 
508 void
510  ArchTimer *timer, RegVal old_cnt_ctl, RegVal cnt_ctl)
511 {
512  uint64_t evnten = bits(cnt_ctl, 2);
513  uint64_t old_evnten = bits(old_cnt_ctl, 2);
514  uint8_t old_trans_to = ev_stream->transitionTo;
515  uint8_t old_trans_bit = ev_stream->transitionBit;
516  ev_stream->transitionTo = !bits(cnt_ctl, 3);
517  ev_stream->transitionBit = bits(cnt_ctl, 7, 4);
518  // Reschedule the Event Stream if enabled and any change in
519  // configuration
520  if (evnten && ((old_evnten != evnten) ||
521  (old_trans_to != ev_stream->transitionTo) ||
522  (old_trans_bit != ev_stream->transitionBit))) {
523 
524  Tick when = timer->whenValue(
525  ev_stream->eventTargetValue(timer->value()));
526  reschedule(ev_stream->event, when, true);
527  } else if (old_evnten && !evnten) {
528  // Event Stream generation disabled
529  if (ev_stream->event.scheduled())
530  deschedule(ev_stream->event);
531  }
532 }
533 
534 void
536 {
537  CoreTimers &core(getTimers(cpu));
538 
539  switch (reg) {
540  case MISCREG_CNTFRQ:
541  case MISCREG_CNTFRQ_EL0:
542  core.cntfrq = val;
543  warn_if(core.cntfrq != systemCounter.freq(), "CNTFRQ configured freq "
544  "does not match the system counter freq\n");
545  return;
546  case MISCREG_CNTKCTL:
547  case MISCREG_CNTKCTL_EL1:
548  {
549  RegVal old_cnt_ctl = core.cntkctl;
550  core.cntkctl = val;
551 
552  ArchTimer *timer = &core.virtEL1;
553  CoreTimers::EventStream *ev_stream = &core.virtEvStream;
554 
555  handleStream(ev_stream, timer, old_cnt_ctl, val);
556  return;
557  }
558  case MISCREG_CNTHCTL:
559  case MISCREG_CNTHCTL_EL2:
560  {
561  RegVal old_cnt_ctl = core.cnthctl;
562  core.cnthctl = val;
563 
564  ArchTimer *timer = &core.physEL1;
565  CoreTimers::EventStream *ev_stream = &core.physEvStream;
566 
567  handleStream(ev_stream, timer, old_cnt_ctl, val);
568  return;
569  }
570  // EL1 physical timer
574  return;
575 
578  core.physEL1.setTimerValue(val);
579  return;
580 
581  case MISCREG_CNTP_CTL_NS:
583  core.physEL1.setControl(val);
584  return;
585 
586  // Count registers
587  case MISCREG_CNTPCT:
588  case MISCREG_CNTPCT_EL0:
589  case MISCREG_CNTVCT:
590  case MISCREG_CNTVCT_EL0:
591  warn("Ignoring write to read only count register: %s\n",
592  miscRegName[reg]);
593  return;
594 
595  // EL1 virtual timer
596  case MISCREG_CNTVOFF:
597  case MISCREG_CNTVOFF_EL2:
598  core.virtEL1.setOffset(val);
599  return;
600 
601  case MISCREG_CNTV_CVAL:
604  return;
605 
606  case MISCREG_CNTV_TVAL:
608  core.virtEL1.setTimerValue(val);
609  return;
610 
611  case MISCREG_CNTV_CTL:
613  core.virtEL1.setControl(val);
614  return;
615 
616  // EL3 physical timer
617  case MISCREG_CNTP_CTL_S:
619  core.physEL3.setControl(val);
620  return;
621 
622  case MISCREG_CNTP_CVAL_S:
625  return;
626 
627  case MISCREG_CNTP_TVAL_S:
629  core.physEL3.setTimerValue(val);
630  return;
631 
632  // EL2 Non-secure physical timer
633  case MISCREG_CNTHP_CTL:
635  core.physNsEL2.setControl(val);
636  return;
637 
638  case MISCREG_CNTHP_CVAL:
641  return;
642 
643  case MISCREG_CNTHP_TVAL:
646  return;
647 
648  // EL2 Non-secure virtual timer
650  core.virtNsEL2.setControl(val);
651  return;
652 
655  return;
656 
659  return;
660 
661  // EL2 Secure physical timer
663  core.physSEL2.setControl(val);
664  return;
665 
668  return;
669 
671  core.physSEL2.setTimerValue(val);
672  return;
673 
674  // EL2 Secure virtual timer
676  core.virtSEL2.setControl(val);
677  return;
678 
681  return;
682 
684  core.virtSEL2.setTimerValue(val);
685  return;
686 
687  default:
688  warn("Writing to unknown register: %s\n", miscRegName[reg]);
689  return;
690  }
691 }
692 
693 
694 RegVal
695 GenericTimer::readMiscReg(int reg, unsigned cpu)
696 {
697  CoreTimers &core(getTimers(cpu));
698 
699  switch (reg) {
700  case MISCREG_CNTFRQ:
701  case MISCREG_CNTFRQ_EL0:
702  return core.cntfrq;
703  case MISCREG_CNTKCTL:
704  case MISCREG_CNTKCTL_EL1:
705  return core.cntkctl & 0x00000000ffffffff;
706  case MISCREG_CNTHCTL:
707  case MISCREG_CNTHCTL_EL2:
708  return core.cnthctl & 0x00000000ffffffff;
709  // EL1 physical timer
712  return core.physEL1.compareValue();
713 
716  return core.physEL1.timerValue();
717 
719  case MISCREG_CNTP_CTL_NS:
720  return core.physEL1.control();
721 
722  case MISCREG_CNTPCT:
723  case MISCREG_CNTPCT_EL0:
724  return core.physEL1.value();
725 
726 
727  // EL1 virtual timer
728  case MISCREG_CNTVCT:
729  case MISCREG_CNTVCT_EL0:
730  return core.virtEL1.value();
731 
732  case MISCREG_CNTVOFF:
733  case MISCREG_CNTVOFF_EL2:
734  return core.virtEL1.offset();
735 
736  case MISCREG_CNTV_CVAL:
738  return core.virtEL1.compareValue();
739 
740  case MISCREG_CNTV_TVAL:
742  return core.virtEL1.timerValue();
743 
744  case MISCREG_CNTV_CTL:
746  return core.virtEL1.control();
747 
748  // EL3 physical timer
749  case MISCREG_CNTP_CTL_S:
751  return core.physEL3.control();
752 
753  case MISCREG_CNTP_CVAL_S:
755  return core.physEL3.compareValue();
756 
757  case MISCREG_CNTP_TVAL_S:
759  return core.physEL3.timerValue();
760 
761  // EL2 Non-secure physical timer
762  case MISCREG_CNTHP_CTL:
764  return core.physNsEL2.control();
765 
766  case MISCREG_CNTHP_CVAL:
768  return core.physNsEL2.compareValue();
769 
770  case MISCREG_CNTHP_TVAL:
772  return core.physNsEL2.timerValue();
773 
774  // EL2 Non-secure virtual timer
776  return core.virtNsEL2.control();
777 
779  return core.virtNsEL2.compareValue();
780 
782  return core.virtNsEL2.timerValue();
783 
784  // EL2 Secure physical timer
786  return core.physSEL2.control();
787 
789  return core.physSEL2.compareValue();
790 
792  return core.physSEL2.timerValue();
793 
794  // EL2 Secure virtual timer
796  return core.virtSEL2.control();
797 
799  return core.virtSEL2.compareValue();
800 
802  return core.virtSEL2.timerValue();
803 
804  default:
805  warn("Reading from unknown register: %s\n", miscRegName[reg]);
806  return 0;
807  }
808 }
809 
811  ArmSystem &system, unsigned cpu,
812  ArmInterruptPin *irq_el3_phys, ArmInterruptPin *irq_el1_phys,
813  ArmInterruptPin *irq_el1_virt, ArmInterruptPin *irq_el2_ns_phys,
814  ArmInterruptPin *irq_el2_ns_virt, ArmInterruptPin *irq_el2_s_phys,
815  ArmInterruptPin *irq_el2_s_virt)
816  : parent(_parent),
817  cntfrq(parent.params().cntfrq),
818  cntkctl(0), cnthctl(0),
819  threadContext(system.threads[cpu]),
820  irqPhysEL3(irq_el3_phys),
821  irqPhysEL1(irq_el1_phys),
822  irqVirtEL1(irq_el1_virt),
823  irqPhysNsEL2(irq_el2_ns_phys),
824  irqVirtNsEL2(irq_el2_ns_virt),
825  irqPhysSEL2(irq_el2_s_phys),
826  irqVirtSEL2(irq_el2_s_virt),
827  physEL3(csprintf("%s.el3_phys_timer%d", parent.name(), cpu),
828  system, parent, parent.systemCounter,
829  irq_el3_phys),
830  physEL1(csprintf("%s.el1_phys_timer%d", parent.name(), cpu),
831  system, parent, parent.systemCounter,
832  irq_el1_phys),
833  virtEL1(csprintf("%s.el1_virt_timer%d", parent.name(), cpu),
834  system, parent, parent.systemCounter,
835  irq_el1_virt),
836  physNsEL2(csprintf("%s.el2_ns_phys_timer%d", parent.name(), cpu),
837  system, parent, parent.systemCounter,
838  irq_el2_ns_phys),
839  virtNsEL2(csprintf("%s.el2_ns_virt_timer%d", parent.name(), cpu),
840  system, parent, parent.systemCounter,
841  irq_el2_ns_virt),
842  physSEL2(csprintf("%s.el2_s_phys_timer%d", parent.name(), cpu),
843  system, parent, parent.systemCounter,
844  irq_el2_s_phys),
845  virtSEL2(csprintf("%s.el2_s_virt_timer%d", parent.name(), cpu),
846  system, parent, parent.systemCounter,
847  irq_el2_s_virt),
848  physEvStream{
850  csprintf("%s.phys_event_gen%d", parent.name(), cpu)), 0, 0
851  },
852  virtEvStream{
853  EventFunctionWrapper([this]{ virtEventStreamCallback(); },
854  csprintf("%s.virt_event_gen%d", parent.name(), cpu)), 0, 0
855  }
856 {
857 }
858 
859 void
861 {
862  eventStreamCallback();
863  schedNextEvent(physEvStream, physEL1);
864 }
865 
866 void
868 {
869  eventStreamCallback();
870  schedNextEvent(virtEvStream, virtEL1);
871 }
872 
873 void
875 {
876  sendEvent(threadContext);
877  threadContext->getCpuPtr()->wakeup(threadContext->threadId());
878 }
879 
880 void
882  ArchTimer &timer)
883 {
884  parent.reschedule(ev_stream.event, timer.whenValue(
885  ev_stream.eventTargetValue(timer.value())), true);
886 }
887 
888 void
890 {
891  schedNextEvent(virtEvStream, virtEL1);
892  schedNextEvent(physEvStream, physEL1);
893 }
894 
895 void
897 {
898  SERIALIZE_SCALAR(cntfrq);
899  SERIALIZE_SCALAR(cntkctl);
900  SERIALIZE_SCALAR(cnthctl);
901 
902  const bool phys_ev_scheduled = physEvStream.event.scheduled();
903  SERIALIZE_SCALAR(phys_ev_scheduled);
904  if (phys_ev_scheduled) {
905  const Tick phys_ev_when = physEvStream.event.when();
906  SERIALIZE_SCALAR(phys_ev_when);
907  }
908  SERIALIZE_SCALAR(physEvStream.transitionTo);
909  SERIALIZE_SCALAR(physEvStream.transitionBit);
910 
911  const bool virt_ev_scheduled = virtEvStream.event.scheduled();
912  SERIALIZE_SCALAR(virt_ev_scheduled);
913  if (virt_ev_scheduled) {
914  const Tick virt_ev_when = virtEvStream.event.when();
915  SERIALIZE_SCALAR(virt_ev_when);
916  }
917  SERIALIZE_SCALAR(virtEvStream.transitionTo);
918  SERIALIZE_SCALAR(virtEvStream.transitionBit);
919 
920  physEL3.serializeSection(cp, "phys_el3_timer");
921  physEL1.serializeSection(cp, "phys_el1_timer");
922  virtEL1.serializeSection(cp, "virt_el1_timer");
923  physNsEL2.serializeSection(cp, "phys_ns_el2_timer");
924  virtNsEL2.serializeSection(cp, "virt_ns_el2_timer");
925  physSEL2.serializeSection(cp, "phys_s_el2_timer");
926  virtSEL2.serializeSection(cp, "virt_s_el2_timer");
927 }
928 
929 void
931 {
932  UNSERIALIZE_SCALAR(cntfrq);
933  UNSERIALIZE_SCALAR(cntkctl);
934  UNSERIALIZE_SCALAR(cnthctl);
935 
936  bool phys_ev_scheduled;
937  UNSERIALIZE_SCALAR(phys_ev_scheduled);
938  if (phys_ev_scheduled) {
939  Tick phys_ev_when;
940  UNSERIALIZE_SCALAR(phys_ev_when);
941  parent.reschedule(physEvStream.event, phys_ev_when, true);
942  }
943  UNSERIALIZE_SCALAR(physEvStream.transitionTo);
944  UNSERIALIZE_SCALAR(physEvStream.transitionBit);
945 
946  bool virt_ev_scheduled;
947  UNSERIALIZE_SCALAR(virt_ev_scheduled);
948  if (virt_ev_scheduled) {
949  Tick virt_ev_when;
950  UNSERIALIZE_SCALAR(virt_ev_when);
951  parent.reschedule(virtEvStream.event, virt_ev_when, true);
952  }
953  UNSERIALIZE_SCALAR(virtEvStream.transitionTo);
954  UNSERIALIZE_SCALAR(virtEvStream.transitionBit);
955 
956  physEL3.unserializeSection(cp, "phys_el3_timer");
957  physEL1.unserializeSection(cp, "phys_el1_timer");
958  virtEL1.unserializeSection(cp, "virt_el1_timer");
959  physNsEL2.unserializeSection(cp, "phys_ns_el2_timer");
960  virtNsEL2.unserializeSection(cp, "virt_ns_el2_timer");
961  physSEL2.unserializeSection(cp, "phys_s_el2_timer");
962  virtSEL2.unserializeSection(cp, "virt_s_el2_timer");
963 }
964 
965 void
967 {
968  DPRINTF(Timer, "Setting %s := 0x%x\n", miscRegName[reg], val);
969  parent.setMiscReg(reg, cpu, val);
970 }
971 
972 RegVal
974 {
975  RegVal value = parent.readMiscReg(reg, cpu);
976  DPRINTF(Timer, "Reading %s as 0x%x\n", miscRegName[reg], value);
977  return value;
978 }
979 
980 GenericTimerFrame::GenericTimerFrame(const GenericTimerFrameParams &p)
981  : PioDevice(p),
982  timerRange(RangeSize(p.cnt_base, ArmSystem::PageBytes)),
983  addrRanges({timerRange}),
984  systemCounter(*p.counter),
985  physTimer(csprintf("%s.phys_timer", name()),
986  *this, systemCounter, p.int_phys->get()),
987  virtTimer(csprintf("%s.virt_timer", name()),
988  *this, systemCounter,
989  p.int_virt->get()),
990  accessBits(0x3f),
991  system(*dynamic_cast<ArmSystem *>(sys))
992 {
994  // Expose optional CNTEL0Base register frame
995  if (p.cnt_el0_base != MaxAddr) {
996  timerEl0Range = RangeSize(p.cnt_el0_base, ArmSystem::PageBytes);
997  accessBitsEl0 = 0x303;
998  addrRanges.push_back(timerEl0Range);
999  }
1000  for (auto &range : addrRanges)
1002 }
1003 
1004 void
1006 {
1007  SERIALIZE_SCALAR(accessBits);
1008  if (hasEl0View())
1009  SERIALIZE_SCALAR(accessBitsEl0);
1011 
1012  physTimer.serializeSection(cp, "phys_timer");
1013  virtTimer.serializeSection(cp, "virt_timer");
1014 }
1015 
1016 void
1018 {
1019  UNSERIALIZE_SCALAR(accessBits);
1020  if (hasEl0View())
1021  UNSERIALIZE_SCALAR(accessBitsEl0);
1023 
1024  physTimer.unserializeSection(cp, "phys_timer");
1025  virtTimer.unserializeSection(cp, "virt_timer");
1026 }
1027 
1028 uint64_t
1030 {
1031  return virtTimer.offset();
1032 }
1033 
1034 void
1036 {
1037  virtTimer.setOffset(new_offset);
1038 }
1039 
1040 bool
1042 {
1043  return timerEl0Range.valid();
1044 }
1045 
1046 uint8_t
1048 {
1049  return accessBits;
1050 }
1051 
1052 void
1054 {
1055  accessBits = data & 0x3f;
1056 }
1057 
1058 bool
1060 {
1061  return nonSecureAccess;
1062 }
1063 
1064 void
1066 {
1067  nonSecureAccess = true;
1068 }
1069 
1070 bool
1072 {
1073  return accessBits.rvoff;
1074 }
1075 
1078 {
1079  return addrRanges;
1080 }
1081 
1082 Tick
1084 {
1085  const Addr addr = pkt->getAddr();
1086  const size_t size = pkt->getSize();
1087  const bool is_sec = pkt->isSecure();
1088  panic_if(size != 4 && size != 8,
1089  "GenericTimerFrame::read: Invalid size %i\n", size);
1090 
1091  bool to_el0 = false;
1092  uint64_t resp = 0;
1093  Addr offset = 0;
1094  if (timerRange.contains(addr)) {
1095  offset = addr - timerRange.start();
1096  } else if (hasEl0View() && timerEl0Range.contains(addr)) {
1098  to_el0 = true;
1099  } else {
1100  panic("GenericTimerFrame::read: Invalid address: 0x%x\n", addr);
1101  }
1102 
1103  resp = timerRead(offset, size, is_sec, to_el0);
1104 
1105  DPRINTF(Timer, "GenericTimerFrame::read: 0x%x<-0x%x(%i) [S = %u]\n", resp,
1106  addr, size, is_sec);
1107 
1108  pkt->setUintX(resp, ByteOrder::little);
1109  pkt->makeResponse();
1110  return 0;
1111 }
1112 
1113 Tick
1115 {
1116  const Addr addr = pkt->getAddr();
1117  const size_t size = pkt->getSize();
1118  const bool is_sec = pkt->isSecure();
1119  panic_if(size != 4 && size != 8,
1120  "GenericTimerFrame::write: Invalid size %i\n", size);
1121 
1122  bool to_el0 = false;
1123  const uint64_t data = pkt->getUintX(ByteOrder::little);
1124  Addr offset = 0;
1125  if (timerRange.contains(addr)) {
1126  offset = addr - timerRange.start();
1127  } else if (hasEl0View() && timerEl0Range.contains(addr)) {
1129  to_el0 = true;
1130  } else {
1131  panic("GenericTimerFrame::write: Invalid address: 0x%x\n", addr);
1132  }
1133 
1134  timerWrite(offset, size, data, is_sec, to_el0);
1135 
1136  DPRINTF(Timer, "GenericTimerFrame::write: 0x%x->0x%x(%i) [S = %u]\n", data,
1137  addr, size, is_sec);
1138 
1139  pkt->makeResponse();
1140  return 0;
1141 }
1142 
1143 uint64_t
1144 GenericTimerFrame::timerRead(Addr addr, size_t size, bool is_sec,
1145  bool to_el0) const
1146 {
1148  !nonSecureAccess)
1149  return 0;
1150 
1151  switch (addr) {
1152  case TIMER_CNTPCT_LO:
1153  if (!accessBits.rpct || (to_el0 && !accessBitsEl0.pcten))
1154  return 0;
1155  else
1156  return physTimer.value();
1157 
1158  case TIMER_CNTPCT_HI:
1159  if (!accessBits.rpct || (to_el0 && !accessBitsEl0.pcten))
1160  return 0;
1161  else
1162  return physTimer.value() >> 32;
1163 
1164  case TIMER_CNTFRQ:
1165  if ((!accessBits.rfrq) ||
1166  (to_el0 && (!accessBitsEl0.pcten && !accessBitsEl0.vcten)))
1167  return 0;
1168  else
1169  return systemCounter.freq();
1170 
1171  case TIMER_CNTEL0ACR:
1172  if (!hasEl0View() || to_el0)
1173  return 0;
1174  else
1175  return accessBitsEl0;
1176 
1177  case TIMER_CNTP_CVAL_LO:
1178  if (!accessBits.rwpt || (to_el0 && !accessBitsEl0.pten))
1179  return 0;
1180  else
1181  return physTimer.compareValue();
1182 
1183  case TIMER_CNTP_CVAL_HI:
1184  if (!accessBits.rwpt || (to_el0 && !accessBitsEl0.pten))
1185  return 0;
1186  else
1187  return physTimer.compareValue() >> 32;
1188 
1189  case TIMER_CNTP_TVAL:
1190  if (!accessBits.rwpt || (to_el0 && !accessBitsEl0.pten))
1191  return 0;
1192  else
1193  return physTimer.timerValue();
1194  case TIMER_CNTP_CTL:
1195  if (!accessBits.rwpt || (to_el0 && !accessBitsEl0.pten))
1196  return 0;
1197  else
1198  return physTimer.control();
1199 
1200  case TIMER_CNTVCT_LO:
1201  if (!accessBits.rvct || (to_el0 && !accessBitsEl0.vcten))
1202  return 0;
1203  else
1204  return virtTimer.value();
1205 
1206  case TIMER_CNTVCT_HI:
1207  if (!accessBits.rvct || (to_el0 && !accessBitsEl0.vcten))
1208  return 0;
1209  else
1210  return virtTimer.value() >> 32;
1211 
1212  case TIMER_CNTVOFF_LO:
1213  if (!accessBits.rvoff || (to_el0))
1214  return 0;
1215  else
1216  return virtTimer.offset();
1217 
1218  case TIMER_CNTVOFF_HI:
1219  if (!accessBits.rvoff || (to_el0))
1220  return 0;
1221  else
1222  return virtTimer.offset() >> 32;
1223 
1224  case TIMER_CNTV_CVAL_LO:
1225  if (!accessBits.rwvt || (to_el0 && !accessBitsEl0.vten))
1226  return 0;
1227  else
1228  return virtTimer.compareValue();
1229 
1230  case TIMER_CNTV_CVAL_HI:
1231  if (!accessBits.rwvt || (to_el0 && !accessBitsEl0.vten))
1232  return 0;
1233  else
1234  return virtTimer.compareValue() >> 32;
1235 
1236  case TIMER_CNTV_TVAL:
1237  if (!accessBits.rwvt || (to_el0 && !accessBitsEl0.vten))
1238  return 0;
1239  else
1240  return virtTimer.timerValue();
1241 
1242  case TIMER_CNTV_CTL:
1243  if (!accessBits.rwvt || (to_el0 && !accessBitsEl0.vten))
1244  return 0;
1245  else
1246  return virtTimer.control();
1247 
1248  default:
1249  warn("GenericTimerFrame::timerRead: Unexpected address (0x%x:%i), "
1250  "assuming RAZ\n", addr, size);
1251  return 0;
1252  }
1253 }
1254 
1255 void
1257  bool is_sec, bool to_el0)
1258 {
1260  !nonSecureAccess)
1261  return;
1262 
1263  switch (addr) {
1265  warn("GenericTimerFrame::timerWrite: RO reg (0x%x) [CNTPCT]\n",
1266  addr);
1267  return;
1268 
1269  case TIMER_CNTFRQ:
1270  warn("GenericTimerFrame::timerWrite: RO reg (0x%x) [CNTFRQ]\n",
1271  addr);
1272  return;
1273 
1274  case TIMER_CNTEL0ACR:
1275  if (!hasEl0View() || to_el0)
1276  return;
1277 
1278  insertBits(accessBitsEl0, 9, 8, data);
1279  insertBits(accessBitsEl0, 1, 0, data);
1280  return;
1281 
1282  case TIMER_CNTP_CVAL_LO:
1283  if ((!accessBits.rwpt) || (to_el0 && !accessBitsEl0.pten))
1284  return;
1285  data = size == 4 ? insertBits(physTimer.compareValue(),
1286  31, 0, data) : data;
1288  return;
1289 
1290  case TIMER_CNTP_CVAL_HI:
1291  if ((!accessBits.rwpt) || (to_el0 && !accessBitsEl0.pten))
1292  return;
1293  data = insertBits(physTimer.compareValue(), 63, 32, data);
1295  return;
1296 
1297  case TIMER_CNTP_TVAL:
1298  if ((!accessBits.rwpt) || (to_el0 && !accessBitsEl0.pten))
1299  return;
1301  return;
1302 
1303  case TIMER_CNTP_CTL:
1304  if ((!accessBits.rwpt) || (to_el0 && !accessBitsEl0.pten))
1305  return;
1307  return;
1308 
1310  warn("GenericTimerFrame::timerWrite: RO reg (0x%x) [CNTVCT]\n",
1311  addr);
1312  return;
1314  warn("GenericTimerFrame::timerWrite: RO reg (0x%x) [CNTVOFF]\n",
1315  addr);
1316  return;
1317 
1318  case TIMER_CNTV_CVAL_LO:
1319  if ((!accessBits.rwvt) || (to_el0 && !accessBitsEl0.vten))
1320  return;
1321  data = size == 4 ? insertBits(virtTimer.compareValue(),
1322  31, 0, data) : data;
1324  return;
1325 
1326  case TIMER_CNTV_CVAL_HI:
1327  if ((!accessBits.rwvt) || (to_el0 && !accessBitsEl0.vten))
1328  return;
1329  data = insertBits(virtTimer.compareValue(), 63, 32, data);
1331  return;
1332 
1333  case TIMER_CNTV_TVAL:
1334  if ((!accessBits.rwvt) || (to_el0 && !accessBitsEl0.vten))
1335  return;
1337  return;
1338 
1339  case TIMER_CNTV_CTL:
1340  if ((!accessBits.rwvt) || (to_el0 && !accessBitsEl0.vten))
1341  return;
1343  return;
1344 
1345  default:
1346  warn("GenericTimerFrame::timerWrite: Unexpected address (0x%x:%i), "
1347  "assuming WI\n", addr, size);
1348  }
1349 }
1350 
1351 GenericTimerMem::GenericTimerMem(const GenericTimerMemParams &p)
1352  : PioDevice(p),
1353  counterCtrlRange(RangeSize(p.cnt_control_base, ArmSystem::PageBytes)),
1354  counterStatusRange(RangeSize(p.cnt_read_base, ArmSystem::PageBytes)),
1355  timerCtrlRange(RangeSize(p.cnt_ctl_base, ArmSystem::PageBytes)),
1356  cnttidr(0x0),
1358  systemCounter(*p.counter),
1359  frames(p.frames),
1360  system(*dynamic_cast<ArmSystem *>(sys))
1361 {
1363  for (auto &range : addrRanges)
1365  fatal_if(frames.size() > MAX_TIMER_FRAMES,
1366  "GenericTimerMem::GenericTimerMem: Architecture states a maximum of "
1367  "8 memory-mapped timer frames, limit surpassed\n");
1368  // Initialize CNTTIDR with each frame's features
1369  for (int i = 0; i < frames.size(); i++) {
1370  uint32_t features = 0x1;
1371  features |= 0x2;
1372  if (frames[i]->hasEl0View())
1373  features |= 0x4;
1374  features <<= i * 4;
1375  replaceBits(cnttidr, (i + 1) * 4 - 1, i * 4, features);
1376  }
1377 }
1378 
1379 void
1381 {
1383  "GenericTimerMem::validateFrameRange: Architecture states each "
1384  "register frame should be in a separate memory page, specified "
1385  "range base address [0x%x] is not compliant\n");
1386 }
1387 
1388 bool
1390 {
1391  return !sys.has(ArmExtension::SECURITY) || is_sec;
1392 }
1393 
1396 {
1397  return addrRanges;
1398 }
1399 
1400 Tick
1402 {
1403  const Addr addr = pkt->getAddr();
1404  const size_t size = pkt->getSize();
1405  const bool is_sec = pkt->isSecure();
1406  panic_if(size != 4 && size != 8,
1407  "GenericTimerMem::read: Invalid size %i\n", size);
1408 
1409  uint64_t resp = 0;
1411  resp = counterCtrlRead(addr - counterCtrlRange.start(), size, is_sec);
1412  else if (counterStatusRange.contains(addr))
1413  resp = counterStatusRead(addr - counterStatusRange.start(), size);
1414  else if (timerCtrlRange.contains(addr))
1415  resp = timerCtrlRead(addr - timerCtrlRange.start(), size, is_sec);
1416  else
1417  panic("GenericTimerMem::read: Invalid address: 0x%x\n", addr);
1418 
1419  DPRINTF(Timer, "GenericTimerMem::read: 0x%x<-0x%x(%i) [S = %u]\n", resp,
1420  addr, size, is_sec);
1421 
1422  pkt->setUintX(resp, ByteOrder::little);
1423  pkt->makeResponse();
1424  return 0;
1425 }
1426 
1427 Tick
1429 {
1430  const Addr addr = pkt->getAddr();
1431  const size_t size = pkt->getSize();
1432  const bool is_sec = pkt->isSecure();
1433  panic_if(size != 4 && size != 8,
1434  "GenericTimerMem::write: Invalid size %i\n", size);
1435 
1436  const uint64_t data = pkt->getUintX(ByteOrder::little);
1438  counterCtrlWrite(addr - counterCtrlRange.start(), size, data, is_sec);
1439  else if (counterStatusRange.contains(addr))
1441  else if (timerCtrlRange.contains(addr))
1442  timerCtrlWrite(addr - timerCtrlRange.start(), size, data, is_sec);
1443  else
1444  panic("GenericTimerMem::write: Invalid address: 0x%x\n", addr);
1445 
1446  DPRINTF(Timer, "GenericTimerMem::write: 0x%x->0x%x(%i) [S = %u]\n", data,
1447  addr, size, is_sec);
1448 
1449  pkt->makeResponse();
1450  return 0;
1451 }
1452 
1453 uint64_t
1454 GenericTimerMem::counterCtrlRead(Addr addr, size_t size, bool is_sec) const
1455 {
1457  return 0;
1458  switch (addr) {
1459  case COUNTER_CTRL_CNTCR:
1460  {
1461  CNTCR cntcr = 0;
1462  cntcr.en = systemCounter.enabled();
1463  cntcr.fcreq = systemCounter.activeFreqEntry();
1464  return cntcr;
1465  }
1466  case COUNTER_CTRL_CNTSR:
1467  {
1468  CNTSR cntsr = 0;
1469  cntsr.fcack = systemCounter.activeFreqEntry();
1470  return cntsr;
1471  }
1472  case COUNTER_CTRL_CNTCV_LO: return systemCounter.value();
1473  case COUNTER_CTRL_CNTCV_HI: return systemCounter.value() >> 32;
1474  case COUNTER_CTRL_CNTSCR: return 0;
1475  case COUNTER_CTRL_CNTID: return 0;
1476  default:
1477  {
1478  auto &freq_table = systemCounter.freqTable();
1479  for (int i = 0; i < (freq_table.size() - 1); i++) {
1480  Addr offset = COUNTER_CTRL_CNTFID + (i * 0x4);
1481  if (addr == offset)
1482  return freq_table[i];
1483  }
1484  warn("GenericTimerMem::counterCtrlRead: Unexpected address "
1485  "(0x%x:%i), assuming RAZ\n", addr, size);
1486  return 0;
1487  }
1488  }
1489 }
1490 
1491 void
1493  bool is_sec)
1494 {
1496  return;
1497 
1498  switch (addr) {
1499  case COUNTER_CTRL_CNTCR:
1500  {
1501  CNTCR val = data;
1502  if (!systemCounter.enabled() && val.en)
1504  else if (systemCounter.enabled() && !val.en)
1506 
1507  if (val.hdbg)
1508  warn("GenericTimerMem::counterCtrlWrite: Halt-on-debug is not "
1509  "supported\n");
1510  if (val.scen)
1511  warn("GenericTimerMem::counterCtrlWrite: Counter Scaling is not "
1512  "supported\n");
1513  if (val.fcreq != systemCounter.activeFreqEntry())
1515  return;
1516  }
1517 
1518  case COUNTER_CTRL_CNTSR:
1519  warn("GenericTimerMem::counterCtrlWrite: RO reg (0x%x) [CNTSR]\n",
1520  addr);
1521  return;
1522 
1523  case COUNTER_CTRL_CNTCV_LO:
1524  data = size == 4 ? insertBits(systemCounter.value(), 31, 0, data)
1525  : data;
1527  return;
1528 
1529  case COUNTER_CTRL_CNTCV_HI:
1530  data = insertBits(systemCounter.value(), 63, 32, data);
1532  return;
1533 
1534  case COUNTER_CTRL_CNTSCR:
1535  return;
1536 
1537  case COUNTER_CTRL_CNTID:
1538  warn("GenericTimerMem::counterCtrlWrite: RO reg (0x%x) [CNTID]\n",
1539  addr);
1540  return;
1541 
1542  default:
1543  {
1544  auto &freq_table = systemCounter.freqTable();
1545  for (int i = 0; i < (freq_table.size() - 1); i++) {
1546  Addr offset = COUNTER_CTRL_CNTFID + (i * 0x4);
1547  if (addr == offset) {
1548  freq_table[i] = data;
1549  // This is changing the currently selected frequency
1550  if (i == systemCounter.activeFreqEntry()) {
1551  // We've changed the frequency in the table entry,
1552  // however the counter will still work with the
1553  // current one until transition is completed
1555  }
1556  return;
1557  }
1558  }
1559  warn("GenericTimerMem::counterCtrlWrite: Unexpected address "
1560  "(0x%x:%i), assuming WI\n", addr, size);
1561  }
1562  }
1563 }
1564 
1565 uint64_t
1567 {
1568  switch (addr) {
1570  case COUNTER_STATUS_CNTCV_HI: return systemCounter.value() >> 32;
1571  default:
1572  warn("GenericTimerMem::counterStatusRead: Unexpected address "
1573  "(0x%x:%i), assuming RAZ\n", addr, size);
1574  return 0;
1575  }
1576 }
1577 
1578 void
1580 {
1581  switch (addr) {
1583  warn("GenericTimerMem::counterStatusWrite: RO reg (0x%x) [CNTCV]\n",
1584  addr);
1585  return;
1586  default:
1587  warn("GenericTimerMem::counterStatusWrite: Unexpected address "
1588  "(0x%x:%i), assuming WI\n", addr, size);
1589  }
1590 }
1591 
1592 uint64_t
1593 GenericTimerMem::timerCtrlRead(Addr addr, size_t size, bool is_sec) const
1594 {
1595  switch (addr) {
1596  case TIMER_CTRL_CNTFRQ:
1597  if (!GenericTimerMem::validateAccessPerm(system, is_sec)) return 0;
1598  return systemCounter.freq();
1599  case TIMER_CTRL_CNTNSAR:
1600  {
1601  if (!GenericTimerMem::validateAccessPerm(system, is_sec)) return 0;
1602  uint32_t cntnsar = 0x0;
1603  for (int i = 0; i < frames.size(); i++) {
1604  if (frames[i]->hasNonSecureAccess())
1605  cntnsar |= 0x1 << i;
1606  }
1607  return cntnsar;
1608  }
1609  case TIMER_CTRL_CNTTIDR: return cnttidr;
1610  default:
1611  for (int i = 0; i < frames.size(); i++) {
1612  Addr cntacr_off = TIMER_CTRL_CNTACR + (i * 0x4);
1613  Addr cntvoff_lo_off = TIMER_CTRL_CNTVOFF_LO + (i * 0x4);
1614  Addr cntvoff_hi_off = TIMER_CTRL_CNTVOFF_HI + (i * 0x4);
1615  // CNTNSAR.NS determines if CNTACR/CNTVOFF are accessible from
1616  // normal world
1617  bool hit = addr == cntacr_off || addr == cntvoff_lo_off ||
1618  addr == cntvoff_hi_off;
1619  bool has_access =
1621  frames[i]->hasNonSecureAccess();
1622  if (hit && !has_access) return 0;
1623  if (addr == cntacr_off)
1624  return frames[i]->getAccessBits();
1625  if (addr == cntvoff_lo_off || addr == cntvoff_hi_off) {
1626  return addr == cntvoff_lo_off ? frames[i]->getVirtOffset()
1627  : frames[i]->getVirtOffset() >> 32;
1628  }
1629  }
1630  warn("GenericTimerMem::timerCtrlRead: Unexpected address (0x%x:%i), "
1631  "assuming RAZ\n", addr, size);
1632  return 0;
1633  }
1634 }
1635 
1636 void
1638  bool is_sec)
1639 {
1640  switch (addr) {
1641  case TIMER_CTRL_CNTFRQ:
1642  if (!GenericTimerMem::validateAccessPerm(system, is_sec)) return;
1644  "GenericTimerMem::timerCtrlWrite: CNTFRQ configured freq "
1645  "does not match the counter freq, ignoring\n");
1646  return;
1647  case TIMER_CTRL_CNTNSAR:
1648  if (!GenericTimerMem::validateAccessPerm(system, is_sec)) return;
1649  for (int i = 0; i < frames.size(); i++) {
1650  // Check if the CNTNSAR.NS bit is set for this frame
1651  if (data & (0x1 << i))
1652  frames[i]->setNonSecureAccess();
1653  }
1654  return;
1655  case TIMER_CTRL_CNTTIDR:
1656  warn("GenericTimerMem::timerCtrlWrite: RO reg (0x%x) [CNTTIDR]\n",
1657  addr);
1658  return;
1659  default:
1660  for (int i = 0; i < frames.size(); i++) {
1661  Addr cntacr_off = TIMER_CTRL_CNTACR + (i * 0x4);
1662  Addr cntvoff_lo_off = TIMER_CTRL_CNTVOFF_LO + (i * 0x4);
1663  Addr cntvoff_hi_off = TIMER_CTRL_CNTVOFF_HI + (i * 0x4);
1664  // CNTNSAR.NS determines if CNTACR/CNTVOFF are accessible from
1665  // normal world
1666  bool hit = addr == cntacr_off || addr == cntvoff_lo_off ||
1667  addr == cntvoff_hi_off;
1668  bool has_access =
1670  frames[i]->hasNonSecureAccess();
1671  if (hit && !has_access) return;
1672  if (addr == cntacr_off) {
1673  frames[i]->setAccessBits(data);
1674  return;
1675  }
1676  if (addr == cntvoff_lo_off || addr == cntvoff_hi_off) {
1677  if (addr == cntvoff_lo_off)
1678  data = size == 4 ? insertBits(frames[i]->getVirtOffset(),
1679  31, 0, data) : data;
1680  else
1681  data = insertBits(frames[i]->getVirtOffset(),
1682  63, 32, data);
1683  frames[i]->setVirtOffset(data);
1684  return;
1685  }
1686  }
1687  warn("GenericTimerMem::timerCtrlWrite: Unexpected address "
1688  "(0x%x:%i), assuming WI\n", addr, size);
1689  }
1690 }
1691 
1692 } // namespace gem5
gem5::GenericTimerMem::COUNTER_STATUS_CNTCV_LO
static const Addr COUNTER_STATUS_CNTCV_LO
Definition: generic_timer.hh:566
gem5::SystemCounter::unserialize
void unserialize(CheckpointIn &cp) override
Unserialize an object.
Definition: generic_timer.cc:238
gem5::ArmSystem::setGenericTimer
void setGenericTimer(GenericTimer *generic_timer)
Sets the pointer to the Generic Timer.
Definition: system.hh:162
gem5::curTick
Tick curTick()
The universal simulation clock.
Definition: cur_tick.hh:46
fatal
#define fatal(...)
This implements a cprintf based fatal() function.
Definition: logging.hh:200
gem5::GenericTimerMem::counterCtrlWrite
void counterCtrlWrite(Addr addr, size_t size, uint64_t data, bool is_sec)
Definition: generic_timer.cc:1492
gem5::GenericTimer::CoreTimers::parent
GenericTimer & parent
Generic Timer parent reference.
Definition: generic_timer.hh:314
gem5::ArmISA::MISCREG_CNTV_TVAL
@ MISCREG_CNTV_TVAL
Definition: misc.hh:432
gem5::Event::when
Tick when() const
Get the time that the event is scheduled.
Definition: eventq.hh:501
gem5::SystemCounter::notifyListeners
void notifyListeners(void) const
Notifies counting speed changes to listeners.
Definition: generic_timer.cc:211
gem5::GenericTimerFrame::timerRange
const AddrRange timerRange
Definition: generic_timer.hh:461
gem5::ArmISA::MISCREG_CNTHVS_TVAL_EL2
@ MISCREG_CNTHVS_TVAL_EL2
Definition: misc.hh:808
gem5::GenericTimer::CoreTimers::virtEventStreamCallback
void virtEventStreamCallback()
Definition: generic_timer.cc:867
gem5::AddrRange::start
Addr start() const
Get the start address of the range.
Definition: addr_range.hh:343
warn
#define warn(...)
Definition: logging.hh:256
gem5::GenericTimerFrame::hasNonSecureAccess
bool hasNonSecureAccess() const
Indicates if non-secure accesses are allowed to this frame.
Definition: generic_timer.cc:1059
gem5::System::Threads::size
int size() const
Definition: system.hh:210
gem5::GenericTimerMem::GenericTimerMem
GenericTimerMem(const GenericTimerMemParams &p)
Definition: generic_timer.cc:1351
gem5::RegVal
uint64_t RegVal
Definition: types.hh:173
gem5::ArchTimer::_control
ArchTimerCtrl _control
Value of the control register ({CNTP/CNTHP/CNTV}_CTL).
Definition: generic_timer.hh:201
gem5::Packet::getUintX
uint64_t getUintX(ByteOrder endian) const
Get the data in the packet byte swapped from the specified endianness and zero-extended to 64 bits.
Definition: packet.cc:352
gem5::statistics::_enabled
bool _enabled
Definition: statistics.cc:282
gem5::ArmISA::MISCREG_CNTPS_CTL_EL1
@ MISCREG_CNTPS_CTL_EL1
Definition: misc.hh:792
data
const char data[]
Definition: circlebuf.test.cc:48
gem5::ArmISA::MISCREG_CNTVCT
@ MISCREG_CNTVCT
Definition: misc.hh:420
gem5::PioDevice
This device is the base class which all devices senstive to an address range inherit from.
Definition: io_device.hh:102
UNSERIALIZE_SCALAR
#define UNSERIALIZE_SCALAR(scalar)
Definition: serialize.hh:575
gem5::SystemCounter::_increment
uint64_t _increment
Value increment in each counter cycle.
Definition: generic_timer.hh:96
gem5::GenericTimerFrame::timerEl0Range
AddrRange timerEl0Range
Definition: generic_timer.hh:462
gem5::ArmISA::MISCREG_CNTFRQ
@ MISCREG_CNTFRQ
Definition: misc.hh:418
gem5::GenericTimerFrame::TIMER_CNTV_CVAL_LO
static const Addr TIMER_CNTV_CVAL_LO
Definition: generic_timer.hh:476
gem5::GenericTimer::GenericTimer
GenericTimer(const Params &p)
Definition: generic_timer.cc:422
gem5::GenericTimerFrame::unserialize
void unserialize(CheckpointIn &cp) override
Unserialize an object.
Definition: generic_timer.cc:1017
gem5::ArmISA::MISCREG_CNTHPS_TVAL_EL2
@ MISCREG_CNTHPS_TVAL_EL2
Definition: misc.hh:801
gem5::ArmISA::MISCREG_CNTV_CTL_EL0
@ MISCREG_CNTV_CTL_EL0
Definition: misc.hh:781
gem5::ArmISA::MISCREG_CNTHVS_CVAL_EL2
@ MISCREG_CNTHVS_CVAL_EL2
Definition: misc.hh:807
gem5::GenericTimerFrame::TIMER_CNTP_CVAL_LO
static const Addr TIMER_CNTP_CVAL_LO
Definition: generic_timer.hh:472
gem5::ArmISA::MISCREG_CNTPS_TVAL_EL1
@ MISCREG_CNTPS_TVAL_EL1
Definition: misc.hh:794
gem5::ArmISA::MISCREG_CNTP_CTL_EL0
@ MISCREG_CNTP_CTL_EL0
Definition: misc.hh:778
gem5::RangeSize
AddrRange RangeSize(Addr start, Addr size)
Definition: addr_range.hh:831
UNSERIALIZE_CONTAINER
#define UNSERIALIZE_CONTAINER(member)
Definition: serialize.hh:634
gem5::ArmISA::MISCREG_CNTHCTL
@ MISCREG_CNTHCTL
Definition: misc.hh:434
gem5::GenericTimerMem::TIMER_CTRL_CNTTIDR
static const Addr TIMER_CTRL_CNTTIDR
Definition: generic_timer.hh:579
gem5::SystemCounter::freqUpdateCallback
void freqUpdateCallback()
Callback for the frequency update.
Definition: generic_timer.cc:191
gem5::GenericTimerFrame::TIMER_CNTVOFF_LO
static const Addr TIMER_CNTVOFF_LO
Definition: generic_timer.hh:470
gem5::GenericTimerMem::COUNTER_CTRL_CNTCV_LO
static const Addr COUNTER_CTRL_CNTCV_LO
Definition: generic_timer.hh:555
gem5::GenericTimerFrame::read
Tick read(PacketPtr pkt) override
Pure virtual function that the device must implement.
Definition: generic_timer.cc:1083
gem5::ArmISA::MISCREG_CNTP_CVAL_S
@ MISCREG_CNTP_CVAL_S
Definition: misc.hh:426
gem5::ArmISA::MISCREG_CNTKCTL
@ MISCREG_CNTKCTL
Definition: misc.hh:433
gem5::AddrRange::contains
bool contains(const Addr &a) const
Determine if the range contains an address.
Definition: addr_range.hh:471
gem5::GenericTimerMem::counterStatusRange
const AddrRange counterStatusRange
Definition: generic_timer.hh:564
gem5::CheckpointIn
Definition: serialize.hh:68
gem5::ArchTimer::ArchTimer
ArchTimer(const std::string &name, SimObject &parent, SystemCounter &sysctr, ArmInterruptPin *interrupt)
Definition: generic_timer.cc:260
base_gic.hh
gem5::replaceBits
constexpr void replaceBits(T &val, unsigned first, unsigned last, B bit_val)
A convenience function to replace bits first to last of val with bit_val in place.
Definition: bitfield.hh:213
gem5::Serializable::serializeSection
void serializeSection(CheckpointOut &cp, const char *name) const
Serialize an object into a new section.
Definition: serialize.cc:74
cur_tick.hh
gem5::GenericTimerMem::COUNTER_CTRL_CNTFID
static const Addr COUNTER_CTRL_CNTFID
Definition: generic_timer.hh:559
gem5::GenericTimerFrame::system
ArmSystem & system
Definition: generic_timer.hh:514
gem5::GenericTimerFrame::TIMER_CNTP_TVAL
static const Addr TIMER_CNTP_TVAL
Definition: generic_timer.hh:474
gem5::GenericTimer::CoreTimers::physSEL2
ArchTimerKvm physSEL2
Definition: generic_timer.hh:341
gem5::X86ISA::val
Bitfield< 63 > val
Definition: misc.hh:776
gem5::sim_clock::Frequency
Tick Frequency
The simulated frequency of curTick(). (In ticks per second)
Definition: core.cc:47
gem5::GenericTimerFrame::TIMER_CNTVOFF_HI
static const Addr TIMER_CNTVOFF_HI
Definition: generic_timer.hh:471
gem5::ArchTimer::scheduleEvents
virtual bool scheduleEvents()
Definition: generic_timer.hh:217
gem5::GenericTimerFrame::TIMER_CNTV_CVAL_HI
static const Addr TIMER_CNTV_CVAL_HI
Definition: generic_timer.hh:477
gem5::GenericTimerMem::getAddrRanges
AddrRangeList getAddrRanges() const override
Every PIO device is obliged to provide an implementation that returns the address ranges the device r...
Definition: generic_timer.cc:1395
gem5::Packet::isSecure
bool isSecure() const
Definition: packet.hh:836
gem5::ArmISA::miscRegName
const char *const miscRegName[]
Definition: misc.hh:1748
gem5::ArchTimer::unserialize
void unserialize(CheckpointIn &cp) override
Unserialize an object.
Definition: generic_timer.cc:382
gem5::X86ISA::system
Bitfield< 15 > system
Definition: misc.hh:1004
gem5::GenericTimerMem::counterCtrlRead
uint64_t counterCtrlRead(Addr addr, size_t size, bool is_sec) const
CNTControlBase (System counter control frame)
Definition: generic_timer.cc:1454
gem5::ArmISA::MISCREG_CNTP_TVAL_NS
@ MISCREG_CNTP_TVAL_NS
Definition: misc.hh:428
gem5::ArchTimer::updateCounter
void updateCounter()
Timer settings or the offset has changed, re-evaluate trigger condition and raise interrupt if necess...
Definition: generic_timer.cc:291
gem5::EventManager::schedule
void schedule(Event &event, Tick when)
Definition: eventq.hh:1012
gem5::GenericTimerMem::counterStatusRead
uint64_t counterStatusRead(Addr addr, size_t size) const
CNTReadBase (System counter status frame)
Definition: generic_timer.cc:1566
gem5::ArchTimer::setOffset
void setOffset(uint64_t val)
Definition: generic_timer.cc:355
gem5::SystemCounter::_enabled
bool _enabled
Indicates if the counter is enabled.
Definition: generic_timer.hh:90
gem5::csprintf
std::string csprintf(const char *format, const Args &...args)
Definition: cprintf.hh:161
gem5::GenericTimerFrame::timerWrite
void timerWrite(Addr addr, size_t size, uint64_t data, bool is_sec, bool to_el0)
Definition: generic_timer.cc:1256
gem5::ArmISA::MISCREG_CNTP_CTL_NS
@ MISCREG_CNTP_CTL_NS
Definition: misc.hh:422
gem5::GenericTimerFrame::TIMER_CNTPCT_HI
static const Addr TIMER_CNTPCT_HI
Definition: generic_timer.hh:465
system.hh
gem5::SystemCounter::registerListener
void registerListener(SystemCounterListener *listener)
Called from System Counter Listeners to register.
Definition: generic_timer.cc:205
gem5::GenericTimer::serialize
void serialize(CheckpointOut &cp) const override
Serialize an object.
Definition: generic_timer.cc:434
gem5::SystemCounter::_period
Tick _period
Cached copy of the counter period (inverse of the frequency).
Definition: generic_timer.hh:102
gem5::ArmISA::i
Bitfield< 7 > i
Definition: misc_types.hh:67
gem5::GenericTimer::CoreTimers::virtEvStream
EventStream virtEvStream
Definition: generic_timer.hh:366
gem5::GenericTimerFrame::addrRanges
AddrRangeList addrRanges
All MMIO ranges GenericTimerFrame responds to.
Definition: generic_timer.hh:482
gem5::ArmISA::MISCREG_CNTVCT_EL0
@ MISCREG_CNTVCT_EL0
Definition: misc.hh:777
gem5::ArmISA::MISCREG_CNTPCT_EL0
@ MISCREG_CNTPCT_EL0
Definition: misc.hh:776
gem5::GenericTimerFrame::setVirtOffset
void setVirtOffset(uint64_t new_offset)
Sets the virtual offset for this frame's virtual timer after a write to CNTVOFF.
Definition: generic_timer.cc:1035
gem5::GenericTimerFrame::TIMER_CNTVCT_LO
static const Addr TIMER_CNTVCT_LO
Definition: generic_timer.hh:466
gem5::System::getKvmVM
KvmVM * getKvmVM() const
Get a pointer to the Kernel Virtual Machine (KVM) SimObject, if present.
Definition: system.hh:333
gem5::GenericTimerMem::TIMER_CTRL_CNTVOFF_HI
static const Addr TIMER_CTRL_CNTVOFF_HI
Definition: generic_timer.hh:582
gem5::ArchTimer::control
uint32_t control() const
Sets the control register.
Definition: generic_timer.hh:239
gem5::GenericTimerMem::read
Tick read(PacketPtr pkt) override
Pure virtual function that the device must implement.
Definition: generic_timer.cc:1401
gem5::ArchTimerKvm::system
ArmSystem & system
Definition: generic_timer.hh:269
gem5::GenericTimerMem::COUNTER_CTRL_CNTSR
static const Addr COUNTER_CTRL_CNTSR
Definition: generic_timer.hh:554
gem5::GenericTimerFrame::TIMER_CNTPCT_LO
static const Addr TIMER_CNTPCT_LO
Definition: generic_timer.hh:464
gem5::ArmISA::MISCREG_CNTKCTL_EL1
@ MISCREG_CNTKCTL_EL1
Definition: misc.hh:790
gem5::GenericTimerFrame::TIMER_CNTVCT_HI
static const Addr TIMER_CNTVCT_HI
Definition: generic_timer.hh:467
gem5::ArmISA::MISCREG_CNTHP_TVAL_EL2
@ MISCREG_CNTHP_TVAL_EL2
Definition: misc.hh:798
gem5::ArchTimer::setControl
void setControl(uint32_t val)
Definition: generic_timer.cc:327
gem5::GenericTimerMem::addrRanges
const AddrRangeList addrRanges
All MMIO ranges GenericTimerMem responds to.
Definition: generic_timer.hh:585
gem5::ArmISA::MISCREG_CNTHCTL_EL2
@ MISCREG_CNTHCTL_EL2
Definition: misc.hh:795
gem5::GenericTimer::CoreTimers::EventStream
Definition: generic_timer.hh:347
gem5::ArmISA::MISCREG_CNTVOFF
@ MISCREG_CNTVOFF
Definition: misc.hh:438
gem5::DrainState
DrainState
Object drain/handover states.
Definition: drain.hh:74
gem5::GenericTimerMem::COUNTER_STATUS_CNTCV_HI
static const Addr COUNTER_STATUS_CNTCV_HI
Definition: generic_timer.hh:567
gem5::GenericTimerMem::counterCtrlRange
const AddrRange counterCtrlRange
Definition: generic_timer.hh:540
gem5::GenericTimerMem::systemCounter
SystemCounter & systemCounter
System counter reference.
Definition: generic_timer.hh:588
gem5::GenericTimer::CoreTimers::cnthctl
ArmISA::CNTHCTL cnthctl
Hypervisor control register.
Definition: generic_timer.hh:323
gem5::GenericTimer::CoreTimers::EventStream::eventTargetValue
uint64_t eventTargetValue(uint64_t val) const
Definition: generic_timer.hh:354
gem5::SystemCounter::serialize
void serialize(CheckpointOut &cp) const override
Serialize an object.
Definition: generic_timer.cc:218
gem5::SystemCounter::whenValue
Tick whenValue(uint64_t target_val)
Returns the tick at which a certain counter value is reached.
Definition: generic_timer.cc:161
gem5::SystemCounter::_freq
uint32_t _freq
Counter frequency (as specified by CNTFRQ).
Definition: generic_timer.hh:92
gem5::GenericTimer::getTimers
CoreTimers & getTimers(int cpu_id)
Definition: generic_timer.cc:476
gem5::ThreadContext
ThreadContext is the external interface to all thread state for anything outside of the CPU.
Definition: thread_context.hh:88
gem5::GenericTimerFrame::TIMER_CNTEL0ACR
static const Addr TIMER_CNTEL0ACR
Definition: generic_timer.hh:469
gem5::Named::name
virtual std::string name() const
Definition: named.hh:47
gem5::Serializable::unserializeSection
void unserializeSection(CheckpointIn &cp, const char *name)
Unserialize an a child object.
Definition: serialize.cc:81
gem5::SystemCounterListener
Abstract class for elements whose events depend on the counting speed of the System Counter.
Definition: generic_timer.hh:76
gem5::VegaISA::p
Bitfield< 54 > p
Definition: pagetable.hh:70
gem5::ArchTimer::offset
uint64_t offset() const
Definition: generic_timer.hh:242
gem5::SimObject::params
const Params & params() const
Definition: sim_object.hh:176
gem5::SystemCounter::activeFreqEntry
size_t activeFreqEntry() const
Returns the currently active frequency table entry.
Definition: generic_timer.hh:131
gem5::GenericTimerFrame::GenericTimerFrame
GenericTimerFrame(const GenericTimerFrameParams &p)
Definition: generic_timer.cc:980
gem5::GenericTimerFrame::hasReadableVoff
bool hasReadableVoff() const
Indicates if CNTVOFF is readable for this frame.
Definition: generic_timer.cc:1071
gem5::VegaISA::PageBytes
const Addr PageBytes
Definition: page_size.hh:42
gem5::MaxAddr
const Addr MaxAddr
Definition: types.hh:171
gem5::GenericTimer::CoreTimers::EventStream::event
EventFunctionWrapper event
Definition: generic_timer.hh:349
DPRINTF
#define DPRINTF(x,...)
Definition: trace.hh:210
gem5::ArchTimer::_systemCounter
SystemCounter & _systemCounter
Definition: generic_timer.hh:196
gem5::Packet
A Packet is used to encapsulate a transfer between two objects in the memory system (e....
Definition: packet.hh:294
gem5::ArmISA::MISCREG_CNTPCT
@ MISCREG_CNTPCT
Definition: misc.hh:419
gem5::GenericTimerISA::readMiscReg
RegVal readMiscReg(int misc_reg) override
Read a system register belonging to this device.
Definition: generic_timer.cc:973
gem5::ArmISA::MISCREG_CNTHP_CVAL_EL2
@ MISCREG_CNTHP_CVAL_EL2
Definition: misc.hh:797
gem5::GenericTimer::CoreTimers::notify
void notify(void) override
Called from the SystemCounter when a change in counting speed occurred Events should be rescheduled p...
Definition: generic_timer.cc:889
gem5::SystemCounter::freq
uint32_t freq() const
Returns the counter frequency.
Definition: generic_timer.hh:123
gem5::GenericTimerMem::counterStatusWrite
void counterStatusWrite(Addr addr, size_t size, uint64_t data)
Definition: generic_timer.cc:1579
gem5::SystemCounter::_activeFreqEntry
size_t _activeFreqEntry
Currently selected entry in the table, its contents should match _freq.
Definition: generic_timer.hh:100
gem5::GenericTimerMem::write
Tick write(PacketPtr pkt) override
Pure virtual function that the device must implement.
Definition: generic_timer.cc:1428
gem5::Tick
uint64_t Tick
Tick count type.
Definition: types.hh:58
gem5::ArmISA::MISCREG_CNTHVS_CTL_EL2
@ MISCREG_CNTHVS_CTL_EL2
Definition: misc.hh:806
gem5::PioDevice::sys
System * sys
Definition: io_device.hh:105
gem5::ArmInterruptPin::clear
virtual void clear()=0
Clear a signalled interrupt.
gem5::GenericTimerFrame::TIMER_CNTV_CTL
static const Addr TIMER_CNTV_CTL
Definition: generic_timer.hh:479
gem5::GenericTimerFrame::TIMER_CNTP_CTL
static const Addr TIMER_CNTP_CTL
Definition: generic_timer.hh:475
gem5::ArmISA::MISCREG_CNTHP_TVAL
@ MISCREG_CNTHP_TVAL
Definition: misc.hh:437
gem5::ArmISA::MISCREG_CNTPS_CVAL_EL1
@ MISCREG_CNTPS_CVAL_EL1
Definition: misc.hh:793
gem5::GenericTimerMem::frames
std::vector< GenericTimerFrame * > frames
Timer frame references.
Definition: generic_timer.hh:594
UNSERIALIZE_OPT_SCALAR
#define UNSERIALIZE_OPT_SCALAR(scalar)
Definition: serialize.hh:582
gem5::GenericTimer
Definition: generic_timer.hh:286
gem5::GenericTimerFrame::hasEl0View
bool hasEl0View() const
Indicates if this frame implements a second EL0 view.
Definition: generic_timer.cc:1041
gem5::ArchTimer::counterLimitReached
void counterLimitReached()
Called when the upcounter reaches the programmed value.
Definition: generic_timer.cc:273
gem5::ArchTimer::whenValue
Tick whenValue(uint64_t target_val)
Definition: generic_timer.hh:247
gem5::SystemCounter::setValue
void setValue(uint64_t new_value)
Sets the value explicitly from writes to CNTCR.CNTCV.
Definition: generic_timer.cc:133
gem5::ArmISA::offset
Bitfield< 23, 0 > offset
Definition: types.hh:144
gem5::AddrRange::valid
bool valid() const
Determine if the range is valid.
Definition: addr_range.hh:336
gem5::GenericTimerMem::validateAccessPerm
static bool validateAccessPerm(ArmSystem &sys, bool is_sec)
Validates an MMIO access permissions.
Definition: generic_timer.cc:1389
gem5::EventManager::reschedule
void reschedule(Event &event, Tick when, bool always=false)
Definition: eventq.hh:1030
gem5::ArchTimer::_parent
EndBitUnion(ArchTimerCtrl) const std SimObject & _parent
Name of this timer.
Definition: generic_timer.hh:188
gem5::insertBits
constexpr T insertBits(T val, unsigned first, unsigned last, B bit_val)
Returns val with bits first to last set to the LSBs of bit_val.
Definition: bitfield.hh:182
gem5::bits
constexpr T bits(T val, unsigned first, unsigned last)
Extract the bitfield from position 'first' to 'last' (inclusive) from 'val' and right justify it.
Definition: bitfield.hh:76
gem5::GenericTimer::CoreTimers::physEL3
ArchTimerKvm physEL3
Definition: generic_timer.hh:336
gem5::GenericTimer::CoreTimers::physEvStream
EventStream physEvStream
Definition: generic_timer.hh:365
gem5::SimObject
Abstract superclass for simulation objects.
Definition: sim_object.hh:146
gem5::DrainState::Drained
@ Drained
Buffers drained, ready for serialization/handover.
gem5::GenericTimer::readMiscReg
RegVal readMiscReg(int misc_reg, unsigned cpu)
Definition: generic_timer.cc:695
gem5::SystemCounter::updateTick
void updateTick(void)
Updates the update tick, normalizes to the lower cycle start tick.
Definition: generic_timer.cc:167
gem5::ArmISA::MISCREG_CNTHP_CTL_EL2
@ MISCREG_CNTHP_CTL_EL2
Definition: misc.hh:796
gem5::ArmISA::evnten
Bitfield< 2 > evnten
Definition: generic_timer_miscregs_types.hh:56
generic_timer.hh
gem5::ArmISA::MISCREG_CNTV_CVAL
@ MISCREG_CNTV_CVAL
Definition: misc.hh:431
gem5::ArmISA::MISCREG_CNTV_CVAL_EL0
@ MISCREG_CNTV_CVAL_EL0
Definition: misc.hh:782
gem5::GenericTimer::CoreTimers::EventStream::transitionBit
uint8_t transitionBit
Definition: generic_timer.hh:351
gem5::ArchTimer::_counterLimitReachedEvent
EventFunctionWrapper _counterLimitReachedEvent
Definition: generic_timer.hh:215
gem5::GenericTimerFrame::TIMER_CNTV_TVAL
static const Addr TIMER_CNTV_TVAL
Definition: generic_timer.hh:478
gem5::GenericTimer::CoreTimers::CoreTimers
CoreTimers(GenericTimer &_parent, ArmSystem &system, unsigned cpu, ArmInterruptPin *irq_el3_phys, ArmInterruptPin *irq_el1_phys, ArmInterruptPin *irq_el1_virt, ArmInterruptPin *irq_el2_ns_phys, ArmInterruptPin *irq_el2_ns_virt, ArmInterruptPin *irq_el2_s_phys, ArmInterruptPin *irq_el2_s_virt)
Definition: generic_timer.cc:810
gem5::Addr
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:147
gem5::ArmISA::MISCREG_CNTHP_CVAL
@ MISCREG_CNTHP_CVAL
Definition: misc.hh:436
name
const std::string & name()
Definition: trace.cc:48
SERIALIZE_SCALAR
#define SERIALIZE_SCALAR(scalar)
Definition: serialize.hh:568
gem5::GenericTimerMem::validateFrameRange
static void validateFrameRange(const AddrRange &range)
Validates a Generic Timer register frame address range.
Definition: generic_timer.cc:1380
gem5::ArmISA::MISCREG_CNTP_TVAL_EL0
@ MISCREG_CNTP_TVAL_EL0
Definition: misc.hh:780
gem5::GenericTimer::system
ArmSystem & system
ARM system containing this timer.
Definition: generic_timer.hh:393
vm.hh
packet_access.hh
gem5::ArmISA::vm
Bitfield< 0 > vm
Definition: misc_types.hh:339
gem5::GenericTimerFrame::nonSecureAccess
bool nonSecureAccess
Reports whether non-secure accesses are allowed to this frame.
Definition: generic_timer.hh:512
gem5::GenericTimerMem::timerCtrlRange
const AddrRange timerCtrlRange
Definition: generic_timer.hh:572
gem5::GenericTimer::CoreTimers::virtEL1
ArchTimerKvm virtEL1
Definition: generic_timer.hh:338
utility.hh
gem5::GenericTimerFrame::setAccessBits
void setAccessBits(uint8_t data)
Updates the access bits after a write to CNTCTLBase.CNTACR.
Definition: generic_timer.cc:1053
gem5::EventManager::deschedule
void deschedule(Event &event)
Definition: eventq.hh:1021
gem5::ArchTimer::_offset
uint64_t _offset
Offset relative to the physical timer (CNTVOFF)
Definition: generic_timer.hh:205
gem5::GenericTimerMem::COUNTER_CTRL_CNTSCR
static const Addr COUNTER_CTRL_CNTSCR
Definition: generic_timer.hh:557
gem5::GenericTimer::CoreTimers::physNsEL2
ArchTimerKvm physNsEL2
Definition: generic_timer.hh:339
gem5::X86ISA::reg
Bitfield< 5, 3 > reg
Definition: types.hh:92
gem5::ArchTimer::setTimerValue
void setTimerValue(uint32_t val)
Sets the TimerValue view of the timer.
Definition: generic_timer.cc:321
gem5::GenericTimerMem::TIMER_CTRL_CNTNSAR
static const Addr TIMER_CTRL_CNTNSAR
Definition: generic_timer.hh:578
gem5::EventFunctionWrapper
Definition: eventq.hh:1136
gem5::SystemCounter::freqTable
std::vector< uint32_t > & freqTable()
Returns a reference to the frequency modes table.
Definition: generic_timer.hh:129
gem5::GenericTimerMem::cnttidr
uint32_t cnttidr
ID register for reporting features of implemented timer frames.
Definition: generic_timer.hh:575
gem5::ArmISA::MISCREG_CNTVOFF_EL2
@ MISCREG_CNTVOFF_EL2
Definition: misc.hh:810
gem5::GenericTimerFrame::timerRead
uint64_t timerRead(Addr addr, size_t size, bool is_sec, bool to_el0) const
CNTBase/CNTEL0Base (Memory-mapped timer frame)
Definition: generic_timer.cc:1144
warn_if
#define warn_if(cond,...)
Conditional warning macro that checks the supplied condition and only prints a warning if the conditi...
Definition: logging.hh:283
panic_if
#define panic_if(cond,...)
Conditional panic macro that checks the supplied condition and only panics if the condition is true a...
Definition: logging.hh:214
gem5::GenericTimerFrame::setNonSecureAccess
void setNonSecureAccess()
Allows non-secure accesses after an enabling write to CNTCTLBase.CNTNSAR.
Definition: generic_timer.cc:1065
gem5::SystemCounter::_nextFreqEntry
size_t _nextFreqEntry
Definition: generic_timer.hh:164
gem5::ArmSystem
Definition: system.hh:92
gem5::SystemCounter::_listeners
std::vector< SystemCounterListener * > _listeners
Listeners to changes in counting speed.
Definition: generic_timer.hh:108
gem5::GenericTimerMem::timerCtrlWrite
void timerCtrlWrite(Addr addr, size_t size, uint64_t data, bool is_sec)
Definition: generic_timer.cc:1637
gem5::ArchTimer::value
uint64_t value() const
Returns the value of the counter which this timer relies on.
Definition: generic_timer.cc:362
gem5::GenericTimer::CoreTimers::cntkctl
ArmISA::CNTKCTL cntkctl
Kernel control register.
Definition: generic_timer.hh:320
gem5::GenericTimerFrame::physTimer
ArchTimer physTimer
Physical and virtual timers.
Definition: generic_timer.hh:488
gem5::SystemCounter::_freqTable
std::vector< uint32_t > _freqTable
Frequency modes table with all possible frequencies for the counter.
Definition: generic_timer.hh:98
gem5::SystemCounter::value
uint64_t value()
Updates and returns the counter value.
Definition: generic_timer.cc:114
gem5::SystemCounter::updateValue
void updateValue(void)
Updates the counter value.
Definition: generic_timer.cc:122
gem5::SystemCounter::_value
uint64_t _value
Counter value (as specified in CNTCV).
Definition: generic_timer.hh:94
gem5::SystemCounter::MAX_FREQ_ENTRIES
static constexpr size_t MAX_FREQ_ENTRIES
Maximum architectural number of frequency table entries.
Definition: generic_timer.hh:111
gem5::ArmISA::MISCREG_CNTHP_CTL
@ MISCREG_CNTHP_CTL
Definition: misc.hh:435
gem5::paramOut
void paramOut(CheckpointOut &cp, const std::string &name, ExtMachInst const &machInst)
Definition: types.cc:40
gem5::SystemCounter::SystemCounter
SystemCounter(const SystemCounterParams &p)
Definition: generic_timer.cc:67
base.hh
gem5::GenericTimerMem::TIMER_CTRL_CNTFRQ
static const Addr TIMER_CTRL_CNTFRQ
Definition: generic_timer.hh:577
gem5::GenericTimerFrame::systemCounter
SystemCounter & systemCounter
System counter reference.
Definition: generic_timer.hh:485
gem5::System::threads
Threads threads
Definition: system.hh:310
gem5::ArmISA::MISCREG_CNTP_CVAL_EL0
@ MISCREG_CNTP_CVAL_EL0
Definition: misc.hh:779
gem5::GenericTimerMem::COUNTER_CTRL_CNTID
static const Addr COUNTER_CTRL_CNTID
Definition: generic_timer.hh:558
gem5::GenericTimer::setMiscReg
void setMiscReg(int misc_reg, unsigned cpu, RegVal val)
Definition: generic_timer.cc:535
gem5::ArchTimer::_interrupt
ArmInterruptPin *const _interrupt
Definition: generic_timer.hh:198
gem5::GenericTimer::systemCounter
SystemCounter & systemCounter
System counter reference.
Definition: generic_timer.hh:386
gem5::ArmISA::MISCREG_CNTHV_TVAL_EL2
@ MISCREG_CNTHV_TVAL_EL2
Definition: misc.hh:805
SERIALIZE_CONTAINER
#define SERIALIZE_CONTAINER(member)
Definition: serialize.hh:626
gem5::ArmISA::sendEvent
void sendEvent(ThreadContext *tc)
Send an event (SEV) to a specific PE if there isn't already a pending event.
Definition: utility.cc:65
gem5::SystemCounter::validateCounterRef
static void validateCounterRef(SystemCounter *sys_cnt)
Validates a System Counter reference.
Definition: generic_timer.cc:91
core.hh
gem5::Packet::makeResponse
void makeResponse()
Take a request packet and modify it in place to be suitable for returning as a response to that reque...
Definition: packet.hh:1062
gem5::ArmISA::MISCREG_CNTP_CVAL_NS
@ MISCREG_CNTP_CVAL_NS
Definition: misc.hh:425
gem5::paramIn
void paramIn(CheckpointIn &cp, const std::string &name, ExtMachInst &machInst)
Definition: types.cc:72
gem5::GenericTimerMem::system
ArmSystem & system
Definition: generic_timer.hh:596
gem5::SystemCounter::enabled
bool enabled() const
Indicates if the counter is enabled.
Definition: generic_timer.hh:121
gem5::GenericTimerFrame::TIMER_CNTFRQ
static const Addr TIMER_CNTFRQ
Definition: generic_timer.hh:468
gem5::GenericTimerFrame::virtTimer
ArchTimer virtTimer
Definition: generic_timer.hh:489
gem5::GenericTimer::CoreTimers::cntfrq
uint32_t cntfrq
System counter frequency as visible from this core.
Definition: generic_timer.hh:317
gem5::GenericTimerFrame::getAddrRanges
AddrRangeList getAddrRanges() const override
Every PIO device is obliged to provide an implementation that returns the address ranges the device r...
Definition: generic_timer.cc:1077
gem5::ArmISA::MISCREG_CNTHPS_CTL_EL2
@ MISCREG_CNTHPS_CTL_EL2
Definition: misc.hh:799
gem5::SystemCounter::disable
void disable()
Disables the counter after a CNTCR.EN == 0.
Definition: generic_timer.cc:106
gem5::SystemCounter::_freqUpdateEvent
EventFunctionWrapper _freqUpdateEvent
Frequency update event handling.
Definition: generic_timer.hh:163
logging.hh
gem5::SystemCounter::freqUpdateSchedule
void freqUpdateSchedule(size_t new_freq_entry)
Schedules a counter frequency update after a CNTCR.FCREQ == 1 This complies with frequency transition...
Definition: generic_timer.cc:173
gem5::ArmSystem::PageBytes
static constexpr Addr PageBytes
Definition: system.hh:146
gem5::GenericTimer::CoreTimers::serialize
void serialize(CheckpointOut &cp) const override
Serialize an object.
Definition: generic_timer.cc:896
gem5::ArmISA::MISCREG_CNTHPS_CVAL_EL2
@ MISCREG_CNTHPS_CVAL_EL2
Definition: misc.hh:800
gem5::GenericTimer::CoreTimers::eventStreamCallback
void eventStreamCallback() const
Definition: generic_timer.cc:874
gem5::ArchTimer::timerValue
uint32_t timerValue() const
Returns the TimerValue view of the timer.
Definition: generic_timer.hh:234
gem5::ArmInterruptPin
Generic representation of an Arm interrupt pin.
Definition: base_gic.hh:199
gem5::CheckpointOut
std::ostream CheckpointOut
Definition: serialize.hh:66
gem5::ArchTimerKvm::scheduleEvents
bool scheduleEvents() override
Definition: generic_timer.cc:411
gem5::ArmInterruptPin::raise
virtual void raise()=0
Signal an interrupt.
gem5::GenericTimerFrame::TIMER_CNTP_CVAL_HI
static const Addr TIMER_CNTP_CVAL_HI
Definition: generic_timer.hh:473
trace.hh
gem5::ArmISA::MISCREG_CNTHV_CVAL_EL2
@ MISCREG_CNTHV_CVAL_EL2
Definition: misc.hh:804
gem5::ArmISA::MISCREG_CNTP_TVAL_S
@ MISCREG_CNTP_TVAL_S
Definition: misc.hh:429
gem5::GenericTimerMem::TIMER_CTRL_CNTACR
static const Addr TIMER_CTRL_CNTACR
Definition: generic_timer.hh:580
gem5::ArchTimer
Per-CPU architected timer.
Definition: generic_timer.hh:179
gem5::GenericTimer::CoreTimers::schedNextEvent
void schedNextEvent(EventStream &ev_stream, ArchTimer &timer)
Definition: generic_timer.cc:881
page_size.hh
gem5::ArchTimer::_counterLimit
uint64_t _counterLimit
Programmed limit value for the upcounter ({CNTP/CNTHP/CNTV}_CVAL).
Definition: generic_timer.hh:203
gem5::ArmISA::MISCREG_CNTFRQ_EL0
@ MISCREG_CNTFRQ_EL0
Definition: misc.hh:775
gem5::AddrRange
The AddrRange class encapsulates an address range, and supports a number of tests to check if two ran...
Definition: addr_range.hh:81
std::list< AddrRange >
gem5::Packet::getAddr
Addr getAddr() const
Definition: packet.hh:807
gem5::GenericTimer::CoreTimers::unserialize
void unserialize(CheckpointIn &cp) override
Unserialize an object.
Definition: generic_timer.cc:930
gem5::GenericTimer::CoreTimers::virtNsEL2
ArchTimerKvm virtNsEL2
Definition: generic_timer.hh:340
gem5::ArmInterruptPin::active
bool active() const
True if interrupt pin is active, false otherwise.
Definition: base_gic.hh:219
gem5::ArchTimer::notify
void notify(void) override
Called from the SystemCounter when a change in counting speed occurred Events should be rescheduled p...
Definition: generic_timer.cc:368
gem5::GenericTimerMem::TIMER_CTRL_CNTVOFF_LO
static const Addr TIMER_CTRL_CNTVOFF_LO
Definition: generic_timer.hh:581
fatal_if
#define fatal_if(cond,...)
Conditional fatal macro that checks the supplied condition and only causes a fatal error if the condi...
Definition: logging.hh:236
gem5::GenericTimerFrame::write
Tick write(PacketPtr pkt) override
Pure virtual function that the device must implement.
Definition: generic_timer.cc:1114
gem5::SystemCounter
Global system counter.
Definition: generic_timer.hh:86
gem5
Reference material can be found at the JEDEC website: UFS standard http://www.jedec....
Definition: gpu_translation_state.hh:37
gem5::GenericTimer::CoreTimers::physEL1
ArchTimerKvm physEL1
Definition: generic_timer.hh:337
gem5::GenericTimer::CoreTimers::virtSEL2
ArchTimerKvm virtSEL2
Definition: generic_timer.hh:342
gem5::ArmISA::MISCREG_CNTV_CTL
@ MISCREG_CNTV_CTL
Definition: misc.hh:430
gem5::ArmISA::MISCREG_CNTP_CTL_S
@ MISCREG_CNTP_CTL_S
Definition: misc.hh:423
gem5::ArmISA::MISCREG_CNTHV_CTL_EL2
@ MISCREG_CNTHV_CTL_EL2
Definition: misc.hh:803
gem5::Packet::setUintX
void setUintX(uint64_t w, ByteOrder endian)
Set the value in the word w after truncating it to the length of the packet and then byteswapping it ...
Definition: packet.cc:361
gem5::ArchTimer::setCompareValue
void setCompareValue(uint64_t val)
Sets the CompareValue view of the timer.
Definition: generic_timer.cc:314
gem5::GenericTimerFrame::serialize
void serialize(CheckpointOut &cp) const override
Serialize an object.
Definition: generic_timer.cc:1005
gem5::ArchTimer::drainResume
void drainResume() override
Resume execution after a successful drain.
Definition: generic_timer.cc:405
gem5::GenericTimerISA::setMiscReg
void setMiscReg(int misc_reg, RegVal val) override
Write to a system register belonging to this device.
Definition: generic_timer.cc:966
gem5::ArchTimer::serialize
void serialize(CheckpointOut &cp) const override
Serialize an object.
Definition: generic_timer.cc:374
gem5::GenericTimer::timers
std::vector< std::unique_ptr< CoreTimers > > timers
Per-CPU physical architected timers.
Definition: generic_timer.hh:389
gem5::GenericTimer::handleStream
void handleStream(CoreTimers::EventStream *ev_stream, ArchTimer *timer, RegVal old_cnt_ctl, RegVal cnt_ctl)
Definition: generic_timer.cc:509
gem5::GenericTimer::createTimers
void createTimers(unsigned cpus)
Definition: generic_timer.cc:485
gem5::GenericTimerMem::COUNTER_CTRL_CNTCV_HI
static const Addr COUNTER_CTRL_CNTCV_HI
Definition: generic_timer.hh:556
gem5::Packet::getSize
unsigned getSize() const
Definition: packet.hh:817
gem5::GenericTimer::CoreTimers::physEventStreamCallback
void physEventStreamCallback()
Definition: generic_timer.cc:860
gem5::ArchTimer::compareValue
uint64_t compareValue() const
Returns the CompareValue view of the timer.
Definition: generic_timer.hh:229
gem5::GenericTimer::unserialize
void unserialize(CheckpointIn &cp) override
Unserialize an object.
Definition: generic_timer.cc:445
gem5::Event::scheduled
bool scheduled() const
Determine if the current event is scheduled.
Definition: eventq.hh:458
gem5::SystemCounter::enable
void enable()
Enables the counter after a CNTCR.EN == 1.
Definition: generic_timer.cc:98
gem5::GenericTimer::CoreTimers::EventStream::transitionTo
uint8_t transitionTo
Definition: generic_timer.hh:350
gem5::GenericTimerMem::timerCtrlRead
uint64_t timerCtrlRead(Addr addr, size_t size, bool is_sec) const
CNTCTLBase (Memory-mapped timer global control frame)
Definition: generic_timer.cc:1593
panic
#define panic(...)
This implements a cprintf based panic() function.
Definition: logging.hh:188
gem5::GenericTimerFrame::getAccessBits
uint8_t getAccessBits() const
Returns the access bits for this frame.
Definition: generic_timer.cc:1047
gem5::X86ISA::addr
Bitfield< 3 > addr
Definition: types.hh:84
gem5::ArmISA::MISCREG_CNTV_TVAL_EL0
@ MISCREG_CNTV_TVAL_EL0
Definition: misc.hh:783
gem5::SystemCounter::_updateTick
Tick _updateTick
Counter cycle start Tick when the counter status affecting its value has been updated.
Definition: generic_timer.hh:105
gem5::GenericTimer::CoreTimers
Definition: generic_timer.hh:301
gem5::GenericTimerFrame::getVirtOffset
uint64_t getVirtOffset() const
Returns the virtual offset for this frame if a virtual timer is implemented.
Definition: generic_timer.cc:1029
gem5::ArchTimer::drain
DrainState drain() override
Draining is the process of clearing out the states of SimObjects.These are the SimObjects that are pa...
Definition: generic_timer.cc:396

Generated on Sun Jul 30 2023 01:56:54 for gem5 by doxygen 1.8.17