Module Name: src
Committed By: martin
Date: Fri Jul 10 11:20:29 UTC 2020
Modified Files:
src/usr.sbin/cpuctl [netbsd-9]: Makefile cpuctl.c cpuctl.h
src/usr.sbin/cpuctl/arch [netbsd-9]: cpuctl_i386.h i386.c
Added Files:
src/sys/arch/x86/x86 [netbsd-9]: identcpu_subr.c
Log Message:
Pull up the following revisions (all via patch) requested by msaitoh in
ticket #995:
usr.sbin/cpuctl/Makefile 1.9
usr.sbin/cpuctl/arch/cpuctl_i386.h 1.5
usr.sbin/cpuctl/arch/i386.c 1.111-1.113
usr.sbin/cpuctl/cpuctl.c 1.31
usr.sbin/cpuctl/cpuctl.h 1.7
sys/arch/x86/x86/identcpu_subr.c 1.1-1.7
- Get TSC frequency from CPUID 0x15 and/or x16 for newer Intel
processors.
- Add 0xa5 and 0xa6 for Comet Lake.
- Rename ci_cpuid_level to ci_max_cpuid and ci_cpuid_extlevel to
ci_max_ext_cpuid to match x86/include/cpu.h. No functional change.
- Sort some entries.
- Add comment.
To generate a diff of this commit:
cvs rdiff -u -r0 -r1.7.2.2 src/sys/arch/x86/x86/identcpu_subr.c
cvs rdiff -u -r1.8 -r1.8.18.1 src/usr.sbin/cpuctl/Makefile
cvs rdiff -u -r1.30 -r1.30.2.1 src/usr.sbin/cpuctl/cpuctl.c
cvs rdiff -u -r1.6 -r1.6.6.1 src/usr.sbin/cpuctl/cpuctl.h
cvs rdiff -u -r1.4 -r1.4.2.1 src/usr.sbin/cpuctl/arch/cpuctl_i386.h
cvs rdiff -u -r1.104.2.5 -r1.104.2.6 src/usr.sbin/cpuctl/arch/i386.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/usr.sbin/cpuctl/Makefile
diff -u src/usr.sbin/cpuctl/Makefile:1.8 src/usr.sbin/cpuctl/Makefile:1.8.18.1
--- src/usr.sbin/cpuctl/Makefile:1.8 Sat Jan 23 21:22:50 2016
+++ src/usr.sbin/cpuctl/Makefile Fri Jul 10 11:20:29 2020
@@ -1,4 +1,4 @@
-# $NetBSD: Makefile,v 1.8 2016/01/23 21:22:50 christos Exp $
+# $NetBSD: Makefile,v 1.8.18.1 2020/07/10 11:20:29 martin Exp $
.include <bsd.own.mk>
@@ -19,6 +19,12 @@ SRCS+= noarch.c
SRCS+= ${MACHINE_ARCH}-asm.S
.endif
+.if ${MACHINE_ARCH} == "x86_64" || ${MACHINE_ARCH} == "i386"
+CPPFLAGS+= -I${.CURDIR} -I${.CURDIR}/arch
+.PATH.c: ${NETBSDSRCDIR}/sys/arch/x86/x86
+SRCS+= identcpu_subr.c
+.endif
+
CPPFLAGS+= -D_KERNTYPES
LDADD+=-lutil
DPADD+=${LIBUTIL}
Index: src/usr.sbin/cpuctl/cpuctl.c
diff -u src/usr.sbin/cpuctl/cpuctl.c:1.30 src/usr.sbin/cpuctl/cpuctl.c:1.30.2.1
--- src/usr.sbin/cpuctl/cpuctl.c:1.30 Sat May 11 11:59:21 2019
+++ src/usr.sbin/cpuctl/cpuctl.c Fri Jul 10 11:20:29 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: cpuctl.c,v 1.30 2019/05/11 11:59:21 maxv Exp $ */
+/* $NetBSD: cpuctl.c,v 1.30.2.1 2020/07/10 11:20:29 martin Exp $ */
/*-
* Copyright (c) 2007, 2008, 2009, 2012, 2015 The NetBSD Foundation, Inc.
@@ -31,7 +31,7 @@
#ifndef lint
#include <sys/cdefs.h>
-__RCSID("$NetBSD: cpuctl.c,v 1.30 2019/05/11 11:59:21 maxv Exp $");
+__RCSID("$NetBSD: cpuctl.c,v 1.30.2.1 2020/07/10 11:20:29 martin Exp $");
#endif /* not lint */
#include <sys/param.h>
@@ -382,3 +382,4 @@ aprint_normal_dev(const char *dev, const
}
__strong_alias(aprint_verbose_dev,aprint_normal_dev)
__strong_alias(aprint_error_dev,aprint_normal_dev)
+__strong_alias(aprint_debug_dev,aprint_normal_dev)
Index: src/usr.sbin/cpuctl/cpuctl.h
diff -u src/usr.sbin/cpuctl/cpuctl.h:1.6 src/usr.sbin/cpuctl/cpuctl.h:1.6.6.1
--- src/usr.sbin/cpuctl/cpuctl.h:1.6 Tue Jan 16 08:23:18 2018
+++ src/usr.sbin/cpuctl/cpuctl.h Fri Jul 10 11:20:29 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: cpuctl.h,v 1.6 2018/01/16 08:23:18 mrg Exp $ */
+/* $NetBSD: cpuctl.h,v 1.6.6.1 2020/07/10 11:20:29 martin Exp $ */
/*-
* Copyright (c) 2008 The NetBSD Foundation, Inc.
@@ -26,12 +26,15 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
+#include <sys/cpuio.h>
+
int aprint_normal(const char *, ...) __printflike(1, 2);
int aprint_verbose(const char *, ...) __printflike(1, 2);
int aprint_error(const char *, ...) __printflike(1, 2);
int aprint_normal_dev(const char *, const char *, ...) __printflike(2, 3);
int aprint_verbose_dev(const char *, const char *, ...) __printflike(2, 3);
int aprint_error_dev(const char *, const char *, ...) __printflike(2, 3);
+int aprint_debug_dev(const char *, const char *, ...) __printflike(2, 3);
void identifycpu(int, const char *);
bool identifycpu_bind(void);
Index: src/usr.sbin/cpuctl/arch/cpuctl_i386.h
diff -u src/usr.sbin/cpuctl/arch/cpuctl_i386.h:1.4 src/usr.sbin/cpuctl/arch/cpuctl_i386.h:1.4.2.1
--- src/usr.sbin/cpuctl/arch/cpuctl_i386.h:1.4 Tue May 21 05:29:21 2019
+++ src/usr.sbin/cpuctl/arch/cpuctl_i386.h Fri Jul 10 11:20:29 2020
@@ -1,4 +1,50 @@
-/* $NetBSD: cpuctl_i386.h,v 1.4 2019/05/21 05:29:21 mlelstv Exp $ */
+/* $NetBSD: cpuctl_i386.h,v 1.4.2.1 2020/07/10 11:20:29 martin Exp $ */
+
+#include <machine/specialreg.h>
+#include <x86/cputypes.h>
+#include <x86/cacheinfo.h>
+
+struct cpu_info {
+ const char *ci_dev;
+ int32_t ci_cpu_type; /* for cpu's without cpuid */
+ uint32_t ci_signature; /* X86 cpuid type */
+ uint32_t ci_vendor[4]; /* vendor string */
+ int32_t ci_max_cpuid; /* highest cpuid supported */
+ uint32_t ci_max_ext_cpuid; /* highest cpuid extended func lv */
+ uint32_t ci_family; /* from ci_signature */
+ uint32_t ci_model; /* from ci_signature */
+ uint32_t ci_feat_val[10]; /* X86 CPUID feature bits
+ * [0] basic features %edx
+ * [1] basic features %ecx
+ * [2] extended features %edx
+ * [3] extended features %ecx
+ * [4] VIA padlock features
+ * [5] structure ext. feat. %ebx
+ * [6] structure ext. feat. %ecx
+ * [7] structure ext. feat. %edx
+ * [8] XCR0 bits (d:0 %eax)
+ * [9] xsave flags (d:1 %eax)
+ */
+ uint32_t ci_cpu_class; /* CPU class */
+ uint32_t ci_brand_id; /* Intel brand id */
+ uint32_t ci_cpu_serial[3]; /* PIII serial number */
+ uint64_t ci_tsc_freq; /* cpu cycles/second */
+ uint8_t ci_packageid;
+ uint8_t ci_coreid;
+ uint8_t ci_smtid;
+ uint32_t ci_initapicid; /* our initial APIC ID */
+
+ uint32_t ci_cur_xsave;
+ uint32_t ci_max_xsave;
+
+ struct x86_cache_info ci_cinfo[CAI_COUNT];
+ void (*ci_info)(struct cpu_info *);
+};
+
+extern int cpu_vendor;
+
+/* For x86/x86/identcpu_subr.c */
+uint64_t cpu_tsc_freq_cpuid(struct cpu_info *);
/* Interfaces to code in i386-asm.S */
Index: src/usr.sbin/cpuctl/arch/i386.c
diff -u src/usr.sbin/cpuctl/arch/i386.c:1.104.2.5 src/usr.sbin/cpuctl/arch/i386.c:1.104.2.6
--- src/usr.sbin/cpuctl/arch/i386.c:1.104.2.5 Tue Apr 14 17:15:02 2020
+++ src/usr.sbin/cpuctl/arch/i386.c Fri Jul 10 11:20:29 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: i386.c,v 1.104.2.5 2020/04/14 17:15:02 martin Exp $ */
+/* $NetBSD: i386.c,v 1.104.2.6 2020/07/10 11:20:29 martin Exp $ */
/*-
* Copyright (c) 1999, 2000, 2001, 2006, 2007, 2008 The NetBSD Foundation, Inc.
@@ -57,7 +57,7 @@
#include <sys/cdefs.h>
#ifndef lint
-__RCSID("$NetBSD: i386.c,v 1.104.2.5 2020/04/14 17:15:02 martin Exp $");
+__RCSID("$NetBSD: i386.c,v 1.104.2.6 2020/07/10 11:20:29 martin Exp $");
#endif /* not lint */
#include <sys/types.h>
@@ -81,7 +81,6 @@ __RCSID("$NetBSD: i386.c,v 1.104.2.5 202
#include <x86/cpuvar.h>
#include <x86/cputypes.h>
-#include <x86/cacheinfo.h>
#include <x86/cpu_ucode.h>
#include "../cpuctl.h"
@@ -90,43 +89,6 @@ __RCSID("$NetBSD: i386.c,v 1.104.2.5 202
/* Size of buffer for printing humanized numbers */
#define HUMAN_BUFSIZE sizeof("999KB")
-struct cpu_info {
- const char *ci_dev;
- int32_t ci_cpu_type; /* for cpu's without cpuid */
- int32_t ci_cpuid_level; /* highest cpuid supported */
- uint32_t ci_cpuid_extlevel; /* highest cpuid extended func lv */
- uint32_t ci_signature; /* X86 cpuid type */
- uint32_t ci_family; /* from ci_signature */
- uint32_t ci_model; /* from ci_signature */
- uint32_t ci_feat_val[10]; /* X86 CPUID feature bits
- * [0] basic features %edx
- * [1] basic features %ecx
- * [2] extended features %edx
- * [3] extended features %ecx
- * [4] VIA padlock features
- * [5] structure ext. feat. %ebx
- * [6] structure ext. feat. %ecx
- * [7] structure ext. feat. %edx
- * [8] XCR0 bits (d:0 %eax)
- * [9] xsave flags (d:1 %eax)
- */
- uint32_t ci_cpu_class; /* CPU class */
- uint32_t ci_brand_id; /* Intel brand id */
- uint32_t ci_vendor[4]; /* vendor string */
- uint32_t ci_cpu_serial[3]; /* PIII serial number */
- uint64_t ci_tsc_freq; /* cpu cycles/second */
- uint8_t ci_packageid;
- uint8_t ci_coreid;
- uint8_t ci_smtid;
- uint32_t ci_initapicid;
-
- uint32_t ci_cur_xsave;
- uint32_t ci_max_xsave;
-
- struct x86_cache_info ci_cinfo[CAI_COUNT];
- void (*ci_info)(struct cpu_info *);
-};
-
struct cpu_nocpuid_nameclass {
int cpu_vendor;
const char *cpu_vendorname;
@@ -197,7 +159,7 @@ static const char * const amd_brand[] =
"4" /* AMD Athlon(tm) 4 */
};
-static int cpu_vendor;
+int cpu_vendor;
static char cpu_brand_string[49];
static char amd_brand_name[48];
static int use_pae, largepagesize;
@@ -391,6 +353,8 @@ const struct cpu_cpuid_nameclass i386_cp
[0x86] = "Atom (Tremont)",
[0x8e] = "7th or 8th gen Core (Kaby Lake, Coffee Lake) or Xeon E (Coffee Lake)",
[0x9e] = "7th or 8th gen Core (Kaby Lake, Coffee Lake) or Xeon E (Coffee Lake)",
+ [0xa5] = "10th gen Core (Comet Lake)",
+ [0xa6] = "10th gen Core (Comet Lake)",
},
"Pentium Pro, II or III", /* Default */
NULL,
@@ -1065,7 +1029,7 @@ intel_cpu_cacheinfo(struct cpu_info *ci)
if (ci->ci_cpu_type >= 0)
return;
- if (ci->ci_cpuid_level < 2)
+ if (ci->ci_max_cpuid < 2)
return;
/*
@@ -1103,13 +1067,13 @@ intel_cpu_cacheinfo(struct cpu_info *ci)
x86_cpuid(2, descs);
}
- if (ci->ci_cpuid_level < 4)
+ if (ci->ci_max_cpuid < 4)
return;
/* Parse the cache info from `cpuid leaf 4', if we have it. */
cpu_dcp_cacheinfo(ci, 4);
- if (ci->ci_cpuid_level < 0x18)
+ if (ci->ci_max_cpuid < 0x18)
return;
/* Parse the TLB info from `cpuid leaf 18H', if we have it. */
x86_cpuid(0x18, descs);
@@ -1583,7 +1547,7 @@ cpu_probe_base_features(struct cpu_info
ci->ci_cpu_type = x86_identify();
if (ci->ci_cpu_type >= 0) {
/* Old pre-cpuid instruction cpu */
- ci->ci_cpuid_level = -1;
+ ci->ci_max_cpuid = -1;
return;
}
@@ -1598,7 +1562,7 @@ cpu_probe_base_features(struct cpu_info
* - Save vendor string.
*/
x86_cpuid(0, descs);
- ci->ci_cpuid_level = descs[0];
+ ci->ci_max_cpuid = descs[0];
/* Save vendor string */
ci->ci_vendor[0] = descs[1];
ci->ci_vendor[2] = descs[2];
@@ -1611,17 +1575,17 @@ cpu_probe_base_features(struct cpu_info
*/
x86_cpuid(0x80000000, descs);
if (descs[0] >= 0x80000000)
- ci->ci_cpuid_extlevel = descs[0];
+ ci->ci_max_ext_cpuid = descs[0];
else {
/* Set lower value than 0x80000000 */
- ci->ci_cpuid_extlevel = 0;
+ ci->ci_max_ext_cpuid = 0;
}
/*
* Fn8000_000[2-4]:
* - Save brand string.
*/
- if (ci->ci_cpuid_extlevel >= 0x80000004) {
+ if (ci->ci_max_ext_cpuid >= 0x80000004) {
x86_cpuid(0x80000002, brand);
x86_cpuid(0x80000003, brand + 4);
x86_cpuid(0x80000004, brand + 8);
@@ -1631,7 +1595,7 @@ cpu_probe_base_features(struct cpu_info
memcpy(cpu_brand_string, ((char *) brand) + i, 48 - i);
}
- if (ci->ci_cpuid_level < 1)
+ if (ci->ci_max_cpuid < 1)
return;
/*
@@ -1656,7 +1620,7 @@ cpu_probe_base_features(struct cpu_info
ci->ci_feat_val[1] = descs[2];
ci->ci_feat_val[0] = descs[3];
- if (ci->ci_cpuid_level < 3)
+ if (ci->ci_max_cpuid < 3)
return;
/*
@@ -1670,7 +1634,7 @@ cpu_probe_base_features(struct cpu_info
ci->ci_cpu_serial[1] = descs[3];
}
- if (ci->ci_cpuid_level < 0x7)
+ if (ci->ci_max_cpuid < 0x7)
return;
x86_cpuid(7, descs);
@@ -1678,7 +1642,7 @@ cpu_probe_base_features(struct cpu_info
ci->ci_feat_val[6] = descs[2];
ci->ci_feat_val[7] = descs[3];
- if (ci->ci_cpuid_level < 0xd)
+ if (ci->ci_max_cpuid < 0xd)
return;
/* Get support XCR0 bits */
@@ -1752,7 +1716,7 @@ cpu_probe_features(struct cpu_info *ci)
const struct cpu_cpuid_nameclass *cpup = NULL;
unsigned int i;
- if (ci->ci_cpuid_level < 1)
+ if (ci->ci_max_cpuid < 1)
return;
for (i = 0; i < __arraycount(i386_cpuid_cpus); i++) {
@@ -1914,9 +1878,9 @@ identifycpu_cpuids_intel(struct cpu_info
{
const char *cpuname = ci->ci_dev;
- if (ci->ci_cpuid_level >= 0x0b)
+ if (ci->ci_max_cpuid >= 0x0b)
identifycpu_cpuids_intel_0x0b(ci);
- else if (ci->ci_cpuid_level >= 4)
+ else if (ci->ci_max_cpuid >= 4)
identifycpu_cpuids_intel_0x04(ci);
aprint_verbose("%s: Cluster/Package ID %u\n", cpuname,
@@ -1943,7 +1907,7 @@ identifycpu_cpuids_amd(struct cpu_info *
x86_cpuid(1, descs);
lp_max = __SHIFTOUT(descs[1], CPUID_HTT_CORES);
- if (cpu_family >= 0x10 && ci->ci_cpuid_extlevel >= 0x8000008) {
+ if (cpu_family >= 0x10 && ci->ci_max_ext_cpuid >= 0x8000008) {
x86_cpuid(0x8000008, descs);
core_max = (descs[2] & 0xff) + 1;
n = (descs[2] >> 12) & 0x0f;
@@ -2033,12 +1997,12 @@ identifycpu(int fd, const char *cpuname)
ci = &cistore;
cpu_probe_base_features(ci, cpuname);
- dump_descs(0x00000000, ci->ci_cpuid_level, cpuname, "basic");
+ dump_descs(0x00000000, ci->ci_max_cpuid, cpuname, "basic");
if ((ci->ci_feat_val[1] & CPUID2_RAZ) != 0) {
x86_cpuid(0x40000000, descs);
dump_descs(0x40000000, descs[0], cpuname, "hypervisor");
}
- dump_descs(0x80000000, ci->ci_cpuid_extlevel, cpuname, "extended");
+ dump_descs(0x80000000, ci->ci_max_ext_cpuid, cpuname, "extended");
cpu_probe_hv_features(ci, cpuname);
cpu_probe_features(ci);
@@ -2164,6 +2128,8 @@ identifycpu(int fd, const char *cpuname)
(((uintmax_t)ci->ci_tsc_freq + 4999) / 10000) % 100);
aprint_normal("\n");
+ (void)cpu_tsc_freq_cpuid(ci);
+
aprint_normal_dev(ci->ci_dev, "family %#x model %#x stepping %#x",
ci->ci_family, ci->ci_model, CPUID_TO_STEPPING(ci->ci_signature));
if (ci->ci_signature != 0)
@@ -2217,7 +2183,7 @@ identifycpu(int fd, const char *cpuname)
x86_print_cache_and_tlb_info(ci);
- if (ci->ci_cpuid_level >= 3 && (ci->ci_feat_val[0] & CPUID_PN)) {
+ if (ci->ci_max_cpuid >= 3 && (ci->ci_feat_val[0] & CPUID_PN)) {
aprint_verbose("%s: serial number %04X-%04X-%04X-%04X-%04X-%04X\n",
cpuname,
ci->ci_cpu_serial[0] / 65536, ci->ci_cpu_serial[0] % 65536,
@@ -2243,12 +2209,12 @@ identifycpu(int fd, const char *cpuname)
/*
* Everything past this point requires a Pentium or later.
*/
- if (ci->ci_cpuid_level < 0)
+ if (ci->ci_max_cpuid < 0)
return;
identifycpu_cpuids(ci);
- if ((ci->ci_cpuid_level >= 5)
+ if ((ci->ci_max_cpuid >= 5)
&& ((cpu_vendor == CPUVENDOR_INTEL)
|| (cpu_vendor == CPUVENDOR_AMD))) {
uint16_t lmin, lmax;
@@ -2271,14 +2237,14 @@ identifycpu(int fd, const char *cpuname)
cpuname, i, num);
}
}
- if ((ci->ci_cpuid_level >= 6)
+ if ((ci->ci_max_cpuid >= 6)
&& ((cpu_vendor == CPUVENDOR_INTEL)
|| (cpu_vendor == CPUVENDOR_AMD))) {
x86_cpuid(6, descs);
print_bits(cpuname, "DSPM-eax", CPUID_DSPM_FLAGS, descs[0]);
print_bits(cpuname, "DSPM-ecx", CPUID_DSPM_FLAGS1, descs[2]);
}
- if ((ci->ci_cpuid_level >= 7)
+ if ((ci->ci_max_cpuid >= 7)
&& ((cpu_vendor == CPUVENDOR_INTEL)
|| (cpu_vendor == CPUVENDOR_AMD))) {
x86_cpuid(7, descs);
@@ -2287,17 +2253,17 @@ identifycpu(int fd, const char *cpuname)
}
if ((cpu_vendor == CPUVENDOR_INTEL) || (cpu_vendor == CPUVENDOR_AMD))
- if (ci->ci_cpuid_extlevel >= 0x80000007)
+ if (ci->ci_max_ext_cpuid >= 0x80000007)
powernow_probe(ci);
if (cpu_vendor == CPUVENDOR_AMD) {
- if (ci->ci_cpuid_extlevel >= 0x80000008) {
+ if (ci->ci_max_ext_cpuid >= 0x80000008) {
x86_cpuid(0x80000008, descs);
print_bits(cpuname, "AMD Extended features",
CPUID_CAPEX_FLAGS, descs[1]);
}
- if ((ci->ci_cpuid_extlevel >= 0x8000000a)
+ if ((ci->ci_max_ext_cpuid >= 0x8000000a)
&& (ci->ci_feat_val[3] & CPUID_SVM) != 0) {
x86_cpuid(0x8000000a, descs);
aprint_verbose("%s: SVM Rev. %d\n", cpuname,
@@ -2307,7 +2273,7 @@ identifycpu(int fd, const char *cpuname)
print_bits(cpuname, "SVM features",
CPUID_AMD_SVM_FLAGS, descs[3]);
}
- if (ci->ci_cpuid_extlevel >= 0x8000001f) {
+ if (ci->ci_max_ext_cpuid >= 0x8000001f) {
x86_cpuid(0x8000001f, descs);
print_bits(cpuname, "Encrypted Memory features",
CPUID_AMD_ENCMEM_FLAGS, descs[0]);
@@ -2315,7 +2281,7 @@ identifycpu(int fd, const char *cpuname)
} else if (cpu_vendor == CPUVENDOR_INTEL) {
int32_t bi_index;
- for (bi_index = 1; bi_index <= ci->ci_cpuid_level; bi_index++) {
+ for (bi_index = 1; bi_index <= ci->ci_max_cpuid; bi_index++) {
x86_cpuid(bi_index, descs);
switch (bi_index) {
case 0x0a:
Added files:
Index: src/sys/arch/x86/x86/identcpu_subr.c
diff -u /dev/null src/sys/arch/x86/x86/identcpu_subr.c:1.7.2.2
--- /dev/null Fri Jul 10 11:20:29 2020
+++ src/sys/arch/x86/x86/identcpu_subr.c Fri Jul 10 11:20:29 2020
@@ -0,0 +1,145 @@
+/* $NetBSD: identcpu_subr.c,v 1.7.2.2 2020/07/10 11:20:29 martin Exp $ */
+
+/*-
+ * 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.7.2.2 2020/07/10 11:20:29 martin 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)) {
+ 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 " Hz\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 " Hz\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 CPUID %" PRIu64
+ " Hz\n", freq);
+
+ return freq;
+}