48#include "config/kvm_isa.hh"
49#include "config/use_kvm.hh"
52#include "debug/Timer.hh"
55#include "params/GenericTimer.hh"
56#include "params/GenericTimerFrame.hh"
57#include "params/GenericTimerMem.hh"
58#include "params/SystemCounter.hh"
65using namespace ArmISA;
79 "frequency not provided\n");
83 "SystemCounter::SystemCounter: Architecture states a maximum of 1004 "
84 "frequency table entries, limit surpassed\n");
93 fatal_if(!sys_cnt,
"SystemCounter::validateCounterRef: No valid system "
94 "counter, can't instantiate system timers\n");
100 DPRINTF(Timer,
"SystemCounter::enable: Counter enabled\n");
108 DPRINTF(Timer,
"SystemCounter::disable: Counter disabled\n");
136 warn(
"Explicit value set with counter enabled, UNKNOWNN result\n");
146 if (target_val > cur_val) {
147 uint64_t num_cycles =
148 std::ceil((target_val - cur_val) / ((
double)
_increment));
177 if (new_freq !=
_freq) {
183 uint64_t target_val =
value();
184 target_val += target_val % std::max(
_increment, new_incr);
193 DPRINTF(Timer,
"SystemCounter::freqUpdateCallback: Changing counter "
220 DPRINTF(Timer,
"SystemCounter::serialize: Serializing\n");
230 if (pending_freq_update) {
240 DPRINTF(Timer,
"SystemCounter::unserialize: Unserializing\n");
248 bool pending_freq_update;
250 if (pending_freq_update) {
251 Tick when_freq_update;
264 : _name(
name), _parent(parent), _systemCounter(sysctr),
265 _interrupt(interrupt),
266 _control(0), _counterLimit(0), _offset(0),
269 _systemCounter.registerListener(
this);
278 DPRINTF(Timer,
"Counter limit reached\n");
282 DPRINTF(Timer,
"Causing interrupt\n");
285 DPRINTF(Timer,
"Kvm mode; skipping simulated interrupt\n");
300 DPRINTF(Timer,
"Clearing interrupt\n");
334 if ((old_ctl.imask && !new_ctl.imask) ||
335 (!old_ctl.enable && new_ctl.enable))
338 else if ((!old_ctl.imask && new_ctl.imask) ||
339 (old_ctl.enable && !new_ctl.enable)) {
342 DPRINTF(Timer,
"Clearing interrupt\n");
413 if constexpr (USE_KVM &&
414 std::string_view(KVM_ISA) == std::string_view(
"arm")) {
424 systemCounter(*
p.counter),
428 fatal_if(!
p.system,
"GenericTimer::GenericTimer: No system specified, "
429 "can't instantiate architected timers\n");
438 for (
int i = 0;
i <
timers.size(); ++
i) {
450 static const unsigned OLD_CPU_MAX = 8;
453 warn(
"Checkpoint does not contain CPU count, assuming %i CPUs\n",
455 cpu_count = OLD_CPU_MAX;
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.",
469 for (
int i = 0;
i < cpu_count; ++
i) {
478 if (cpu_id >=
timers.size())
487 assert(
timers.size() < cpus);
490 const unsigned old_cpu_count(
timers.size());
492 for (
unsigned i = old_cpu_count;
i < cpus; ++
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)));
513 uint64_t old_evnten =
bits(old_cnt_ctl, 2);
527 }
else if (old_evnten && !
evnten) {
544 "does not match the system counter freq\n");
591 warn(
"Ignoring write to read only count register: %s\n",
705 return core.
cntkctl & 0x00000000ffffffff;
708 return core.
cnthctl & 0x00000000ffffffff;
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,
830 physEL1(
csprintf(
"%s.el1_phys_timer%d", parent.
name(), cpu),
831 system, parent, parent.systemCounter,
833 virtEL1(
csprintf(
"%s.el1_virt_timer%d", parent.
name(), cpu),
834 system, parent, parent.systemCounter,
836 physNsEL2(
csprintf(
"%s.el2_ns_phys_timer%d", parent.
name(), cpu),
837 system, parent, parent.systemCounter,
839 virtNsEL2(
csprintf(
"%s.el2_ns_virt_timer%d", parent.
name(), cpu),
840 system, parent, parent.systemCounter,
842 physSEL2(
csprintf(
"%s.el2_s_phys_timer%d", parent.
name(), cpu),
843 system, parent, parent.systemCounter,
845 virtSEL2(
csprintf(
"%s.el2_s_virt_timer%d", parent.
name(), cpu),
846 system, parent, parent.systemCounter,
850 csprintf(
"%s.phys_event_gen%d", parent.name(), cpu)), 0, 0
854 csprintf(
"%s.virt_event_gen%d", parent.name(), cpu)), 0, 0
869 eventStreamCallback();
870 schedNextEvent(virtEvStream, virtEL1);
877 threadContext->getCpuPtr()->wakeup(threadContext->threadId());
891 schedNextEvent(virtEvStream, virtEL1);
892 schedNextEvent(physEvStream, physEL1);
902 const bool phys_ev_scheduled = physEvStream.event.scheduled();
904 if (phys_ev_scheduled) {
905 const Tick phys_ev_when = physEvStream.event.when();
911 const bool virt_ev_scheduled = virtEvStream.event.scheduled();
913 if (virt_ev_scheduled) {
914 const Tick virt_ev_when = virtEvStream.event.when();
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");
936 bool phys_ev_scheduled;
938 if (phys_ev_scheduled) {
941 parent.reschedule(physEvStream.event, phys_ev_when,
true);
946 bool virt_ev_scheduled;
948 if (virt_ev_scheduled) {
951 parent.reschedule(virtEvStream.event, virt_ev_when,
true);
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");
969 parent.setMiscReg(
reg, cpu,
val);
975 RegVal value = parent.readMiscReg(
reg, cpu);
984 systemCounter(*
p.counter),
986 *
this, systemCounter,
p.int_phys->get()),
988 *
this, systemCounter,
997 accessBitsEl0 = 0x303;
998 addrRanges.push_back(timerEl0Range);
1000 for (
auto &range : addrRanges)
1001 GenericTimerMem::validateFrameRange(range);
1055 accessBits =
data & 0x3f;
1073 return accessBits.rvoff;
1086 const size_t size = pkt->
getSize();
1087 const bool is_sec = pkt->
isSecure();
1089 "GenericTimerFrame::read: Invalid size %i\n", size);
1091 bool to_el0 =
false;
1100 panic(
"GenericTimerFrame::read: Invalid address: 0x%x\n",
addr);
1105 DPRINTF(Timer,
"GenericTimerFrame::read: 0x%x<-0x%x(%i) [S = %u]\n", resp,
1106 addr, size, is_sec);
1108 pkt->
setUintX(resp, ByteOrder::little);
1117 const size_t size = pkt->
getSize();
1118 const bool is_sec = pkt->
isSecure();
1120 "GenericTimerFrame::write: Invalid size %i\n", size);
1122 bool to_el0 =
false;
1123 const uint64_t
data = pkt->
getUintX(ByteOrder::little);
1131 panic(
"GenericTimerFrame::write: Invalid address: 0x%x\n",
addr);
1136 DPRINTF(Timer,
"GenericTimerFrame::write: 0x%x->0x%x(%i) [S = %u]\n",
data,
1137 addr, size, is_sec);
1153 if (!accessBits.rpct || (to_el0 && !accessBitsEl0.pcten))
1159 if (!accessBits.rpct || (to_el0 && !accessBitsEl0.pcten))
1165 if ((!accessBits.rfrq) ||
1166 (to_el0 && (!accessBitsEl0.pcten && !accessBitsEl0.vcten)))
1175 return accessBitsEl0;
1178 if (!accessBits.rwpt || (to_el0 && !accessBitsEl0.pten))
1184 if (!accessBits.rwpt || (to_el0 && !accessBitsEl0.pten))
1190 if (!accessBits.rwpt || (to_el0 && !accessBitsEl0.pten))
1195 if (!accessBits.rwpt || (to_el0 && !accessBitsEl0.pten))
1201 if (!accessBits.rvct || (to_el0 && !accessBitsEl0.vcten))
1207 if (!accessBits.rvct || (to_el0 && !accessBitsEl0.vcten))
1213 if (!accessBits.rvoff || (to_el0))
1219 if (!accessBits.rvoff || (to_el0))
1225 if (!accessBits.rwvt || (to_el0 && !accessBitsEl0.vten))
1231 if (!accessBits.rwvt || (to_el0 && !accessBitsEl0.vten))
1237 if (!accessBits.rwvt || (to_el0 && !accessBitsEl0.vten))
1243 if (!accessBits.rwvt || (to_el0 && !accessBitsEl0.vten))
1249 warn(
"GenericTimerFrame::timerRead: Unexpected address (0x%x:%i), "
1250 "assuming RAZ\n",
addr, size);
1257 bool is_sec,
bool to_el0)
1265 warn(
"GenericTimerFrame::timerWrite: RO reg (0x%x) [CNTPCT]\n",
1270 warn(
"GenericTimerFrame::timerWrite: RO reg (0x%x) [CNTFRQ]\n",
1283 if ((!accessBits.rwpt) || (to_el0 && !accessBitsEl0.pten))
1291 if ((!accessBits.rwpt) || (to_el0 && !accessBitsEl0.pten))
1298 if ((!accessBits.rwpt) || (to_el0 && !accessBitsEl0.pten))
1304 if ((!accessBits.rwpt) || (to_el0 && !accessBitsEl0.pten))
1310 warn(
"GenericTimerFrame::timerWrite: RO reg (0x%x) [CNTVCT]\n",
1314 warn(
"GenericTimerFrame::timerWrite: RO reg (0x%x) [CNTVOFF]\n",
1319 if ((!accessBits.rwvt) || (to_el0 && !accessBitsEl0.vten))
1327 if ((!accessBits.rwvt) || (to_el0 && !accessBitsEl0.vten))
1334 if ((!accessBits.rwvt) || (to_el0 && !accessBitsEl0.vten))
1340 if ((!accessBits.rwvt) || (to_el0 && !accessBitsEl0.vten))
1346 warn(
"GenericTimerFrame::timerWrite: Unexpected address (0x%x:%i), "
1347 "assuming WI\n",
addr, size);
1357 addrRanges{counterCtrlRange, counterStatusRange, timerCtrlRange},
1358 systemCounter(*
p.counter),
1366 "GenericTimerMem::GenericTimerMem: Architecture states a maximum of "
1367 "8 memory-mapped timer frames, limit surpassed\n");
1369 for (
int i = 0;
i <
frames.size();
i++) {
1370 uint32_t features = 0x1;
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");
1391 return !
sys.has(ArmExtension::SECURITY) || is_sec;
1404 const size_t size = pkt->
getSize();
1405 const bool is_sec = pkt->
isSecure();
1407 "GenericTimerMem::read: Invalid size %i\n", size);
1417 panic(
"GenericTimerMem::read: Invalid address: 0x%x\n",
addr);
1419 DPRINTF(Timer,
"GenericTimerMem::read: 0x%x<-0x%x(%i) [S = %u]\n", resp,
1420 addr, size, is_sec);
1422 pkt->
setUintX(resp, ByteOrder::little);
1431 const size_t size = pkt->
getSize();
1432 const bool is_sec = pkt->
isSecure();
1434 "GenericTimerMem::write: Invalid size %i\n", size);
1436 const uint64_t
data = pkt->
getUintX(ByteOrder::little);
1444 panic(
"GenericTimerMem::write: Invalid address: 0x%x\n",
addr);
1446 DPRINTF(Timer,
"GenericTimerMem::write: 0x%x->0x%x(%i) [S = %u]\n",
data,
1447 addr, size, is_sec);
1459 case COUNTER_CTRL_CNTCR:
1479 for (
int i = 0;
i < (freq_table.size() - 1);
i++) {
1482 return freq_table[
i];
1484 warn(
"GenericTimerMem::counterCtrlRead: Unexpected address "
1485 "(0x%x:%i), assuming RAZ\n",
addr, size);
1499 case COUNTER_CTRL_CNTCR:
1508 warn(
"GenericTimerMem::counterCtrlWrite: Halt-on-debug is not "
1511 warn(
"GenericTimerMem::counterCtrlWrite: Counter Scaling is not "
1519 warn(
"GenericTimerMem::counterCtrlWrite: RO reg (0x%x) [CNTSR]\n",
1538 warn(
"GenericTimerMem::counterCtrlWrite: RO reg (0x%x) [CNTID]\n",
1545 for (
int i = 0;
i < (freq_table.size() - 1);
i++) {
1548 freq_table[
i] =
data;
1559 warn(
"GenericTimerMem::counterCtrlWrite: Unexpected address "
1560 "(0x%x:%i), assuming WI\n",
addr, size);
1572 warn(
"GenericTimerMem::counterStatusRead: Unexpected address "
1573 "(0x%x:%i), assuming RAZ\n",
addr, size);
1583 warn(
"GenericTimerMem::counterStatusWrite: RO reg (0x%x) [CNTCV]\n",
1587 warn(
"GenericTimerMem::counterStatusWrite: Unexpected address "
1588 "(0x%x:%i), assuming WI\n",
addr, size);
1602 uint32_t cntnsar = 0x0;
1603 for (
int i = 0;
i <
frames.size();
i++) {
1604 if (
frames[
i]->hasNonSecureAccess())
1605 cntnsar |= 0x1 <<
i;
1611 for (
int i = 0;
i <
frames.size();
i++) {
1617 bool hit =
addr == cntacr_off ||
addr == cntvoff_lo_off ||
1618 addr == cntvoff_hi_off;
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;
1630 warn(
"GenericTimerMem::timerCtrlRead: Unexpected address (0x%x:%i), "
1631 "assuming RAZ\n",
addr, size);
1644 "GenericTimerMem::timerCtrlWrite: CNTFRQ configured freq "
1645 "does not match the counter freq, ignoring\n");
1649 for (
int i = 0;
i <
frames.size();
i++) {
1651 if (
data & (0x1 <<
i))
1652 frames[
i]->setNonSecureAccess();
1656 warn(
"GenericTimerMem::timerCtrlWrite: RO reg (0x%x) [CNTTIDR]\n",
1660 for (
int i = 0;
i <
frames.size();
i++) {
1666 bool hit =
addr == cntacr_off ||
addr == cntvoff_lo_off ||
1667 addr == cntvoff_hi_off;
1670 frames[
i]->hasNonSecureAccess();
1671 if (hit && !has_access)
return;
1672 if (
addr == cntacr_off) {
1676 if (
addr == cntvoff_lo_off ||
addr == cntvoff_hi_off) {
1677 if (
addr == cntvoff_lo_off)
1687 warn(
"GenericTimerMem::timerCtrlWrite: Unexpected address "
1688 "(0x%x:%i), assuming WI\n",
addr, size);
Base class for ARM GIC implementations.
The AddrRange class encapsulates an address range, and supports a number of tests to check if two ran...
bool scheduleEvents() override
Per-CPU architected timer.
EventFunctionWrapper _counterLimitReachedEvent
void setTimerValue(uint32_t val)
Sets the TimerValue view of the timer.
uint32_t timerValue() const
Returns the TimerValue view of the timer.
virtual bool scheduleEvents()
DrainState drain() override
Draining is the process of clearing out the states of SimObjects.These are the SimObjects that are pa...
EndBitUnion(ArchTimerCtrl) const std SimObject & _parent
Name of this timer.
void drainResume() override
Resume execution after a successful drain.
uint64_t compareValue() const
Returns the CompareValue view of the timer.
uint64_t _offset
Offset relative to the physical timer (CNTVOFF)
void notify(void) override
Called from the SystemCounter when a change in counting speed occurred Events should be rescheduled p...
void setCompareValue(uint64_t val)
Sets the CompareValue view of the timer.
ArchTimer(const std::string &name, SimObject &parent, SystemCounter &sysctr, ArmInterruptPin *interrupt)
ArchTimerCtrl _control
Value of the control register ({CNTP/CNTHP/CNTV}_CTL).
void setOffset(uint64_t val)
void serialize(CheckpointOut &cp) const override
Serialize an object.
void unserialize(CheckpointIn &cp) override
Unserialize an object.
uint64_t value() const
Returns the value of the counter which this timer relies on.
void setControl(uint32_t val)
uint32_t control() const
Sets the control register.
void updateCounter()
Timer settings or the offset has changed, re-evaluate trigger condition and raise interrupt if necess...
SystemCounter & _systemCounter
void counterLimitReached()
Called when the upcounter reaches the programmed value.
ArmInterruptPin *const _interrupt
uint64_t _counterLimit
Programmed limit value for the upcounter ({CNTP/CNTHP/CNTV}_CVAL).
Tick whenValue(uint64_t target_val)
Generic representation of an Arm interrupt pin.
virtual void clear()=0
Clear a signalled interrupt.
virtual void raise()=0
Signal an interrupt.
bool active() const
True if interrupt pin is active, false otherwise.
void setGenericTimer(GenericTimer *generic_timer)
Sets the pointer to the Generic Timer.
static constexpr Addr PageBytes
GenericTimerFrame(const GenericTimerFrameParams &p)
static const Addr TIMER_CNTP_CTL
void serialize(CheckpointOut &cp) const override
Serialize an object.
static const Addr TIMER_CNTV_TVAL
bool nonSecureAccess
Reports whether non-secure accesses are allowed to this frame.
uint64_t timerRead(Addr addr, size_t size, bool is_sec, bool to_el0) const
CNTBase/CNTEL0Base (Memory-mapped timer frame)
bool hasEl0View() const
Indicates if this frame implements a second EL0 view.
static const Addr TIMER_CNTP_CVAL_HI
void unserialize(CheckpointIn &cp) override
Unserialize an object.
Tick read(PacketPtr pkt) override
Pure virtual function that the device must implement.
static const Addr TIMER_CNTV_CVAL_LO
static const Addr TIMER_CNTVCT_LO
uint8_t getAccessBits() const
Returns the access bits for this frame.
static const Addr TIMER_CNTFRQ
SystemCounter & systemCounter
System counter reference.
bool hasNonSecureAccess() const
Indicates if non-secure accesses are allowed to this frame.
ArchTimer physTimer
Physical and virtual timers.
static const Addr TIMER_CNTP_CVAL_LO
void setAccessBits(uint8_t data)
Updates the access bits after a write to CNTCTLBase.CNTACR.
static const Addr TIMER_CNTV_CVAL_HI
void setVirtOffset(uint64_t new_offset)
Sets the virtual offset for this frame's virtual timer after a write to CNTVOFF.
const AddrRange timerRange
AddrRangeList getAddrRanges() const override
Every PIO device is obliged to provide an implementation that returns the address ranges the device r...
static const Addr TIMER_CNTP_TVAL
static const Addr TIMER_CNTVOFF_HI
static const Addr TIMER_CNTVCT_HI
AddrRangeList addrRanges
All MMIO ranges GenericTimerFrame responds to.
bool hasReadableVoff() const
Indicates if CNTVOFF is readable for this frame.
static const Addr TIMER_CNTPCT_LO
static const Addr TIMER_CNTVOFF_LO
static const Addr TIMER_CNTPCT_HI
uint64_t getVirtOffset() const
Returns the virtual offset for this frame if a virtual timer is implemented.
static const Addr TIMER_CNTEL0ACR
void setNonSecureAccess()
Allows non-secure accesses after an enabling write to CNTCTLBase.CNTNSAR.
static const Addr TIMER_CNTV_CTL
void timerWrite(Addr addr, size_t size, uint64_t data, bool is_sec, bool to_el0)
Tick write(PacketPtr pkt) override
Pure virtual function that the device must implement.
RegVal readMiscReg(int misc_reg) override
Read a system register belonging to this device.
void setMiscReg(int misc_reg, RegVal val) override
Write to a system register belonging to this device.
void counterCtrlWrite(Addr addr, size_t size, uint64_t data, bool is_sec)
static const Addr COUNTER_CTRL_CNTID
uint64_t counterCtrlRead(Addr addr, size_t size, bool is_sec) const
CNTControlBase (System counter control frame)
const AddrRange timerCtrlRange
static const Addr TIMER_CTRL_CNTTIDR
static const Addr COUNTER_CTRL_CNTCV_HI
static const Addr COUNTER_CTRL_CNTFID
GenericTimerMem(const GenericTimerMemParams &p)
static const Addr COUNTER_CTRL_CNTCV_LO
void counterStatusWrite(Addr addr, size_t size, uint64_t data)
std::vector< GenericTimerFrame * > frames
Timer frame references.
static const Addr TIMER_CTRL_CNTFRQ
static const Addr COUNTER_STATUS_CNTCV_HI
static const Addr COUNTER_CTRL_CNTSCR
const AddrRange counterStatusRange
static const Addr TIMER_CTRL_CNTACR
uint64_t timerCtrlRead(Addr addr, size_t size, bool is_sec) const
CNTCTLBase (Memory-mapped timer global control frame)
const AddrRange counterCtrlRange
Tick read(PacketPtr pkt) override
Pure virtual function that the device must implement.
static const Addr TIMER_CTRL_CNTVOFF_LO
static void validateFrameRange(const AddrRange &range)
Validates a Generic Timer register frame address range.
uint64_t counterStatusRead(Addr addr, size_t size) const
CNTReadBase (System counter status frame)
static const Addr COUNTER_STATUS_CNTCV_LO
AddrRangeList getAddrRanges() const override
Every PIO device is obliged to provide an implementation that returns the address ranges the device r...
void timerCtrlWrite(Addr addr, size_t size, uint64_t data, bool is_sec)
Tick write(PacketPtr pkt) override
Pure virtual function that the device must implement.
uint32_t cnttidr
ID register for reporting features of implemented timer frames.
static const Addr COUNTER_CTRL_CNTSR
SystemCounter & systemCounter
System counter reference.
const AddrRangeList addrRanges
All MMIO ranges GenericTimerMem responds to.
static constexpr size_t MAX_TIMER_FRAMES
Maximum architectural number of memory-mapped timer frames.
static const Addr TIMER_CTRL_CNTNSAR
static bool validateAccessPerm(ArmSystem &sys, bool is_sec)
Validates an MMIO access permissions.
static const Addr TIMER_CTRL_CNTVOFF_HI
void notify(void) override
Called from the SystemCounter when a change in counting speed occurred Events should be rescheduled p...
void serialize(CheckpointOut &cp) const override
Serialize an object.
void schedNextEvent(EventStream &ev_stream, ArchTimer &timer)
void virtEventStreamCallback()
uint32_t cntfrq
System counter frequency as visible from this core.
void eventStreamCallback() const
void unserialize(CheckpointIn &cp) override
Unserialize an object.
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)
ArmISA::CNTHCTL cnthctl
Hypervisor control register.
ArmISA::CNTKCTL cntkctl
Kernel control register.
void physEventStreamCallback()
std::vector< std::unique_ptr< CoreTimers > > timers
Per-CPU physical architected timers.
void serialize(CheckpointOut &cp) const override
Serialize an object.
void setMiscReg(int misc_reg, unsigned cpu, RegVal val)
CoreTimers & getTimers(int cpu_id)
RegVal readMiscReg(int misc_reg, unsigned cpu)
void unserialize(CheckpointIn &cp) override
Unserialize an object.
void createTimers(unsigned cpus)
SystemCounter & systemCounter
System counter reference.
void handleStream(CoreTimers::EventStream *ev_stream, ArchTimer *timer, RegVal old_cnt_ctl, RegVal cnt_ctl)
ArmSystem & system
ARM system containing this timer.
GenericTimer(const Params &p)
bool validEnvironment() const
Verify gem5 configuration will support KVM emulation.
A Packet is used to encapsulate a transfer between two objects in the memory system (e....
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 ...
void makeResponse()
Take a request packet and modify it in place to be suitable for returning as a response to that reque...
uint64_t getUintX(ByteOrder endian) const
Get the data in the packet byte swapped from the specified endianness and zero-extended to 64 bits.
This device is the base class which all devices senstive to an address range inherit from.
Abstract superclass for simulation objects.
Abstract class for elements whose events depend on the counting speed of the System Counter.
void updateValue(void)
Updates the counter value.
uint32_t _freq
Counter frequency (as specified by CNTFRQ).
std::vector< uint32_t > _freqTable
Frequency modes table with all possible frequencies for the counter.
bool enabled() const
Indicates if the counter is enabled.
std::vector< SystemCounterListener * > _listeners
Listeners to changes in counting speed.
void setValue(uint64_t new_value)
Sets the value explicitly from writes to CNTCR.CNTCV.
Tick _period
Cached copy of the counter period (inverse of the frequency).
Tick whenValue(uint64_t target_val)
Returns the tick at which a certain counter value is reached.
SystemCounter(const SystemCounterParams &p)
EventFunctionWrapper _freqUpdateEvent
Frequency update event handling.
size_t activeFreqEntry() const
Returns the currently active frequency table entry.
static constexpr size_t MAX_FREQ_ENTRIES
Maximum architectural number of frequency table entries.
static void validateCounterRef(SystemCounter *sys_cnt)
Validates a System Counter reference.
void updateTick(void)
Updates the update tick, normalizes to the lower cycle start tick.
uint64_t value()
Updates and returns the counter value.
void disable()
Disables the counter after a CNTCR.EN == 0.
void notifyListeners(void) const
Notifies counting speed changes to listeners.
void serialize(CheckpointOut &cp) const override
Serialize an object.
std::vector< uint32_t > & freqTable()
Returns a reference to the frequency modes table.
void enable()
Enables the counter after a CNTCR.EN == 1.
uint64_t _value
Counter value (as specified in CNTCV).
uint32_t freq() const
Returns the counter frequency.
void freqUpdateCallback()
Callback for the frequency update.
Tick _updateTick
Counter cycle start Tick when the counter status affecting its value has been updated.
uint64_t _increment
Value increment in each counter cycle.
size_t _activeFreqEntry
Currently selected entry in the table, its contents should match _freq.
void registerListener(SystemCounterListener *listener)
Called from System Counter Listeners to register.
void freqUpdateSchedule(size_t new_freq_entry)
Schedules a counter frequency update after a CNTCR.FCREQ == 1 This complies with frequency transition...
void unserialize(CheckpointIn &cp) override
Unserialize an object.
bool _enabled
Indicates if the counter is enabled.
KvmVM * getKvmVM() const
Get a pointer to the Kernel Virtual Machine (KVM) SimObject, if present.
ThreadContext is the external interface to all thread state for anything outside of the CPU.
This module implements the global system counter and the local per-CPU architected timers as specifie...
AddrRange RangeSize(Addr start, Addr size)
bool valid() const
Determine if the range is valid.
bool contains(const Addr &a) const
Determine if the range contains an address.
Addr start() const
Get the start address of the range.
constexpr T bits(T val, unsigned first, unsigned last)
Extract the bitfield from position 'first' to 'last' (inclusive) from 'val' and right justify it.
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.
constexpr uint64_t sext(uint64_t val)
Sign-extend an N-bit value to 64 bits.
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.
DrainState
Object drain/handover states.
@ Drained
Buffers drained, ready for serialization/handover.
void deschedule(Event &event)
bool scheduled() const
Determine if the current event is scheduled.
void schedule(Event &event, Tick when)
void reschedule(Event &event, Tick when, bool always=false)
Tick when() const
Get the time that the event is scheduled.
#define panic(...)
This implements a cprintf based panic() function.
#define fatal_if(cond,...)
Conditional fatal macro that checks the supplied condition and only causes a fatal error if the condi...
#define fatal(...)
This implements a cprintf based fatal() function.
#define panic_if(cond,...)
Conditional panic macro that checks the supplied condition and only panics if the condition is true a...
#define UNSERIALIZE_CONTAINER(member)
#define UNSERIALIZE_OPT_SCALAR(scalar)
void serializeSection(CheckpointOut &cp, const char *name) const
Serialize an object into a new section.
#define SERIALIZE_CONTAINER(member)
void unserializeSection(CheckpointIn &cp, const char *name)
Unserialize an a child object.
const Params & params() const
#define warn_if(cond,...)
Conditional warning macro that checks the supplied condition and only prints a warning if the conditi...
void sendEvent(ThreadContext *tc)
Send an event (SEV) to a specific PE if there isn't already a pending event.
@ MISCREG_CNTHPS_CVAL_EL2
@ MISCREG_CNTHPS_TVAL_EL2
@ MISCREG_CNTHVS_TVAL_EL2
@ MISCREG_CNTHVS_CVAL_EL2
const char *const miscRegName[]
Tick Frequency
The simulated frequency of curTick(). (In ticks per second)
Copyright (c) 2024 - Pranith Kumar Copyright (c) 2020 Inria All rights reserved.
Tick curTick()
The universal simulation clock.
std::ostream CheckpointOut
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
void paramOut(CheckpointOut &cp, const std::string &name, ExtMachInst const &machInst)
void paramIn(CheckpointIn &cp, const std::string &name, ExtMachInst &machInst)
uint64_t Tick
Tick count type.
std::string csprintf(const char *format, const Args &...args)
#define UNSERIALIZE_SCALAR(scalar)
#define SERIALIZE_SCALAR(scalar)
EventFunctionWrapper event
uint64_t eventTargetValue(uint64_t val) const
const std::string & name()