Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 06 Aug 2026 22:31:47 +0000
From:      Alexander Ziaee <ziaee@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org
Cc:        Matt Delco <delco@google.com>
Subject:   git: 3c0afd5bea93 - stable/14 - x86: Handle when MPERF/APERF MSRs aren't writable
Message-ID:  <6a750b53.1fe20.b463d94@gitrepo.freebsd.org>

index | next in thread | raw e-mail

The branch stable/14 has been updated by ziaee:

URL: https://cgit.FreeBSD.org/src/commit/?id=3c0afd5bea93a77a63632d3858896160932e7013

commit 3c0afd5bea93a77a63632d3858896160932e7013
Author:     Matt Delco <delco@google.com>
AuthorDate: 2026-03-26 17:30:31 +0000
Commit:     Alexander Ziaee <ziaee@FreeBSD.org>
CommitDate: 2026-08-06 22:25:08 +0000

    x86: Handle when MPERF/APERF MSRs aren't writable
    
    For performance and/or correct reasons some hypervisors allow
    MPERF/APERF MSRs to be read but not written to. This change
    modifies the handling of these MSRs to not rely on writes.
    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:         Jim Mattson <jmattson@google.com>
    Reviewed by:            jrtc27, imp, kib, markj, olce, obiwac
    Differential Revision:  https://reviews.freebsd.org/D55996
    
    (cherry picked from commit 7e7d4e711ff94d114c93fd522d4125aa9bd9f5cd)
---
 sys/x86/x86/cpu_machdep.c | 14 +++++++-------
 sys/x86/x86/tsc.c         |  9 ++++++---
 2 files changed, 13 insertions(+), 10 deletions(-)

diff --git a/sys/x86/x86/cpu_machdep.c b/sys/x86/x86/cpu_machdep.c
index dd19c2a46dbb..d082f19e3d36 100644
--- a/sys/x86/x86/cpu_machdep.c
+++ b/sys/x86/x86/cpu_machdep.c
@@ -424,7 +424,7 @@ int
 cpu_est_clockrate(int cpu_id, uint64_t *rate)
 {
 	uint64_t tsc1, tsc2;
-	uint64_t acnt, mcnt, perf;
+	uint64_t acnt_start, acnt_end, mcnt_start, mcnt_end, perf;
 	register_t reg;
 	int error = 0;
 
@@ -454,20 +454,20 @@ cpu_est_clockrate(int cpu_id, uint64_t *rate)
 	/* Calibrate by measuring a short delay. */
 	reg = intr_disable();
 	if (tsc_is_invariant) {
-		wrmsr(MSR_MPERF, 0);
-		wrmsr(MSR_APERF, 0);
+		mcnt_start = rdmsr(MSR_MPERF);
+		acnt_start = rdmsr(MSR_APERF);
 		tsc1 = rdtsc();
 		DELAY(1000);
-		mcnt = rdmsr(MSR_MPERF);
-		acnt = rdmsr(MSR_APERF);
+		mcnt_end = rdmsr(MSR_MPERF);
+		acnt_end = rdmsr(MSR_APERF);
 		tsc2 = rdtsc();
 		intr_restore(reg);
-		if (mcnt == 0) {
+		if (mcnt_end == mcnt_start) {
 			tsc_perf_stat = 0;
 			error = EOPNOTSUPP;
 			goto err;
 		}
-		perf = 1000 * acnt / mcnt;
+		perf = 1000 * (acnt_end - acnt_start) / (mcnt_end - mcnt_start);
 		*rate = (tsc2 - tsc1) * perf;
 	} else {
 		tsc1 = rdtsc();
diff --git a/sys/x86/x86/tsc.c b/sys/x86/x86/tsc.c
index 5874b2195dea..36de8036289b 100644
--- a/sys/x86/x86/tsc.c
+++ b/sys/x86/x86/tsc.c
@@ -433,6 +433,8 @@ probe_tsc_freq_late(void)
 void
 start_TSC(void)
 {
+	uint64_t mperf, aperf;
+
 	if ((cpu_feature & CPUID_TSC) == 0 || tsc_disabled)
 		return;
 
@@ -442,11 +444,12 @@ start_TSC(void)
 		/*
 		 * XXX Some emulators expose host CPUID without actual support
 		 * for these MSRs.  We must test whether they really work.
+		 * They may also be read-only, so test for increment.
 		 */
-		wrmsr(MSR_MPERF, 0);
-		wrmsr(MSR_APERF, 0);
+		mperf = rdmsr(MSR_MPERF);
+		aperf = rdmsr(MSR_APERF);
 		DELAY(10);
-		if (rdmsr(MSR_MPERF) > 0 && rdmsr(MSR_APERF) > 0)
+		if (rdmsr(MSR_MPERF) != mperf && rdmsr(MSR_APERF) != aperf)
 			tsc_perf_stat = 1;
 	}
 


home | help

Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?6a750b53.1fe20.b463d94>