acpi_cpu_md.c revision 1.4 1 1.4 jruoho /* $NetBSD: acpi_cpu_md.c,v 1.4 2010/08/04 16:16:55 jruoho Exp $ */
2 1.1 jruoho
3 1.1 jruoho /*-
4 1.1 jruoho * Copyright (c) 2010 Jukka Ruohonen <jruohonen (at) iki.fi>
5 1.1 jruoho * All rights reserved.
6 1.1 jruoho *
7 1.1 jruoho * Redistribution and use in source and binary forms, with or without
8 1.1 jruoho * modification, are permitted provided that the following conditions
9 1.1 jruoho * are met:
10 1.1 jruoho *
11 1.1 jruoho * 1. Redistributions of source code must retain the above copyright
12 1.1 jruoho * notice, this list of conditions and the following disclaimer.
13 1.1 jruoho * 2. Redistributions in binary form must reproduce the above copyright
14 1.1 jruoho * notice, this list of conditions and the following disclaimer in the
15 1.1 jruoho * documentation and/or other materials provided with the distribution.
16 1.1 jruoho *
17 1.1 jruoho * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 1.1 jruoho * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 1.1 jruoho * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 1.1 jruoho * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 1.1 jruoho * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 1.1 jruoho * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 1.1 jruoho * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 1.1 jruoho * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 1.1 jruoho * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 1.1 jruoho * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 1.1 jruoho * SUCH DAMAGE.
28 1.1 jruoho */
29 1.1 jruoho #include <sys/cdefs.h>
30 1.4 jruoho __KERNEL_RCSID(0, "$NetBSD: acpi_cpu_md.c,v 1.4 2010/08/04 16:16:55 jruoho Exp $");
31 1.1 jruoho
32 1.1 jruoho #include <sys/param.h>
33 1.1 jruoho #include <sys/bus.h>
34 1.1 jruoho #include <sys/kcore.h>
35 1.4 jruoho #include <sys/xcall.h>
36 1.1 jruoho
37 1.1 jruoho #include <x86/cpu.h>
38 1.1 jruoho #include <x86/cpuvar.h>
39 1.1 jruoho #include <x86/machdep.h>
40 1.1 jruoho #include <x86/cputypes.h>
41 1.1 jruoho
42 1.1 jruoho #include <dev/acpi/acpica.h>
43 1.1 jruoho #include <dev/acpi/acpi_cpu.h>
44 1.1 jruoho
45 1.1 jruoho static char native_idle_text[16];
46 1.1 jruoho void (*native_idle)(void) = NULL;
47 1.1 jruoho
48 1.1 jruoho extern uint32_t cpus_running;
49 1.1 jruoho
50 1.1 jruoho uint32_t
51 1.1 jruoho acpicpu_md_cap(void)
52 1.1 jruoho {
53 1.1 jruoho struct cpu_info *ci = curcpu();
54 1.1 jruoho uint32_t val = 0;
55 1.1 jruoho
56 1.1 jruoho if (cpu_vendor != CPUVENDOR_INTEL)
57 1.1 jruoho return val;
58 1.1 jruoho
59 1.1 jruoho /*
60 1.1 jruoho * Basic SMP C-states (required for _CST).
61 1.1 jruoho */
62 1.1 jruoho val |= ACPICPU_PDC_C_C1PT | ACPICPU_PDC_C_C2C3;
63 1.1 jruoho
64 1.1 jruoho /*
65 1.1 jruoho * If MONITOR/MWAIT is available, announce
66 1.1 jruoho * support for native instructions in all C-states.
67 1.1 jruoho */
68 1.1 jruoho if ((ci->ci_feat_val[1] & CPUID2_MONITOR) != 0)
69 1.1 jruoho val |= ACPICPU_PDC_C_C1_FFH | ACPICPU_PDC_C_C2C3_FFH;
70 1.1 jruoho
71 1.1 jruoho return val;
72 1.1 jruoho }
73 1.1 jruoho
74 1.1 jruoho uint32_t
75 1.1 jruoho acpicpu_md_quirks(void)
76 1.1 jruoho {
77 1.1 jruoho struct cpu_info *ci = curcpu();
78 1.1 jruoho uint32_t val = 0;
79 1.1 jruoho
80 1.1 jruoho if (acpicpu_md_cpus_running() == 1)
81 1.1 jruoho val |= ACPICPU_FLAG_C_BM;
82 1.1 jruoho
83 1.1 jruoho if ((ci->ci_feat_val[1] & CPUID2_MONITOR) != 0)
84 1.1 jruoho val |= ACPICPU_FLAG_C_MWAIT;
85 1.1 jruoho
86 1.1 jruoho switch (cpu_vendor) {
87 1.1 jruoho
88 1.1 jruoho case CPUVENDOR_INTEL:
89 1.1 jruoho val |= ACPICPU_FLAG_C_BM | ACPICPU_FLAG_C_ARB;
90 1.1 jruoho
91 1.1 jruoho /*
92 1.1 jruoho * Bus master arbitration is not
93 1.1 jruoho * needed on some recent Intel CPUs.
94 1.1 jruoho */
95 1.1 jruoho if (CPUID2FAMILY(ci->ci_signature) > 15)
96 1.1 jruoho val &= ~ACPICPU_FLAG_C_ARB;
97 1.1 jruoho
98 1.1 jruoho if (CPUID2FAMILY(ci->ci_signature) == 6 &&
99 1.1 jruoho CPUID2MODEL(ci->ci_signature) >= 15)
100 1.1 jruoho val &= ~ACPICPU_FLAG_C_ARB;
101 1.1 jruoho
102 1.1 jruoho break;
103 1.1 jruoho
104 1.1 jruoho case CPUVENDOR_AMD:
105 1.1 jruoho
106 1.1 jruoho /*
107 1.1 jruoho * XXX: Deal with the AMD C1E extension here.
108 1.1 jruoho */
109 1.1 jruoho break;
110 1.1 jruoho }
111 1.1 jruoho
112 1.1 jruoho return val;
113 1.1 jruoho }
114 1.1 jruoho
115 1.1 jruoho uint32_t
116 1.1 jruoho acpicpu_md_cpus_running(void)
117 1.1 jruoho {
118 1.1 jruoho
119 1.1 jruoho return popcount32(cpus_running);
120 1.1 jruoho }
121 1.1 jruoho
122 1.1 jruoho int
123 1.1 jruoho acpicpu_md_idle_init(void)
124 1.1 jruoho {
125 1.1 jruoho const size_t size = sizeof(native_idle_text);
126 1.1 jruoho
127 1.1 jruoho KASSERT(native_idle == NULL);
128 1.1 jruoho
129 1.1 jruoho x86_disable_intr();
130 1.1 jruoho x86_cpu_idle_get(&native_idle, native_idle_text, size);
131 1.1 jruoho x86_enable_intr();
132 1.1 jruoho
133 1.1 jruoho return 0;
134 1.1 jruoho }
135 1.1 jruoho
136 1.1 jruoho int
137 1.1 jruoho acpicpu_md_idle_start(void)
138 1.1 jruoho {
139 1.1 jruoho
140 1.1 jruoho KASSERT(native_idle != NULL);
141 1.1 jruoho KASSERT(native_idle_text[0] != '\0');
142 1.1 jruoho
143 1.1 jruoho x86_disable_intr();
144 1.1 jruoho x86_cpu_idle_set(acpicpu_cstate_idle, "acpi");
145 1.1 jruoho x86_enable_intr();
146 1.1 jruoho
147 1.1 jruoho return 0;
148 1.1 jruoho }
149 1.1 jruoho
150 1.1 jruoho int
151 1.1 jruoho acpicpu_md_idle_stop(void)
152 1.1 jruoho {
153 1.4 jruoho uint64_t xc;
154 1.1 jruoho
155 1.1 jruoho KASSERT(native_idle != NULL);
156 1.1 jruoho KASSERT(native_idle_text[0] != '\0');
157 1.1 jruoho
158 1.1 jruoho x86_disable_intr();
159 1.1 jruoho x86_cpu_idle_set(native_idle, native_idle_text);
160 1.1 jruoho x86_enable_intr();
161 1.1 jruoho
162 1.4 jruoho /*
163 1.4 jruoho * Run a cross-call to ensure that all CPUs are
164 1.4 jruoho * out from the ACPI idle-loop before detachment.
165 1.4 jruoho */
166 1.4 jruoho xc = xc_broadcast(0, (xcfunc_t)nullop, NULL, NULL);
167 1.4 jruoho xc_wait(xc);
168 1.1 jruoho
169 1.1 jruoho return 0;
170 1.1 jruoho }
171 1.1 jruoho
172 1.3 jruoho /*
173 1.3 jruoho * The MD idle loop. Called with interrupts disabled.
174 1.3 jruoho */
175 1.1 jruoho void
176 1.1 jruoho acpicpu_md_idle_enter(int method, int state)
177 1.1 jruoho {
178 1.3 jruoho struct cpu_info *ci = curcpu();
179 1.1 jruoho
180 1.1 jruoho switch (method) {
181 1.1 jruoho
182 1.1 jruoho case ACPICPU_C_STATE_FFH:
183 1.3 jruoho
184 1.3 jruoho x86_enable_intr();
185 1.3 jruoho x86_monitor(&ci->ci_want_resched, 0, 0);
186 1.3 jruoho
187 1.3 jruoho if (__predict_false(ci->ci_want_resched) != 0)
188 1.3 jruoho return;
189 1.3 jruoho
190 1.1 jruoho x86_mwait((state - 1) << 4, 0);
191 1.1 jruoho break;
192 1.1 jruoho
193 1.1 jruoho case ACPICPU_C_STATE_HALT:
194 1.3 jruoho
195 1.3 jruoho if (__predict_false(ci->ci_want_resched) != 0) {
196 1.3 jruoho x86_enable_intr();
197 1.3 jruoho return;
198 1.3 jruoho }
199 1.3 jruoho
200 1.1 jruoho x86_stihlt();
201 1.1 jruoho break;
202 1.1 jruoho }
203 1.1 jruoho }
204