git: 1ca34862dc45 - main - x86/tsc: fetch frequency from CPUID when running on Xen

From: Roger Pau Monné <royger_at_FreeBSD.org>
Date: Fri, 18 Mar 2022 09:21:11 UTC
The branch main has been updated by royger:

URL: https://cgit.FreeBSD.org/src/commit/?id=1ca34862dc45e0074b5aa31d9e491a2684ac6640

commit 1ca34862dc45e0074b5aa31d9e491a2684ac6640
Author:     Roger Pau Monné <royger@FreeBSD.org>
AuthorDate: 2022-03-16 08:56:40 +0000
Commit:     Roger Pau Monné <royger@FreeBSD.org>
CommitDate: 2022-03-18 09:21:04 +0000

    x86/tsc: fetch frequency from CPUID when running on Xen
    
    Introduce a helper to fetch the TSC frequency from CPUID when running
    under Xen.
    
    Since the TSC can also be initialized early when running as a Xen
    guest pull out the call to tsc_init() from the
    early_clock_source_init() handlers and place it in clock_init(), as
    otherwise all handlers would call tsc_init() anyway.
    
    Reviewed by: markj
    Sponsored by: Citrix Systems R&D
    Differential revision: https://reviews.freebsd.org/D34581
---
 sys/amd64/amd64/machdep.c |  1 -
 sys/i386/i386/machdep.c   |  1 -
 sys/x86/isa/clock.c       |  1 +
 sys/x86/x86/tsc.c         | 21 +++++++++++++++++++++
 4 files changed, 22 insertions(+), 2 deletions(-)

diff --git a/sys/amd64/amd64/machdep.c b/sys/amd64/amd64/machdep.c
index b7810440a551..55a278de6020 100644
--- a/sys/amd64/amd64/machdep.c
+++ b/sys/amd64/amd64/machdep.c
@@ -1167,7 +1167,6 @@ static void
 native_clock_source_init(void)
 {
 	i8254_init();
-	tsc_init();
 }
 
 static void
diff --git a/sys/i386/i386/machdep.c b/sys/i386/i386/machdep.c
index 6913c0691fd4..9fee973d9e82 100644
--- a/sys/i386/i386/machdep.c
+++ b/sys/i386/i386/machdep.c
@@ -208,7 +208,6 @@ static void
 i386_clock_source_init(void)
 {
 	i8254_init();
-	tsc_init();
 }
 
 static void
diff --git a/sys/x86/isa/clock.c b/sys/x86/isa/clock.c
index f21f847709cd..730aee5e9a2a 100644
--- a/sys/x86/isa/clock.c
+++ b/sys/x86/isa/clock.c
@@ -129,6 +129,7 @@ clock_init(void)
 	mtx_init(&clock_lock, "clk", NULL, MTX_SPIN | MTX_NOPROFILE);
 	/* Init the clock in order to use DELAY */
 	init_ops.early_clock_source_init();
+	tsc_init();
 }
 
 static int
diff --git a/sys/x86/x86/tsc.c b/sys/x86/x86/tsc.c
index 0fdd70a690a3..96f209e4c08d 100644
--- a/sys/x86/x86/tsc.c
+++ b/sys/x86/x86/tsc.c
@@ -147,6 +147,21 @@ tsc_freq_vmware(void)
 	tsc_early_calib_exact = 1;
 }
 
+static void
+tsc_freq_xen(void)
+{
+	u_int regs[4];
+
+	/*
+	 * Must run *after* generic tsc_freq_cpuid_vm, so that when Xen is
+	 * emulating Viridian support the Viridian leaf is used instead.
+	 */
+	KASSERT(hv_high >= 0x40000003, ("Invalid max hypervisor leaf on Xen"));
+	cpuid_count(0x40000003, 0, regs);
+	tsc_freq = (uint64_t)(regs[2]) * 1000;
+	tsc_early_calib_exact = 1;
+}
+
 /*
  * Calculate TSC frequency using information from the CPUID leaf 0x15 'Time
  * Stamp Counter and Nominal Core Crystal Clock'.  If leaf 0x15 is not
@@ -358,6 +373,12 @@ probe_tsc_freq_early(void)
 			printf(
 		    "Early TSC frequency %juHz derived from VMWare hypercall\n",
 			    (uintmax_t)tsc_freq);
+	} else if (vm_guest == VM_GUEST_XEN) {
+		tsc_freq_xen();
+		if (bootverbose)
+			printf(
+			"Early TSC frequency %juHz derived from Xen CPUID\n",
+			    (uintmax_t)tsc_freq);
 	} else if (tsc_freq_cpuid(&tsc_freq)) {
 		/*
 		 * If possible, use the value obtained from CPUID as the initial