aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatt Delco <delco@google.com>2026-03-26 17:22:54 +0000
committerAlexander Ziaee <ziaee@FreeBSD.org>2026-03-26 19:02:06 +0000
commitc505fc1468849150f48484b225b6476d8316de57 (patch)
treeaef2dd24588af36f92bb2b2671074a599d77d93b
parent4b16ff49bf4bf875997fe4c80a0afc0d440b7aac (diff)
x86: Guard clock frequency against a divide by 0
We may be running in a Virtual Machine which may not fully support hardware performance counters. If the MPERF counter somehow ends up at zero, return an error and fail gracefully instead of panicking. This patch is part of Google Cloud Engine (GCE) C4-LSSD turnup. Sponsored by: Google Tested by: NetApp (previous) PR: 292808 MFC after: 3 days Co-authored-by: Aymeric Wibo <obiwac@google.com> Co-authored-by: Jim Mattson <jmattson@google.com> Suggested by: jrtc27 (split out this part) Reviewed by: imp, obiwac, olce Differential Revision: https://reviews.freebsd.org/D56056
-rw-r--r--sys/x86/x86/cpu_machdep.c9
1 files changed, 8 insertions, 1 deletions
diff --git a/sys/x86/x86/cpu_machdep.c b/sys/x86/x86/cpu_machdep.c
index 5483fbd6dd4e..775fee97d3cd 100644
--- a/sys/x86/x86/cpu_machdep.c
+++ b/sys/x86/x86/cpu_machdep.c
@@ -425,6 +425,7 @@ cpu_est_clockrate(int cpu_id, uint64_t *rate)
uint64_t tsc1, tsc2;
uint64_t acnt, mcnt, perf;
register_t reg;
+ int error = 0;
if (pcpu_find(cpu_id) == NULL || rate == NULL)
return (EINVAL);
@@ -460,6 +461,11 @@ cpu_est_clockrate(int cpu_id, uint64_t *rate)
acnt = rdmsr(MSR_APERF);
tsc2 = rdtsc();
intr_restore(reg);
+ if (mcnt == 0) {
+ tsc_perf_stat = 0;
+ error = EOPNOTSUPP;
+ goto err;
+ }
perf = 1000 * acnt / mcnt;
*rate = (tsc2 - tsc1) * perf;
} else {
@@ -470,6 +476,7 @@ cpu_est_clockrate(int cpu_id, uint64_t *rate)
*rate = (tsc2 - tsc1) * 1000;
}
+err:
#ifdef SMP
if (smp_cpus > 1) {
thread_lock(curthread);
@@ -478,7 +485,7 @@ cpu_est_clockrate(int cpu_id, uint64_t *rate)
}
#endif
- return (0);
+ return (error);
}
/*