Annotation of src/sys/arch/x86/x86/identcpu_subr.c, Revision 1.1
1.1 ! msaitoh 1: /*-
! 2: * Copyright (c) 2020 The NetBSD Foundation, Inc.
! 3: * All rights reserved.
! 4: *
! 5: * This code is derived from software contributed to The NetBSD Foundation
! 6: * by Masanobu SAITOH.
! 7: *
! 8: * Redistribution and use in source and binary forms, with or without
! 9: * modification, are permitted provided that the following conditions
! 10: * are met:
! 11: * 1. Redistributions of source code must retain the above copyright
! 12: * notice, this list of conditions and the following disclaimer.
! 13: * 2. Redistributions in binary form must reproduce the above copyright
! 14: * notice, this list of conditions and the following disclaimer in the
! 15: * documentation and/or other materials provided with the distribution.
! 16: *
! 17: * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
! 18: * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
! 19: * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
! 20: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
! 21: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
! 22: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
! 23: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
! 24: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
! 25: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
! 26: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
! 27: * POSSIBILITY OF SUCH DAMAGE.
! 28: */
! 29:
! 30: /*
! 31: * Subroutines for CPU.
! 32: * This file is shared between kernel and userland.
! 33: * See src/usr.sbin/cpuctl/{Makefile, arch/i386.c}).
! 34: */
! 35: #include <sys/cdefs.h>
! 36: __KERNEL_RCSID(0, "$NetBSD:$");
! 37:
! 38: #ifdef _KERNEL_OPT
! 39: #include "lapic.h"
! 40: #endif
! 41:
! 42: #include <sys/param.h>
! 43:
! 44: #ifdef _KERNEL
! 45: #include <sys/systm.h>
! 46: #include <x86/cpuvar.h>
! 47: #include <x86/apicvar.h>
! 48: #include <machine/cpufunc.h>
! 49: #include <machine/cputypes.h>
! 50: #include <machine/specialreg.h>
! 51: #else
! 52: #include <stdarg.h>
! 53: #include <stdbool.h>
! 54: #include <stdio.h>
! 55: #include <stdlib.h>
! 56: #include <string.h>
! 57: #include "cpuctl.h"
! 58: #include "cpuctl_i386.h"
! 59: #endif
! 60:
! 61: uint64_t
! 62: cpu_tsc_freq_cpuid(struct cpu_info *ci)
! 63: {
! 64: uint64_t freq = 0, khz;
! 65: uint32_t descs[4];
! 66: uint32_t denominator, numerator;
! 67:
! 68: if (!((ci->ci_max_cpuid >= 0x15) && (cpu_vendor == CPUVENDOR_INTEL)))
! 69: return 0;
! 70:
! 71: x86_cpuid(0x15, descs);
! 72: denominator = descs[0];
! 73: numerator = descs[1];
! 74: if ((denominator == 0) || numerator == 0) {
! 75: aprint_debug_dev(ci->ci_dev,
! 76: "TSC/core crystal clock ratio is not enumerated\n");
! 77: } else {
! 78: khz = 0;
! 79: if (descs[2] != 0)
! 80: khz = descs[2] / 1000;
! 81: else if (CPUID_TO_FAMILY(ci->ci_signature) == 6) {
! 82: /*
! 83: * Table 18-85 Nominal Core Crystal Clock Frequency,
! 84: * 18.7.3 Determining the Processor Base Frequency,
! 85: * Intel SDM.
! 86: */
! 87: switch (CPUID_TO_MODEL(ci->ci_signature)) {
! 88: case 0x55: /* Xeon Scalable */
! 89: case 0x5f: /*
! 90: * Atom Goldmont (Denverton). Right?
! 91: * XXX Not documented!
! 92: */
! 93: khz = 25000; /* 25.0 MHz */
! 94: break;
! 95: case 0x4e: /* 7th gen Core (Skylake) */
! 96: case 0x5e: /* 7th gen Core (Skylake) */
! 97: case 0x8e: /* 8th gen Core (Kaby Lake) */
! 98: case 0x9e: /* 8th gen Core (Kaby Lake) */
! 99: khz = 24000; /* 24.0 MHz */
! 100: break;
! 101: case 0x5c: /* Atom Goldmont */
! 102: khz = 19200; /* 19.2 MHz */
! 103: break;
! 104: default: /* Unknown */
! 105: break;
! 106: }
! 107: }
! 108: freq = khz * 1000 * numerator / denominator;
! 109: if (ci->ci_max_cpuid >= 0x16) {
! 110: x86_cpuid(0x16, descs);
! 111: if (descs[0] != 0) {
! 112: aprint_verbose_dev(ci->ci_dev,
! 113: "CPU base freq %" PRIu64 "\n",
! 114: (uint64_t)descs[0] * 1000000);
! 115:
! 116: /*
! 117: * If we couldn't get frequency from
! 118: * CPUID 0x15, use CPUID 0x16 EAX.
! 119: */
! 120: if (freq == 0) {
! 121: khz = (uint64_t)descs[0] * 1000
! 122: * denominator / numerator;
! 123: freq = (uint64_t)descs[0] * 1000000;
! 124: }
! 125: }
! 126: if (descs[1] != 0) {
! 127: aprint_verbose_dev(ci->ci_dev,
! 128: "CPU max freq %" PRIu64 "\n",
! 129: (uint64_t)descs[1] * 1000000);
! 130: }
! 131: }
! 132: #if defined(_KERNEL) && NLAPIC > 0
! 133: if ((khz != 0) && (lapic_per_second == 0)) {
! 134: lapic_per_second = khz * 1000;
! 135: aprint_debug_dev(ci->ci_dev,
! 136: "lapic_per_second set to %" PRIu32 "\n",
! 137: lapic_per_second);
! 138: }
! 139: #endif
! 140: }
! 141: if (freq != 0)
! 142: aprint_verbose_dev(ci->ci_dev, "TSC freq %" PRIu64 "\n",
! 143: freq);
! 144:
! 145: return freq;
! 146: }
CVSweb <webmaster@jp.NetBSD.org>