1/* $NetBSD: intel_busclock.c,v 1.26 2023/01/20 01:35:03 msaitoh Exp $ */ 2 3/*- 4 * Copyright (c) 1999, 2000, 2001 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Frank van der Linden, and by Jason R. Thorpe. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32#include <sys/cdefs.h> 33__KERNEL_RCSID(0, "$NetBSD: intel_busclock.c,v 1.26 2023/01/20 01:35:03 msaitoh Exp $"); 34 35#include <sys/param.h> 36#include <sys/systm.h> 37#include <sys/device.h> 38#include <sys/cpu.h> 39 40#include <machine/specialreg.h> 41#include <machine/pio.h> 42 43#include <x86/cpuvar.h> 44#include <x86/cpufunc.h> 45#include <x86/est.h> 46 47int 48via_get_bus_clock(struct cpu_info *ci) 49{ 50 uint64_t msr; 51 int bus, bus_clock = 0; 52 53 msr = rdmsr(MSR_EBL_CR_POWERON); 54 bus = (msr >> 18) & 0x3; 55 switch (bus) { 56 case 0: 57 bus_clock = 10000; 58 break; 59 case 1: 60 bus_clock = 13333; 61 break; 62 case 2: 63 bus_clock = 20000; 64 break; 65 case 3: 66 bus_clock = 16667; 67 break; 68 default: 69 break; 70 } 71 72 return bus_clock; 73} 74 75int 76viac7_get_bus_clock(struct cpu_info *ci) 77{ 78 uint64_t msr; 79 int mult; 80 81 msr = rdmsr(MSR_PERF_STATUS); 82 mult = (msr >> 8) & 0xff; 83 if (mult == 0) 84 return 0; 85 86 return ((ci->ci_data.cpu_cc_freq + 10000000) / 10000000 * 10000000) / 87 mult / 10000; 88} 89 90int 91p3_get_bus_clock(struct cpu_info *ci) 92{ 93 uint64_t msr; 94 int bus, bus_clock = 0; 95 uint32_t model; 96 97 model = CPUID_TO_MODEL(ci->ci_signature); 98 99 switch (model) { 100 case 0x9: /* Pentium M (130 nm, Banias) */ 101 bus_clock = 10000; 102 break; 103 case 0xc: /* Core i7, Atom, model 1 */ 104 /* 105 * Newer CPUs will GP when attempting to access MSR_FSB_FREQ. 106 * In the long-term, use ACPI instead of all this. 107 */ 108 if (rdmsr_safe(MSR_FSB_FREQ, &msr) == EFAULT) { 109 aprint_debug_dev(ci->ci_dev, 110 "unable to determine bus speed"); 111 goto print_msr; 112 } 113 bus = (msr >> 0) & 0x7; 114 switch (bus) { 115 case 1: 116 bus_clock = 13333; 117 break; 118 default: 119 aprint_debug("%s: unknown Atom FSB_FREQ " 120 "value %d", device_xname(ci->ci_dev), bus); 121 goto print_msr; 122 } 123 break; 124 case 0xd: /* Pentium M (90 nm, Dothan) */ 125 if (rdmsr_safe(MSR_FSB_FREQ, &msr) == EFAULT) { 126 aprint_debug_dev(ci->ci_dev, 127 "unable to determine bus speed"); 128 goto print_msr; 129 } 130 bus = (msr >> 0) & 0x7; 131 switch (bus) { 132 case 0: 133 bus_clock = 10000; 134 break; 135 case 1: 136 bus_clock = 13333; 137 break; 138 default: 139 aprint_debug("%s: unknown Pentium M FSB_FREQ " 140 "value %d", device_xname(ci->ci_dev), bus); 141 goto print_msr; 142 } 143 break; 144 case 0xe: /* Core Duo/Solo */ 145 case 0xf: /* Core Xeon */ 146 case 0x17: /* Xeon [35]000, Core 2 Quad [89]00 */ 147 if (rdmsr_safe(MSR_FSB_FREQ, &msr) == EFAULT) { 148 aprint_debug_dev(ci->ci_dev, 149 "unable to determine bus speed"); 150 goto print_msr; 151 } 152 bus = (msr >> 0) & 0x7; 153 switch (bus) { 154 case 5: 155 bus_clock = 10000; 156 break; 157 case 1: 158 bus_clock = 13333; 159 break; 160 case 3: 161 bus_clock = 16667; 162 break; 163 case 2: 164 bus_clock = 20000; 165 break; 166 case 0: 167 bus_clock = 26667; 168 break; 169 case 4: 170 bus_clock = 33333; 171 break; 172 case 6: 173 bus_clock = 40000; 174 break; 175 default: 176 aprint_debug("%s: unknown Core FSB_FREQ value %d", 177 device_xname(ci->ci_dev), bus); 178 goto print_msr; 179 } 180 break; 181 case 0x1: /* Pentium Pro, model 1 */ 182 case 0x3: /* Pentium II, model 3 */ 183 case 0x5: /* Pentium II, II Xeon, Celeron, model 5 */ 184 case 0x6: /* Celeron, model 6 */ 185 case 0x7: /* Pentium III, III Xeon, model 7 */ 186 case 0x8: /* Pentium III, III Xeon, Celeron, model 8 */ 187 case 0xa: /* Pentium III Xeon, model A */ 188 case 0xb: /* Pentium III, model B */ 189 msr = rdmsr(MSR_EBL_CR_POWERON); 190 bus = (msr >> 18) & 0x3; 191 switch (bus) { 192 case 0: 193 bus_clock = 6666; 194 break; 195 case 1: 196 bus_clock = 13333; 197 break; 198 case 2: 199 bus_clock = 10000; 200 break; 201 case 3: 202 bus_clock = 10666; 203 break; 204 default: 205 aprint_debug("%s: unknown i686 EBL_CR_POWERON " 206 "value %d ", device_xname(ci->ci_dev), bus); 207 goto print_msr; 208 } 209 break; 210 case 0x1c: /* Atom */ 211 case 0x26: 212 case 0x27: 213 case 0x35: 214 case 0x36: 215 if (rdmsr_safe(MSR_FSB_FREQ, &msr) == EFAULT) { 216 aprint_debug_dev(ci->ci_dev, 217 "unable to determine bus speed"); 218 goto print_msr; 219 } 220 bus = (msr >> 0) & 0x7; 221 switch (bus) { 222 case 7: 223 bus_clock = 8333; 224 break; 225 case 5: 226 bus_clock = 10000; 227 break; 228 case 1: 229 bus_clock = 13333; 230 break; 231 case 3: 232 bus_clock = 16667; 233 break; 234 default: 235 aprint_debug("%s: unknown Atom FSB_FREQ value %d", 236 device_xname(ci->ci_dev), bus); 237 goto print_msr; 238 } 239 break; 240 case 0x37: /* Silvermont */ 241 case 0x4a: 242 case 0x4d: 243 case 0x5a: 244 case 0x5d: 245 if (rdmsr_safe(MSR_FSB_FREQ, &msr) == EFAULT) { 246 aprint_debug_dev(ci->ci_dev, 247 "unable to determine bus speed"); 248 goto print_msr; 249 } 250 bus = (msr >> 0) & 0x7; 251 switch (bus) { 252 case 4: 253 bus_clock = 8000; 254 break; 255 case 0: 256 bus_clock = 8333; 257 break; 258 case 1: 259 bus_clock = 10000; 260 break; 261 case 2: 262 bus_clock = 13333; 263 break; 264 case 3: 265 bus_clock = 11667; 266 break; 267 default: 268 aprint_debug("%s: unknown Silvermont FSB_FREQ value %d", 269 device_xname(ci->ci_dev), bus); 270 goto print_msr; 271 } 272 break; 273 case 0x4c: /* Airmont */ 274 if (rdmsr_safe(MSR_FSB_FREQ, &msr) == EFAULT) { 275 aprint_debug_dev(ci->ci_dev, 276 "unable to determine bus speed"); 277 goto print_msr; 278 } 279 bus = (msr >> 0) & 0x0f; 280 switch (bus) { 281 case 0: 282 bus_clock = 8333; 283 break; 284 case 1: 285 bus_clock = 10000; 286 break; 287 case 2: 288 bus_clock = 13333; 289 break; 290 case 3: 291 bus_clock = 11666; 292 break; 293 case 4: 294 bus_clock = 8000; 295 break; 296 case 5: 297 bus_clock = 9333; 298 break; 299 case 6: 300 bus_clock = 9000; 301 break; 302 case 7: 303 bus_clock = 8888; 304 break; 305 case 8: 306 bus_clock = 8750; 307 break; 308 default: 309 aprint_debug("%s: unknown Airmont FSB_FREQ value %d", 310 device_xname(ci->ci_dev), bus); 311 goto print_msr; 312 } 313 break; 314 default: 315 aprint_debug("%s: unknown i686 model %02x, can't get bus clock", 316 device_xname(ci->ci_dev), 317 CPUID_TO_MODEL(ci->ci_signature)); 318print_msr: 319 /* 320 * Show the EBL_CR_POWERON MSR, so we'll at least have 321 * some extra information, such as clock ratio, etc. 322 */ 323 aprint_debug(" (0x%" PRIu64 ")\n", rdmsr(MSR_EBL_CR_POWERON)); 324 break; 325 } 326 327 return bus_clock; 328} 329 330int 331p4_get_bus_clock(struct cpu_info *ci) 332{ 333 uint64_t msr; 334 int bus, bus_clock = 0; 335 336 msr = rdmsr(MSR_EBC_FREQUENCY_ID); 337 if (CPUID_TO_MODEL(ci->ci_signature) < 2) { 338 bus = (msr >> 21) & 0x7; 339 switch (bus) { 340 case 0: 341 bus_clock = 10000; 342 break; 343 case 1: 344 bus_clock = 13333; 345 break; 346 default: 347 aprint_debug("%s: unknown Pentium 4 (model %d) " 348 "EBC_FREQUENCY_ID value %d\n", 349 device_xname(ci->ci_dev), 350 CPUID_TO_MODEL(ci->ci_signature), bus); 351 break; 352 } 353 } else { 354 bus = (msr >> 16) & 0x7; 355 switch (bus) { 356 case 0: 357 bus_clock = (CPUID_TO_MODEL(ci->ci_signature) == 2) ? 358 10000 : 26667; 359 break; 360 case 1: 361 bus_clock = 13333; 362 break; 363 case 2: 364 bus_clock = 20000; 365 break; 366 case 3: 367 bus_clock = 16667; 368 break; 369 case 4: 370 bus_clock = 33333; 371 break; 372 default: 373 aprint_debug("%s: unknown Pentium 4 (model %d) " 374 "EBC_FREQUENCY_ID value %d\n", 375 device_xname(ci->ci_dev), 376 CPUID_TO_MODEL(ci->ci_signature), bus); 377 break; 378 } 379 } 380 381 return bus_clock; 382} 383