From: Emily Ehlert <ehemily@amazon.de>
To: <lenb@kernel.org>
Cc: <linux-pm@vger.kernel.org>, <linux-kernel@vger.kernel.org>,
Emily Ehlert <ehemily@amazon.com>
Subject: [PATCH 2/2] tools/power/turbostat: Fix division by zero when TDP calculation fails
Date: Thu, 13 Nov 2025 19:16:09 +0000 [thread overview]
Message-ID: <20251113191609.28574-2-ehemily@amazon.de> (raw)
In-Reply-To: <20251113191609.28574-1-ehemily@amazon.de>
From: Emily Ehlert <ehemily@amazon.com>
turbostat uses hard coded features for CPU families and expects access to
RAPL (Running Average Power Limit) MSRs. When RAPL or power info is not
available, turbostat reads PKG_POWER_INFO MSR to calculate TDP with
RAPL_POWER_UNIT MSR. If TDP calculation results in 0, no zero check is
performed and the 0 TDP is used in division, resulting in an invalid
rapl_joule_counter_range. This variable is later used in msr_sum_record()
as a timer parameter to timer_settime() syscall, causing issues.
Fix the issue by:
- Introduce zero check for tdp in rapl_probe_intel() and rapl_probe_amd()
- Introduce global variable no_rapl which is set to true if zero check fails
- Skip RAPL-dependent functions when no_rapl is true
- Add assertions and guards to prevent RAPL operations when disabled
Signed-off-by: Emily Ehlert <ehemily@amazon.com>
---
tools/power/x86/turbostat/turbostat.c | 27 ++++++++++++++++++++++++---
1 file changed, 24 insertions(+), 3 deletions(-)
diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c
index 9a2be201a3a6..9c6ee0acbe12 100644
--- a/tools/power/x86/turbostat/turbostat.c
+++ b/tools/power/x86/turbostat/turbostat.c
@@ -531,6 +531,7 @@ static struct timeval procsysfs_tv_begin;
int ignore_stdin;
bool no_msr;
bool no_perf;
+bool no_rapl;
enum gfx_sysfs_idx {
GFX_rc6,
@@ -3119,6 +3120,10 @@ int dump_counters(PER_THREAD_PARAMS)
double rapl_counter_get_value(const struct rapl_counter *c, enum rapl_unit desired_unit, double interval)
{
+ if (no_rapl) {
+ return NAN;
+ }
+
assert(desired_unit != RAPL_UNIT_INVALID);
/*
@@ -4696,6 +4701,8 @@ static size_t cstate_counter_info_count_perf(const struct cstate_counter_info_t
void write_rapl_counter(struct rapl_counter *rc, struct rapl_counter_info_t *rci, unsigned int idx)
{
+ assert(!no_rapl);
+
if (rci->source[idx] == COUNTER_SOURCE_NONE)
return;
@@ -4706,6 +4713,8 @@ void write_rapl_counter(struct rapl_counter *rc, struct rapl_counter_info_t *rci
int get_rapl_counters(int cpu, unsigned int domain, struct core_data *c, struct pkg_data *p)
{
+ assert(!no_rapl);
+
struct platform_counters *pplat_cnt = p == package_odd ? &platform_counters_odd : &platform_counters_even;
unsigned long long perf_data[NUM_RAPL_COUNTERS + 1];
struct rapl_counter_info_t *rci;
@@ -5147,7 +5156,7 @@ int get_counters(PER_THREAD_PARAMS)
if (!is_cpu_first_thread_in_core(t, c, p))
goto done;
- if (platform->has_per_core_rapl) {
+ if (platform->has_per_core_rapl && !no_rapl) {
status = get_rapl_counters(cpu, get_rapl_domain_id(cpu), c, p);
if (status != 0)
return status;
@@ -5213,7 +5222,7 @@ int get_counters(PER_THREAD_PARAMS)
if (DO_BIC(BIC_SYS_LPI))
p->sys_lpi = cpuidle_cur_sys_lpi_us;
- if (!platform->has_per_core_rapl) {
+ if (!platform->has_per_core_rapl && !no_rapl) {
status = get_rapl_counters(cpu, get_rapl_domain_id(cpu), c, p);
if (status != 0)
return status;
@@ -7650,6 +7659,12 @@ void rapl_probe_intel(void)
tdp = get_tdp_intel();
+ if (tdp == 0.0) {
+ no_rapl = true;
+ fprintf(outf, "RAPL: Could not calculate TDP (TDP: %.0f, MSR_RAPL_POWER_UNIT: %llx)\n", tdp, msr);
+ return;
+ }
+
rapl_joule_counter_range = 0xFFFFFFFF * rapl_energy_units / tdp;
if (!quiet)
fprintf(outf, "RAPL: %.0f sec. Joule Counter Range, at %.0f Watts\n", rapl_joule_counter_range, tdp);
@@ -7680,6 +7695,12 @@ void rapl_probe_amd(void)
tdp = get_tdp_amd();
+ if (tdp == 0.0) {
+ no_rapl = true;
+ fprintf(outf, "RAPL: Could not calculate TDP (TDP: %.0f, MSR_RAPL_POWER_UNIT: %llx)\n", tdp, msr);
+ return;
+ }
+
rapl_joule_counter_range = 0xFFFFFFFF * rapl_energy_units / tdp;
if (!quiet)
fprintf(outf, "RAPL: %.0f sec. Joule Counter Range, at %.0f Watts\n", rapl_joule_counter_range, tdp);
@@ -11215,7 +11236,7 @@ int main(int argc, char **argv)
turbostat_init();
- if (!no_msr)
+ if (!no_msr && !no_rapl)
msr_sum_record();
/* dump counters and exit */
--
2.47.3
Amazon Web Services Development Center Germany GmbH
Tamara-Danz-Str. 13
10243 Berlin
Geschaeftsfuehrung: Christian Schlaeger, Christof Hellmis
Eingetragen am Amtsgericht Charlottenburg unter HRB 257764 B
Sitz: Berlin
Ust-ID: DE 365 538 597
next prev parent reply other threads:[~2025-11-13 19:17 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-11-13 19:16 [PATCH 1/2] tools/power/turbostat: Set per_cpu_msr_sum to NULL after free Emily Ehlert
2025-11-13 19:16 ` Emily Ehlert [this message]
2025-11-25 18:13 ` [PATCH 2/2] tools/power/turbostat: Fix division by zero when TDP calculation fails Len Brown
2025-11-28 13:59 ` Ehlert, Emily
2025-11-30 5:27 ` Len Brown
2025-12-01 8:55 ` Ehlert, Emily
2025-12-01 17:07 ` Len Brown
2025-12-01 19:14 ` Len Brown
2025-12-02 9:09 ` Ehlert, Emily
2025-12-02 16:20 ` Len Brown
2025-11-25 18:06 ` [PATCH 1/2] tools/power/turbostat: Set per_cpu_msr_sum to NULL after free Len Brown
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20251113191609.28574-2-ehemily@amazon.de \
--to=ehemily@amazon.de \
--cc=ehemily@amazon.com \
--cc=lenb@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-pm@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.