Module Name: src Committed By: imil Date: Thu Mar 6 06:31:53 UTC 2025
Modified Files: src/sys/arch/x86/include: apicvar.h src/sys/arch/x86/x86: cpu.c identcpu_subr.c lapic.c Log Message: Add support for CPUID leaf 0x40000010, which enables VMware-compatible TSC and LAPIC frequency detection for virtual machines. To generate a diff of this commit: cvs rdiff -u -r1.8 -r1.9 src/sys/arch/x86/include/apicvar.h cvs rdiff -u -r1.210 -r1.211 src/sys/arch/x86/x86/cpu.c cvs rdiff -u -r1.9 -r1.10 src/sys/arch/x86/x86/identcpu_subr.c cvs rdiff -u -r1.90 -r1.91 src/sys/arch/x86/x86/lapic.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/arch/x86/include/apicvar.h diff -u src/sys/arch/x86/include/apicvar.h:1.8 src/sys/arch/x86/include/apicvar.h:1.9 --- src/sys/arch/x86/include/apicvar.h:1.8 Sat Apr 25 15:26:18 2020 +++ src/sys/arch/x86/include/apicvar.h Thu Mar 6 06:31:52 2025 @@ -1,4 +1,4 @@ -/* $NetBSD: apicvar.h,v 1.8 2020/04/25 15:26:18 bouyer Exp $ */ +/* $NetBSD: apicvar.h,v 1.9 2025/03/06 06:31:52 imil Exp $ */ /*- * Copyright (c) 2000 The NetBSD Foundation, Inc. @@ -56,5 +56,6 @@ void apic_format_redir(const char *, con /* For lapic.c */ extern uint32_t lapic_per_second; +extern bool lapic_from_cpuid; #endif /* !_X86_APICVAR_H_ */ Index: src/sys/arch/x86/x86/cpu.c diff -u src/sys/arch/x86/x86/cpu.c:1.210 src/sys/arch/x86/x86/cpu.c:1.211 --- src/sys/arch/x86/x86/cpu.c:1.210 Mon Apr 22 23:07:47 2024 +++ src/sys/arch/x86/x86/cpu.c Thu Mar 6 06:31:53 2025 @@ -1,4 +1,4 @@ -/* $NetBSD: cpu.c,v 1.210 2024/04/22 23:07:47 andvar Exp $ */ +/* $NetBSD: cpu.c,v 1.211 2025/03/06 06:31:53 imil Exp $ */ /* * Copyright (c) 2000-2020 NetBSD Foundation, Inc. @@ -62,7 +62,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.210 2024/04/22 23:07:47 andvar Exp $"); +__KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.211 2025/03/06 06:31:53 imil Exp $"); #include "opt_ddb.h" #include "opt_mpbios.h" /* for MPDEBUG */ @@ -1416,7 +1416,8 @@ cpu_shutdown(device_t dv, int how) void cpu_get_tsc_freq(struct cpu_info *ci) { - uint64_t freq = 0, freq_from_cpuid, t0, t1; + static uint64_t freq_from_cpuid = 0; + uint64_t freq = 0, t0, t1; int64_t overhead; if (CPU_IS_PRIMARY(ci) && cpu_hascounter()) { @@ -1426,7 +1427,13 @@ cpu_get_tsc_freq(struct cpu_info *ci) * The function also set lapic_per_second variable if it's * known. This is required for Intel's Comet Lake and newer * processors to set LAPIC timer correctly. + * + * If TSC freq is already known by CPUID, don't go through + * tests again. */ + if (freq_from_cpuid != 0) + return; + if (ci->ci_data.cpu_cc_freq == 0) freq = freq_from_cpuid = cpu_tsc_freq_cpuid(ci); if (freq != 0) Index: src/sys/arch/x86/x86/identcpu_subr.c diff -u src/sys/arch/x86/x86/identcpu_subr.c:1.9 src/sys/arch/x86/x86/identcpu_subr.c:1.10 --- src/sys/arch/x86/x86/identcpu_subr.c:1.9 Thu Oct 7 13:04:18 2021 +++ src/sys/arch/x86/x86/identcpu_subr.c Thu Mar 6 06:31:53 2025 @@ -1,4 +1,4 @@ -/* $NetBSD: identcpu_subr.c,v 1.9 2021/10/07 13:04:18 msaitoh Exp $ */ +/* $NetBSD: identcpu_subr.c,v 1.10 2025/03/06 06:31:53 imil Exp $ */ /*- * Copyright (c) 2020 The NetBSD Foundation, Inc. @@ -35,7 +35,7 @@ * See src/usr.sbin/cpuctl/{Makefile, arch/i386.c}). */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: identcpu_subr.c,v 1.9 2021/10/07 13:04:18 msaitoh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: identcpu_subr.c,v 1.10 2025/03/06 06:31:53 imil Exp $"); #ifdef _KERNEL_OPT #include "lapic.h" @@ -62,14 +62,44 @@ __KERNEL_RCSID(0, "$NetBSD: identcpu_sub #include "cpuctl_i386.h" #endif -uint64_t -cpu_tsc_freq_cpuid(struct cpu_info *ci) +#ifdef _KERNEL +static uint64_t +tsc_freq_vmware_cpuid(struct cpu_info *ci) +{ + uint32_t descs[4]; + uint64_t freq; + + if (ci->ci_max_ext_cpuid < 0x40000010) + return 0; + + x86_cpuid(0x40000010, descs); + + freq = descs[0]; + if (freq == 0) + return 0; + + aprint_verbose( + "got tsc frequency from vmware compatible cpuid\n"); + + if (descs[1] > 0) { + aprint_verbose( + "got lapic frequency from vmware compatible cpuid\n"); + lapic_per_second = descs[1] * 1000; + lapic_from_cpuid = true; + } + + return freq * 1000; +} +#endif + +static uint64_t +tsc_freq_cpuid(struct cpu_info *ci) { uint64_t freq = 0, khz; uint32_t descs[4]; uint32_t denominator, numerator; - if (!((ci->ci_max_cpuid >= 0x15) && (cpu_vendor == CPUVENDOR_INTEL))) + if (ci->ci_max_cpuid < 0x15) return 0; x86_cpuid(0x15, descs); @@ -139,6 +169,21 @@ cpu_tsc_freq_cpuid(struct cpu_info *ci) } #endif } + return freq; +} + +uint64_t +cpu_tsc_freq_cpuid(struct cpu_info *ci) +{ + uint64_t freq = 0; + + if (cpu_vendor == CPUVENDOR_INTEL) + freq = tsc_freq_cpuid(ci); +#ifdef _KERNEL + /* VMware compatible tsc frequency query */ + if (freq == 0 && vm_guest > VM_GUEST_NO) + freq = tsc_freq_vmware_cpuid(ci); +#endif if (freq != 0) aprint_verbose_dev(ci->ci_dev, "TSC freq CPUID %" PRIu64 " Hz\n", freq); Index: src/sys/arch/x86/x86/lapic.c diff -u src/sys/arch/x86/x86/lapic.c:1.90 src/sys/arch/x86/x86/lapic.c:1.91 --- src/sys/arch/x86/x86/lapic.c:1.90 Sun Feb 25 18:27:54 2024 +++ src/sys/arch/x86/x86/lapic.c Thu Mar 6 06:31:53 2025 @@ -1,4 +1,4 @@ -/* $NetBSD: lapic.c,v 1.90 2024/02/25 18:27:54 andvar Exp $ */ +/* $NetBSD: lapic.c,v 1.91 2025/03/06 06:31:53 imil Exp $ */ /*- * Copyright (c) 2000, 2008, 2020 The NetBSD Foundation, Inc. @@ -32,7 +32,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: lapic.c,v 1.90 2024/02/25 18:27:54 andvar Exp $"); +__KERNEL_RCSID(0, "$NetBSD: lapic.c,v 1.91 2025/03/06 06:31:53 imil Exp $"); #include "acpica.h" #include "ioapic.h" @@ -131,6 +131,7 @@ bool x2apic_enable = true; #else bool x2apic_enable = false; #endif +bool lapic_from_cpuid = false; static bool lapic_broken_periodic __read_mostly; @@ -606,9 +607,11 @@ lapic_initclock(void) /* * Recalibrate the timer using the cycle counter, now that * the cycle counter itself has been recalibrated. + * + * Not needed when lapic_per_second is read from CPUID. */ - lapic_calibrate_timer(true); - + if (!lapic_from_cpuid) + lapic_calibrate_timer(true); /* * Hook up time counter. This assume that all LAPICs have * the same frequency.