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; +}