ARMv7 Generic Timers
This page is current with the description of the ARM Generic Timer behaviour specified in the ARMv7 manual. There may have been differences introduced in ARMv8 and AArch64. This page does not take such differences, if they exist, into account.
This page is meant to be a quick reference and refresher on the way the ARMv7 generic timers work.
The ARM Generic Timers (henceforth, "GT") are architecturally specified in ARMv7 as an OPTIONAL extension to the ARMv7-a and ARMv7-r streams. The feature is specified to provide a system-wide timestamp-counter (henceforth, "syscounter") reference which operates independent of the CPU clock's frequency, allowing for TSC measurements which are invariant over time, regardless of processor scaling, power state and throttling.
This upcounter can be read in two forms, and these readout-forms are logically distinct from the actual value of the syscounter (though the physcounter will usually reflect the syscounter exactly):
- Physical upcounter readout ("physcounter"). This is read as a 64-bit read using the CNTPCT register.
- Virtual upcounter readout ("virtcounter"). This is the value of the physical timer, minus a 64-bit virtual offset (CNTVOFF). This is read using the CNTVCT register.
The feature also specifies a set of 4 timers per CPU which base their operation on these two upcounters:
- Secure phystimer: based on
- Non-secure phystimer: based on
- Hypervisor timer: based on
- Virtual timer: based on
The GT's syscounter is specified to present the following behaviour to software:
- At least 56 bits wide. Any read from the syscounter, physcounter or virtcounter is zero-extended to 64 bits.
- The syscounter increments at a fixed frequency, with architecturally supported ranges being from 1-50 MHz.
- Supports clock multiplication to save power. I.e, the hardware crystal may operate at a lower frequency than the frequency claimed by the platform, and a multiplier may applied to the readout value to present the illusion of operation at a higher frequency. The underlying crystal's frequency may change dynamically at runtime.
- Roll-over time is guaranteed to be at least 40 years.
- Clock drift is not required to be at any level of accuracy, but ARM RECOMMENDS that drift be not greater than 10 seconds per 24 hours. The use of clock multiplication must not change the drift behaviour of the sysupcounter.
- The syscounter is architecturally specified to begin counting from 0 at #RESET.
- The syscounter must be implemented in the always-on power domain.
All agents (including devices in the system other than the host processors) reading the syscounter must be presented with a uniform view of the passage of time.
The control registers for the system counter are not accessible as coprocessor interface registers, and are only accessible through a memory mapped interface. The controls include enabling/disabling the syscounter, setting the syscounter's value, changing the syscounter's frequency and multiplier, and enabling/disabling halt-on-debug, so that a debugger can halt the syscounter when a processor enters halting debug-mode.
The physical and virtual upcounters as well as the timer registers are architecturally configurable.
Enables PL1 software to control access to the counters and timers from PL0 modes.
- Bits PL0PCTEN and PL0VCTEN enable/disable access to CNTVCT, CNTPCT and CNTFREQ from PL0 modes.
- Bit PL0PTEN enables/disables access to CNTP_CTL, CNTP_CVAL and CNTP_TVAL from PL0 modes.
- Bit PL0VTEN enables/disables access to CNTV_CTL, CNTV_CVAL and CNTV_TVAL from PL0 modes.
- Bits EVENTEN, EVENTDIR and EVENTI enable and control the direction and bit-position of the bit that triggers the events generated by the virtual counter (CNTVCT).
Enables PL2 software to control access to the counters and timers from non-secure PL1 and PL0 modes.
- Bit PL1PCTEN enables/disables access to CNTPCT from non-secure PL1 and PL0 modes.
- PL1PCEN enables/disables access to the phyisical timer registers (CNTP_CTL, CNTP_TVAL, CNTP_CVAL) from non-secure PL1 and PL0 mode.
The CNTFREQ register is only writeable by secure PL1 mode software, and must be initialized to state the frequency of the system upcounter, in Hz. CNTFREQ is readable by PL2, secure and non-secure PL1 by default. CNTKCTL.PL0PCTEN enables CNTFREQ to be read from secure and non-secure PL0.
Use ISB to ensure that CNTPCT reads are executed in order.
- Is always accessible from PL2.
- Is always accessible from PL1 modes. However, if hypervisor extensions are supported accesses to CNTPCT will generate a hyp-trap from PL1 unless CNTHCTL.PL1PCTEN is set to 1.
- Is only accessible from PL0 modes if CNTKCTL.PL0CTEN is set to 1. Attempts to access CNTPCT from PL0 when CNTKCTL.PL0CTEN==0 will trigger an #UNDEFINED exception.
CNTPCT is logically meant to be read by PL2 hypervisors when they need to read a timestamp value. It can be read by secure PL1 software with no hindrances as well. There is no statement about whether or not it can be accessed from PL3 monitors.
- Accessible as R/W from PL2.
- Accessible from PL3 (Monitor mode) only when SCR.NS==1.
If the virtualization extensions are not supported, accesses to CNTVOFF from PL3 are UNPREDICTABLE, and reads of CNTVCT act as if CNTVOFF is zero. CNTVOFF is logically meant to be written by a PL2 hypervisor when switching between GuestVMs. It is also writeable by PL3 when SCR.NS=1, but this is not very useful to a PL3 monitor.
In a processor that doesn't support the virtualization extensions, CNTVCT is identical to CNTPCT.
- Always accessible from secure PL1.
- Always accessible from non-secure PL1 and PL2.
- Accessible from PL0 modes when CNTKCTL.PL0VCTEN==1.
CNTVCT is logically meant to be used by both secure and non-secure PL1 kernels. It can be read by PL2 hypervisors, but the usefulness of such a read is questionable, when they can instead read CNTPCT. There is no statement about whether or not it can be accessed from PL3 monitors.
Virtual counter Event Streams
Events can be triggered by the virtcounter through the use of the CNTKCTL register. You would set the bit position whose transition from 0=>1 or 1=>0 will trigger an event, and then enable the event. The design of this feature obviously means that virtcounter events can only be triggered on power-of-2 counter-values.
- The timers can be used as either count-up or count-down timers.
- The timers can operate in either physical or virtual time.
- The timers output signals can be configured as level-sensitive PPI IRQ signals to the GICC.
Security Extentions not implemented
- Physical timer and virtual timer.
The virtual timer should be used by PL1 kernels. The physical timer should ideally be left alone.
Security extensions implemented, no Hypervisor extensions implemented
- non-secure physical timer.
- Secure physical timer.
- Virtual timer.
The virtual timer should be used by non-secure PL1 kernels. The secure physical timer should be used by PL3 monitors and secure PL1 kernels. The non-secure physical timer should be ideally left alone, and seems to exist solely for the sake of supporting non-secure PL1 kernels which insist on using the physcounter and physical registers instead of the virtcounter and virtual registers.
Security extensions and hypervisor extensions implemented
- Non-secure PL1 physical timer.
- Secure PL1 physical timer.
- Non-secure PL2 physical timer.
- Virtual timer.
The virtual timer should be used by non-secure PL1 kernels. The secure PL1 physical timer should be used by secure PL1 kernels. The non-secure PL2 physical timer should be used by PL2 hypervisors. The non-secure PL1 physical timer should be left alone, ideally and seems to exist solely for the sake of supporting non-secure PL1 kernels that insist on using the physcounter and physical registers instead of the virtcounter and virtual registers.