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
This commit is contained in:
committed by
Alexander Ziaee
parent
c505fc1468
commit
7e7d4e711f
@@ -423,7 +423,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;
|
||||
|
||||
@@ -453,20 +453,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();
|
||||
|
||||
+6
-3
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user