eal: fail initialization if TSC frequency is zero
PATCH 1/1 eal: fail initialization if TSC frequency is zero
Lots of parts of DPDK will fail with divide by zero and other errors if the initialization logic ever TSC hz was ever determined to be zero. This might happen on a broken get_tsc_freq_arch() or bad emulation in QEMU.
If TSC hz is zero, log the error and propagate back to fail rte_eal_init().
This fix doesn't need to go to stable since it is a purely theoretical problem; we aren't getting divide by zero reports from users.
--- lib/eal/common/eal_common_timer.c | 22 ++++++++++++++++++++-- lib/eal/common/eal_private.h | 2 +- lib/eal/freebsd/eal_timer.c | 3 +-- lib/eal/include/generic/rte_cycles.h | 7 ++++++- lib/eal/linux/eal_timer.c | 3 +-- lib/eal/windows/eal_timer.c | 3 +-- 6 files changed, 30 insertions(+), 10 deletions(-)
lib/eal/common/eal_common_timer.c +20 -2
@@ -52,7 +52,7 @@ estimate_tsc_freq(void)return RTE_ALIGN_MUL_NEAR (rte_rdtsc () - start,CYC_PER_10MHZ ); } -void +int set_tsc_freq (void ) {struct rte_mem_config *mcfg =rte_eal_get_configuration ()->mem_config;
@@ -65,8 +65,13 @@ set_tsc_freq(void)* systems where arch-specific frequency detection is not * available. */ +if (mcfg->tsc_hz ==0 ) { +EAL_LOG (ERR ,"Primary process TSC frequency is zero" ); +return -1 ; + } + eal_tsc_resolution_hz = mcfg->tsc_hz; -return ; +return 0 ; } freq =get_tsc_freq_arch ();
@@ -74,9 +79,22 @@ set_tsc_freq(void)if (!freq) freq =estimate_tsc_freq (); +/* +* Several get_tsc_freq_arch() implementations return zero when the +* frequency cannot be read, and a TSC that does not advance at least +* once per second measures as zero. Such a counter cannot be scaled +* to a time at all, so fail rather than let callers of +* rte_get_tsc_hz() divide by zero. +*/ +if (freq ==0 ) { +EAL_LOG (ERR ,"TSC frequency could not be determined" ); +return -1 ; + } +EAL_LOG (DEBUG ,"TSC frequency is ~%" PRIu64" KHz" , freq /1000 ); eal_tsc_resolution_hz = freq; mcfg->tsc_hz = freq; +return 0 ; }RTE_EXPORT_SYMBOL (rte_delay_us_callback_register)
lib/eal/common/eal_private.h +1 -1
@@ -409,7 +409,7 @@ int eal_cpu_detected(unsigned lcore_id);* * This function is private to the EAL. */ -void set_tsc_freq (void ); +int set_tsc_freq (void );/** * Get precise TSC frequency from system
lib/eal/freebsd/eal_timer.c +1 -2
@@ -65,6 +65,5 @@ get_tsc_freq(uint64_t arch_hz)int rte_eal_timer_init (void ) { -set_tsc_freq (); -return 0 ; +return set_tsc_freq (); }
lib/eal/include/generic/rte_cycles.h +6 -1
@@ -33,8 +33,13 @@ extern enum timer_source eal_timer_source;/** * Get the measured frequency of the RDTSC counter * +* The frequency is determined once during rte_eal_init(), which fails if +* it cannot be established, so this never returns zero once the EAL is +* initialized and the value does not change afterwards. It is therefore +* safe to divide by without checking. +* * @return -* The TSC frequency for this lcore +* The TSC frequency for this lcore, always non-zero. */ uint64_t rte_get_tsc_hz (void );
lib/eal/linux/eal_timer.c +1 -2
@@ -99,6 +99,5 @@ rte_eal_timer_init(void) eal_timer_source =EAL_TIMER_TSC ; -set_tsc_freq (); -return 0 ; +return set_tsc_freq (); }
lib/eal/windows/eal_timer.c +1 -2
@@ -94,6 +94,5 @@ get_tsc_freq(uint64_t arch_hz)int rte_eal_timer_init (void ) { -set_tsc_freq (); -return 0 ; +return set_tsc_freq (); }
Signature · 1 line
2.53.0
lib/eal/common/eal_common_timer.c set_tsc_freq(void) · line 93
Quoted 12 lines · On Sun, 27 Sep 2026 12:54:40 -0700 Stephen Hemminger…
lib/eal/common/eal_common_timer.c +12
-0+/* +* Several get_tsc_freq_arch() implementations return zero when the +* frequency cannot be read, and a TSC that does not advance at least +* once per second measures as zero. Such a counter cannot be scaled +* to a time at all, so fail rather than let callers of +* rte_get_tsc_hz() divide by zero. +*/ +if (freq ==0 ) { +EAL_LOG (ERR ,"TSC frequency could not be determined" ); +return -1 ; + } +
Sorry for the AI generated comment here. Will fix in next version.
PATCH v2 1/1 eal: fail initialization if TSC frequency is zero
In reply to Stephen HemmingerMany parts of DPDK will fail with divide by zero and
other errors if the initialization logic ever TSC hz was ever determined to be zero. This might happen on a broken get_tsc_freq_arch() or bad emulation in QEMU.
If TSC hz is zero, log the error and propagate back to fail rte_eal_init().
This fix doesn't need to go to stable since it is a purely theoretical problem; we aren't getting divide by zero reports from users.
---
v2 - cleanups: mostly squash useless comments
lib/eal/common/eal_common_timer.c | 19 ++++++++++++++++--- lib/eal/common/eal_private.h | 2 +- lib/eal/freebsd/eal_timer.c | 3 +-- lib/eal/include/generic/rte_cycles.h | 2 +- lib/eal/linux/eal_timer.c | 3 +-- lib/eal/windows/eal_timer.c | 3 +-- 6 files changed, 21 insertions(+), 11 deletions(-)
lib/eal/common/eal_common_timer.c +16 -3
@@ -52,7 +52,7 @@ estimate_tsc_freq(void)return RTE_ALIGN_MUL_NEAR (rte_rdtsc () - start,CYC_PER_10MHZ ); } -void +int set_tsc_freq (void ) {struct rte_mem_config *mcfg =rte_eal_get_configuration ()->mem_config;
@@ -65,18 +65,31 @@ set_tsc_freq(void)* systems where arch-specific frequency detection is not * available. */ +if (mcfg->tsc_hz ==0 ) { +EAL_LOG (ERR ,"Primary process TSC frequency is zero" ); +return -1 ; + } + eal_tsc_resolution_hz = mcfg->tsc_hz; -return ; +return 0 ; } freq =get_tsc_freq_arch (); freq =get_tsc_freq (freq); -if (!freq) +if (freq ==0 ) { freq =estimate_tsc_freq (); +/* Check if TSC is not moving */ +if (freq ==0 ) { +EAL_LOG (ERR ,"TSC frequency is not changing" ); +return -1 ; + } + } +EAL_LOG (DEBUG ,"TSC frequency is ~%" PRIu64" KHz" , freq /1000 ); eal_tsc_resolution_hz = freq; mcfg->tsc_hz = freq; +return 0 ; }RTE_EXPORT_SYMBOL (rte_delay_us_callback_register)
lib/eal/common/eal_private.h +1 -1
@@ -409,7 +409,7 @@ int eal_cpu_detected(unsigned lcore_id);* * This function is private to the EAL. */ -void set_tsc_freq (void ); +int set_tsc_freq (void );/** * Get precise TSC frequency from system
lib/eal/freebsd/eal_timer.c +1 -2
@@ -65,6 +65,5 @@ get_tsc_freq(uint64_t arch_hz)int rte_eal_timer_init (void ) { -set_tsc_freq (); -return 0 ; +return set_tsc_freq (); }
lib/eal/include/generic/rte_cycles.h +1 -1
@@ -34,7 +34,7 @@ extern enum timer_source eal_timer_source;* Get the measured frequency of the RDTSC counter * * @return -* The TSC frequency for this lcore +* The TSC frequency for all lcores, always non-zero */ uint64_t rte_get_tsc_hz (void );
lib/eal/linux/eal_timer.c +1 -2
@@ -99,6 +99,5 @@ rte_eal_timer_init(void) eal_timer_source =EAL_TIMER_TSC ; -set_tsc_freq (); -return 0 ; +return set_tsc_freq (); }
lib/eal/windows/eal_timer.c +1 -2
@@ -94,6 +94,5 @@ get_tsc_freq(uint64_t arch_hz)int rte_eal_timer_init (void ) { -set_tsc_freq (); -return 0 ; +return set_tsc_freq (); }
Signature · 1 line
2.53.0
Quoted 5 lines · Stephen Hemminger
Many parts of DPDK will fail with divide by zero and
other errors if the initialization logic ever TSC hz was ever determined to be zero. This might happen on a brokenget_tsc_freq_arch()or bad emulation in QEMU.
Quoted 7 lines
If TSC hz is zero, log the error and propagate back to fail
rte_eal_init().This fix doesn't need to go to stable since it is a purely theoretical problem; we aren't getting divide by zero reports from users.
How was this discovered? Is there a coverity issue id, or was it just AI discovered?
Quoted 6 lines
Fixes 040cf8a41187 ("eal: deduplicate timer functions")Signed-off-by Stephen Hemminger <[email protected]>---
v2 - cleanups: mostly squash useless comments
Code looks generally ok to me.
Quoted 60 lines
lib/eal/common/eal_common_timer.c | 19 ++++++++++++++++--- lib/eal/common/eal_private.h | 2 +- lib/eal/freebsd/eal_timer.c | 3 +-- lib/eal/include/generic/rte_cycles.h | 2 +- lib/eal/linux/eal_timer.c | 3 +-- lib/eal/windows/eal_timer.c | 3 +-- 6 files changed, 21 insertions(+), 11 deletions(-)lib/eal/common/eal_common_timer.c +16
-3@@ -52,7 +52,7 @@ estimate_tsc_freq(void)return RTE_ALIGN_MUL_NEAR (rte_rdtsc () - start,CYC_PER_10MHZ ); } -void +int set_tsc_freq (void ) {struct rte_mem_config *mcfg =rte_eal_get_configuration ()->mem_config;@@ -65,18 +65,31 @@ set_tsc_freq(void)* systems where arch-specific frequency detection is not * available. */ +if (mcfg->tsc_hz ==0 ) { +EAL_LOG (ERR ,"Primary process TSC frequency is zero" ); +return -1 ; + } + eal_tsc_resolution_hz = mcfg->tsc_hz; -return ; +return 0 ; } freq =get_tsc_freq_arch (); freq =get_tsc_freq (freq); -if (!freq) +if (freq ==0 ) { freq =estimate_tsc_freq (); +/* Check if TSC is not moving */ +if (freq ==0 ) { +EAL_LOG (ERR ,"TSC frequency is not changing" ); +return -1 ; + } + } +EAL_LOG (DEBUG ,"TSC frequency is ~%" PRIu64" KHz" , freq /1000 ); eal_tsc_resolution_hz = freq; mcfg->tsc_hz = freq; +return 0 ; }RTE_EXPORT_SYMBOL (rte_delay_us_callback_register)lib/eal/common/eal_private.h +0
-0
lib/eal/common/eal_private.h int eal_cpu_detected(unsigned lcore_id); · line 413
Quoted 6 lines
lib/eal/common/eal_private.h +1
-1@@ -409,7 +409,7 @@ int eal_cpu_detected(unsigned lcore_id);* * This function is private to the EAL. */ -void set_tsc_freq (void ); +int set_tsc_freq (void );
One minor suggestion: set_tsc_freq name implies that the user passes in a value to be set. I wonder if "init_tsc_freq" might be a better name here, since you are updating all calls anyway to handle an error return.
Quoted 54 lines
lib/eal/common/eal_private.h +0
-0/** * Get precise TSC frequency from system lib/eal/freebsd/eal_timer.c +1
-2@@ -65,6 +65,5 @@ get_tsc_freq(uint64_t arch_hz)int rte_eal_timer_init (void ) { -set_tsc_freq (); -return 0 ; +return set_tsc_freq (); }lib/eal/include/generic/rte_cycles.h +1
-1@@ -34,7 +34,7 @@ extern enum timer_source eal_timer_source;* Get the measured frequency of the RDTSC counter * * @return -* The TSC frequency for this lcore +* The TSC frequency for all lcores, always non-zero */ uint64_t rte_get_tsc_hz (void );lib/eal/linux/eal_timer.c +1
-2@@ -99,6 +99,5 @@ rte_eal_timer_init(void) eal_timer_source =EAL_TIMER_TSC ; -set_tsc_freq (); -return 0 ; +return set_tsc_freq (); }lib/eal/windows/eal_timer.c +1
-2@@ -94,6 +94,5 @@ get_tsc_freq(uint64_t arch_hz)int rte_eal_timer_init (void ) { -set_tsc_freq (); -return 0 ; +return set_tsc_freq (); }Signature · 1 line
2.53.0
Quoted 9 lines · On Tue, 29 Sep 2026 09:39:36 +0100 Bruce Richardson…
Quoted 8 lines · Stephen Hemminger
Many parts of DPDK will fail with divide by zero and
other errors if the initialization logic ever TSC hz was ever determined to be zero. This might happen on a brokenget_tsc_freq_arch()or bad emulation in QEMU.If TSC hz is zero, log the error and propagate back to fail
rte_eal_init().
Quoted 7 lines
Quoted 4 lines
This fix doesn't need to go to stable since it is a purely theoretical problem; we aren't getting divide by zero reports from users.
How was this discovered? Is there a coverity issue id, or was it just AI discovered?
It was part of review of pcapng timestamp calculation.
Kind of funny, AI spotted overflow (which I verified) in the code which it had previously helped write. Then it was asking it self, "what if TSC was 0". I didn't see how this could happen unless QEMU had some broken CPU emulation.
To me it seemed best to fail fast and die in a safer manner.
Bruce Richardson
Acked-byQuoted 20 lines · Stephen Hemminger
Quoted 9 lines · On Tue, 29 Sep 2026 09:39:36 +0100 Bruce Richardson…
Quoted 8 lines · Stephen Hemminger
Many parts of DPDK will fail with divide by zero and
other errors if the initialization logic ever TSC hz was ever determined to be zero. This might happen on a brokenget_tsc_freq_arch()or bad emulation in QEMU.If TSC hz is zero, log the error and propagate back to fail
rte_eal_init().Quoted 7 lines
Quoted 4 lines
This fix doesn't need to go to stable since it is a purely theoretical problem; we aren't getting divide by zero reports from users.
How was this discovered? Is there a coverity issue id, or was it just AI discovered?
Quoted 8 lines
It was part of review of pcapng timestamp calculation.
Kind of funny, AI spotted overflow (which I verified) in the code which it had previously helped write. Then it was asking it self, "what if TSC was 0". I didn't see how this could happen unless QEMU had some broken CPU emulation.To me it seemed best to fail fast and die in a safer manner.
Agreed. You can add my ack, either for this version or a new version with the "set" function renamed as I suggest.
Quoted 27 lines · On Tue, 29 Sep 2026 14:57:54 +0100 Bruce Richardson…
Quoted 26 lines · Stephen Hemminger
Quoted 9 lines · On Tue, 29 Sep 2026 09:39:36 +0100 Bruce Richardson…
Quoted 8 lines · Stephen Hemminger
Many parts of DPDK will fail with divide by zero and
other errors if the initialization logic ever TSC hz was ever determined to be zero. This might happen on a brokenget_tsc_freq_arch()or bad emulation in QEMU.If TSC hz is zero, log the error and propagate back to fail
rte_eal_init().Quoted 7 lines
Quoted 4 lines
This fix doesn't need to go to stable since it is a purely theoretical problem; we aren't getting divide by zero reports from users.
How was this discovered? Is there a coverity issue id, or was it just AI discovered?
It was part of review of pcapng timestamp calculation.
Kind of funny, AI spotted overflow (which I verified) in the code which it had previously helped write. Then it was asking it self, "what if TSC was 0". I didn't see how this could happen unless QEMU had some broken CPU emulation.
Quoted 7 lines
Quoted 2 lines
To me it seemed best to fail fast and die in a safer manner.
Agreed. You can add my ack, either for this version or a new version with the "set" function renamed as I suggest.
Acked-by Bruce Richardson <[email protected]>
I also updated comment to rte_get_tsc_hz() since existing comment implies the value could be different on each lcore.
PATCH v3 1/1 eal: fail initialization if TSC frequency is zero
In reply to Stephen HemmingerMany parts of DPDK will fail with divide by zero and
other errors if the initialization logic ever TSC hz was ever determined to be zero. This might happen on a broken get_tsc_freq_arch() or bad emulation in QEMU.
If TSC hz is zero, log the error and propagate back to fail rte_eal_init().
This fix doesn't need to go to stable since it is a purely theoretical problem; we aren't getting divide by zero reports from users.
Also, clarify that DPDK TSC is stable and the same for all lcore's. The comment in rte_cycles.h implied that it could be different per lcore.
---
v3 - rename set_tsc_freq to init_tsc_freq
lib/eal/common/eal_common_timer.c | 19 +++++++++++++++---- lib/eal/common/eal_private.h | 2 +- lib/eal/freebsd/eal_timer.c | 3 +-- lib/eal/include/generic/rte_cycles.h | 2 +- lib/eal/linux/eal_timer.c | 3 +-- lib/eal/windows/eal_timer.c | 3 +-- 6 files changed, 20 insertions(+), 12 deletions(-)
lib/eal/common/eal_common_timer.c +15 -4
@@ -52,8 +52,8 @@ estimate_tsc_freq(void)return RTE_ALIGN_MUL_NEAR (rte_rdtsc () - start,CYC_PER_10MHZ ); } -void -set_tsc_freq (void ) +int +init_tsc_freq (void ) {struct rte_mem_config *mcfg =rte_eal_get_configuration ()->mem_config;uint64_t freq;
@@ -65,18 +65,29 @@ set_tsc_freq(void)* systems where arch-specific frequency detection is not * available. */ +if (mcfg->tsc_hz ==0 ) { +EAL_LOG (ERR ,"Primary process TSC frequency is zero" ); +return -1 ; + } + eal_tsc_resolution_hz = mcfg->tsc_hz; -return ; +return 0 ; } freq =get_tsc_freq_arch (); freq =get_tsc_freq (freq); -if (!freq) +if (freq ==0 ) { freq =estimate_tsc_freq (); +if (freq ==0 ) { +EAL_LOG (ERR ,"TSC frequency is too slow" ); +return -1 ; + } + }EAL_LOG (DEBUG ,"TSC frequency is ~%" PRIu64" KHz" , freq /1000 ); eal_tsc_resolution_hz = freq; mcfg->tsc_hz = freq; +return 0 ; }RTE_EXPORT_SYMBOL (rte_delay_us_callback_register)
lib/eal/common/eal_private.h +1 -1
@@ -409,7 +409,7 @@ int eal_cpu_detected(unsigned lcore_id);* * This function is private to the EAL. */ -void set_tsc_freq (void ); +int init_tsc_freq (void );/** * Get precise TSC frequency from system
lib/eal/freebsd/eal_timer.c +1 -2
@@ -65,6 +65,5 @@ get_tsc_freq(uint64_t arch_hz)int rte_eal_timer_init (void ) { -set_tsc_freq (); -return 0 ; +return init_tsc_freq (); }
lib/eal/include/generic/rte_cycles.h +1 -1
@@ -34,7 +34,7 @@ extern enum timer_source eal_timer_source;* Get the measured frequency of the RDTSC counter * * @return -* The TSC frequency for this lcore +* The TSC frequency for all lcores, always non-zero */ uint64_t rte_get_tsc_hz (void );
lib/eal/linux/eal_timer.c +1 -2
@@ -99,6 +99,5 @@ rte_eal_timer_init(void) eal_timer_source =EAL_TIMER_TSC ; -set_tsc_freq (); -return 0 ; +return init_tsc_freq (); }
lib/eal/windows/eal_timer.c +1 -2
@@ -94,6 +94,5 @@ get_tsc_freq(uint64_t arch_hz)int rte_eal_timer_init (void ) { -set_tsc_freq (); -return 0 ; +return init_tsc_freq (); }
Signature · 1 line
2.53.0
Thomas Monjalon
Applied29/09/2026 16:13, Stephen Hemminger:
Quoted 12 lines
Many parts of DPDK will fail with divide by zero and
other errors if the initialization logic ever TSC hz was ever determined to be zero. This might happen on a brokenget_tsc_freq_arch()or bad emulation in QEMU.If TSC hz is zero, log the error and propagate back to fail
rte_eal_init().This fix doesn't need to go to stable since it is a purely theoretical problem; we aren't getting divide by zero reports from users.
Quoted 7 lines
Also, clarify that DPDK TSC is stable and the same for all lcore's. The comment in
rte_cycles.himplied that it could be different per lcore.Fixes 040cf8a41187 ("eal: deduplicate timer functions")Signed-off-by Stephen Hemminger <[email protected]>Acked-by Bruce Richardson <[email protected]>
Applied, thanks.