acpi_cpu_md.c revision 1.20 1 /* $NetBSD: acpi_cpu_md.c,v 1.20 2010/08/20 07:00:17 jruoho Exp $ */
2
3 /*-
4 * Copyright (c) 2010 Jukka Ruohonen <jruohonen (at) 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.20 2010/08/20 07:00:17 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 #define MSR_0FH_CONTROL 0xc0010041 /* Family 0Fh (and K7). */
52 #define MSR_0FH_STATUS 0xc0010042
53
54 #define MSR_10H_LIMIT 0xc0010061 /* Families 10h and 11h. */
55 #define MSR_10H_CONTROL 0xc0010062
56 #define MSR_10H_STATUS 0xc0010063
57 #define MSR_10H_CONFIG 0xc0010064
58
59 static char native_idle_text[16];
60 void (*native_idle)(void) = NULL;
61
62 static int acpicpu_md_quirks_piix4(struct pci_attach_args *);
63 static void acpicpu_md_pstate_status(void *, void *);
64 static void acpicpu_md_tstate_status(void *, void *);
65 static int acpicpu_md_pstate_sysctl_init(void);
66 static int acpicpu_md_pstate_sysctl_get(SYSCTLFN_PROTO);
67 static int acpicpu_md_pstate_sysctl_set(SYSCTLFN_PROTO);
68 static int acpicpu_md_pstate_sysctl_all(SYSCTLFN_PROTO);
69
70 extern uint32_t cpus_running;
71 extern struct acpicpu_softc **acpicpu_sc;
72 static struct sysctllog *acpicpu_log = NULL;
73
74 uint32_t
75 acpicpu_md_cap(void)
76 {
77 struct cpu_info *ci = curcpu();
78 uint32_t val = 0;
79
80 if (cpu_vendor != CPUVENDOR_IDT &&
81 cpu_vendor != CPUVENDOR_INTEL)
82 return val;
83
84 /*
85 * Basic SMP C-states (required for _CST).
86 */
87 val |= ACPICPU_PDC_C_C1PT | ACPICPU_PDC_C_C2C3;
88
89 /*
90 * If MONITOR/MWAIT is available, announce
91 * support for native instructions in all C-states.
92 */
93 if ((ci->ci_feat_val[1] & CPUID2_MONITOR) != 0)
94 val |= ACPICPU_PDC_C_C1_FFH | ACPICPU_PDC_C_C2C3_FFH;
95
96 /*
97 * Set native P- and T-states, if available.
98 */
99 if ((ci->ci_feat_val[1] & CPUID2_EST) != 0)
100 val |= ACPICPU_PDC_P_FFH;
101
102 if ((ci->ci_feat_val[0] & CPUID_ACPI) != 0)
103 val |= ACPICPU_PDC_T_FFH;
104
105 return val;
106 }
107
108 uint32_t
109 acpicpu_md_quirks(void)
110 {
111 struct cpu_info *ci = curcpu();
112 struct pci_attach_args pa;
113 uint32_t family, val = 0;
114
115 if (acpicpu_md_cpus_running() == 1)
116 val |= ACPICPU_FLAG_C_BM;
117
118 if ((ci->ci_feat_val[1] & CPUID2_MONITOR) != 0)
119 val |= ACPICPU_FLAG_C_FFH;
120
121 switch (cpu_vendor) {
122
123 case CPUVENDOR_IDT:
124 case CPUVENDOR_INTEL:
125
126 if ((ci->ci_feat_val[1] & CPUID2_EST) != 0)
127 val |= ACPICPU_FLAG_P_FFH;
128
129 if ((ci->ci_feat_val[0] & CPUID_ACPI) != 0)
130 val |= ACPICPU_FLAG_T_FFH;
131
132 val |= ACPICPU_FLAG_C_BM | ACPICPU_FLAG_C_ARB;
133 break;
134
135 case CPUVENDOR_AMD:
136
137 family = CPUID2FAMILY(ci->ci_signature);
138
139 if (family == 0xf)
140 family += CPUID2EXTFAMILY(ci->ci_signature);
141
142 switch (family) {
143
144 case 0x10:
145 case 0x11:
146
147 if ((ci->ci_feat_val[2] & CPUID_APM_HWP) != 0)
148 val |= ACPICPU_FLAG_P_FFH;
149 }
150
151 break;
152 }
153
154 /*
155 * There are several erratums for PIIX4.
156 */
157 if (pci_find_device(&pa, acpicpu_md_quirks_piix4) != 0)
158 val |= ACPICPU_FLAG_PIIX4;
159
160 return val;
161 }
162
163 static int
164 acpicpu_md_quirks_piix4(struct pci_attach_args *pa)
165 {
166
167 /*
168 * XXX: The pci_find_device(9) function only
169 * deals with attached devices. Change this
170 * to use something like pci_device_foreach().
171 */
172 if (PCI_VENDOR(pa->pa_id) != PCI_VENDOR_INTEL)
173 return 0;
174
175 if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_INTEL_82371AB_ISA ||
176 PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_INTEL_82440MX_PMC)
177 return 1;
178
179 return 0;
180 }
181
182 uint32_t
183 acpicpu_md_cpus_running(void)
184 {
185
186 return popcount32(cpus_running);
187 }
188
189 int
190 acpicpu_md_idle_start(void)
191 {
192 const size_t size = sizeof(native_idle_text);
193
194 x86_disable_intr();
195 x86_cpu_idle_get(&native_idle, native_idle_text, size);
196 x86_cpu_idle_set(acpicpu_cstate_idle, "acpi");
197 x86_enable_intr();
198
199 return 0;
200 }
201
202 int
203 acpicpu_md_idle_stop(void)
204 {
205 uint64_t xc;
206
207 x86_disable_intr();
208 x86_cpu_idle_set(native_idle, native_idle_text);
209 x86_enable_intr();
210
211 /*
212 * Run a cross-call to ensure that all CPUs are
213 * out from the ACPI idle-loop before detachment.
214 */
215 xc = xc_broadcast(0, (xcfunc_t)nullop, NULL, NULL);
216 xc_wait(xc);
217
218 return 0;
219 }
220
221 /*
222 * The MD idle loop. Called with interrupts disabled.
223 */
224 void
225 acpicpu_md_idle_enter(int method, int state)
226 {
227 struct cpu_info *ci = curcpu();
228
229 switch (method) {
230
231 case ACPICPU_C_STATE_FFH:
232
233 x86_enable_intr();
234 x86_monitor(&ci->ci_want_resched, 0, 0);
235
236 if (__predict_false(ci->ci_want_resched) != 0)
237 return;
238
239 x86_mwait((state - 1) << 4, 0);
240 break;
241
242 case ACPICPU_C_STATE_HALT:
243
244 if (__predict_false(ci->ci_want_resched) != 0) {
245 x86_enable_intr();
246 return;
247 }
248
249 x86_stihlt();
250 break;
251 }
252 }
253
254 int
255 acpicpu_md_pstate_start(void)
256 {
257 const uint64_t est = __BIT(16);
258 uint64_t val;
259
260 switch (cpu_vendor) {
261
262 case CPUVENDOR_IDT:
263 case CPUVENDOR_INTEL:
264
265 val = rdmsr(MSR_MISC_ENABLE);
266
267 if ((val & est) == 0) {
268
269 val |= est;
270
271 wrmsr(MSR_MISC_ENABLE, val);
272 val = rdmsr(MSR_MISC_ENABLE);
273
274 if ((val & est) == 0)
275 return ENOTTY;
276 }
277 }
278
279 return acpicpu_md_pstate_sysctl_init();
280 }
281
282 int
283 acpicpu_md_pstate_stop(void)
284 {
285
286 if (acpicpu_log != NULL)
287 sysctl_teardown(&acpicpu_log);
288
289 return 0;
290 }
291
292 int
293 acpicpu_md_pstate_pss(struct acpicpu_softc *sc)
294 {
295 struct acpicpu_pstate *ps, msr;
296 struct cpu_info *ci = curcpu();
297 uint32_t family, i = 0;
298
299 (void)memset(&msr, 0, sizeof(struct acpicpu_pstate));
300
301 switch (cpu_vendor) {
302
303 case CPUVENDOR_IDT:
304 case CPUVENDOR_INTEL:
305 msr.ps_control_addr = MSR_PERF_CTL;
306 msr.ps_control_mask = __BITS(0, 15);
307
308 msr.ps_status_addr = MSR_PERF_STATUS;
309 msr.ps_status_mask = __BITS(0, 15);
310 break;
311
312 case CPUVENDOR_AMD:
313
314 family = CPUID2FAMILY(ci->ci_signature);
315
316 if (family == 0xf)
317 family += CPUID2EXTFAMILY(ci->ci_signature);
318
319 switch (family) {
320
321 case 0x10:
322 case 0x11:
323 msr.ps_control_addr = MSR_10H_CONTROL;
324 msr.ps_control_mask = __BITS(0, 2);
325
326 msr.ps_status_addr = MSR_10H_STATUS;
327 msr.ps_status_mask = __BITS(0, 2);
328 break;
329
330 default:
331
332 if ((sc->sc_flags & ACPICPU_FLAG_P_XPSS) == 0)
333 return EOPNOTSUPP;
334 }
335
336 break;
337
338 default:
339 return ENODEV;
340 }
341
342 while (i < sc->sc_pstate_count) {
343
344 ps = &sc->sc_pstate[i];
345
346 if (ps->ps_status_addr == 0)
347 ps->ps_status_addr = msr.ps_status_addr;
348
349 if (ps->ps_status_mask == 0)
350 ps->ps_status_mask = msr.ps_status_mask;
351
352 if (ps->ps_control_addr == 0)
353 ps->ps_control_addr = msr.ps_control_addr;
354
355 if (ps->ps_control_mask == 0)
356 ps->ps_control_mask = msr.ps_control_mask;
357
358 i++;
359 }
360
361 return 0;
362 }
363
364 int
365 acpicpu_md_pstate_get(struct acpicpu_softc *sc, uint32_t *freq)
366 {
367 struct acpicpu_pstate *ps = NULL;
368 uint64_t val;
369 uint32_t i;
370
371 for (i = 0; i < sc->sc_pstate_count; i++) {
372
373 ps = &sc->sc_pstate[i];
374
375 if (ps->ps_freq != 0)
376 break;
377 }
378
379 if (__predict_false(ps == NULL))
380 return ENODEV;
381
382 if (ps->ps_status_addr == 0)
383 return EINVAL;
384
385 val = rdmsr(ps->ps_status_addr);
386
387 if (ps->ps_status_mask != 0)
388 val = val & ps->ps_status_mask;
389
390 for (i = 0; i < sc->sc_pstate_count; i++) {
391
392 ps = &sc->sc_pstate[i];
393
394 if (ps->ps_freq == 0)
395 continue;
396
397 if (val == ps->ps_status) {
398 *freq = ps->ps_freq;
399 return 0;
400 }
401 }
402
403 return EIO;
404 }
405
406 int
407 acpicpu_md_pstate_set(struct acpicpu_pstate *ps)
408 {
409 struct msr_rw_info msr;
410 uint64_t xc;
411 int rv = 0;
412
413 msr.msr_read = false;
414 msr.msr_type = ps->ps_control_addr;
415 msr.msr_value = ps->ps_control;
416
417 if (ps->ps_control_mask != 0) {
418 msr.msr_mask = ps->ps_control_mask;
419 msr.msr_read = true;
420 }
421
422 xc = xc_broadcast(0, (xcfunc_t)x86_msr_xcall, &msr, NULL);
423 xc_wait(xc);
424
425 if (ps->ps_status_addr == 0)
426 return 0;
427
428 xc = xc_broadcast(0, (xcfunc_t)acpicpu_md_pstate_status, ps, &rv);
429 xc_wait(xc);
430
431 return rv;
432 }
433
434 static void
435 acpicpu_md_pstate_status(void *arg1, void *arg2)
436 {
437 struct acpicpu_pstate *ps = arg1;
438 uint64_t val;
439 int i;
440
441 for (i = val = 0; i < ACPICPU_P_STATE_RETRY; i++) {
442
443 val = rdmsr(ps->ps_status_addr);
444
445 if (ps->ps_status_mask != 0)
446 val = val & ps->ps_status_mask;
447
448 if (val == ps->ps_status)
449 return;
450
451 DELAY(ps->ps_latency);
452 }
453
454 *(uintptr_t *)arg2 = EAGAIN;
455 }
456
457 int
458 acpicpu_md_tstate_get(struct acpicpu_softc *sc, uint32_t *percent)
459 {
460 struct acpicpu_tstate *ts;
461 uint64_t val;
462 uint32_t i;
463
464 val = rdmsr(MSR_THERM_CONTROL);
465
466 for (i = 0; i < sc->sc_tstate_count; i++) {
467
468 ts = &sc->sc_tstate[i];
469
470 if (ts->ts_percent == 0)
471 continue;
472
473 if (val == ts->ts_control || val == ts->ts_status) {
474 *percent = ts->ts_percent;
475 return 0;
476 }
477 }
478
479 return EIO;
480 }
481
482 int
483 acpicpu_md_tstate_set(struct acpicpu_tstate *ts)
484 {
485 struct msr_rw_info msr;
486 uint64_t xc;
487 int rv = 0;
488
489 msr.msr_read = true;
490 msr.msr_type = MSR_THERM_CONTROL;
491 msr.msr_value = ts->ts_control;
492 msr.msr_mask = __BITS(1, 4);
493
494 xc = xc_broadcast(0, (xcfunc_t)x86_msr_xcall, &msr, NULL);
495 xc_wait(xc);
496
497 if (ts->ts_status == 0)
498 return 0;
499
500 xc = xc_broadcast(0, (xcfunc_t)acpicpu_md_tstate_status, ts, &rv);
501 xc_wait(xc);
502
503 return rv;
504 }
505
506 static void
507 acpicpu_md_tstate_status(void *arg1, void *arg2)
508 {
509 struct acpicpu_tstate *ts = arg1;
510 uint64_t val;
511 int i;
512
513 for (i = val = 0; i < ACPICPU_T_STATE_RETRY; i++) {
514
515 val = rdmsr(MSR_THERM_CONTROL);
516
517 if (val == ts->ts_status)
518 return;
519
520 DELAY(ts->ts_latency);
521 }
522
523 *(uintptr_t *)arg2 = EAGAIN;
524 }
525
526 /*
527 * A kludge for backwards compatibility.
528 */
529 static int
530 acpicpu_md_pstate_sysctl_init(void)
531 {
532 const struct sysctlnode *fnode, *mnode, *rnode;
533 const char *str;
534 int rv;
535
536 switch (cpu_vendor) {
537
538 case CPUVENDOR_IDT:
539 case CPUVENDOR_INTEL:
540 str = "est";
541 break;
542
543 case CPUVENDOR_AMD:
544 str = "powernow";
545 break;
546
547 default:
548 return ENODEV;
549 }
550
551
552 rv = sysctl_createv(&acpicpu_log, 0, NULL, &rnode,
553 CTLFLAG_PERMANENT, CTLTYPE_NODE, "machdep", NULL,
554 NULL, 0, NULL, 0, CTL_MACHDEP, CTL_EOL);
555
556 if (rv != 0)
557 goto fail;
558
559 rv = sysctl_createv(&acpicpu_log, 0, &rnode, &mnode,
560 0, CTLTYPE_NODE, str, NULL,
561 NULL, 0, NULL, 0, CTL_CREATE, CTL_EOL);
562
563 if (rv != 0)
564 goto fail;
565
566 rv = sysctl_createv(&acpicpu_log, 0, &mnode, &fnode,
567 0, CTLTYPE_NODE, "frequency", NULL,
568 NULL, 0, NULL, 0, CTL_CREATE, CTL_EOL);
569
570 if (rv != 0)
571 goto fail;
572
573 rv = sysctl_createv(&acpicpu_log, 0, &fnode, &rnode,
574 CTLFLAG_READWRITE, CTLTYPE_INT, "target", NULL,
575 acpicpu_md_pstate_sysctl_set, 0, NULL, 0, CTL_CREATE, CTL_EOL);
576
577 if (rv != 0)
578 goto fail;
579
580 rv = sysctl_createv(&acpicpu_log, 0, &fnode, &rnode,
581 CTLFLAG_READONLY, CTLTYPE_INT, "current", NULL,
582 acpicpu_md_pstate_sysctl_get, 0, NULL, 0, CTL_CREATE, CTL_EOL);
583
584 if (rv != 0)
585 goto fail;
586
587 rv = sysctl_createv(&acpicpu_log, 0, &fnode, &rnode,
588 CTLFLAG_READONLY, CTLTYPE_STRING, "available", NULL,
589 acpicpu_md_pstate_sysctl_all, 0, NULL, 0, CTL_CREATE, CTL_EOL);
590
591 if (rv != 0)
592 goto fail;
593
594 return 0;
595
596 fail:
597 if (acpicpu_log != NULL) {
598 sysctl_teardown(&acpicpu_log);
599 acpicpu_log = NULL;
600 }
601
602 return rv;
603 }
604
605 static int
606 acpicpu_md_pstate_sysctl_get(SYSCTLFN_ARGS)
607 {
608 struct cpu_info *ci = curcpu();
609 struct acpicpu_softc *sc;
610 struct sysctlnode node;
611 uint32_t freq;
612 int err;
613
614 sc = acpicpu_sc[ci->ci_acpiid];
615
616 if (sc == NULL)
617 return ENXIO;
618
619 err = acpicpu_pstate_get(sc, &freq);
620
621 if (err != 0)
622 return err;
623
624 node = *rnode;
625 node.sysctl_data = &freq;
626
627 err = sysctl_lookup(SYSCTLFN_CALL(&node));
628
629 if (err != 0 || newp == NULL)
630 return err;
631
632 return 0;
633 }
634
635 static int
636 acpicpu_md_pstate_sysctl_set(SYSCTLFN_ARGS)
637 {
638 struct cpu_info *ci = curcpu();
639 struct acpicpu_softc *sc;
640 struct sysctlnode node;
641 uint32_t freq;
642 int err;
643
644 sc = acpicpu_sc[ci->ci_acpiid];
645
646 if (sc == NULL)
647 return ENXIO;
648
649 err = acpicpu_pstate_get(sc, &freq);
650
651 if (err != 0)
652 return err;
653
654 node = *rnode;
655 node.sysctl_data = &freq;
656
657 err = sysctl_lookup(SYSCTLFN_CALL(&node));
658
659 if (err != 0 || newp == NULL)
660 return err;
661
662 err = acpicpu_pstate_set(sc, freq);
663
664 if (err != 0)
665 return err;
666
667 return 0;
668 }
669
670 static int
671 acpicpu_md_pstate_sysctl_all(SYSCTLFN_ARGS)
672 {
673 struct cpu_info *ci = curcpu();
674 struct acpicpu_softc *sc;
675 struct sysctlnode node;
676 char buf[1024];
677 size_t len;
678 uint32_t i;
679 int err;
680
681 sc = acpicpu_sc[ci->ci_acpiid];
682
683 if (sc == NULL)
684 return ENXIO;
685
686 (void)memset(&buf, 0, sizeof(buf));
687
688 mutex_enter(&sc->sc_mtx);
689
690 for (len = 0, i = sc->sc_pstate_max; i < sc->sc_pstate_count; i++) {
691
692 if (sc->sc_pstate[i].ps_freq == 0)
693 continue;
694
695 len += snprintf(buf + len, sizeof(buf) - len, "%u%s",
696 sc->sc_pstate[i].ps_freq,
697 i < (sc->sc_pstate_count - 1) ? " " : "");
698 }
699
700 mutex_exit(&sc->sc_mtx);
701
702 node = *rnode;
703 node.sysctl_data = buf;
704
705 err = sysctl_lookup(SYSCTLFN_CALL(&node));
706
707 if (err != 0 || newp == NULL)
708 return err;
709
710 return 0;
711 }
712
713