Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src Get TSC frequency from CPUID 0x15 and/or x16 for newer Intel...
details: https://anonhg.NetBSD.org/src/rev/e04a06ef8ed5
branches: trunk
changeset: 931051:e04a06ef8ed5
user: msaitoh <msaitoh%NetBSD.org@localhost>
date: Tue Apr 21 02:56:36 2020 +0000
description:
Get TSC frequency from CPUID 0x15 and/or x16 for newer Intel processors.
- If the max CPUID leaf is >= 0x15, take TSC value from CPUID. Some processors
can take TSC/core crystal clock ratio but core crystal clock frequency
can't be taken. Intel SDM give us the values for some processors.
- It also required to change lapic_per_second to make LAPIC timer correctly.
- Add new file x86/x86/identcpu_subr.c to share common subroutines between
kernel and userland. Some code in x86/x86/identcpu.c and cpuctl/arch/i386.c
will be moved to this file in future.
- Add comment to clarify.
diffstat:
sys/arch/x86/conf/files.x86 | 3 +-
sys/arch/x86/include/apicvar.h | 5 +-
sys/arch/x86/include/cpu.h | 5 +-
sys/arch/x86/x86/cpu.c | 16 +++-
sys/arch/x86/x86/hyperv.c | 10 +-
sys/arch/x86/x86/identcpu_subr.c | 146 +++++++++++++++++++++++++++++++++++++
sys/arch/x86/x86/tsc.c | 9 +-
sys/arch/xen/conf/files.xen | 3 +-
usr.sbin/cpuctl/Makefile | 8 +-
usr.sbin/cpuctl/arch/cpuctl_i386.h | 48 +++++++++++-
usr.sbin/cpuctl/arch/i386.c | 46 +----------
usr.sbin/cpuctl/cpuctl.c | 5 +-
usr.sbin/cpuctl/cpuctl.h | 5 +-
13 files changed, 247 insertions(+), 62 deletions(-)
diffs (truncated from 543 to 300 lines):
diff -r 6735647710fa -r e04a06ef8ed5 sys/arch/x86/conf/files.x86
--- a/sys/arch/x86/conf/files.x86 Mon Apr 20 21:57:22 2020 +0000
+++ b/sys/arch/x86/conf/files.x86 Tue Apr 21 02:56:36 2020 +0000
@@ -1,4 +1,4 @@
-# $NetBSD: files.x86,v 1.107 2019/02/15 08:54:01 nonaka Exp $
+# $NetBSD: files.x86,v 1.108 2020/04/21 02:56:36 msaitoh Exp $
# options for MP configuration through the MP spec
defflag opt_mpbios.h MPBIOS MPDEBUG MPBIOS_SCANPCI
@@ -91,6 +91,7 @@
file arch/x86/x86/errata.c machdep
file arch/x86/x86/genfb_machdep.c machdep
file arch/x86/x86/identcpu.c machdep
+file arch/x86/x86/identcpu_subr.c machdep
file arch/x86/x86/i8259.c machdep
file arch/x86/x86/intr.c machdep
file arch/x86/x86/kgdb_machdep.c kgdb
diff -r 6735647710fa -r e04a06ef8ed5 sys/arch/x86/include/apicvar.h
--- a/sys/arch/x86/include/apicvar.h Mon Apr 20 21:57:22 2020 +0000
+++ b/sys/arch/x86/include/apicvar.h Tue Apr 21 02:56:36 2020 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: apicvar.h,v 1.6 2019/06/14 09:23:42 msaitoh Exp $ */
+/* $NetBSD: apicvar.h,v 1.7 2020/04/21 02:56:37 msaitoh Exp $ */
/*-
* Copyright (c) 2000 The NetBSD Foundation, Inc.
@@ -54,4 +54,7 @@
void apic_format_redir(const char *, const char *, int, int, uint32_t,
uint32_t);
+/* For lapic.c */
+extern uint32_t lapic_per_second;
+
#endif /* !_X86_APICVAR_H_ */
diff -r 6735647710fa -r e04a06ef8ed5 sys/arch/x86/include/cpu.h
--- a/sys/arch/x86/include/cpu.h Mon Apr 20 21:57:22 2020 +0000
+++ b/sys/arch/x86/include/cpu.h Tue Apr 21 02:56:36 2020 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: cpu.h,v 1.120 2020/04/13 22:54:11 bouyer Exp $ */
+/* $NetBSD: cpu.h,v 1.121 2020/04/21 02:56:37 msaitoh Exp $ */
/*
* Copyright (c) 1990 The Regents of the University of California.
@@ -490,6 +490,9 @@
void cpu_identify(struct cpu_info *);
void identify_hypervisor(void);
+/* identcpu_subr.c */
+uint64_t cpu_tsc_freq_cpuid(struct cpu_info *);
+
typedef enum vm_guest {
VM_GUEST_NO = 0,
VM_GUEST_VM,
diff -r 6735647710fa -r e04a06ef8ed5 sys/arch/x86/x86/cpu.c
--- a/sys/arch/x86/x86/cpu.c Mon Apr 20 21:57:22 2020 +0000
+++ b/sys/arch/x86/x86/cpu.c Tue Apr 21 02:56:36 2020 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: cpu.c,v 1.184 2020/04/20 04:23:23 msaitoh Exp $ */
+/* $NetBSD: cpu.c,v 1.185 2020/04/21 02:56:37 msaitoh Exp $ */
/*
* Copyright (c) 2000-2012 NetBSD Foundation, Inc.
@@ -62,7 +62,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.184 2020/04/20 04:23:23 msaitoh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.185 2020/04/21 02:56:37 msaitoh Exp $");
#include "opt_ddb.h"
#include "opt_mpbios.h" /* for MPDEBUG */
@@ -1291,12 +1291,20 @@
return cpu_stop(dv);
}
+/* Get the TSC frequency and set it to ci->ci_data.cpu_cc_freq. */
void
cpu_get_tsc_freq(struct cpu_info *ci)
{
- uint64_t last_tsc;
+ uint64_t freq = 0, last_tsc;
+
+ if (cpu_hascounter())
+ freq = cpu_tsc_freq_cpuid(ci);
- if (cpu_hascounter()) {
+ if (freq != 0) {
+ /* Use TSC frequency taken from CPUID. */
+ ci->ci_data.cpu_cc_freq = freq;
+ } else {
+ /* Calibrate TSC frequency. */
last_tsc = cpu_counter_serializing();
x86_delay(100000);
ci->ci_data.cpu_cc_freq =
diff -r 6735647710fa -r e04a06ef8ed5 sys/arch/x86/x86/hyperv.c
--- a/sys/arch/x86/x86/hyperv.c Mon Apr 20 21:57:22 2020 +0000
+++ b/sys/arch/x86/x86/hyperv.c Tue Apr 21 02:56:36 2020 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: hyperv.c,v 1.6 2019/12/07 11:45:45 nonaka Exp $ */
+/* $NetBSD: hyperv.c,v 1.7 2020/04/21 02:56:37 msaitoh Exp $ */
/*-
* Copyright (c) 2009-2012,2016-2017 Microsoft Corp.
@@ -33,7 +33,7 @@
*/
#include <sys/cdefs.h>
#ifdef __KERNEL_RCSID
-__KERNEL_RCSID(0, "$NetBSD: hyperv.c,v 1.6 2019/12/07 11:45:45 nonaka Exp $");
+__KERNEL_RCSID(0, "$NetBSD: hyperv.c,v 1.7 2020/04/21 02:56:37 msaitoh Exp $");
#endif
#ifdef __FBSDID
__FBSDID("$FreeBSD: head/sys/dev/hyperv/vmbus/hyperv.c 331757 2018-03-30 02:25:12Z emaste $");
@@ -67,6 +67,7 @@
#include <machine/cputypes.h>
#include <machine/cpuvar.h>
#include <machine/cpu_counter.h>
+#include <x86/apicvar.h>
#include <x86/efi.h>
#include <dev/wsfb/genfbvar.h>
@@ -571,11 +572,8 @@
#if NLAPIC > 0
if ((hyperv_features & CPUID_HV_MSR_TIME_FREQ) &&
- (hyperv_features3 & CPUID3_HV_TIME_FREQ)) {
- extern uint32_t lapic_per_second;
-
+ (hyperv_features3 & CPUID3_HV_TIME_FREQ))
lapic_per_second = rdmsr(MSR_HV_APIC_FREQUENCY);
- }
#endif
return hyperv_init_hypercall();
diff -r 6735647710fa -r e04a06ef8ed5 sys/arch/x86/x86/identcpu_subr.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/arch/x86/x86/identcpu_subr.c Tue Apr 21 02:56:36 2020 +0000
@@ -0,0 +1,146 @@
+/*-
+ * Copyright (c) 2020 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Masanobu SAITOH.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Subroutines for CPU.
+ * This file is shared between kernel and userland.
+ * See src/usr.sbin/cpuctl/{Makefile, arch/i386.c}).
+ */
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: identcpu_subr.c,v 1.1 2020/04/21 02:56:37 msaitoh Exp $");
+
+#ifdef _KERNEL_OPT
+#include "lapic.h"
+#endif
+
+#include <sys/param.h>
+
+#ifdef _KERNEL
+#include <sys/systm.h>
+#include <x86/cpuvar.h>
+#include <x86/apicvar.h>
+#include <machine/cpufunc.h>
+#include <machine/cputypes.h>
+#include <machine/specialreg.h>
+#else
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "cpuctl.h"
+#include "cpuctl_i386.h"
+#endif
+
+uint64_t
+cpu_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)))
+ return 0;
+
+ x86_cpuid(0x15, descs);
+ denominator = descs[0];
+ numerator = descs[1];
+ if ((denominator == 0) || numerator == 0) {
+ aprint_debug_dev(ci->ci_dev,
+ "TSC/core crystal clock ratio is not enumerated\n");
+ } else {
+ khz = 0;
+ if (descs[2] != 0)
+ khz = descs[2] / 1000;
+ else if (CPUID_TO_FAMILY(ci->ci_signature) == 6) {
+ /*
+ * Table 18-85 Nominal Core Crystal Clock Frequency,
+ * 18.7.3 Determining the Processor Base Frequency,
+ * Intel SDM.
+ */
+ switch (CPUID_TO_MODEL(ci->ci_signature)) {
+ case 0x55: /* Xeon Scalable */
+ case 0x5f: /*
+ * Atom Goldmont (Denverton). Right?
+ * XXX Not documented!
+ */
+ khz = 25000; /* 25.0 MHz */
+ break;
+ case 0x4e: /* 7th gen Core (Skylake) */
+ case 0x5e: /* 7th gen Core (Skylake) */
+ case 0x8e: /* 8th gen Core (Kaby Lake) */
+ case 0x9e: /* 8th gen Core (Kaby Lake) */
+ khz = 24000; /* 24.0 MHz */
+ break;
+ case 0x5c: /* Atom Goldmont */
+ khz = 19200; /* 19.2 MHz */
+ break;
+ default: /* Unknown */
+ break;
+ }
+ }
+ freq = khz * 1000 * numerator / denominator;
+ if (ci->ci_max_cpuid >= 0x16) {
+ x86_cpuid(0x16, descs);
+ if (descs[0] != 0) {
+ aprint_verbose_dev(ci->ci_dev,
+ "CPU base freq %" PRIu64 "\n",
+ (uint64_t)descs[0] * 1000000);
+
+ /*
+ * If we couldn't get frequency from
+ * CPUID 0x15, use CPUID 0x16 EAX.
+ */
+ if (freq == 0) {
+ khz = (uint64_t)descs[0] * 1000
+ * denominator / numerator;
+ freq = (uint64_t)descs[0] * 1000000;
+ }
+ }
+ if (descs[1] != 0) {
+ aprint_verbose_dev(ci->ci_dev,
+ "CPU max freq %" PRIu64 "\n",
+ (uint64_t)descs[1] * 1000000);
+ }
+ }
+#if defined(_KERNEL) && NLAPIC > 0
+ if ((khz != 0) && (lapic_per_second == 0)) {
+ lapic_per_second = khz * 1000;
+ aprint_debug_dev(ci->ci_dev,
+ "lapic_per_second set to %" PRIu32 "\n",
+ lapic_per_second);
+ }
+#endif
+ }
+ if (freq != 0)
+ aprint_verbose_dev(ci->ci_dev, "TSC freq %" PRIu64 "\n",
+ freq);
+
+ return freq;
+}
diff -r 6735647710fa -r e04a06ef8ed5 sys/arch/x86/x86/tsc.c
--- a/sys/arch/x86/x86/tsc.c Mon Apr 20 21:57:22 2020 +0000
+++ b/sys/arch/x86/x86/tsc.c Tue Apr 21 02:56:36 2020 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: tsc.c,v 1.40 2020/04/06 09:24:50 msaitoh Exp $ */
+/* $NetBSD: tsc.c,v 1.41 2020/04/21 02:56:37 msaitoh Exp $ */
/*-
* Copyright (c) 2008 The NetBSD Foundation, Inc.
@@ -27,7 +27,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: tsc.c,v 1.40 2020/04/06 09:24:50 msaitoh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: tsc.c,v 1.41 2020/04/21 02:56:37 msaitoh Exp $");
#include <sys/param.h>
Home |
Main Index |
Thread Index |
Old Index