est.c revision 1.10
1/* $NetBSD: est.c,v 1.10 2009/02/17 12:27:13 jmcneill Exp $ */ 2/* 3 * Copyright (c) 2003 Michael Eriksson. 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. The name of the author may not be used to endorse or promote products 15 * derived from this software without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28/*- 29 * Copyright (c) 2004 The NetBSD Foundation, Inc. 30 * All rights reserved. 31 * 32 * Redistribution and use in source and binary forms, with or without 33 * modification, are permitted provided that the following conditions 34 * are met: 35 * 1. Redistributions of source code must retain the above copyright 36 * notice, this list of conditions and the following disclaimer. 37 * 2. Redistributions in binary form must reproduce the above copyright 38 * notice, this list of conditions and the following disclaimer in the 39 * documentation and/or other materials provided with the distribution. 40 * 41 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 42 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 43 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 44 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 45 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 46 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 47 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 48 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 49 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 50 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 51 * POSSIBILITY OF SUCH DAMAGE. 52 */ 53 54/* 55 * This is a driver for Intel's Enhanced SpeedStep Technology (EST), 56 * as implemented in Pentium M processors. 57 * 58 * Reference documentation: 59 * 60 * - IA-32 Intel Architecture Software Developer's Manual, Volume 3: 61 * System Programming Guide. 62 * Section 13.14, Enhanced Intel SpeedStep technology. 63 * Table B-2, MSRs in Pentium M Processors. 64 * http://www.intel.com/design/pentium4/manuals/253668.htm 65 * 66 * - Intel Pentium M Processor Datasheet. 67 * Table 5, Voltage and Current Specifications. 68 * http://www.intel.com/design/mobile/datashts/252612.htm 69 * 70 * - Intel Pentium M Processor on 90 nm Process with 2-MB L2 Cache Datasheet 71 * Table 3-4, 3-5, 3-6, Voltage and Current Specifications. 72 * http://www.intel.com/design/mobile/datashts/302189.htm 73 * 74 * - Linux cpufreq patches, speedstep-centrino.c. 75 * Encoding of MSR_PERF_CTL and MSR_PERF_STATUS. 76 * http://www.codemonkey.org.uk/projects/cpufreq/cpufreq-2.4.22-pre6-1.gz 77 * 78 * ACPI objects: _PCT is MSR location, _PSS is freq/voltage, _PPC is caps. 79 */ 80 81/* #define EST_DEBUG */ 82 83#include <sys/cdefs.h> 84__KERNEL_RCSID(0, "$NetBSD: est.c,v 1.10 2009/02/17 12:27:13 jmcneill Exp $"); 85 86#include <sys/param.h> 87#include <sys/systm.h> 88#include <sys/malloc.h> 89#include <sys/sysctl.h> 90#include <sys/once.h> 91 92#include <x86/cpuvar.h> 93#include <x86/cputypes.h> 94#include <x86/cpu_msr.h> 95 96#include <machine/cpu.h> 97#include <machine/specialreg.h> 98 99#include "opt_est.h" 100#ifdef EST_FREQ_USERWRITE 101#define EST_TARGET_CTLFLAG (CTLFLAG_READWRITE | CTLFLAG_ANYWRITE) 102#else 103#define EST_TARGET_CTLFLAG CTLFLAG_READWRITE 104#endif 105 106/* Convert MHz and mV into IDs for passing to the MSR. */ 107#define ID16(MHz, mV, bus_clk) \ 108 ((((MHz * 100 + 50) / bus_clk) << 8) | ((mV ? mV - 700 : 0) >> 4)) 109 110/* Possible bus speeds (multiplied by 100 for rounding) */ 111enum { BUS100 = 10000, BUS133 = 13333, BUS166 = 16666, BUS200 = 20000 }; 112 113/* Ultra Low Voltage Intel Pentium M processor 900 MHz */ 114static const uint16_t pm130_900_ulv[] = { 115 ID16( 900, 1004, BUS100), 116 ID16( 800, 988, BUS100), 117 ID16( 600, 844, BUS100), 118}; 119 120/* Ultra Low Voltage Intel Pentium M processor 1.00 GHz */ 121static const uint16_t pm130_1000_ulv[] = { 122 ID16(1000, 1004, BUS100), 123 ID16( 900, 988, BUS100), 124 ID16( 800, 972, BUS100), 125 ID16( 600, 844, BUS100), 126}; 127 128/* Ultra Low Voltage Intel Pentium M processor 1.10 GHz */ 129static const uint16_t pm130_1100_ulv[] = { 130 ID16(1100, 1004, BUS100), 131 ID16(1000, 988, BUS100), 132 ID16( 900, 972, BUS100), 133 ID16( 800, 956, BUS100), 134 ID16( 600, 844, BUS100), 135}; 136 137/* Low Voltage Intel Pentium M processor 1.10 GHz */ 138static const uint16_t pm130_1100_lv[] = { 139 ID16(1100, 1180, BUS100), 140 ID16(1000, 1164, BUS100), 141 ID16( 900, 1100, BUS100), 142 ID16( 800, 1020, BUS100), 143 ID16( 600, 956, BUS100), 144}; 145 146/* Low Voltage Intel Pentium M processor 1.20 GHz */ 147static const uint16_t pm130_1200_lv[] = { 148 ID16(1200, 1180, BUS100), 149 ID16(1100, 1164, BUS100), 150 ID16(1000, 1100, BUS100), 151 ID16( 900, 1020, BUS100), 152 ID16( 800, 1004, BUS100), 153 ID16( 600, 956, BUS100), 154}; 155 156/* Low Voltage Intel Pentium M processor 1.30 GHz */ 157static const uint16_t pm130_1300_lv[] = { 158 ID16(1300, 1180, BUS100), 159 ID16(1200, 1164, BUS100), 160 ID16(1100, 1100, BUS100), 161 ID16(1000, 1020, BUS100), 162 ID16( 900, 1004, BUS100), 163 ID16( 800, 988, BUS100), 164 ID16( 600, 956, BUS100), 165}; 166 167/* Intel Pentium M processor 1.30 GHz */ 168static const uint16_t pm130_1300[] = { 169 ID16(1300, 1388, BUS100), 170 ID16(1200, 1356, BUS100), 171 ID16(1000, 1292, BUS100), 172 ID16( 800, 1260, BUS100), 173 ID16( 600, 956, BUS100), 174}; 175 176/* Intel Pentium M processor 1.40 GHz */ 177static const uint16_t pm130_1400[] = { 178 ID16(1400, 1484, BUS100), 179 ID16(1200, 1436, BUS100), 180 ID16(1000, 1308, BUS100), 181 ID16( 800, 1180, BUS100), 182 ID16( 600, 956, BUS100), 183}; 184 185/* Intel Pentium M processor 1.50 GHz */ 186static const uint16_t pm130_1500[] = { 187 ID16(1500, 1484, BUS100), 188 ID16(1400, 1452, BUS100), 189 ID16(1200, 1356, BUS100), 190 ID16(1000, 1228, BUS100), 191 ID16( 800, 1116, BUS100), 192 ID16( 600, 956, BUS100), 193}; 194 195/* Intel Pentium M processor 1.60 GHz */ 196static const uint16_t pm130_1600[] = { 197 ID16(1600, 1484, BUS100), 198 ID16(1400, 1420, BUS100), 199 ID16(1200, 1276, BUS100), 200 ID16(1000, 1164, BUS100), 201 ID16( 800, 1036, BUS100), 202 ID16( 600, 956, BUS100), 203}; 204 205/* Intel Pentium M processor 1.70 GHz */ 206static const uint16_t pm130_1700[] = { 207 ID16(1700, 1484, BUS100), 208 ID16(1400, 1308, BUS100), 209 ID16(1200, 1228, BUS100), 210 ID16(1000, 1116, BUS100), 211 ID16( 800, 1004, BUS100), 212 ID16( 600, 956, BUS100), 213}; 214 215/* Intel Pentium M processor 723 1.0 GHz */ 216static const uint16_t pm90_n723[] = { 217 ID16(1000, 940, BUS100), 218 ID16( 900, 908, BUS100), 219 ID16( 800, 876, BUS100), 220 ID16( 600, 812, BUS100), 221}; 222 223/* Intel Pentium M processor 733 1.1 GHz, VID #G */ 224static const uint16_t pm90_n733g[] = { 225 ID16(1100, 956, BUS100), 226 ID16(1000, 940, BUS100), 227 ID16( 900, 908, BUS100), 228 ID16( 800, 876, BUS100), 229 ID16( 600, 812, BUS100), 230}; 231 232/* Intel Pentium M processor 733 1.1 GHz, VID #H */ 233static const uint16_t pm90_n733h[] = { 234 ID16(1100, 940, BUS100), 235 ID16(1000, 924, BUS100), 236 ID16( 900, 892, BUS100), 237 ID16( 800, 876, BUS100), 238 ID16( 600, 812, BUS100), 239}; 240 241/* Intel Pentium M processor 733 1.1 GHz, VID #I */ 242static const uint16_t pm90_n733i[] = { 243 ID16(1100, 924, BUS100), 244 ID16(1000, 908, BUS100), 245 ID16( 900, 892, BUS100), 246 ID16( 800, 860, BUS100), 247 ID16( 600, 812, BUS100), 248}; 249 250/* Intel Pentium M processor 733 1.1 GHz, VID #J */ 251static const uint16_t pm90_n733j[] = { 252 ID16(1100, 908, BUS100), 253 ID16(1000, 892, BUS100), 254 ID16( 900, 876, BUS100), 255 ID16( 800, 860, BUS100), 256 ID16( 600, 812, BUS100), 257}; 258 259/* Intel Pentium M processor 733 1.1 GHz, VID #K */ 260static const uint16_t pm90_n733k[] = { 261 ID16(1100, 892, BUS100), 262 ID16(1000, 876, BUS100), 263 ID16( 900, 860, BUS100), 264 ID16( 800, 844, BUS100), 265 ID16( 600, 812, BUS100), 266}; 267 268/* Intel Pentium M processor 733 1.1 GHz, VID #L */ 269static const uint16_t pm90_n733l[] = { 270 ID16(1100, 876, BUS100), 271 ID16(1000, 876, BUS100), 272 ID16( 900, 860, BUS100), 273 ID16( 800, 844, BUS100), 274 ID16( 600, 812, BUS100), 275}; 276 277/* Intel Pentium M processor 753 1.2 GHz, VID #G */ 278static const uint16_t pm90_n753g[] = { 279 ID16(1200, 956, BUS100), 280 ID16(1100, 940, BUS100), 281 ID16(1000, 908, BUS100), 282 ID16( 900, 892, BUS100), 283 ID16( 800, 860, BUS100), 284 ID16( 600, 812, BUS100), 285}; 286 287/* Intel Pentium M processor 753 1.2 GHz, VID #H */ 288static const uint16_t pm90_n753h[] = { 289 ID16(1200, 940, BUS100), 290 ID16(1100, 924, BUS100), 291 ID16(1000, 908, BUS100), 292 ID16( 900, 876, BUS100), 293 ID16( 800, 860, BUS100), 294 ID16( 600, 812, BUS100), 295}; 296 297/* Intel Pentium M processor 753 1.2 GHz, VID #I */ 298static const uint16_t pm90_n753i[] = { 299 ID16(1200, 924, BUS100), 300 ID16(1100, 908, BUS100), 301 ID16(1000, 892, BUS100), 302 ID16( 900, 876, BUS100), 303 ID16( 800, 860, BUS100), 304 ID16( 600, 812, BUS100), 305}; 306 307/* Intel Pentium M processor 753 1.2 GHz, VID #J */ 308static const uint16_t pm90_n753j[] = { 309 ID16(1200, 908, BUS100), 310 ID16(1100, 892, BUS100), 311 ID16(1000, 876, BUS100), 312 ID16( 900, 860, BUS100), 313 ID16( 800, 844, BUS100), 314 ID16( 600, 812, BUS100), 315}; 316 317/* Intel Pentium M processor 753 1.2 GHz, VID #K */ 318static const uint16_t pm90_n753k[] = { 319 ID16(1200, 892, BUS100), 320 ID16(1100, 892, BUS100), 321 ID16(1000, 876, BUS100), 322 ID16( 900, 860, BUS100), 323 ID16( 800, 844, BUS100), 324 ID16( 600, 812, BUS100), 325}; 326 327/* Intel Pentium M processor 753 1.2 GHz, VID #L */ 328static const uint16_t pm90_n753l[] = { 329 ID16(1200, 876, BUS100), 330 ID16(1100, 876, BUS100), 331 ID16(1000, 860, BUS100), 332 ID16( 900, 844, BUS100), 333 ID16( 800, 844, BUS100), 334 ID16( 600, 812, BUS100), 335}; 336 337/* Intel Pentium M processor 773 1.3 GHz, VID #G */ 338static const uint16_t pm90_n773g[] = { 339 ID16(1300, 956, BUS100), 340 ID16(1200, 940, BUS100), 341 ID16(1100, 924, BUS100), 342 ID16(1000, 908, BUS100), 343 ID16( 900, 876, BUS100), 344 ID16( 800, 860, BUS100), 345 ID16( 600, 812, BUS100), 346}; 347 348/* Intel Pentium M processor 773 1.3 GHz, VID #H */ 349static const uint16_t pm90_n773h[] = { 350 ID16(1300, 940, BUS100), 351 ID16(1200, 924, BUS100), 352 ID16(1100, 908, BUS100), 353 ID16(1000, 892, BUS100), 354 ID16( 900, 876, BUS100), 355 ID16( 800, 860, BUS100), 356 ID16( 600, 812, BUS100), 357}; 358 359/* Intel Pentium M processor 773 1.3 GHz, VID #I */ 360static const uint16_t pm90_n773i[] = { 361 ID16(1300, 924, BUS100), 362 ID16(1200, 908, BUS100), 363 ID16(1100, 892, BUS100), 364 ID16(1000, 876, BUS100), 365 ID16( 900, 860, BUS100), 366 ID16( 800, 844, BUS100), 367 ID16( 600, 812, BUS100), 368}; 369 370/* Intel Pentium M processor 773 1.3 GHz, VID #J */ 371static const uint16_t pm90_n773j[] = { 372 ID16(1300, 908, BUS100), 373 ID16(1200, 908, BUS100), 374 ID16(1100, 892, BUS100), 375 ID16(1000, 876, BUS100), 376 ID16( 900, 860, BUS100), 377 ID16( 800, 844, BUS100), 378 ID16( 600, 812, BUS100), 379}; 380 381/* Intel Pentium M processor 773 1.3 GHz, VID #K */ 382static const uint16_t pm90_n773k[] = { 383 ID16(1300, 892, BUS100), 384 ID16(1200, 892, BUS100), 385 ID16(1100, 876, BUS100), 386 ID16(1000, 860, BUS100), 387 ID16( 900, 860, BUS100), 388 ID16( 800, 844, BUS100), 389 ID16( 600, 812, BUS100), 390}; 391 392/* Intel Pentium M processor 773 1.3 GHz, VID #L */ 393static const uint16_t pm90_n773l[] = { 394 ID16(1300, 876, BUS100), 395 ID16(1200, 876, BUS100), 396 ID16(1100, 860, BUS100), 397 ID16(1000, 860, BUS100), 398 ID16( 900, 844, BUS100), 399 ID16( 800, 844, BUS100), 400 ID16( 600, 812, BUS100), 401}; 402 403/* Intel Pentium M processor 738 1.4 GHz */ 404static const uint16_t pm90_n738[] = { 405 ID16(1400, 1116, BUS100), 406 ID16(1300, 1116, BUS100), 407 ID16(1200, 1100, BUS100), 408 ID16(1100, 1068, BUS100), 409 ID16(1000, 1052, BUS100), 410 ID16( 900, 1036, BUS100), 411 ID16( 800, 1020, BUS100), 412 ID16( 600, 988, BUS100), 413}; 414 415/* Intel Pentium M processor 758 1.5 GHz */ 416static const uint16_t pm90_n758[] = { 417 ID16(1500, 1116, BUS100), 418 ID16(1400, 1116, BUS100), 419 ID16(1300, 1100, BUS100), 420 ID16(1200, 1084, BUS100), 421 ID16(1100, 1068, BUS100), 422 ID16(1000, 1052, BUS100), 423 ID16( 900, 1036, BUS100), 424 ID16( 800, 1020, BUS100), 425 ID16( 600, 988, BUS100), 426}; 427 428/* Intel Pentium M processor 778 1.6 GHz */ 429static const uint16_t pm90_n778[] = { 430 ID16(1600, 1116, BUS100), 431 ID16(1500, 1116, BUS100), 432 ID16(1400, 1100, BUS100), 433 ID16(1300, 1184, BUS100), 434 ID16(1200, 1068, BUS100), 435 ID16(1100, 1052, BUS100), 436 ID16(1000, 1052, BUS100), 437 ID16( 900, 1036, BUS100), 438 ID16( 800, 1020, BUS100), 439 ID16( 600, 988, BUS100), 440}; 441 442/* Intel Pentium M processor 710 1.4 GHz, 533 MHz FSB */ 443static const uint16_t pm90_n710[] = { 444 ID16(1400, 1340, BUS133), 445 ID16(1200, 1228, BUS133), 446 ID16(1000, 1148, BUS133), 447 ID16( 800, 1068, BUS133), 448 ID16( 600, 998, BUS133), 449}; 450 451/* Intel Pentium M processor 715 1.5 GHz, VID #A */ 452static const uint16_t pm90_n715a[] = { 453 ID16(1500, 1340, BUS100), 454 ID16(1200, 1228, BUS100), 455 ID16(1000, 1148, BUS100), 456 ID16( 800, 1068, BUS100), 457 ID16( 600, 988, BUS100), 458}; 459 460/* Intel Pentium M processor 715 1.5 GHz, VID #B */ 461static const uint16_t pm90_n715b[] = { 462 ID16(1500, 1324, BUS100), 463 ID16(1200, 1212, BUS100), 464 ID16(1000, 1148, BUS100), 465 ID16( 800, 1068, BUS100), 466 ID16( 600, 988, BUS100), 467}; 468 469/* Intel Pentium M processor 715 1.5 GHz, VID #C */ 470static const uint16_t pm90_n715c[] = { 471 ID16(1500, 1308, BUS100), 472 ID16(1200, 1212, BUS100), 473 ID16(1000, 1132, BUS100), 474 ID16( 800, 1068, BUS100), 475 ID16( 600, 988, BUS100), 476}; 477 478/* Intel Pentium M processor 715 1.5 GHz, VID #D */ 479static const uint16_t pm90_n715d[] = { 480 ID16(1500, 1276, BUS100), 481 ID16(1200, 1180, BUS100), 482 ID16(1000, 1116, BUS100), 483 ID16( 800, 1052, BUS100), 484 ID16( 600, 988, BUS100), 485}; 486 487/* Intel Pentium M processor 725 1.6 GHz, VID #A */ 488static const uint16_t pm90_n725a[] = { 489 ID16(1600, 1340, BUS100), 490 ID16(1400, 1276, BUS100), 491 ID16(1200, 1212, BUS100), 492 ID16(1000, 1132, BUS100), 493 ID16( 800, 1068, BUS100), 494 ID16( 600, 988, BUS100), 495}; 496 497/* Intel Pentium M processor 725 1.6 GHz, VID #B */ 498static const uint16_t pm90_n725b[] = { 499 ID16(1600, 1324, BUS100), 500 ID16(1400, 1260, BUS100), 501 ID16(1200, 1196, BUS100), 502 ID16(1000, 1132, BUS100), 503 ID16( 800, 1068, BUS100), 504 ID16( 600, 988, BUS100), 505}; 506 507/* Intel Pentium M processor 725 1.6 GHz, VID #C */ 508static const uint16_t pm90_n725c[] = { 509 ID16(1600, 1308, BUS100), 510 ID16(1400, 1244, BUS100), 511 ID16(1200, 1180, BUS100), 512 ID16(1000, 1116, BUS100), 513 ID16( 800, 1052, BUS100), 514 ID16( 600, 988, BUS100), 515}; 516 517/* Intel Pentium M processor 725 1.6 GHz, VID #D */ 518static const uint16_t pm90_n725d[] = { 519 ID16(1600, 1276, BUS100), 520 ID16(1400, 1228, BUS100), 521 ID16(1200, 1164, BUS100), 522 ID16(1000, 1116, BUS100), 523 ID16( 800, 1052, BUS100), 524 ID16( 600, 988, BUS100), 525}; 526 527/* Intel Pentium M processor 730 1.6 GHz, 533 MHz FSB */ 528static const uint16_t pm90_n730[] = { 529 ID16(1600, 1308, BUS133), 530 ID16(1333, 1260, BUS133), 531 ID16(1200, 1212, BUS133), 532 ID16(1067, 1180, BUS133), 533 ID16( 800, 988, BUS133), 534}; 535 536/* Intel Pentium M processor 735 1.7 GHz, VID #A */ 537static const uint16_t pm90_n735a[] = { 538 ID16(1700, 1340, BUS100), 539 ID16(1400, 1244, BUS100), 540 ID16(1200, 1180, BUS100), 541 ID16(1000, 1116, BUS100), 542 ID16( 800, 1052, BUS100), 543 ID16( 600, 988, BUS100), 544}; 545 546/* Intel Pentium M processor 735 1.7 GHz, VID #B */ 547static const uint16_t pm90_n735b[] = { 548 ID16(1700, 1324, BUS100), 549 ID16(1400, 1244, BUS100), 550 ID16(1200, 1180, BUS100), 551 ID16(1000, 1116, BUS100), 552 ID16( 800, 1052, BUS100), 553 ID16( 600, 988, BUS100), 554}; 555 556/* Intel Pentium M processor 735 1.7 GHz, VID #C */ 557static const uint16_t pm90_n735c[] = { 558 ID16(1700, 1308, BUS100), 559 ID16(1400, 1228, BUS100), 560 ID16(1200, 1164, BUS100), 561 ID16(1000, 1116, BUS100), 562 ID16( 800, 1052, BUS100), 563 ID16( 600, 988, BUS100), 564}; 565 566/* Intel Pentium M processor 735 1.7 GHz, VID #D */ 567static const uint16_t pm90_n735d[] = { 568 ID16(1700, 1276, BUS100), 569 ID16(1400, 1212, BUS100), 570 ID16(1200, 1148, BUS100), 571 ID16(1000, 1100, BUS100), 572 ID16( 800, 1052, BUS100), 573 ID16( 600, 988, BUS100), 574}; 575 576/* Intel Pentium M processor 740 1.73 GHz, 533 MHz FSB */ 577static const uint16_t pm90_n740[] = { 578 ID16(1733, 1356, BUS133), 579 ID16(1333, 1212, BUS133), 580 ID16(1067, 1100, BUS133), 581 ID16( 800, 988, BUS133), 582}; 583 584/* Intel Pentium M processor 745 1.8 GHz, VID #A */ 585static const uint16_t pm90_n745a[] = { 586 ID16(1800, 1340, BUS100), 587 ID16(1600, 1292, BUS100), 588 ID16(1400, 1228, BUS100), 589 ID16(1200, 1164, BUS100), 590 ID16(1000, 1116, BUS100), 591 ID16( 800, 1052, BUS100), 592 ID16( 600, 988, BUS100), 593}; 594 595/* Intel Pentium M processor 745 1.8 GHz, VID #B */ 596static const uint16_t pm90_n745b[] = { 597 ID16(1800, 1324, BUS100), 598 ID16(1600, 1276, BUS100), 599 ID16(1400, 1212, BUS100), 600 ID16(1200, 1164, BUS100), 601 ID16(1000, 1116, BUS100), 602 ID16( 800, 1052, BUS100), 603 ID16( 600, 988, BUS100), 604}; 605 606/* Intel Pentium M processor 745 1.8 GHz, VID #C */ 607static const uint16_t pm90_n745c[] = { 608 ID16(1800, 1308, BUS100), 609 ID16(1600, 1260, BUS100), 610 ID16(1400, 1212, BUS100), 611 ID16(1200, 1148, BUS100), 612 ID16(1000, 1100, BUS100), 613 ID16( 800, 1052, BUS100), 614 ID16( 600, 988, BUS100), 615}; 616 617/* Intel Pentium M processor 745 1.8 GHz, VID #D */ 618static const uint16_t pm90_n745d[] = { 619 ID16(1800, 1276, BUS100), 620 ID16(1600, 1228, BUS100), 621 ID16(1400, 1180, BUS100), 622 ID16(1200, 1132, BUS100), 623 ID16(1000, 1084, BUS100), 624 ID16( 800, 1036, BUS100), 625 ID16( 600, 988, BUS100), 626}; 627 628/* Intel Pentium M processor 750 1.86 GHz, 533 MHz FSB */ 629/* values extracted from \_PR\NPSS (via _PSS) SDST ACPI table */ 630static const uint16_t pm90_n750[] = { 631 ID16(1867, 1308, BUS133), 632 ID16(1600, 1228, BUS133), 633 ID16(1333, 1148, BUS133), 634 ID16(1067, 1068, BUS133), 635 ID16( 800, 988, BUS133), 636}; 637 638/* Intel Pentium M processor 755 2.0 GHz, VID #A */ 639static const uint16_t pm90_n755a[] = { 640 ID16(2000, 1340, BUS100), 641 ID16(1800, 1292, BUS100), 642 ID16(1600, 1244, BUS100), 643 ID16(1400, 1196, BUS100), 644 ID16(1200, 1148, BUS100), 645 ID16(1000, 1100, BUS100), 646 ID16( 800, 1052, BUS100), 647 ID16( 600, 988, BUS100), 648}; 649 650/* Intel Pentium M processor 755 2.0 GHz, VID #B */ 651static const uint16_t pm90_n755b[] = { 652 ID16(2000, 1324, BUS100), 653 ID16(1800, 1276, BUS100), 654 ID16(1600, 1228, BUS100), 655 ID16(1400, 1180, BUS100), 656 ID16(1200, 1132, BUS100), 657 ID16(1000, 1084, BUS100), 658 ID16( 800, 1036, BUS100), 659 ID16( 600, 988, BUS100), 660}; 661 662/* Intel Pentium M processor 755 2.0 GHz, VID #C */ 663static const uint16_t pm90_n755c[] = { 664 ID16(2000, 1308, BUS100), 665 ID16(1800, 1276, BUS100), 666 ID16(1600, 1228, BUS100), 667 ID16(1400, 1180, BUS100), 668 ID16(1200, 1132, BUS100), 669 ID16(1000, 1084, BUS100), 670 ID16( 800, 1036, BUS100), 671 ID16( 600, 988, BUS100), 672}; 673 674/* Intel Pentium M processor 755 2.0 GHz, VID #D */ 675static const uint16_t pm90_n755d[] = { 676 ID16(2000, 1276, BUS100), 677 ID16(1800, 1244, BUS100), 678 ID16(1600, 1196, BUS100), 679 ID16(1400, 1164, BUS100), 680 ID16(1200, 1116, BUS100), 681 ID16(1000, 1084, BUS100), 682 ID16( 800, 1036, BUS100), 683 ID16( 600, 988, BUS100), 684}; 685 686/* Intel Pentium M processor 760 2.0 GHz, 533 MHz FSB */ 687static const uint16_t pm90_n760[] = { 688 ID16(2000, 1356, BUS133), 689 ID16(1600, 1244, BUS133), 690 ID16(1333, 1164, BUS133), 691 ID16(1067, 1084, BUS133), 692 ID16( 800, 988, BUS133), 693}; 694 695/* Intel Pentium M processor 765 2.1 GHz, VID #A */ 696static const uint16_t pm90_n765a[] = { 697 ID16(2100, 1340, BUS100), 698 ID16(1800, 1276, BUS100), 699 ID16(1600, 1228, BUS100), 700 ID16(1400, 1180, BUS100), 701 ID16(1200, 1132, BUS100), 702 ID16(1000, 1084, BUS100), 703 ID16( 800, 1036, BUS100), 704 ID16( 600, 988, BUS100), 705}; 706 707/* Intel Pentium M processor 765 2.1 GHz, VID #B */ 708static const uint16_t pm90_n765b[] = { 709 ID16(2100, 1324, BUS100), 710 ID16(1800, 1260, BUS100), 711 ID16(1600, 1212, BUS100), 712 ID16(1400, 1180, BUS100), 713 ID16(1200, 1132, BUS100), 714 ID16(1000, 1084, BUS100), 715 ID16( 800, 1036, BUS100), 716 ID16( 600, 988, BUS100), 717}; 718 719/* Intel Pentium M processor 765 2.1 GHz, VID #C */ 720static const uint16_t pm90_n765c[] = { 721 ID16(2100, 1308, BUS100), 722 ID16(1800, 1244, BUS100), 723 ID16(1600, 1212, BUS100), 724 ID16(1400, 1164, BUS100), 725 ID16(1200, 1116, BUS100), 726 ID16(1000, 1084, BUS100), 727 ID16( 800, 1036, BUS100), 728 ID16( 600, 988, BUS100), 729}; 730 731/* Intel Pentium M processor 765 2.1 GHz, VID #E */ 732static const uint16_t pm90_n765e[] = { 733 ID16(2100, 1356, BUS100), 734 ID16(1800, 1292, BUS100), 735 ID16(1600, 1244, BUS100), 736 ID16(1400, 1196, BUS100), 737 ID16(1200, 1148, BUS100), 738 ID16(1000, 1100, BUS100), 739 ID16( 800, 1052, BUS100), 740 ID16( 600, 988, BUS100), 741}; 742 743/* Intel Pentium M processor 770 2.13 GHz */ 744static const uint16_t pm90_n770[] = { 745 ID16(2133, 1356, BUS133), 746 ID16(1867, 1292, BUS133), 747 ID16(1600, 1212, BUS133), 748 ID16(1333, 1148, BUS133), 749 ID16(1067, 1068, BUS133), 750 ID16( 800, 988, BUS133), 751}; 752 753/* Intel Pentium M processor 780 2.26 GHz */ 754static const uint16_t pm90_n780[] = { 755 ID16(2267, 1388, BUS133), 756 ID16(1867, 1292, BUS133), 757 ID16(1600, 1212, BUS133), 758 ID16(1333, 1148, BUS133), 759 ID16(1067, 1068, BUS133), 760 ID16( 800, 988, BUS133), 761}; 762 763/* 764 * VIA C7-M 500 MHz FSB, 400 MHz FSB, and ULV variants. 765 * Data from the "VIA C7-M Processor BIOS Writer's Guide (v2.17)" datasheet. 766 */ 767 768/* 1.00GHz Centaur C7-M ULV */ 769static const uint16_t C7M_770_ULV[] = { 770 ID16(1000, 844, BUS100), 771 ID16( 800, 796, BUS100), 772 ID16( 600, 796, BUS100), 773 ID16( 400, 796, BUS100), 774}; 775 776/* 1.00GHz Centaur C7-M ULV */ 777static const uint16_t C7M_779_ULV[] = { 778 ID16(1000, 796, BUS100), 779 ID16( 800, 796, BUS100), 780 ID16( 600, 796, BUS100), 781 ID16( 400, 796, BUS100), 782}; 783 784/* 1.20GHz Centaur C7-M ULV */ 785static const uint16_t C7M_772_ULV[] = { 786 ID16(1200, 844, BUS100), 787 ID16(1000, 844, BUS100), 788 ID16( 800, 828, BUS100), 789 ID16( 600, 796, BUS100), 790 ID16( 400, 796, BUS100), 791}; 792 793/* 1.50GHz Centaur C7-M ULV */ 794static const uint16_t C7M_775_ULV[] = { 795 ID16(1500, 956, BUS100), 796 ID16(1400, 940, BUS100), 797 ID16(1000, 860, BUS100), 798 ID16( 800, 828, BUS100), 799 ID16( 600, 796, BUS100), 800 ID16( 400, 796, BUS100), 801}; 802 803/* 1.20GHz Centaur C7-M 400 MHz FSB */ 804static const uint16_t C7M_771[] = { 805 ID16(1200, 860, BUS100), 806 ID16(1000, 860, BUS100), 807 ID16( 800, 844, BUS100), 808 ID16( 600, 844, BUS100), 809 ID16( 400, 844, BUS100), 810}; 811 812/* 1.50GHz Centaur C7-M 400 MHz FSB */ 813static const uint16_t C7M_754[] = { 814 ID16(1500, 1004, BUS100), 815 ID16(1400, 988, BUS100), 816 ID16(1000, 940, BUS100), 817 ID16( 800, 844, BUS100), 818 ID16( 600, 844, BUS100), 819 ID16( 400, 844, BUS100), 820}; 821 822/* 1.60GHz Centaur C7-M 400 MHz FSB */ 823static const uint16_t C7M_764[] = { 824 ID16(1600, 1084, BUS100), 825 ID16(1400, 1052, BUS100), 826 ID16(1000, 1004, BUS100), 827 ID16( 800, 844, BUS100), 828 ID16( 600, 844, BUS100), 829 ID16( 400, 844, BUS100), 830}; 831 832/* 1.80GHz Centaur C7-M 400 MHz FSB */ 833static const uint16_t C7M_784[] = { 834 ID16(1800, 1148, BUS100), 835 ID16(1600, 1100, BUS100), 836 ID16(1400, 1052, BUS100), 837 ID16(1000, 1004, BUS100), 838 ID16( 800, 844, BUS100), 839 ID16( 600, 844, BUS100), 840 ID16( 400, 844, BUS100), 841}; 842 843/* 2.00GHz Centaur C7-M 400 MHz FSB */ 844static const uint16_t C7M_794[] = { 845 ID16(2000, 1148, BUS100), 846 ID16(1800, 1132, BUS100), 847 ID16(1600, 1100, BUS100), 848 ID16(1400, 1052, BUS100), 849 ID16(1000, 1004, BUS100), 850 ID16( 800, 844, BUS100), 851 ID16( 600, 844, BUS100), 852 ID16( 400, 844, BUS100), 853}; 854 855/* 1.60GHz Centaur C7-M 533 MHz FSB */ 856static const uint16_t C7M_765[] = { 857 ID16(1600, 1084, BUS133), 858 ID16(1467, 1052, BUS133), 859 ID16(1200, 1004, BUS133), 860 ID16( 800, 844, BUS133), 861 ID16( 667, 844, BUS133), 862 ID16( 533, 844, BUS133), 863}; 864 865/* 2.00GHz Centaur C7-M 533 MHz FSB */ 866static const uint16_t C7M_785[] = { 867 ID16(1867, 1148, BUS133), 868 ID16(1600, 1100, BUS133), 869 ID16(1467, 1052, BUS133), 870 ID16(1200, 1004, BUS133), 871 ID16( 800, 844, BUS133), 872 ID16( 667, 844, BUS133), 873 ID16( 533, 844, BUS133), 874}; 875 876/* 2.00GHz Centaur C7-M 533 MHz FSB */ 877static const uint16_t C7M_795[] = { 878 ID16(2000, 1148, BUS133), 879 ID16(1867, 1132, BUS133), 880 ID16(1600, 1100, BUS133), 881 ID16(1467, 1052, BUS133), 882 ID16(1200, 1004, BUS133), 883 ID16( 800, 844, BUS133), 884 ID16( 667, 844, BUS133), 885 ID16( 533, 844, BUS133), 886}; 887 888/* 1.00GHz VIA Eden 90nm 'Esther' */ 889static const uint16_t eden90_1000[] = { 890 ID16(1000, 844, BUS100), 891 ID16( 800, 844, BUS100), 892 ID16( 600, 844, BUS100), 893 ID16( 400, 844, BUS100), 894}; 895 896struct fqlist { 897 int vendor; 898 unsigned bus_clk; 899 unsigned n; 900 const uint16_t *table; 901}; 902 903#define ENTRY(ven, bus_clk, tab) \ 904 { CPUVENDOR_##ven, bus_clk == BUS133 ? 1 : 0, __arraycount(tab), tab } 905 906#define BUS_CLK(fqp) ((fqp)->bus_clk ? BUS133 : BUS100) 907 908static const struct fqlist est_cpus[] = { 909 ENTRY(INTEL, BUS100, pm130_900_ulv), 910 ENTRY(INTEL, BUS100, pm130_1000_ulv), 911 ENTRY(INTEL, BUS100, pm130_1100_ulv), 912 ENTRY(INTEL, BUS100, pm130_1100_lv), 913 ENTRY(INTEL, BUS100, pm130_1200_lv), 914 ENTRY(INTEL, BUS100, pm130_1300_lv), 915 ENTRY(INTEL, BUS100, pm130_1300), 916 ENTRY(INTEL, BUS100, pm130_1400), 917 ENTRY(INTEL, BUS100, pm130_1500), 918 ENTRY(INTEL, BUS100, pm130_1600), 919 ENTRY(INTEL, BUS100, pm130_1700), 920 ENTRY(INTEL, BUS100, pm90_n723), 921 ENTRY(INTEL, BUS100, pm90_n733g), 922 ENTRY(INTEL, BUS100, pm90_n733h), 923 ENTRY(INTEL, BUS100, pm90_n733i), 924 ENTRY(INTEL, BUS100, pm90_n733j), 925 ENTRY(INTEL, BUS100, pm90_n733k), 926 ENTRY(INTEL, BUS100, pm90_n733l), 927 ENTRY(INTEL, BUS100, pm90_n753g), 928 ENTRY(INTEL, BUS100, pm90_n753h), 929 ENTRY(INTEL, BUS100, pm90_n753i), 930 ENTRY(INTEL, BUS100, pm90_n753j), 931 ENTRY(INTEL, BUS100, pm90_n753k), 932 ENTRY(INTEL, BUS100, pm90_n753l), 933 ENTRY(INTEL, BUS100, pm90_n773g), 934 ENTRY(INTEL, BUS100, pm90_n773h), 935 ENTRY(INTEL, BUS100, pm90_n773i), 936 ENTRY(INTEL, BUS100, pm90_n773j), 937 ENTRY(INTEL, BUS100, pm90_n773k), 938 ENTRY(INTEL, BUS100, pm90_n773l), 939 ENTRY(INTEL, BUS100, pm90_n738), 940 ENTRY(INTEL, BUS100, pm90_n758), 941 ENTRY(INTEL, BUS100, pm90_n778), 942 943 ENTRY(INTEL, BUS133, pm90_n710), 944 ENTRY(INTEL, BUS100, pm90_n715a), 945 ENTRY(INTEL, BUS100, pm90_n715b), 946 ENTRY(INTEL, BUS100, pm90_n715c), 947 ENTRY(INTEL, BUS100, pm90_n715d), 948 ENTRY(INTEL, BUS100, pm90_n725a), 949 ENTRY(INTEL, BUS100, pm90_n725b), 950 ENTRY(INTEL, BUS100, pm90_n725c), 951 ENTRY(INTEL, BUS100, pm90_n725d), 952 ENTRY(INTEL, BUS133, pm90_n730), 953 ENTRY(INTEL, BUS100, pm90_n735a), 954 ENTRY(INTEL, BUS100, pm90_n735b), 955 ENTRY(INTEL, BUS100, pm90_n735c), 956 ENTRY(INTEL, BUS100, pm90_n735d), 957 ENTRY(INTEL, BUS133, pm90_n740), 958 ENTRY(INTEL, BUS100, pm90_n745a), 959 ENTRY(INTEL, BUS100, pm90_n745b), 960 ENTRY(INTEL, BUS100, pm90_n745c), 961 ENTRY(INTEL, BUS100, pm90_n745d), 962 ENTRY(INTEL, BUS133, pm90_n750), 963 ENTRY(INTEL, BUS100, pm90_n755a), 964 ENTRY(INTEL, BUS100, pm90_n755b), 965 ENTRY(INTEL, BUS100, pm90_n755c), 966 ENTRY(INTEL, BUS100, pm90_n755d), 967 ENTRY(INTEL, BUS133, pm90_n760), 968 ENTRY(INTEL, BUS100, pm90_n765a), 969 ENTRY(INTEL, BUS100, pm90_n765b), 970 ENTRY(INTEL, BUS100, pm90_n765c), 971 ENTRY(INTEL, BUS100, pm90_n765e), 972 ENTRY(INTEL, BUS133, pm90_n770), 973 ENTRY(INTEL, BUS133, pm90_n780), 974 975 ENTRY(IDT, BUS100, C7M_770_ULV), 976 ENTRY(IDT, BUS100, C7M_779_ULV), 977 ENTRY(IDT, BUS100, C7M_772_ULV), 978 ENTRY(IDT, BUS100, C7M_771), 979 ENTRY(IDT, BUS100, C7M_775_ULV), 980 ENTRY(IDT, BUS100, C7M_754), 981 ENTRY(IDT, BUS100, C7M_764), 982 ENTRY(IDT, BUS133, C7M_765), 983 ENTRY(IDT, BUS100, C7M_784), 984 ENTRY(IDT, BUS133, C7M_785), 985 ENTRY(IDT, BUS100, C7M_794), 986 ENTRY(IDT, BUS133, C7M_795), 987 988 ENTRY(IDT, BUS100, eden90_1000) 989}; 990 991#define MSR2FREQINC(msr) (((int) (msr) >> 8) & 0xff) 992#define MSR2VOLTINC(msr) ((int) (msr) & 0xff) 993 994#define MSR2MHZ(msr, bus) ((MSR2FREQINC((msr)) * (bus) + 50) / 100) 995#define MSR2MV(msr) (MSR2VOLTINC(msr) * 16 + 700) 996 997static const struct fqlist *est_fqlist; /* not NULL if functional */ 998static uint16_t *fake_table; /* guessed est_cpu table */ 999static struct fqlist fake_fqlist; 1000static int est_node_target, est_node_current; 1001static const char est_desc[] = "Enhanced SpeedStep"; 1002static int lvendor, bus_clock; 1003 1004static int est_sysctl_helper(SYSCTLFN_PROTO); 1005static int est_init_once(void); 1006static void est_init_main(int); 1007 1008static int 1009est_sysctl_helper(SYSCTLFN_ARGS) 1010{ 1011 struct msr_cpu_broadcast mcb; 1012 struct sysctlnode node; 1013 int fq, oldfq, error; 1014 1015 if (est_fqlist == NULL) 1016 return EOPNOTSUPP; 1017 1018 node = *rnode; 1019 node.sysctl_data = &fq; 1020 1021 oldfq = 0; 1022 if (rnode->sysctl_num == est_node_target) 1023 fq = oldfq = MSR2MHZ(rdmsr(MSR_PERF_CTL), bus_clock); 1024 else if (rnode->sysctl_num == est_node_current) 1025 fq = MSR2MHZ(rdmsr(MSR_PERF_STATUS), bus_clock); 1026 else 1027 return EOPNOTSUPP; 1028 1029 error = sysctl_lookup(SYSCTLFN_CALL(&node)); 1030 if (error || newp == NULL) 1031 return error; 1032 1033 /* support writing to ...frequency.target */ 1034 if (rnode->sysctl_num == est_node_target && fq != oldfq) { 1035 int i; 1036 1037 for (i = est_fqlist->n - 1; i > 0; i--) 1038 if (MSR2MHZ(est_fqlist->table[i], bus_clock) >= fq) 1039 break; 1040 fq = MSR2MHZ(est_fqlist->table[i], bus_clock); 1041 mcb.msr_read = true; 1042 mcb.msr_type = MSR_PERF_CTL; 1043 mcb.msr_mask = 0xffffULL; 1044 mcb.msr_value = est_fqlist->table[i]; 1045 msr_cpu_broadcast(&mcb); 1046 } 1047 1048 return 0; 1049} 1050 1051static int 1052est_init_once(void) 1053{ 1054 est_init_main(lvendor); 1055 return 0; 1056} 1057 1058void 1059est_init(int vendor) 1060{ 1061 int error; 1062 static ONCE_DECL(est_initialized); 1063 1064 lvendor = vendor; 1065 1066 error = RUN_ONCE(&est_initialized, est_init_once); 1067 if (__predict_false(error != 0)) 1068 return; 1069} 1070 1071static void 1072est_init_main(int vendor) 1073{ 1074#ifdef __i386__ 1075 const struct fqlist *fql; 1076#endif 1077 const struct sysctlnode *node, *estnode, *freqnode; 1078 uint64_t msr; 1079 uint16_t cur, idhi, idlo; 1080 uint8_t crhi, crlo, crcur; 1081 int i, mv, rc; 1082 size_t len, freq_len; 1083 char *freq_names; 1084 const char *cpuname; 1085 1086 cpuname = device_xname(curcpu()->ci_dev); 1087 1088 if (CPUID2FAMILY(curcpu()->ci_signature) == 15) 1089 bus_clock = p4_get_bus_clock(curcpu()); 1090 else if (CPUID2FAMILY(curcpu()->ci_signature) == 6) { 1091 if (vendor == CPUVENDOR_IDT) 1092 bus_clock = via_get_bus_clock(curcpu()); 1093 else 1094 bus_clock = p3_get_bus_clock(curcpu()); 1095 } 1096 1097 if (bus_clock == 0) { 1098 aprint_debug("%s: unknown system bus clock\n", __func__); 1099 return; 1100 } 1101 1102 msr = rdmsr(MSR_PERF_STATUS); 1103 idhi = (msr >> 32) & 0xffff; 1104 idlo = (msr >> 48) & 0xffff; 1105 cur = msr & 0xffff; 1106 crhi = (idhi >> 8) & 0xff; 1107 crlo = (idlo >> 8) & 0xff; 1108 crcur = (cur >> 8) & 0xff; 1109 1110#ifdef __i386__ 1111 if (idhi == 0 || idlo == 0 || cur == 0 || 1112 ((cur >> 8) & 0xff) < ((idlo >> 8) & 0xff) || 1113 ((cur >> 8) & 0xff) > ((idhi >> 8) & 0xff)) { 1114 aprint_debug("%s: strange msr value 0x%016llx\n", __func__, msr); 1115 return; 1116 } 1117#endif 1118 1119#ifdef __amd64__ 1120 if (crlo == 0 || crhi == crlo) { 1121 aprint_debug("%s: crlo == 0 || crhi == crlo\n", __func__); 1122 return; 1123 } 1124 1125 if (crhi == 0 || crcur == 0 || crlo > crhi || 1126 crcur < crlo || crcur > crhi) { 1127 /* 1128 * Do complain about other weirdness, because we first want to 1129 * know about it, before we decide what to do with it 1130 */ 1131 aprint_debug("%s: strange msr value 0x%" PRIu64 "\n", 1132 __func__, msr); 1133 return; 1134 } 1135#endif 1136 1137 msr = rdmsr(MSR_PERF_STATUS); 1138 mv = MSR2MV(msr); 1139 1140#ifdef __i386__ 1141 /* 1142 * Find an entry which matches (vendor, bus_clock, idhi, idlo) 1143 */ 1144 est_fqlist = NULL; 1145 for (i = 0; i < __arraycount(est_cpus); i++) { 1146 fql = &est_cpus[i]; 1147 if (vendor == fql->vendor && bus_clock == BUS_CLK(fql) && 1148 idhi == fql->table[0] && idlo == fql->table[fql->n - 1]) { 1149 est_fqlist = fql; 1150 break; 1151 } 1152 } 1153#endif 1154 1155 if (est_fqlist == NULL) { 1156 int j, tablesize, freq, volt; 1157 int minfreq, minvolt, maxfreq, maxvolt, freqinc, voltinc; 1158 1159 /* 1160 * Some CPUs report the same frequency in idhi and idlo, 1161 * so do not run est on them. 1162 */ 1163 if (idhi == idlo) { 1164 aprint_debug("%s: idhi == idlo\n", __func__); 1165 return; 1166 } 1167 1168#ifdef EST_DEBUG 1169 printf("%s: bus_clock = %d\n", __func__, bus_clock); 1170 printf("%s: idlo = 0x%x\n", __func__, idlo); 1171 printf("%s: lo %4d mV, %4d MHz\n", __func__, 1172 MSR2MV(idlo), MSR2MHZ(idlo, bus_clock)); 1173 printf("%s: raw %4d , %4d \n", __func__, 1174 (idlo & 0xff), ((idlo >> 8) & 0xff)); 1175 printf("%s: idhi = 0x%x\n", __func__, idhi); 1176 printf("%s: hi %4d mV, %4d MHz\n", __func__, 1177 MSR2MV(idhi), MSR2MHZ(idhi, bus_clock)); 1178 printf("%s: raw %4d , %4d \n", __func__, 1179 (idhi & 0xff), ((idhi >> 8) & 0xff)); 1180 printf("%s: cur = 0x%x\n", __func__, cur); 1181#endif 1182 1183 /* 1184 * Generate a fake table with the power states we know, 1185 * interpolating the voltages and frequencies between the 1186 * high and low values. The (milli)voltages are always 1187 * rounded up when computing the table. 1188 */ 1189 minfreq = MSR2FREQINC(idlo); 1190 maxfreq = MSR2FREQINC(idhi); 1191 minvolt = MSR2VOLTINC(idlo); 1192 maxvolt = MSR2VOLTINC(idhi); 1193 freqinc = maxfreq - minfreq; 1194 voltinc = maxvolt - minvolt; 1195 1196 /* Avoid diving by zero. */ 1197 if (freqinc == 0) 1198 return; 1199 1200 if (freqinc < voltinc || voltinc == 0) { 1201 tablesize = maxfreq - minfreq + 1; 1202 if (voltinc != 0) 1203 voltinc = voltinc * 100 / freqinc - 1; 1204 freqinc = 100; 1205 } else { 1206 tablesize = maxvolt - minvolt + 1; 1207 freqinc = freqinc * 100 / voltinc - 1; 1208 voltinc = 100; 1209 } 1210 1211 fake_table = malloc(tablesize * sizeof(uint16_t), M_DEVBUF, 1212 M_WAITOK); 1213 fake_fqlist.n = tablesize; 1214 1215 /* The frequency/voltage table is highest frequency first */ 1216 freq = maxfreq * 100; 1217 volt = maxvolt * 100; 1218 for (j = 0; j < tablesize; j++) { 1219 fake_table[j] = (((freq + 99) / 100) << 8) + 1220 (volt + 99) / 100; 1221#ifdef EST_DEBUG 1222 printf("%s: fake entry %d: %4d mV, %4d MHz " 1223 "MSR*100 mV = %4d freq = %4d\n", 1224 __func__, j, MSR2MV(fake_table[j]), 1225 MSR2MHZ(fake_table[j], bus_clock), 1226 volt, freq); 1227#endif /* EST_DEBUG */ 1228 freq -= freqinc; 1229 volt -= voltinc; 1230 } 1231 fake_fqlist.vendor = vendor; 1232 fake_fqlist.table = fake_table; 1233 est_fqlist = &fake_fqlist; 1234 } 1235 1236 /* 1237 * OK, tell the user the available frequencies. 1238 */ 1239 freq_len = est_fqlist->n * (sizeof("9999 ")-1) + 1; 1240 freq_names = malloc(freq_len, M_SYSCTLDATA, M_WAITOK); 1241 freq_names[0] = '\0'; 1242 len = 0; 1243 for (i = 0; i < est_fqlist->n; i++) { 1244 len += snprintf(freq_names + len, freq_len - len, "%d%s", 1245 MSR2MHZ(est_fqlist->table[i], bus_clock), 1246 i < est_fqlist->n - 1 ? " " : ""); 1247 } 1248 1249 aprint_debug("%s: %s (%d mV) ", cpuname, est_desc, mv); 1250 aprint_debug("%d (MHz): %s\n", MSR2MHZ(msr, bus_clock), freq_names); 1251 1252 /* 1253 * Setup the sysctl sub-tree machdep.est.* 1254 */ 1255 if ((rc = sysctl_createv(NULL, 0, NULL, &node, 1256 CTLFLAG_PERMANENT, CTLTYPE_NODE, "machdep", NULL, 1257 NULL, 0, NULL, 0, CTL_MACHDEP, CTL_EOL)) != 0) 1258 goto err; 1259 1260 if ((rc = sysctl_createv(NULL, 0, &node, &estnode, 1261 0, CTLTYPE_NODE, "est", NULL, 1262 NULL, 0, NULL, 0, CTL_CREATE, CTL_EOL)) != 0) 1263 goto err; 1264 1265 if ((rc = sysctl_createv(NULL, 0, &estnode, &freqnode, 1266 0, CTLTYPE_NODE, "frequency", NULL, 1267 NULL, 0, NULL, 0, CTL_CREATE, CTL_EOL)) != 0) 1268 goto err; 1269 1270 if ((rc = sysctl_createv(NULL, 0, &freqnode, &node, 1271 EST_TARGET_CTLFLAG, CTLTYPE_INT, "target", NULL, 1272 est_sysctl_helper, 0, NULL, 0, CTL_CREATE, CTL_EOL)) != 0) 1273 goto err; 1274 est_node_target = node->sysctl_num; 1275 1276 if ((rc = sysctl_createv(NULL, 0, &freqnode, &node, 1277 0, CTLTYPE_INT, "current", NULL, 1278 est_sysctl_helper, 0, NULL, 0, CTL_CREATE, CTL_EOL)) != 0) 1279 goto err; 1280 est_node_current = node->sysctl_num; 1281 1282 if ((rc = sysctl_createv(NULL, 0, &freqnode, &node, 1283 0, CTLTYPE_STRING, "available", NULL, 1284 NULL, 0, freq_names, freq_len, CTL_CREATE, CTL_EOL)) != 0) 1285 goto err; 1286 1287 return; 1288 1289 err: 1290 free(freq_names, M_SYSCTLDATA); 1291 aprint_error("%s: sysctl_createv failed (rc = %d)\n", __func__, rc); 1292} 1293