pub struct GenericTimer<const BITS: u32 = 64>(/* private fields */);Expand description
The aarch64 generic timer virtual counter (CNTVCT_EL0).
The architecture requires a constant frequency, consistent across cores. Its period must be at least 40 years. Access to this counter may be disabled by the kernel. It is almost always available on Linux.
§Frequency
The frequency of the counter can be read from CNTFRQ_EL0, so it does not need calibration.
This value is typically populated by firmware.
From Armv8.6 and Armv9.1 on, the frequency must be exactly 1GHz.
Before those, the counter frequency was typically between 1MHz and 50MHz.
The clock frequency is represented in 32-bits, which means the frequency will be at most u32::MAX Hz ≈ 4.3GHz.
Note that even on newer systems the resolution may be lower than 1GHz. For example, the counter may atomically increase by 40 every 40ns.
§Bit Size
The hardware counter has 56-64 bits (implementation dependent).
From Armv8.6 and Armv9.1 on, the counter must be 64 bits.
BITS is the counter width assumed by this clock and must be in 56..=64.
A mismatch with the hardware in either direction has downsides.
If the width on the target machine is not known, a tradeoff has to be made.
If BITS is greater than the hardware size, calculations involving instants between which the counter rolled over will be incorrect.
Typically, CNTVCT_EL0 is reset to 0 at boot, so rollover will occur if a machine stays running for longer than the rollover time.
Arm requires the rollover time to be at least 40 years.
It is recommended that most applications go with BITS=64.
If BITS is less than the hardware size, the top bits of the value read from CNTVCT_EL0 are discarded.
This makes the clock function correctly, but reduces rollover time.
In the worst case, rollover time is slightly over 6 months.
Keep in mind that instant comparison only works reliably if the two instants are less than half of a rollover time from each other.
Implementations§
Source§impl<const BITS: u32> GenericTimer<BITS>
impl<const BITS: u32> GenericTimer<BITS>
Sourcepub fn new_assume_accessible() -> Self
pub fn new_assume_accessible() -> Self
Returns a GenericTimer, assuming CNTVCT_EL0 is readable from EL0.
Operating systems that expose a userspace clock without a syscall enable this, which
covers Linux and macOS. If it is disabled, Clock::now traps with SIGILL. There is no
way to query this from EL0, so prefer GenericTimer::try_new_linux_sys on Linux.
Sourcepub fn try_new_linux_sys() -> Result<Self, GenericTimerUnavailable>
pub fn try_new_linux_sys() -> Result<Self, GenericTimerUnavailable>
Returns Ok(GenericTimer) if the Linux kernel reports arch_sys_counter as an available clocksource.
Sourcepub fn read_cntfrq(&self) -> u32
pub fn read_cntfrq(&self) -> u32
Returns the counter frequency in Hz as reported by CNTFRQ_EL0.
Sourcepub fn calibration_from_cntfrq(&self) -> U64Calibration<BITS>
pub fn calibration_from_cntfrq(&self) -> U64Calibration<BITS>
Returns a calibration derived from CNTFRQ_EL0.
§Panics
Panics if CNTFRQ_EL0 is zero, which means firmware did not populate it.