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