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