1 /* $NetBSD: acpi_cpu_md.c,v 1.38 2011/01/13 03:40:50 jruoho Exp $ */ 2 3 /*- 4 * Copyright (c) 2010 Jukka Ruohonen <jruohonen@iki.fi> 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 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 AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 */ 29 #include <sys/cdefs.h> 30 __KERNEL_RCSID(0, "$NetBSD: acpi_cpu_md.c,v 1.38 2011/01/13 03:40:50 jruoho Exp $"); 31 32 #include <sys/param.h> 33 #include <sys/bus.h> 34 #include <sys/kcore.h> 35 #include <sys/sysctl.h> 36 #include <sys/xcall.h> 37 38 #include <x86/cpu.h> 39 #include <x86/cpufunc.h> 40 #include <x86/cputypes.h> 41 #include <x86/cpuvar.h> 42 #include <x86/cpu_msr.h> 43 #include <x86/machdep.h> 44 45 #include <dev/acpi/acpica.h> 46 #include <dev/acpi/acpi_cpu.h> 47 48 #include <dev/pci/pcivar.h> 49 #include <dev/pci/pcidevs.h> 50 51 #include <machine/acpi_machdep.h> 52 53 /* 54 * AMD C1E. 55 */ 56 #define MSR_CMPHALT 0xc0010055 57 58 #define MSR_CMPHALT_SMI __BIT(27) 59 #define MSR_CMPHALT_C1E __BIT(28) 60 #define MSR_CMPHALT_BMSTS __BIT(29) 61 62 /* 63 * AMD families 10h and 11h. 64 */ 65 #define MSR_10H_LIMIT 0xc0010061 66 #define MSR_10H_CONTROL 0xc0010062 67 #define MSR_10H_STATUS 0xc0010063 68 #define MSR_10H_CONFIG 0xc0010064 69 70 /* 71 * AMD family 0Fh. 72 */ 73 #define MSR_0FH_CONTROL 0xc0010041 74 #define MSR_0FH_STATUS 0xc0010042 75 76 #define MSR_0FH_STATUS_CFID __BITS( 0, 5) 77 #define MSR_0FH_STATUS_CVID __BITS(32, 36) 78 #define MSR_0FH_STATUS_PENDING __BITS(31, 31) 79 80 #define MSR_0FH_CONTROL_FID __BITS( 0, 5) 81 #define MSR_0FH_CONTROL_VID __BITS( 8, 12) 82 #define MSR_0FH_CONTROL_CHG __BITS(16, 16) 83 #define MSR_0FH_CONTROL_CNT __BITS(32, 51) 84 85 #define ACPI_0FH_STATUS_FID __BITS( 0, 5) 86 #define ACPI_0FH_STATUS_VID __BITS( 6, 10) 87 88 #define ACPI_0FH_CONTROL_FID __BITS( 0, 5) 89 #define ACPI_0FH_CONTROL_VID __BITS( 6, 10) 90 #define ACPI_0FH_CONTROL_VST __BITS(11, 17) 91 #define ACPI_0FH_CONTROL_MVS __BITS(18, 19) 92 #define ACPI_0FH_CONTROL_PLL __BITS(20, 26) 93 #define ACPI_0FH_CONTROL_RVO __BITS(28, 29) 94 #define ACPI_0FH_CONTROL_IRT __BITS(30, 31) 95 96 #define FID_TO_VCO_FID(fidd) (((fid) < 8) ? (8 + ((fid) << 1)) : (fid)) 97 98 static char native_idle_text[16]; 99 void (*native_idle)(void) = NULL; 100 101 static int acpicpu_md_quirks_piix4(struct pci_attach_args *); 102 static void acpicpu_md_pstate_status(void *, void *); 103 static int acpicpu_md_pstate_fidvid_get(struct acpicpu_softc *, 104 uint32_t *); 105 static int acpicpu_md_pstate_fidvid_set(struct acpicpu_pstate *); 106 static int acpicpu_md_pstate_fidvid_read(uint32_t *, uint32_t *); 107 static void acpicpu_md_pstate_fidvid_write(uint32_t, uint32_t, 108 uint32_t, uint32_t); 109 static void acpicpu_md_tstate_status(void *, void *); 110 static int acpicpu_md_pstate_sysctl_init(void); 111 static int acpicpu_md_pstate_sysctl_get(SYSCTLFN_PROTO); 112 static int acpicpu_md_pstate_sysctl_set(SYSCTLFN_PROTO); 113 static int acpicpu_md_pstate_sysctl_all(SYSCTLFN_PROTO); 114 115 extern struct acpicpu_softc **acpicpu_sc; 116 static bool acpicpu_pstate_status = false; 117 static struct sysctllog *acpicpu_log = NULL; 118 119 uint32_t 120 acpicpu_md_cap(void) 121 { 122 struct cpu_info *ci = curcpu(); 123 uint32_t val = 0; 124 125 if (cpu_vendor != CPUVENDOR_IDT && 126 cpu_vendor != CPUVENDOR_INTEL) 127 return val; 128 129 /* 130 * Basic SMP C-states (required for _CST). 131 */ 132 val |= ACPICPU_PDC_C_C1PT | ACPICPU_PDC_C_C2C3; 133 134 /* 135 * If MONITOR/MWAIT is available, announce 136 * support for native instructions in all C-states. 137 */ 138 if ((ci->ci_feat_val[1] & CPUID2_MONITOR) != 0) 139 val |= ACPICPU_PDC_C_C1_FFH | ACPICPU_PDC_C_C2C3_FFH; 140 141 /* 142 * Set native P- and T-states, if available. 143 */ 144 if ((ci->ci_feat_val[1] & CPUID2_EST) != 0) 145 val |= ACPICPU_PDC_P_FFH; 146 147 if ((ci->ci_feat_val[0] & CPUID_ACPI) != 0) 148 val |= ACPICPU_PDC_T_FFH; 149 150 return val; 151 } 152 153 uint32_t 154 acpicpu_md_quirks(void) 155 { 156 struct cpu_info *ci = curcpu(); 157 struct pci_attach_args pa; 158 uint32_t family, val = 0; 159 uint32_t regs[4]; 160 161 if (acpi_md_ncpus() == 1) 162 val |= ACPICPU_FLAG_C_BM; 163 164 if ((ci->ci_feat_val[1] & CPUID2_MONITOR) != 0) 165 val |= ACPICPU_FLAG_C_FFH; 166 167 val |= ACPICPU_FLAG_C_APIC | ACPICPU_FLAG_C_TSC; 168 169 switch (cpu_vendor) { 170 171 case CPUVENDOR_IDT: 172 173 if ((ci->ci_feat_val[1] & CPUID2_EST) != 0) 174 val |= ACPICPU_FLAG_P_FFH; 175 176 if ((ci->ci_feat_val[0] & CPUID_ACPI) != 0) 177 val |= ACPICPU_FLAG_T_FFH; 178 179 break; 180 181 case CPUVENDOR_INTEL: 182 183 val |= ACPICPU_FLAG_C_BM | ACPICPU_FLAG_C_ARB; 184 185 if ((ci->ci_feat_val[1] & CPUID2_EST) != 0) 186 val |= ACPICPU_FLAG_P_FFH; 187 188 if ((ci->ci_feat_val[0] & CPUID_ACPI) != 0) 189 val |= ACPICPU_FLAG_T_FFH; 190 191 /* 192 * Check whether MSR_APERF, MSR_MPERF, and Turbo 193 * Boost are available. Also see if we might have 194 * an invariant local APIC timer ("ARAT"). 195 */ 196 if (cpuid_level >= 0x06) { 197 198 x86_cpuid(0x06, regs); 199 200 if ((regs[2] & CPUID_DSPM_HWF) != 0) 201 val |= ACPICPU_FLAG_P_HW; 202 203 if ((regs[0] & CPUID_DSPM_IDA) != 0) 204 val |= ACPICPU_FLAG_P_TURBO; 205 206 if ((regs[0] & CPUID_DSPM_ARAT) != 0) 207 val &= ~ACPICPU_FLAG_C_APIC; 208 } 209 210 /* 211 * Detect whether TSC is invariant. If it is not, 212 * we keep the flag to note that TSC will not run 213 * at constant rate. Depending on the CPU, this may 214 * affect P- and T-state changes, but especially 215 * relevant are C-states; with variant TSC, states 216 * larger than C1 may completely stop the counter. 217 */ 218 x86_cpuid(0x80000000, regs); 219 220 if (regs[0] >= 0x80000007) { 221 222 x86_cpuid(0x80000007, regs); 223 224 if ((regs[3] & __BIT(8)) != 0) 225 val &= ~ACPICPU_FLAG_C_TSC; 226 } 227 228 break; 229 230 case CPUVENDOR_AMD: 231 232 x86_cpuid(0x80000000, regs); 233 234 if (regs[0] < 0x80000007) 235 break; 236 237 x86_cpuid(0x80000007, regs); 238 239 family = CPUID2FAMILY(ci->ci_signature); 240 241 if (family == 0xf) 242 family += CPUID2EXTFAMILY(ci->ci_signature); 243 244 switch (family) { 245 246 case 0x0f: 247 248 if ((regs[3] & CPUID_APM_FID) == 0) 249 break; 250 251 if ((regs[3] & CPUID_APM_VID) == 0) 252 break; 253 254 val |= ACPICPU_FLAG_P_FFH | ACPICPU_FLAG_P_FIDVID; 255 break; 256 257 case 0x10: 258 case 0x11: 259 260 if ((regs[3] & CPUID_APM_TSC) != 0) 261 val &= ~ACPICPU_FLAG_C_TSC; 262 263 if ((regs[3] & CPUID_APM_HWP) != 0) 264 val |= ACPICPU_FLAG_P_FFH; 265 266 if ((regs[3] & CPUID_APM_CPB) != 0) 267 val |= ACPICPU_FLAG_P_TURBO; 268 269 val |= ACPICPU_FLAG_C_C1E; 270 break; 271 } 272 273 break; 274 } 275 276 /* 277 * There are several erratums for PIIX4. 278 */ 279 if (pci_find_device(&pa, acpicpu_md_quirks_piix4) != 0) 280 val |= ACPICPU_FLAG_PIIX4; 281 282 return val; 283 } 284 285 static int 286 acpicpu_md_quirks_piix4(struct pci_attach_args *pa) 287 { 288 289 /* 290 * XXX: The pci_find_device(9) function only 291 * deals with attached devices. Change this 292 * to use something like pci_device_foreach(). 293 */ 294 if (PCI_VENDOR(pa->pa_id) != PCI_VENDOR_INTEL) 295 return 0; 296 297 if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_INTEL_82371AB_ISA || 298 PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_INTEL_82440MX_PMC) 299 return 1; 300 301 return 0; 302 } 303 304 void 305 acpicpu_md_quirks_c1e(void) 306 { 307 const uint64_t c1e = MSR_CMPHALT_SMI | MSR_CMPHALT_C1E; 308 uint64_t val; 309 310 val = rdmsr(MSR_CMPHALT); 311 312 if ((val & c1e) != 0) 313 wrmsr(MSR_CMPHALT, val & ~c1e); 314 } 315 316 int 317 acpicpu_md_idle_start(struct acpicpu_softc *sc) 318 { 319 const size_t size = sizeof(native_idle_text); 320 struct acpicpu_cstate *cs; 321 bool ipi = false; 322 int i; 323 324 x86_cpu_idle_get(&native_idle, native_idle_text, size); 325 326 for (i = 0; i < ACPI_C_STATE_COUNT; i++) { 327 328 cs = &sc->sc_cstate[i]; 329 330 if (cs->cs_method == ACPICPU_C_STATE_HALT) { 331 ipi = true; 332 break; 333 } 334 } 335 336 x86_cpu_idle_set(acpicpu_cstate_idle, "acpi", ipi); 337 338 return 0; 339 } 340 341 int 342 acpicpu_md_idle_stop(void) 343 { 344 uint64_t xc; 345 bool ipi; 346 347 ipi = (native_idle != x86_cpu_idle_halt) ? false : true; 348 x86_cpu_idle_set(native_idle, native_idle_text, ipi); 349 350 /* 351 * Run a cross-call to ensure that all CPUs are 352 * out from the ACPI idle-loop before detachment. 353 */ 354 xc = xc_broadcast(0, (xcfunc_t)nullop, NULL, NULL); 355 xc_wait(xc); 356 357 return 0; 358 } 359 360 /* 361 * Called with interrupts disabled. 362 * Caller should enable interrupts after return. 363 */ 364 void 365 acpicpu_md_idle_enter(int method, int state) 366 { 367 struct cpu_info *ci = curcpu(); 368 369 switch (method) { 370 371 case ACPICPU_C_STATE_FFH: 372 373 x86_enable_intr(); 374 x86_monitor(&ci->ci_want_resched, 0, 0); 375 376 if (__predict_false(ci->ci_want_resched != 0)) 377 return; 378 379 x86_mwait((state - 1) << 4, 0); 380 break; 381 382 case ACPICPU_C_STATE_HALT: 383 384 if (__predict_false(ci->ci_want_resched != 0)) 385 return; 386 387 x86_stihlt(); 388 break; 389 } 390 } 391 392 int 393 acpicpu_md_pstate_start(void) 394 { 395 const uint64_t est = __BIT(16); 396 uint64_t val; 397 398 switch (cpu_vendor) { 399 400 case CPUVENDOR_IDT: 401 case CPUVENDOR_INTEL: 402 403 val = rdmsr(MSR_MISC_ENABLE); 404 405 if ((val & est) == 0) { 406 407 val |= est; 408 409 wrmsr(MSR_MISC_ENABLE, val); 410 val = rdmsr(MSR_MISC_ENABLE); 411 412 if ((val & est) == 0) 413 return ENOTTY; 414 } 415 } 416 417 return acpicpu_md_pstate_sysctl_init(); 418 } 419 420 int 421 acpicpu_md_pstate_stop(void) 422 { 423 424 if (acpicpu_log != NULL) 425 sysctl_teardown(&acpicpu_log); 426 427 return 0; 428 } 429 430 int 431 acpicpu_md_pstate_pss(struct acpicpu_softc *sc) 432 { 433 struct acpicpu_pstate *ps, msr; 434 struct cpu_info *ci = curcpu(); 435 uint32_t family, i = 0; 436 437 (void)memset(&msr, 0, sizeof(struct acpicpu_pstate)); 438 439 switch (cpu_vendor) { 440 441 case CPUVENDOR_IDT: 442 case CPUVENDOR_INTEL: 443 444 /* 445 * If the so-called Turbo Boost is present, 446 * the P0-state is always the "turbo state". 447 * 448 * For discussion, see: 449 * 450 * Intel Corporation: Intel Turbo Boost Technology 451 * in Intel Core(tm) Microarchitectures (Nehalem) 452 * Based Processors. White Paper, November 2008. 453 */ 454 if ((sc->sc_flags & ACPICPU_FLAG_P_TURBO) != 0) 455 sc->sc_pstate[0].ps_flags |= ACPICPU_FLAG_P_TURBO; 456 457 msr.ps_control_addr = MSR_PERF_CTL; 458 msr.ps_control_mask = __BITS(0, 15); 459 460 msr.ps_status_addr = MSR_PERF_STATUS; 461 msr.ps_status_mask = __BITS(0, 15); 462 break; 463 464 case CPUVENDOR_AMD: 465 466 if ((sc->sc_flags & ACPICPU_FLAG_P_FIDVID) != 0) 467 msr.ps_flags |= ACPICPU_FLAG_P_FIDVID; 468 469 family = CPUID2FAMILY(ci->ci_signature); 470 471 if (family == 0xf) 472 family += CPUID2EXTFAMILY(ci->ci_signature); 473 474 switch (family) { 475 476 case 0x0f: 477 msr.ps_control_addr = MSR_0FH_CONTROL; 478 msr.ps_status_addr = MSR_0FH_STATUS; 479 break; 480 481 case 0x10: 482 case 0x11: 483 msr.ps_control_addr = MSR_10H_CONTROL; 484 msr.ps_control_mask = __BITS(0, 2); 485 486 msr.ps_status_addr = MSR_10H_STATUS; 487 msr.ps_status_mask = __BITS(0, 2); 488 break; 489 490 default: 491 492 if ((sc->sc_flags & ACPICPU_FLAG_P_XPSS) == 0) 493 return EOPNOTSUPP; 494 } 495 496 break; 497 498 default: 499 return ENODEV; 500 } 501 502 /* 503 * Fill the P-state structures with MSR addresses that are 504 * known to be correct. If we do not know the addresses, 505 * leave the values intact. If a vendor uses XPSS, we do 506 * not necessary need to do anything to support new CPUs. 507 */ 508 while (i < sc->sc_pstate_count) { 509 510 ps = &sc->sc_pstate[i]; 511 512 if (msr.ps_flags != 0) 513 ps->ps_flags |= msr.ps_flags; 514 515 if (msr.ps_status_addr != 0) 516 ps->ps_status_addr = msr.ps_status_addr; 517 518 if (msr.ps_status_mask != 0) 519 ps->ps_status_mask = msr.ps_status_mask; 520 521 if (msr.ps_control_addr != 0) 522 ps->ps_control_addr = msr.ps_control_addr; 523 524 if (msr.ps_control_mask != 0) 525 ps->ps_control_mask = msr.ps_control_mask; 526 527 i++; 528 } 529 530 return 0; 531 } 532 533 int 534 acpicpu_md_pstate_get(struct acpicpu_softc *sc, uint32_t *freq) 535 { 536 struct acpicpu_pstate *ps = NULL; 537 uint64_t val; 538 uint32_t i; 539 540 if ((sc->sc_flags & ACPICPU_FLAG_P_FIDVID) != 0) 541 return acpicpu_md_pstate_fidvid_get(sc, freq); 542 543 for (i = 0; i < sc->sc_pstate_count; i++) { 544 545 ps = &sc->sc_pstate[i]; 546 547 if (__predict_true(ps->ps_freq != 0)) 548 break; 549 } 550 551 if (__predict_false(ps == NULL)) 552 return ENODEV; 553 554 if (__predict_false(ps->ps_status_addr == 0)) 555 return EINVAL; 556 557 val = rdmsr(ps->ps_status_addr); 558 559 if (__predict_true(ps->ps_status_mask != 0)) 560 val = val & ps->ps_status_mask; 561 562 for (i = 0; i < sc->sc_pstate_count; i++) { 563 564 ps = &sc->sc_pstate[i]; 565 566 if (__predict_false(ps->ps_freq == 0)) 567 continue; 568 569 if (val == ps->ps_status) { 570 *freq = ps->ps_freq; 571 return 0; 572 } 573 } 574 575 return EIO; 576 } 577 578 int 579 acpicpu_md_pstate_set(struct acpicpu_pstate *ps) 580 { 581 struct msr_rw_info msr; 582 uint64_t xc; 583 int rv = 0; 584 585 if (__predict_false(ps->ps_control_addr == 0)) 586 return EINVAL; 587 588 if ((ps->ps_flags & ACPICPU_FLAG_P_FIDVID) != 0) 589 return acpicpu_md_pstate_fidvid_set(ps); 590 591 msr.msr_read = false; 592 msr.msr_type = ps->ps_control_addr; 593 msr.msr_value = ps->ps_control; 594 595 if (__predict_true(ps->ps_control_mask != 0)) { 596 msr.msr_mask = ps->ps_control_mask; 597 msr.msr_read = true; 598 } 599 600 xc = xc_broadcast(0, (xcfunc_t)x86_msr_xcall, &msr, NULL); 601 xc_wait(xc); 602 603 /* 604 * Due several problems, we bypass the 605 * relatively expensive status check. 606 */ 607 if (acpicpu_pstate_status != true) { 608 DELAY(ps->ps_latency); 609 return 0; 610 } 611 612 xc = xc_broadcast(0, (xcfunc_t)acpicpu_md_pstate_status, ps, &rv); 613 xc_wait(xc); 614 615 return rv; 616 } 617 618 static void 619 acpicpu_md_pstate_status(void *arg1, void *arg2) 620 { 621 struct acpicpu_pstate *ps = arg1; 622 uint64_t val; 623 int i; 624 625 for (i = val = 0; i < ACPICPU_P_STATE_RETRY; i++) { 626 627 val = rdmsr(ps->ps_status_addr); 628 629 if (__predict_true(ps->ps_status_mask != 0)) 630 val = val & ps->ps_status_mask; 631 632 if (val == ps->ps_status) 633 return; 634 635 DELAY(ps->ps_latency); 636 } 637 638 *(uintptr_t *)arg2 = EAGAIN; 639 } 640 641 static int 642 acpicpu_md_pstate_fidvid_get(struct acpicpu_softc *sc, uint32_t *freq) 643 { 644 struct acpicpu_pstate *ps; 645 uint32_t fid, i, vid; 646 uint32_t cfid, cvid; 647 int rv; 648 649 /* 650 * AMD family 0Fh needs special treatment. 651 * While it wants to use ACPI, it does not 652 * comply with the ACPI specifications. 653 */ 654 rv = acpicpu_md_pstate_fidvid_read(&cfid, &cvid); 655 656 if (rv != 0) 657 return rv; 658 659 for (i = 0; i < sc->sc_pstate_count; i++) { 660 661 ps = &sc->sc_pstate[i]; 662 663 if (__predict_false(ps->ps_freq == 0)) 664 continue; 665 666 fid = __SHIFTOUT(ps->ps_status, ACPI_0FH_STATUS_FID); 667 vid = __SHIFTOUT(ps->ps_status, ACPI_0FH_STATUS_VID); 668 669 if (cfid == fid && cvid == vid) { 670 *freq = ps->ps_freq; 671 return 0; 672 } 673 } 674 675 return EIO; 676 } 677 678 static int 679 acpicpu_md_pstate_fidvid_set(struct acpicpu_pstate *ps) 680 { 681 const uint64_t ctrl = ps->ps_control; 682 uint32_t cfid, cvid, fid, i, irt; 683 uint32_t pll, vco_cfid, vco_fid; 684 uint32_t val, vid, vst; 685 int rv; 686 687 rv = acpicpu_md_pstate_fidvid_read(&cfid, &cvid); 688 689 if (rv != 0) 690 return rv; 691 692 fid = __SHIFTOUT(ctrl, ACPI_0FH_CONTROL_FID); 693 vid = __SHIFTOUT(ctrl, ACPI_0FH_CONTROL_VID); 694 irt = __SHIFTOUT(ctrl, ACPI_0FH_CONTROL_IRT); 695 vst = __SHIFTOUT(ctrl, ACPI_0FH_CONTROL_VST); 696 pll = __SHIFTOUT(ctrl, ACPI_0FH_CONTROL_PLL); 697 698 vst = vst * 20; 699 pll = pll * 1000 / 5; 700 irt = 10 * __BIT(irt); 701 702 /* 703 * Phase 1. 704 */ 705 while (cvid > vid) { 706 707 val = 1 << __SHIFTOUT(ctrl, ACPI_0FH_CONTROL_MVS); 708 val = (val > cvid) ? 0 : cvid - val; 709 710 acpicpu_md_pstate_fidvid_write(cfid, val, 1, vst); 711 rv = acpicpu_md_pstate_fidvid_read(NULL, &cvid); 712 713 if (rv != 0) 714 return rv; 715 } 716 717 i = __SHIFTOUT(ctrl, ACPI_0FH_CONTROL_RVO); 718 719 for (; i > 0 && cvid > 0; --i) { 720 721 acpicpu_md_pstate_fidvid_write(cfid, cvid - 1, 1, vst); 722 rv = acpicpu_md_pstate_fidvid_read(NULL, &cvid); 723 724 if (rv != 0) 725 return rv; 726 } 727 728 /* 729 * Phase 2. 730 */ 731 if (cfid != fid) { 732 733 vco_fid = FID_TO_VCO_FID(fid); 734 vco_cfid = FID_TO_VCO_FID(cfid); 735 736 while (abs(vco_fid - vco_cfid) > 2) { 737 738 if (fid <= cfid) 739 val = cfid - 2; 740 else { 741 val = (cfid > 6) ? cfid + 2 : 742 FID_TO_VCO_FID(cfid) + 2; 743 } 744 745 acpicpu_md_pstate_fidvid_write(val, cvid, pll, irt); 746 rv = acpicpu_md_pstate_fidvid_read(&cfid, NULL); 747 748 if (rv != 0) 749 return rv; 750 751 vco_cfid = FID_TO_VCO_FID(cfid); 752 } 753 754 acpicpu_md_pstate_fidvid_write(fid, cvid, pll, irt); 755 rv = acpicpu_md_pstate_fidvid_read(&cfid, NULL); 756 757 if (rv != 0) 758 return rv; 759 } 760 761 /* 762 * Phase 3. 763 */ 764 if (cvid != vid) { 765 766 acpicpu_md_pstate_fidvid_write(cfid, vid, 1, vst); 767 rv = acpicpu_md_pstate_fidvid_read(NULL, &cvid); 768 769 if (rv != 0) 770 return rv; 771 } 772 773 if (cfid != fid || cvid != vid) 774 return EIO; 775 776 return 0; 777 } 778 779 static int 780 acpicpu_md_pstate_fidvid_read(uint32_t *cfid, uint32_t *cvid) 781 { 782 int i = ACPICPU_P_STATE_RETRY * 100; 783 uint64_t val; 784 785 do { 786 val = rdmsr(MSR_0FH_STATUS); 787 788 } while (__SHIFTOUT(val, MSR_0FH_STATUS_PENDING) != 0 && --i >= 0); 789 790 if (i == 0) 791 return EAGAIN; 792 793 if (cfid != NULL) 794 *cfid = __SHIFTOUT(val, MSR_0FH_STATUS_CFID); 795 796 if (cvid != NULL) 797 *cvid = __SHIFTOUT(val, MSR_0FH_STATUS_CVID); 798 799 return 0; 800 } 801 802 static void 803 acpicpu_md_pstate_fidvid_write(uint32_t fid, 804 uint32_t vid, uint32_t cnt, uint32_t tmo) 805 { 806 struct msr_rw_info msr; 807 uint64_t xc; 808 809 msr.msr_read = false; 810 msr.msr_type = MSR_0FH_CONTROL; 811 msr.msr_value = 0; 812 813 msr.msr_value |= __SHIFTIN(fid, MSR_0FH_CONTROL_FID); 814 msr.msr_value |= __SHIFTIN(vid, MSR_0FH_CONTROL_VID); 815 msr.msr_value |= __SHIFTIN(cnt, MSR_0FH_CONTROL_CNT); 816 msr.msr_value |= __SHIFTIN(0x1, MSR_0FH_CONTROL_CHG); 817 818 xc = xc_broadcast(0, (xcfunc_t)x86_msr_xcall, &msr, NULL); 819 xc_wait(xc); 820 821 DELAY(tmo); 822 } 823 824 int 825 acpicpu_md_tstate_get(struct acpicpu_softc *sc, uint32_t *percent) 826 { 827 struct acpicpu_tstate *ts; 828 uint64_t val; 829 uint32_t i; 830 831 val = rdmsr(MSR_THERM_CONTROL); 832 833 for (i = 0; i < sc->sc_tstate_count; i++) { 834 835 ts = &sc->sc_tstate[i]; 836 837 if (ts->ts_percent == 0) 838 continue; 839 840 if (val == ts->ts_status) { 841 *percent = ts->ts_percent; 842 return 0; 843 } 844 } 845 846 return EIO; 847 } 848 849 int 850 acpicpu_md_tstate_set(struct acpicpu_tstate *ts) 851 { 852 struct msr_rw_info msr; 853 uint64_t xc; 854 int rv = 0; 855 856 msr.msr_read = true; 857 msr.msr_type = MSR_THERM_CONTROL; 858 msr.msr_value = ts->ts_control; 859 msr.msr_mask = __BITS(1, 4); 860 861 xc = xc_broadcast(0, (xcfunc_t)x86_msr_xcall, &msr, NULL); 862 xc_wait(xc); 863 864 if (ts->ts_status == 0) { 865 DELAY(ts->ts_latency); 866 return 0; 867 } 868 869 xc = xc_broadcast(0, (xcfunc_t)acpicpu_md_tstate_status, ts, &rv); 870 xc_wait(xc); 871 872 return rv; 873 } 874 875 static void 876 acpicpu_md_tstate_status(void *arg1, void *arg2) 877 { 878 struct acpicpu_tstate *ts = arg1; 879 uint64_t val; 880 int i; 881 882 for (i = val = 0; i < ACPICPU_T_STATE_RETRY; i++) { 883 884 val = rdmsr(MSR_THERM_CONTROL); 885 886 if (val == ts->ts_status) 887 return; 888 889 DELAY(ts->ts_latency); 890 } 891 892 *(uintptr_t *)arg2 = EAGAIN; 893 } 894 895 /* 896 * A kludge for backwards compatibility. 897 */ 898 static int 899 acpicpu_md_pstate_sysctl_init(void) 900 { 901 const struct sysctlnode *fnode, *mnode, *rnode; 902 const char *str; 903 int rv; 904 905 switch (cpu_vendor) { 906 907 case CPUVENDOR_IDT: 908 case CPUVENDOR_INTEL: 909 str = "est"; 910 break; 911 912 case CPUVENDOR_AMD: 913 str = "powernow"; 914 break; 915 916 default: 917 return ENODEV; 918 } 919 920 921 rv = sysctl_createv(&acpicpu_log, 0, NULL, &rnode, 922 CTLFLAG_PERMANENT, CTLTYPE_NODE, "machdep", NULL, 923 NULL, 0, NULL, 0, CTL_MACHDEP, CTL_EOL); 924 925 if (rv != 0) 926 goto fail; 927 928 rv = sysctl_createv(&acpicpu_log, 0, &rnode, &mnode, 929 0, CTLTYPE_NODE, str, NULL, 930 NULL, 0, NULL, 0, CTL_CREATE, CTL_EOL); 931 932 if (rv != 0) 933 goto fail; 934 935 rv = sysctl_createv(&acpicpu_log, 0, &mnode, &fnode, 936 0, CTLTYPE_NODE, "frequency", NULL, 937 NULL, 0, NULL, 0, CTL_CREATE, CTL_EOL); 938 939 if (rv != 0) 940 goto fail; 941 942 rv = sysctl_createv(&acpicpu_log, 0, &fnode, &rnode, 943 CTLFLAG_READWRITE, CTLTYPE_INT, "target", NULL, 944 acpicpu_md_pstate_sysctl_set, 0, NULL, 0, CTL_CREATE, CTL_EOL); 945 946 if (rv != 0) 947 goto fail; 948 949 rv = sysctl_createv(&acpicpu_log, 0, &fnode, &rnode, 950 CTLFLAG_READONLY, CTLTYPE_INT, "current", NULL, 951 acpicpu_md_pstate_sysctl_get, 0, NULL, 0, CTL_CREATE, CTL_EOL); 952 953 if (rv != 0) 954 goto fail; 955 956 rv = sysctl_createv(&acpicpu_log, 0, &fnode, &rnode, 957 CTLFLAG_READONLY, CTLTYPE_STRING, "available", NULL, 958 acpicpu_md_pstate_sysctl_all, 0, NULL, 0, CTL_CREATE, CTL_EOL); 959 960 if (rv != 0) 961 goto fail; 962 963 return 0; 964 965 fail: 966 if (acpicpu_log != NULL) { 967 sysctl_teardown(&acpicpu_log); 968 acpicpu_log = NULL; 969 } 970 971 return rv; 972 } 973 974 static int 975 acpicpu_md_pstate_sysctl_get(SYSCTLFN_ARGS) 976 { 977 struct cpu_info *ci = curcpu(); 978 struct acpicpu_softc *sc; 979 struct sysctlnode node; 980 uint32_t freq; 981 int err; 982 983 sc = acpicpu_sc[ci->ci_acpiid]; 984 985 if (sc == NULL) 986 return ENXIO; 987 988 err = acpicpu_pstate_get(sc, &freq); 989 990 if (err != 0) 991 return err; 992 993 node = *rnode; 994 node.sysctl_data = &freq; 995 996 err = sysctl_lookup(SYSCTLFN_CALL(&node)); 997 998 if (err != 0 || newp == NULL) 999 return err; 1000 1001 return 0; 1002 } 1003 1004 static int 1005 acpicpu_md_pstate_sysctl_set(SYSCTLFN_ARGS) 1006 { 1007 struct cpu_info *ci = curcpu(); 1008 struct acpicpu_softc *sc; 1009 struct sysctlnode node; 1010 uint32_t freq; 1011 int err; 1012 1013 sc = acpicpu_sc[ci->ci_acpiid]; 1014 1015 if (sc == NULL) 1016 return ENXIO; 1017 1018 err = acpicpu_pstate_get(sc, &freq); 1019 1020 if (err != 0) 1021 return err; 1022 1023 node = *rnode; 1024 node.sysctl_data = &freq; 1025 1026 err = sysctl_lookup(SYSCTLFN_CALL(&node)); 1027 1028 if (err != 0 || newp == NULL) 1029 return err; 1030 1031 err = acpicpu_pstate_set(sc, freq); 1032 1033 if (err != 0) 1034 return err; 1035 1036 return 0; 1037 } 1038 1039 static int 1040 acpicpu_md_pstate_sysctl_all(SYSCTLFN_ARGS) 1041 { 1042 struct cpu_info *ci = curcpu(); 1043 struct acpicpu_softc *sc; 1044 struct sysctlnode node; 1045 char buf[1024]; 1046 size_t len; 1047 uint32_t i; 1048 int err; 1049 1050 sc = acpicpu_sc[ci->ci_acpiid]; 1051 1052 if (sc == NULL) 1053 return ENXIO; 1054 1055 (void)memset(&buf, 0, sizeof(buf)); 1056 1057 mutex_enter(&sc->sc_mtx); 1058 1059 for (len = 0, i = sc->sc_pstate_max; i < sc->sc_pstate_count; i++) { 1060 1061 if (sc->sc_pstate[i].ps_freq == 0) 1062 continue; 1063 1064 len += snprintf(buf + len, sizeof(buf) - len, "%u%s", 1065 sc->sc_pstate[i].ps_freq, 1066 i < (sc->sc_pstate_count - 1) ? " " : ""); 1067 } 1068 1069 mutex_exit(&sc->sc_mtx); 1070 1071 node = *rnode; 1072 node.sysctl_data = buf; 1073 1074 err = sysctl_lookup(SYSCTLFN_CALL(&node)); 1075 1076 if (err != 0 || newp == NULL) 1077 return err; 1078 1079 return 0; 1080 } 1081 1082