07_timestamps - Why abort if the frequency read back as 0? #224
Replies: 1 comment
-
|
Good question! There are a few reasons this check exists and the abort happens in assembly rather than letting Rust handle it. The core issue is that ARCH_TIMER_COUNTER_FREQUENCY is declared in Rust as NonZeroU32. If assembly wrote a zero into it, you'd have an invalid NonZeroU32 - that's immediate undefined behavior before a single line of Rust executes. The type invariant has to be upheld from the moment Rust starts. There's also a practical runtime reason: the frequency is used as the divisor in all timestamp calculations in time.rs. The code uses NonZeroU64 specifically so that div() is infallible. If zero somehow got through, every call to uptime() or spin_for() would trap. As for why it can't just print an error message - at that point in boot.s, the UART driver hasn't been initialized yet. The stack is set up but _start_rust hasn't been called. There's genuinely nothing to print to. A parking loop (wfe) is the only safe thing to do when the execution environment doesn't exist yet. The reason you'd actually hit this in practice is QEMU - it doesn't initialize CNTFRQ_EL0 unless firmware does, so it reads as 0. On real RPi3/4 hardware, firmware always sets it (typically 19.2 MHz or 54 MHz), so this guard is mainly a sanity check for emulators and non-standard firmware. |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
In
boot.s, it says "Abort if the frequency read back as 0." I wonder why? Why would it be zero? Damaged / malfunctioning hardware? And if it is zero, why not boot the Rust code and have the Rust code check if it's zero, and display a text error instead of a parking loop? I would assume that in the case that it is 0, it's better to have a readable error message than being confused about why nothing is happening.Beta Was this translation helpful? Give feedback.
All reactions