acpi_cpu_md.c revision 1.19 1 /* $NetBSD: acpi_cpu_md.c,v 1.19 2010/08/20 06:34:32 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.19 2010/08/20 06:34:32 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
258 return acpicpu_md_pstate_sysctl_init();
259 }
260
261 int
262 acpicpu_md_pstate_stop(void)
263 {
264
265 if (acpicpu_log != NULL)
266 sysctl_teardown(&acpicpu_log);
267
268 return 0;
269 }
270
271 int
272 acpicpu_md_pstate_pss(struct acpicpu_softc *sc)
273 {
274 struct acpicpu_pstate *ps, msr;
275 struct cpu_info *ci = curcpu();
276 uint32_t family, i = 0;
277
278 (void)memset(&msr, 0, sizeof(struct acpicpu_pstate));
279
280 switch (cpu_vendor) {
281
282 case CPUVENDOR_IDT:
283 case CPUVENDOR_INTEL:
284 msr.ps_control_addr = MSR_PERF_CTL;
285 msr.ps_control_mask = __BITS(0, 15);
286
287 msr.ps_status_addr = MSR_PERF_STATUS;
288 msr.ps_status_mask = __BITS(0, 15);
289 break;
290
291 case CPUVENDOR_AMD:
292
293 family = CPUID2FAMILY(ci->ci_signature);
294
295 if (family == 0xf)
296 family += CPUID2EXTFAMILY(ci->ci_signature);
297
298 switch (family) {
299
300 case 0x10:
301 case 0x11:
302 msr.ps_control_addr = MSR_10H_CONTROL;
303 msr.ps_control_mask = __BITS(0, 2);
304
305 msr.ps_status_addr = MSR_10H_STATUS;
306 msr.ps_status_mask = __BITS(0, 2);
307 break;
308
309 default:
310
311 if ((sc->sc_flags & ACPICPU_FLAG_P_XPSS) == 0)
312 return EOPNOTSUPP;
313 }
314
315 break;
316
317 default:
318 return ENODEV;
319 }
320
321 while (i < sc->sc_pstate_count) {
322
323 ps = &sc->sc_pstate[i];
324
325 if (ps->ps_status_addr == 0)
326 ps->ps_status_addr = msr.ps_status_addr;
327
328 if (ps->ps_status_mask == 0)
329 ps->ps_status_mask = msr.ps_status_mask;
330
331 if (ps->ps_control_addr == 0)
332 ps->ps_control_addr = msr.ps_control_addr;
333
334 if (ps->ps_control_mask == 0)
335 ps->ps_control_mask = msr.ps_control_mask;
336
337 i++;
338 }
339
340 return 0;
341 }
342
343 int
344 acpicpu_md_pstate_get(struct acpicpu_softc *sc, uint32_t *freq)
345 {
346 struct acpicpu_pstate *ps = NULL;
347 uint64_t val;
348 uint32_t i;
349
350 for (i = 0; i < sc->sc_pstate_count; i++) {
351
352 ps = &sc->sc_pstate[i];
353
354 if (ps->ps_freq != 0)
355 break;
356 }
357
358 if (__predict_false(ps == NULL))
359 return ENODEV;
360
361 if (ps->ps_status_addr == 0)
362 return EINVAL;
363
364 val = rdmsr(ps->ps_status_addr);
365
366 if (ps->ps_status_mask != 0)
367 val = val & ps->ps_status_mask;
368
369 for (i = 0; i < sc->sc_pstate_count; i++) {
370
371 ps = &sc->sc_pstate[i];
372
373 if (ps->ps_freq == 0)
374 continue;
375
376 if (val == ps->ps_status) {
377 *freq = ps->ps_freq;
378 return 0;
379 }
380 }
381
382 return EIO;
383 }
384
385 int
386 acpicpu_md_pstate_set(struct acpicpu_pstate *ps)
387 {
388 struct msr_rw_info msr;
389 uint64_t xc;
390 int rv = 0;
391
392 msr.msr_read = false;
393 msr.msr_type = ps->ps_control_addr;
394 msr.msr_value = ps->ps_control;
395
396 if (ps->ps_control_mask != 0) {
397 msr.msr_mask = ps->ps_control_mask;
398 msr.msr_read = true;
399 }
400
401 xc = xc_broadcast(0, (xcfunc_t)x86_msr_xcall, &msr, NULL);
402 xc_wait(xc);
403
404 if (ps->ps_status_addr == 0)
405 return 0;
406
407 xc = xc_broadcast(0, (xcfunc_t)acpicpu_md_pstate_status, ps, &rv);
408 xc_wait(xc);
409
410 return rv;
411 }
412
413 static void
414 acpicpu_md_pstate_status(void *arg1, void *arg2)
415 {
416 struct acpicpu_pstate *ps = arg1;
417 uint64_t val;
418 int i;
419
420 for (i = val = 0; i < ACPICPU_P_STATE_RETRY; i++) {
421
422 val = rdmsr(ps->ps_status_addr);
423
424 if (ps->ps_status_mask != 0)
425 val = val & ps->ps_status_mask;
426
427 if (val == ps->ps_status)
428 return;
429
430 DELAY(ps->ps_latency);
431 }
432
433 *(uintptr_t *)arg2 = EAGAIN;
434 }
435
436 int
437 acpicpu_md_tstate_get(struct acpicpu_softc *sc, uint32_t *percent)
438 {
439 struct acpicpu_tstate *ts;
440 uint64_t val;
441 uint32_t i;
442
443 val = rdmsr(MSR_THERM_CONTROL);
444
445 for (i = 0; i < sc->sc_tstate_count; i++) {
446
447 ts = &sc->sc_tstate[i];
448
449 if (ts->ts_percent == 0)
450 continue;
451
452 if (val == ts->ts_control || val == ts->ts_status) {
453 *percent = ts->ts_percent;
454 return 0;
455 }
456 }
457
458 return EIO;
459 }
460
461 int
462 acpicpu_md_tstate_set(struct acpicpu_tstate *ts)
463 {
464 struct msr_rw_info msr;
465 uint64_t xc;
466 int rv = 0;
467
468 msr.msr_read = true;
469 msr.msr_type = MSR_THERM_CONTROL;
470 msr.msr_value = ts->ts_control;
471 msr.msr_mask = __BITS(1, 4);
472
473 xc = xc_broadcast(0, (xcfunc_t)x86_msr_xcall, &msr, NULL);
474 xc_wait(xc);
475
476 if (ts->ts_status == 0)
477 return 0;
478
479 xc = xc_broadcast(0, (xcfunc_t)acpicpu_md_tstate_status, ts, &rv);
480 xc_wait(xc);
481
482 return rv;
483 }
484
485 static void
486 acpicpu_md_tstate_status(void *arg1, void *arg2)
487 {
488 struct acpicpu_tstate *ts = arg1;
489 uint64_t val;
490 int i;
491
492 for (i = val = 0; i < ACPICPU_T_STATE_RETRY; i++) {
493
494 val = rdmsr(MSR_THERM_CONTROL);
495
496 if (val == ts->ts_status)
497 return;
498
499 DELAY(ts->ts_latency);
500 }
501
502 *(uintptr_t *)arg2 = EAGAIN;
503 }
504
505 /*
506 * A kludge for backwards compatibility.
507 */
508 static int
509 acpicpu_md_pstate_sysctl_init(void)
510 {
511 const struct sysctlnode *fnode, *mnode, *rnode;
512 const char *str;
513 int rv;
514
515 switch (cpu_vendor) {
516
517 case CPUVENDOR_IDT:
518 case CPUVENDOR_INTEL:
519 str = "est";
520 break;
521
522 case CPUVENDOR_AMD:
523 str = "powernow";
524 break;
525
526 default:
527 return ENODEV;
528 }
529
530
531 rv = sysctl_createv(&acpicpu_log, 0, NULL, &rnode,
532 CTLFLAG_PERMANENT, CTLTYPE_NODE, "machdep", NULL,
533 NULL, 0, NULL, 0, CTL_MACHDEP, CTL_EOL);
534
535 if (rv != 0)
536 goto fail;
537
538 rv = sysctl_createv(&acpicpu_log, 0, &rnode, &mnode,
539 0, CTLTYPE_NODE, str, NULL,
540 NULL, 0, NULL, 0, CTL_CREATE, CTL_EOL);
541
542 if (rv != 0)
543 goto fail;
544
545 rv = sysctl_createv(&acpicpu_log, 0, &mnode, &fnode,
546 0, CTLTYPE_NODE, "frequency", NULL,
547 NULL, 0, NULL, 0, CTL_CREATE, CTL_EOL);
548
549 if (rv != 0)
550 goto fail;
551
552 rv = sysctl_createv(&acpicpu_log, 0, &fnode, &rnode,
553 CTLFLAG_READWRITE, CTLTYPE_INT, "target", NULL,
554 acpicpu_md_pstate_sysctl_set, 0, NULL, 0, CTL_CREATE, CTL_EOL);
555
556 if (rv != 0)
557 goto fail;
558
559 rv = sysctl_createv(&acpicpu_log, 0, &fnode, &rnode,
560 CTLFLAG_READONLY, CTLTYPE_INT, "current", NULL,
561 acpicpu_md_pstate_sysctl_get, 0, NULL, 0, CTL_CREATE, CTL_EOL);
562
563 if (rv != 0)
564 goto fail;
565
566 rv = sysctl_createv(&acpicpu_log, 0, &fnode, &rnode,
567 CTLFLAG_READONLY, CTLTYPE_STRING, "available", NULL,
568 acpicpu_md_pstate_sysctl_all, 0, NULL, 0, CTL_CREATE, CTL_EOL);
569
570 if (rv != 0)
571 goto fail;
572
573 return 0;
574
575 fail:
576 if (acpicpu_log != NULL) {
577 sysctl_teardown(&acpicpu_log);
578 acpicpu_log = NULL;
579 }
580
581 return rv;
582 }
583
584 static int
585 acpicpu_md_pstate_sysctl_get(SYSCTLFN_ARGS)
586 {
587 struct cpu_info *ci = curcpu();
588 struct acpicpu_softc *sc;
589 struct sysctlnode node;
590 uint32_t freq;
591 int err;
592
593 sc = acpicpu_sc[ci->ci_acpiid];
594
595 if (sc == NULL)
596 return ENXIO;
597
598 err = acpicpu_pstate_get(sc, &freq);
599
600 if (err != 0)
601 return err;
602
603 node = *rnode;
604 node.sysctl_data = &freq;
605
606 err = sysctl_lookup(SYSCTLFN_CALL(&node));
607
608 if (err != 0 || newp == NULL)
609 return err;
610
611 return 0;
612 }
613
614 static int
615 acpicpu_md_pstate_sysctl_set(SYSCTLFN_ARGS)
616 {
617 struct cpu_info *ci = curcpu();
618 struct acpicpu_softc *sc;
619 struct sysctlnode node;
620 uint32_t freq;
621 int err;
622
623 sc = acpicpu_sc[ci->ci_acpiid];
624
625 if (sc == NULL)
626 return ENXIO;
627
628 err = acpicpu_pstate_get(sc, &freq);
629
630 if (err != 0)
631 return err;
632
633 node = *rnode;
634 node.sysctl_data = &freq;
635
636 err = sysctl_lookup(SYSCTLFN_CALL(&node));
637
638 if (err != 0 || newp == NULL)
639 return err;
640
641 err = acpicpu_pstate_set(sc, freq);
642
643 if (err != 0)
644 return err;
645
646 return 0;
647 }
648
649 static int
650 acpicpu_md_pstate_sysctl_all(SYSCTLFN_ARGS)
651 {
652 struct cpu_info *ci = curcpu();
653 struct acpicpu_softc *sc;
654 struct sysctlnode node;
655 char buf[1024];
656 size_t len;
657 uint32_t i;
658 int err;
659
660 sc = acpicpu_sc[ci->ci_acpiid];
661
662 if (sc == NULL)
663 return ENXIO;
664
665 (void)memset(&buf, 0, sizeof(buf));
666
667 mutex_enter(&sc->sc_mtx);
668
669 for (len = 0, i = sc->sc_pstate_max; i < sc->sc_pstate_count; i++) {
670
671 if (sc->sc_pstate[i].ps_freq == 0)
672 continue;
673
674 len += snprintf(buf + len, sizeof(buf) - len, "%u%s",
675 sc->sc_pstate[i].ps_freq,
676 i < (sc->sc_pstate_count - 1) ? " " : "");
677 }
678
679 mutex_exit(&sc->sc_mtx);
680
681 node = *rnode;
682 node.sysctl_data = buf;
683
684 err = sysctl_lookup(SYSCTLFN_CALL(&node));
685
686 if (err != 0 || newp == NULL)
687 return err;
688
689 return 0;
690 }
691
692