git: 51e77b34e4bf - stable/13 - TSC: Use 0x40000010 CPUID leaf for all VM types

From: Colin Percival <cperciva_at_FreeBSD.org>
Date: Fri, 11 Feb 2022 06:52:08 UTC
The branch stable/13 has been updated by cperciva:

URL: https://cgit.FreeBSD.org/src/commit/?id=51e77b34e4bf76c8aa2c882f64ef923c2fbe6108

commit 51e77b34e4bf76c8aa2c882f64ef923c2fbe6108
Author:     Colin Percival <cperciva@FreeBSD.org>
AuthorDate: 2022-01-04 07:28:36 +0000
Commit:     Colin Percival <cperciva@FreeBSD.org>
CommitDate: 2022-02-11 06:52:00 +0000

    TSC: Use 0x40000010 CPUID leaf for all VM types
    
    While this CPUID leaf was originally only used by VMWare, other
    hypervisors now also use it to announce the TSC frequency to guests.
    
    This speeds up the boot process by 100 ms in EC2 and other systems,
    by allowing the early calibration DELAY to be skipped.
    
    Reviewed by:    markj
    Sponsored by:   https://www.patreon.com/cperciva
    
    (cherry picked from commit 4a432614f68cf35879dbb4ebef089f5b8db95334)
---
 sys/x86/x86/tsc.c | 29 +++++++++++++++++++++--------
 1 file changed, 21 insertions(+), 8 deletions(-)

diff --git a/sys/x86/x86/tsc.c b/sys/x86/x86/tsc.c
index 1b6c8282e44e..e0c23767573e 100644
--- a/sys/x86/x86/tsc.c
+++ b/sys/x86/x86/tsc.c
@@ -121,19 +121,29 @@ static struct timecounter tsc_timecounter = {
 #endif
 };
 
+static int
+tsc_freq_cpuid_vm(void)
+{
+	u_int regs[4];
+
+	if (vm_guest == VM_GUEST_NO)
+		return (false);
+	if (hv_high < 0x40000010)
+		return (false);
+	do_cpuid(0x40000010, regs);
+	tsc_freq = (uint64_t)(regs[0]) * 1000;
+	tsc_early_calib_exact = 1;
+	return (true);
+}
+
 static void
 tsc_freq_vmware(void)
 {
 	u_int regs[4];
 
-	if (hv_high >= 0x40000010) {
-		do_cpuid(0x40000010, regs);
-		tsc_freq = regs[0] * 1000;
-	} else {
-		vmware_hvcall(VMW_HVCMD_GETHZ, regs);
-		if (regs[1] != UINT_MAX)
-			tsc_freq = regs[0] | ((uint64_t)regs[1] << 32);
-	}
+	vmware_hvcall(VMW_HVCMD_GETHZ, regs);
+	if (regs[1] != UINT_MAX)
+		tsc_freq = regs[0] | ((uint64_t)regs[1] << 32);
 	tsc_early_calib_exact = 1;
 }
 
@@ -305,6 +315,9 @@ probe_tsc_freq(void)
 		break;
 	}
 
+	if (tsc_freq_cpuid_vm())
+		return;
+
 	if (vm_guest == VM_GUEST_VMWARE) {
 		tsc_freq_vmware();
 		return;