Move the sysctl function pointers used by acpicpu(4) to x86/cpu.c. Rename these so that the same pointers may be used in other parts.diff -r1.5 -r1.6 src/sys/arch/x86/acpi/acpi_cpu_md.c
(jruoho)
--- src/sys/arch/x86/acpi/acpi_cpu_md.c 2010/08/08 16:58:41 1.5
+++ src/sys/arch/x86/acpi/acpi_cpu_md.c 2010/08/09 04:18:48 1.6
@@ -1,444 +1,428 @@ | @@ -1,444 +1,428 @@ | |||
1 | /* $NetBSD: acpi_cpu_md.c,v 1.5 2010/08/08 16:58:41 jruoho Exp $ */ | 1 | /* $NetBSD: acpi_cpu_md.c,v 1.6 2010/08/09 04:18:48 jruoho Exp $ */ | |
2 | 2 | |||
3 | /*- | 3 | /*- | |
4 | * Copyright (c) 2010 Jukka Ruohonen <jruohonen@iki.fi> | 4 | * Copyright (c) 2010 Jukka Ruohonen <jruohonen@iki.fi> | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * Redistribution and use in source and binary forms, with or without | 7 | * Redistribution and use in source and binary forms, with or without | |
8 | * modification, are permitted provided that the following conditions | 8 | * modification, are permitted provided that the following conditions | |
9 | * are met: | 9 | * are met: | |
10 | * | 10 | * | |
11 | * 1. Redistributions of source code must retain the above copyright | 11 | * 1. Redistributions of source code must retain the above copyright | |
12 | * notice, this list of conditions and the following disclaimer. | 12 | * notice, this list of conditions and the following disclaimer. | |
13 | * 2. Redistributions in binary form must reproduce the above copyright | 13 | * 2. Redistributions in binary form must reproduce the above copyright | |
14 | * notice, this list of conditions and the following disclaimer in the | 14 | * notice, this list of conditions and the following disclaimer in the | |
15 | * documentation and/or other materials provided with the distribution. | 15 | * documentation and/or other materials provided with the distribution. | |
16 | * | 16 | * | |
17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND | 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 | 18 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | 19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE | 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE | |
21 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | 21 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
22 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | 22 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
23 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | 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 | 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 | 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 | 26 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
27 | * SUCH DAMAGE. | 27 | * SUCH DAMAGE. | |
28 | */ | 28 | */ | |
29 | #include <sys/cdefs.h> | 29 | #include <sys/cdefs.h> | |
30 | __KERNEL_RCSID(0, "$NetBSD: acpi_cpu_md.c,v 1.5 2010/08/08 16:58:41 jruoho Exp $"); | 30 | __KERNEL_RCSID(0, "$NetBSD: acpi_cpu_md.c,v 1.6 2010/08/09 04:18:48 jruoho Exp $"); | |
31 | 31 | |||
32 | #include <sys/param.h> | 32 | #include <sys/param.h> | |
33 | #include <sys/bus.h> | 33 | #include <sys/bus.h> | |
34 | #include <sys/kcore.h> | 34 | #include <sys/kcore.h> | |
35 | #include <sys/sysctl.h> | 35 | #include <sys/sysctl.h> | |
36 | #include <sys/xcall.h> | 36 | #include <sys/xcall.h> | |
37 | 37 | |||
38 | #include <x86/cpu.h> | 38 | #include <x86/cpu.h> | |
39 | #include <x86/cpufunc.h> | 39 | #include <x86/cpufunc.h> | |
40 | #include <x86/cputypes.h> | 40 | #include <x86/cputypes.h> | |
41 | #include <x86/cpuvar.h> | 41 | #include <x86/cpuvar.h> | |
42 | #include <x86/cpu_msr.h> | 42 | #include <x86/cpu_msr.h> | |
43 | #include <x86/machdep.h> | 43 | #include <x86/machdep.h> | |
44 | 44 | |||
45 | #include <dev/acpi/acpica.h> | 45 | #include <dev/acpi/acpica.h> | |
46 | #include <dev/acpi/acpi_cpu.h> | 46 | #include <dev/acpi/acpi_cpu.h> | |
47 | 47 | |||
48 | static char native_idle_text[16]; | 48 | static char native_idle_text[16]; | |
49 | void (*native_idle)(void) = NULL; | 49 | void (*native_idle)(void) = NULL; | |
50 | 50 | |||
51 | static int acpicpu_md_pstate_sysctl_get(SYSCTLFN_PROTO); | 51 | static int acpicpu_md_pstate_sysctl_get(SYSCTLFN_PROTO); | |
52 | static int acpicpu_md_pstate_sysctl_set(SYSCTLFN_PROTO); | 52 | static int acpicpu_md_pstate_sysctl_set(SYSCTLFN_PROTO); | |
53 | static int acpicpu_md_pstate_sysctl_all(SYSCTLFN_PROTO); | 53 | static int acpicpu_md_pstate_sysctl_all(SYSCTLFN_PROTO); | |
54 | 54 | |||
55 | extern uint32_t cpus_running; | 55 | extern uint32_t cpus_running; | |
56 | extern struct acpicpu_softc **acpicpu_sc; | 56 | extern struct acpicpu_softc **acpicpu_sc; | |
57 | 57 | |||
58 | uint32_t | 58 | uint32_t | |
59 | acpicpu_md_cap(void) | 59 | acpicpu_md_cap(void) | |
60 | { | 60 | { | |
61 | struct cpu_info *ci = curcpu(); | 61 | struct cpu_info *ci = curcpu(); | |
62 | uint32_t val = 0; | 62 | uint32_t val = 0; | |
63 | 63 | |||
64 | if (cpu_vendor != CPUVENDOR_INTEL) | 64 | if (cpu_vendor != CPUVENDOR_INTEL) | |
65 | return val; | 65 | return val; | |
66 | 66 | |||
67 | /* | 67 | /* | |
68 | * Basic SMP C-states (required for _CST). | 68 | * Basic SMP C-states (required for _CST). | |
69 | */ | 69 | */ | |
70 | val |= ACPICPU_PDC_C_C1PT | ACPICPU_PDC_C_C2C3; | 70 | val |= ACPICPU_PDC_C_C1PT | ACPICPU_PDC_C_C2C3; | |
71 | 71 | |||
72 | /* | 72 | /* | |
73 | * If MONITOR/MWAIT is available, announce | 73 | * If MONITOR/MWAIT is available, announce | |
74 | * support for native instructions in all C-states. | 74 | * support for native instructions in all C-states. | |
75 | */ | 75 | */ | |
76 | if ((ci->ci_feat_val[1] & CPUID2_MONITOR) != 0) | 76 | if ((ci->ci_feat_val[1] & CPUID2_MONITOR) != 0) | |
77 | val |= ACPICPU_PDC_C_C1_FFH | ACPICPU_PDC_C_C2C3_FFH; | 77 | val |= ACPICPU_PDC_C_C1_FFH | ACPICPU_PDC_C_C2C3_FFH; | |
78 | 78 | |||
79 | /* | 79 | /* | |
80 | * Set native P-states if EST is available. | 80 | * Set native P-states if EST is available. | |
81 | */ | 81 | */ | |
82 | if ((ci->ci_feat_val[1] & CPUID2_EST) != 0) | 82 | if ((ci->ci_feat_val[1] & CPUID2_EST) != 0) | |
83 | val |= ACPICPU_PDC_P_FFH; | 83 | val |= ACPICPU_PDC_P_FFH; | |
84 | 84 | |||
85 | return val; | 85 | return val; | |
86 | } | 86 | } | |
87 | 87 | |||
88 | uint32_t | 88 | uint32_t | |
89 | acpicpu_md_quirks(void) | 89 | acpicpu_md_quirks(void) | |
90 | { | 90 | { | |
91 | struct cpu_info *ci = curcpu(); | 91 | struct cpu_info *ci = curcpu(); | |
92 | uint32_t val = 0; | 92 | uint32_t val = 0; | |
93 | 93 | |||
94 | if (acpicpu_md_cpus_running() == 1) | 94 | if (acpicpu_md_cpus_running() == 1) | |
95 | val |= ACPICPU_FLAG_C_BM; | 95 | val |= ACPICPU_FLAG_C_BM; | |
96 | 96 | |||
97 | if ((ci->ci_feat_val[1] & CPUID2_MONITOR) != 0) | 97 | if ((ci->ci_feat_val[1] & CPUID2_MONITOR) != 0) | |
98 | val |= ACPICPU_FLAG_C_FFH; | 98 | val |= ACPICPU_FLAG_C_FFH; | |
99 | 99 | |||
100 | switch (cpu_vendor) { | 100 | switch (cpu_vendor) { | |
101 | 101 | |||
102 | case CPUVENDOR_INTEL: | 102 | case CPUVENDOR_INTEL: | |
103 | 103 | |||
104 | val |= ACPICPU_FLAG_C_BM | ACPICPU_FLAG_C_ARB; | 104 | val |= ACPICPU_FLAG_C_BM | ACPICPU_FLAG_C_ARB; | |
105 | 105 | |||
106 | if ((ci->ci_feat_val[1] & CPUID2_EST) != 0) | 106 | if ((ci->ci_feat_val[1] & CPUID2_EST) != 0) | |
107 | val |= ACPICPU_FLAG_P_FFH; | 107 | val |= ACPICPU_FLAG_P_FFH; | |
108 | 108 | |||
109 | /* | 109 | /* | |
110 | * Bus master arbitration is not | 110 | * Bus master arbitration is not | |
111 | * needed on some recent Intel CPUs. | 111 | * needed on some recent Intel CPUs. | |
112 | */ | 112 | */ | |
113 | if (CPUID2FAMILY(ci->ci_signature) > 15) | 113 | if (CPUID2FAMILY(ci->ci_signature) > 15) | |
114 | val &= ~ACPICPU_FLAG_C_ARB; | 114 | val &= ~ACPICPU_FLAG_C_ARB; | |
115 | 115 | |||
116 | if (CPUID2FAMILY(ci->ci_signature) == 6 && | 116 | if (CPUID2FAMILY(ci->ci_signature) == 6 && | |
117 | CPUID2MODEL(ci->ci_signature) >= 15) | 117 | CPUID2MODEL(ci->ci_signature) >= 15) | |
118 | val &= ~ACPICPU_FLAG_C_ARB; | 118 | val &= ~ACPICPU_FLAG_C_ARB; | |
119 | 119 | |||
120 | break; | 120 | break; | |
121 | 121 | |||
122 | case CPUVENDOR_AMD: | 122 | case CPUVENDOR_AMD: | |
123 | 123 | |||
124 | /* | 124 | /* | |
125 | * XXX: Deal with the AMD C1E extension here. | 125 | * XXX: Deal with the AMD C1E extension here. | |
126 | */ | 126 | */ | |
127 | break; | 127 | break; | |
128 | } | 128 | } | |
129 | 129 | |||
130 | return val; | 130 | return val; | |
131 | } | 131 | } | |
132 | 132 | |||
133 | uint32_t | 133 | uint32_t | |
134 | acpicpu_md_cpus_running(void) | 134 | acpicpu_md_cpus_running(void) | |
135 | { | 135 | { | |
136 | 136 | |||
137 | return popcount32(cpus_running); | 137 | return popcount32(cpus_running); | |
138 | } | 138 | } | |
139 | 139 | |||
140 | int | 140 | int | |
141 | acpicpu_md_idle_init(void) | 141 | acpicpu_md_idle_init(void) | |
142 | { | 142 | { | |
143 | const size_t size = sizeof(native_idle_text); | 143 | const size_t size = sizeof(native_idle_text); | |
144 | 144 | |||
145 | x86_disable_intr(); | 145 | x86_disable_intr(); | |
146 | x86_cpu_idle_get(&native_idle, native_idle_text, size); | 146 | x86_cpu_idle_get(&native_idle, native_idle_text, size); | |
147 | x86_enable_intr(); | 147 | x86_enable_intr(); | |
148 | 148 | |||
149 | return 0; | 149 | return 0; | |
150 | } | 150 | } | |
151 | 151 | |||
152 | int | 152 | int | |
153 | acpicpu_md_idle_start(void) | 153 | acpicpu_md_idle_start(void) | |
154 | { | 154 | { | |
155 | 155 | |||
156 | x86_disable_intr(); | 156 | x86_disable_intr(); | |
157 | x86_cpu_idle_set(acpicpu_cstate_idle, "acpi"); | 157 | x86_cpu_idle_set(acpicpu_cstate_idle, "acpi"); | |
158 | x86_enable_intr(); | 158 | x86_enable_intr(); | |
159 | 159 | |||
160 | return 0; | 160 | return 0; | |
161 | } | 161 | } | |
162 | 162 | |||
163 | int | 163 | int | |
164 | acpicpu_md_idle_stop(void) | 164 | acpicpu_md_idle_stop(void) | |
165 | { | 165 | { | |
166 | uint64_t xc; | 166 | uint64_t xc; | |
167 | 167 | |||
168 | x86_disable_intr(); | 168 | x86_disable_intr(); | |
169 | x86_cpu_idle_set(native_idle, native_idle_text); | 169 | x86_cpu_idle_set(native_idle, native_idle_text); | |
170 | x86_enable_intr(); | 170 | x86_enable_intr(); | |
171 | 171 | |||
172 | /* | 172 | /* | |
173 | * Run a cross-call to ensure that all CPUs are | 173 | * Run a cross-call to ensure that all CPUs are | |
174 | * out from the ACPI idle-loop before detachment. | 174 | * out from the ACPI idle-loop before detachment. | |
175 | */ | 175 | */ | |
176 | xc = xc_broadcast(0, (xcfunc_t)nullop, NULL, NULL); | 176 | xc = xc_broadcast(0, (xcfunc_t)nullop, NULL, NULL); | |
177 | xc_wait(xc); | 177 | xc_wait(xc); | |
178 | 178 | |||
179 | return 0; | 179 | return 0; | |
180 | } | 180 | } | |
181 | 181 | |||
182 | /* | 182 | /* | |
183 | * The MD idle loop. Called with interrupts disabled. | 183 | * The MD idle loop. Called with interrupts disabled. | |
184 | */ | 184 | */ | |
185 | void | 185 | void | |
186 | acpicpu_md_idle_enter(int method, int state) | 186 | acpicpu_md_idle_enter(int method, int state) | |
187 | { | 187 | { | |
188 | struct cpu_info *ci = curcpu(); | 188 | struct cpu_info *ci = curcpu(); | |
189 | 189 | |||
190 | switch (method) { | 190 | switch (method) { | |
191 | 191 | |||
192 | case ACPICPU_C_STATE_FFH: | 192 | case ACPICPU_C_STATE_FFH: | |
193 | 193 | |||
194 | x86_enable_intr(); | 194 | x86_enable_intr(); | |
195 | x86_monitor(&ci->ci_want_resched, 0, 0); | 195 | x86_monitor(&ci->ci_want_resched, 0, 0); | |
196 | 196 | |||
197 | if (__predict_false(ci->ci_want_resched) != 0) | 197 | if (__predict_false(ci->ci_want_resched) != 0) | |
198 | return; | 198 | return; | |
199 | 199 | |||
200 | x86_mwait((state - 1) << 4, 0); | 200 | x86_mwait((state - 1) << 4, 0); | |
201 | break; | 201 | break; | |
202 | 202 | |||
203 | case ACPICPU_C_STATE_HALT: | 203 | case ACPICPU_C_STATE_HALT: | |
204 | 204 | |||
205 | if (__predict_false(ci->ci_want_resched) != 0) { | 205 | if (__predict_false(ci->ci_want_resched) != 0) { | |
206 | x86_enable_intr(); | 206 | x86_enable_intr(); | |
207 | return; | 207 | return; | |
208 | } | 208 | } | |
209 | 209 | |||
210 | x86_stihlt(); | 210 | x86_stihlt(); | |
211 | break; | 211 | break; | |
212 | } | 212 | } | |
213 | } | 213 | } | |
214 | 214 | |||
215 | int | 215 | int | |
216 | acpicpu_md_pstate_start(void) | 216 | acpicpu_md_pstate_start(void) | |
217 | { | 217 | { | |
218 | 218 | |||
219 | switch (cpu_vendor) { | 219 | cpu_freq_sysctl_get = acpicpu_md_pstate_sysctl_get; | |
220 | 220 | cpu_freq_sysctl_set = acpicpu_md_pstate_sysctl_set; | ||
221 | case CPUVENDOR_INTEL: | 221 | cpu_freq_sysctl_all = acpicpu_md_pstate_sysctl_all; | |
222 | est_sysctl_get = acpicpu_md_pstate_sysctl_get; | |||
223 | est_sysctl_set = acpicpu_md_pstate_sysctl_set; | |||
224 | est_sysctl_all = acpicpu_md_pstate_sysctl_all; | |||
225 | break; | |||
226 | ||||
227 | default: | |||
228 | return ENODEV; | |||
229 | } | |||
230 | 222 | |||
231 | return 0; | 223 | return 0; | |
232 | } | 224 | } | |
233 | 225 | |||
234 | int | 226 | int | |
235 | acpicpu_md_pstate_stop(void) | 227 | acpicpu_md_pstate_stop(void) | |
236 | { | 228 | { | |
237 | 229 | |||
238 | switch (cpu_vendor) { | 230 | cpu_freq_sysctl_get = NULL; | |
239 | 231 | cpu_freq_sysctl_set = NULL; | ||
240 | case CPUVENDOR_INTEL: | 232 | cpu_freq_sysctl_all = NULL; | |
241 | est_sysctl_get = NULL; | |||
242 | est_sysctl_set = NULL; | |||
243 | est_sysctl_all = NULL; | |||
244 | break; | |||
245 | ||||
246 | default: | |||
247 | return ENODEV; | |||
248 | } | |||
249 | 233 | |||
250 | return 0; | 234 | return 0; | |
251 | } | 235 | } | |
252 | 236 | |||
253 | static int | 237 | static int | |
254 | acpicpu_md_pstate_sysctl_get(SYSCTLFN_ARGS) | 238 | acpicpu_md_pstate_sysctl_get(SYSCTLFN_ARGS) | |
255 | { | 239 | { | |
256 | struct cpu_info *ci = curcpu(); | 240 | struct cpu_info *ci = curcpu(); | |
257 | struct acpicpu_softc *sc; | 241 | struct acpicpu_softc *sc; | |
258 | struct sysctlnode node; | 242 | struct sysctlnode node; | |
259 | uint32_t freq; | 243 | uint32_t freq; | |
260 | int err; | 244 | int err; | |
261 | 245 | |||
262 | /* | 246 | /* | |
263 | * We can use any ACPI CPU to manipulate the | 247 | * We can use any ACPI CPU to manipulate the | |
264 | * frequencies. In MP environments all CPUs | 248 | * frequencies. In MP environments all CPUs | |
265 | * are mandated to support the same number of | 249 | * are mandated to support the same number of | |
266 | * P-states and each state must have identical | 250 | * P-states and each state must have identical | |
267 | * parameters across CPUs. | 251 | * parameters across CPUs. | |
268 | */ | 252 | */ | |
269 | sc = acpicpu_sc[ci->ci_acpiid]; | 253 | sc = acpicpu_sc[ci->ci_acpiid]; | |
270 | 254 | |||
271 | if (sc == NULL) | 255 | if (sc == NULL) | |
272 | return ENXIO; | 256 | return ENXIO; | |
273 | 257 | |||
274 | err = acpicpu_pstate_get(sc, &freq); | 258 | err = acpicpu_pstate_get(sc, &freq); | |
275 | 259 | |||
276 | if (err != 0) | 260 | if (err != 0) | |
277 | return err; | 261 | return err; | |
278 | 262 | |||
279 | node = *rnode; | 263 | node = *rnode; | |
280 | node.sysctl_data = &freq; | 264 | node.sysctl_data = &freq; | |
281 | 265 | |||
282 | err = sysctl_lookup(SYSCTLFN_CALL(&node)); | 266 | err = sysctl_lookup(SYSCTLFN_CALL(&node)); | |
283 | 267 | |||
284 | if (err != 0 || newp == NULL) | 268 | if (err != 0 || newp == NULL) | |
285 | return err; | 269 | return err; | |
286 | 270 | |||
287 | return 0; | 271 | return 0; | |
288 | } | 272 | } | |
289 | 273 | |||
290 | static int | 274 | static int | |
291 | acpicpu_md_pstate_sysctl_set(SYSCTLFN_ARGS) | 275 | acpicpu_md_pstate_sysctl_set(SYSCTLFN_ARGS) | |
292 | { | 276 | { | |
293 | struct cpu_info *ci = curcpu(); | 277 | struct cpu_info *ci = curcpu(); | |
294 | struct acpicpu_softc *sc; | 278 | struct acpicpu_softc *sc; | |
295 | struct sysctlnode node; | 279 | struct sysctlnode node; | |
296 | uint32_t freq; | 280 | uint32_t freq; | |
297 | int err; | 281 | int err; | |
298 | 282 | |||
299 | sc = acpicpu_sc[ci->ci_acpiid]; | 283 | sc = acpicpu_sc[ci->ci_acpiid]; | |
300 | 284 | |||
301 | if (sc == NULL) | 285 | if (sc == NULL) | |
302 | return ENXIO; | 286 | return ENXIO; | |
303 | 287 | |||
304 | err = acpicpu_pstate_get(sc, &freq); | 288 | err = acpicpu_pstate_get(sc, &freq); | |
305 | 289 | |||
306 | if (err != 0) | 290 | if (err != 0) | |
307 | return err; | 291 | return err; | |
308 | 292 | |||
309 | node = *rnode; | 293 | node = *rnode; | |
310 | node.sysctl_data = &freq; | 294 | node.sysctl_data = &freq; | |
311 | 295 | |||
312 | err = sysctl_lookup(SYSCTLFN_CALL(&node)); | 296 | err = sysctl_lookup(SYSCTLFN_CALL(&node)); | |
313 | 297 | |||
314 | if (err != 0 || newp == NULL) | 298 | if (err != 0 || newp == NULL) | |
315 | return err; | 299 | return err; | |
316 | 300 | |||
317 | err = acpicpu_pstate_set(sc, freq); | 301 | err = acpicpu_pstate_set(sc, freq); | |
318 | 302 | |||
319 | if (err != 0) | 303 | if (err != 0) | |
320 | return err; | 304 | return err; | |
321 | 305 | |||
322 | return 0; | 306 | return 0; | |
323 | } | 307 | } | |
324 | 308 | |||
325 | static int | 309 | static int | |
326 | acpicpu_md_pstate_sysctl_all(SYSCTLFN_ARGS) | 310 | acpicpu_md_pstate_sysctl_all(SYSCTLFN_ARGS) | |
327 | { | 311 | { | |
328 | struct cpu_info *ci = curcpu(); | 312 | struct cpu_info *ci = curcpu(); | |
329 | struct acpicpu_softc *sc; | 313 | struct acpicpu_softc *sc; | |
330 | struct sysctlnode node; | 314 | struct sysctlnode node; | |
331 | char buf[1024]; | 315 | char buf[1024]; | |
332 | size_t len; | 316 | size_t len; | |
333 | uint32_t i; | 317 | uint32_t i; | |
334 | int err; | 318 | int err; | |
335 | 319 | |||
336 | sc = acpicpu_sc[ci->ci_acpiid]; | 320 | sc = acpicpu_sc[ci->ci_acpiid]; | |
337 | 321 | |||
338 | if (sc == NULL) | 322 | if (sc == NULL) | |
339 | return ENXIO; | 323 | return ENXIO; | |
340 | 324 | |||
341 | (void)memset(&buf, 0, sizeof(buf)); | 325 | (void)memset(&buf, 0, sizeof(buf)); | |
342 | 326 | |||
343 | mutex_enter(&sc->sc_mtx); | 327 | mutex_enter(&sc->sc_mtx); | |
344 | 328 | |||
345 | for (len = 0, i = sc->sc_pstate_max; i < sc->sc_pstate_count; i++) { | 329 | for (len = 0, i = sc->sc_pstate_max; i < sc->sc_pstate_count; i++) { | |
346 | 330 | |||
347 | if (sc->sc_pstate[i].ps_freq == 0) | 331 | if (sc->sc_pstate[i].ps_freq == 0) | |
348 | continue; | 332 | continue; | |
349 | 333 | |||
350 | len += snprintf(buf + len, sizeof(buf) - len, "%u%s", | 334 | len += snprintf(buf + len, sizeof(buf) - len, "%u%s", | |
351 | sc->sc_pstate[i].ps_freq, | 335 | sc->sc_pstate[i].ps_freq, | |
352 | i < (sc->sc_pstate_count - 1) ? " " : ""); | 336 | i < (sc->sc_pstate_count - 1) ? " " : ""); | |
353 | } | 337 | } | |
354 | 338 | |||
355 | mutex_exit(&sc->sc_mtx); | 339 | mutex_exit(&sc->sc_mtx); | |
356 | 340 | |||
357 | node = *rnode; | 341 | node = *rnode; | |
358 | node.sysctl_data = buf; | 342 | node.sysctl_data = buf; | |
359 | 343 | |||
360 | err = sysctl_lookup(SYSCTLFN_CALL(&node)); | 344 | err = sysctl_lookup(SYSCTLFN_CALL(&node)); | |
361 | 345 | |||
362 | if (err != 0 || newp == NULL) | 346 | if (err != 0 || newp == NULL) | |
363 | return err; | 347 | return err; | |
364 | 348 | |||
365 | return 0; | 349 | return 0; | |
366 | } | 350 | } | |
367 | 351 | |||
368 | int | 352 | int | |
369 | acpicpu_md_pstate_get(struct acpicpu_softc *sc, uint32_t *freq) | 353 | acpicpu_md_pstate_get(struct acpicpu_softc *sc, uint32_t *freq) | |
370 | { | 354 | { | |
371 | struct acpicpu_pstate *ps; | 355 | struct acpicpu_pstate *ps; | |
372 | uint64_t val; | 356 | uint64_t val; | |
373 | uint32_t i; | 357 | uint32_t i; | |
374 | 358 | |||
375 | switch (cpu_vendor) { | 359 | switch (cpu_vendor) { | |
376 | 360 | |||
377 | case CPUVENDOR_INTEL: | 361 | case CPUVENDOR_INTEL: | |
378 | 362 | |||
379 | val = rdmsr(MSR_PERF_STATUS); | 363 | val = rdmsr(MSR_PERF_STATUS); | |
380 | val = val & 0xffff; | 364 | val = val & 0xffff; | |
381 | 365 | |||
382 | mutex_enter(&sc->sc_mtx); | 366 | mutex_enter(&sc->sc_mtx); | |
383 | 367 | |||
384 | for (i = sc->sc_pstate_max; i < sc->sc_pstate_count; i++) { | 368 | for (i = sc->sc_pstate_max; i < sc->sc_pstate_count; i++) { | |
385 | 369 | |||
386 | ps = &sc->sc_pstate[i]; | 370 | ps = &sc->sc_pstate[i]; | |
387 | 371 | |||
388 | if (ps->ps_freq == 0) | 372 | if (ps->ps_freq == 0) | |
389 | continue; | 373 | continue; | |
390 | 374 | |||
391 | if (val == ps->ps_status) { | 375 | if (val == ps->ps_status) { | |
392 | mutex_exit(&sc->sc_mtx); | 376 | mutex_exit(&sc->sc_mtx); | |
393 | *freq = ps->ps_freq; | 377 | *freq = ps->ps_freq; | |
394 | return 0; | 378 | return 0; | |
395 | } | 379 | } | |
396 | } | 380 | } | |
397 | 381 | |||
398 | mutex_exit(&sc->sc_mtx); | 382 | mutex_exit(&sc->sc_mtx); | |
399 | 383 | |||
400 | return EIO; | 384 | return EIO; | |
401 | 385 | |||
402 | default: | 386 | default: | |
403 | return ENODEV; | 387 | return ENODEV; | |
404 | } | 388 | } | |
405 | 389 | |||
406 | return 0; | 390 | return 0; | |
407 | } | 391 | } | |
408 | 392 | |||
409 | int | 393 | int | |
410 | acpicpu_md_pstate_set(struct acpicpu_pstate *ps) | 394 | acpicpu_md_pstate_set(struct acpicpu_pstate *ps) | |
411 | { | 395 | { | |
412 | struct msr_rw_info msr; | 396 | struct msr_rw_info msr; | |
413 | uint64_t xc, val; | 397 | uint64_t xc, val; | |
414 | int i; | 398 | int i; | |
415 | 399 | |||
416 | switch (cpu_vendor) { | 400 | switch (cpu_vendor) { | |
417 | 401 | |||
418 | case CPUVENDOR_INTEL: | 402 | case CPUVENDOR_INTEL: | |
419 | msr.msr_read = true; | 403 | msr.msr_read = true; | |
420 | msr.msr_type = MSR_PERF_CTL; | 404 | msr.msr_type = MSR_PERF_CTL; | |
421 | msr.msr_value = ps->ps_control; | 405 | msr.msr_value = ps->ps_control; | |
422 | msr.msr_mask = 0xffffULL; | 406 | msr.msr_mask = 0xffffULL; | |
423 | break; | 407 | break; | |
424 | 408 | |||
425 | default: | 409 | default: | |
426 | return ENODEV; | 410 | return ENODEV; | |
427 | } | 411 | } | |
428 | 412 | |||
429 | xc = xc_broadcast(0, (xcfunc_t)x86_msr_xcall, &msr, NULL); | 413 | xc = xc_broadcast(0, (xcfunc_t)x86_msr_xcall, &msr, NULL); | |
430 | xc_wait(xc); | 414 | xc_wait(xc); | |
431 | 415 | |||
432 | for (i = val = 0; i < ACPICPU_P_STATE_RETRY; i++) { | 416 | for (i = val = 0; i < ACPICPU_P_STATE_RETRY; i++) { | |
433 | 417 | |||
434 | val = rdmsr(MSR_PERF_STATUS); | 418 | val = rdmsr(MSR_PERF_STATUS); | |
435 | val = val & 0xffff; | 419 | val = val & 0xffff; | |
436 | 420 | |||
437 | if (val == ps->ps_status) | 421 | if (val == ps->ps_status) | |
438 | return 0; | 422 | return 0; | |
439 | 423 | |||
440 | DELAY(ps->ps_latency); | 424 | DELAY(ps->ps_latency); | |
441 | } | 425 | } | |
442 | 426 | |||
443 | return EAGAIN; | 427 | return EAGAIN; | |
444 | } | 428 | } |
--- src/sys/arch/x86/include/cpuvar.h 2010/08/08 16:58:42 1.35
+++ src/sys/arch/x86/include/cpuvar.h 2010/08/09 04:18:48 1.36
@@ -1,159 +1,159 @@ | @@ -1,159 +1,159 @@ | |||
1 | /* $NetBSD: cpuvar.h,v 1.35 2010/08/08 16:58:42 jruoho Exp $ */ | 1 | /* $NetBSD: cpuvar.h,v 1.36 2010/08/09 04:18:48 jruoho Exp $ */ | |
2 | 2 | |||
3 | /*- | 3 | /*- | |
4 | * Copyright (c) 2000, 2007 The NetBSD Foundation, Inc. | 4 | * Copyright (c) 2000, 2007 The NetBSD Foundation, Inc. | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * This code is derived from software contributed to The NetBSD Foundation | 7 | * This code is derived from software contributed to The NetBSD Foundation | |
8 | * by RedBack Networks Inc. | 8 | * by RedBack Networks Inc. | |
9 | * | 9 | * | |
10 | * Author: Bill Sommerfeld | 10 | * Author: Bill Sommerfeld | |
11 | * | 11 | * | |
12 | * Redistribution and use in source and binary forms, with or without | 12 | * Redistribution and use in source and binary forms, with or without | |
13 | * modification, are permitted provided that the following conditions | 13 | * modification, are permitted provided that the following conditions | |
14 | * are met: | 14 | * are met: | |
15 | * 1. Redistributions of source code must retain the above copyright | 15 | * 1. Redistributions of source code must retain the above copyright | |
16 | * notice, this list of conditions and the following disclaimer. | 16 | * notice, this list of conditions and the following disclaimer. | |
17 | * 2. Redistributions in binary form must reproduce the above copyright | 17 | * 2. Redistributions in binary form must reproduce the above copyright | |
18 | * notice, this list of conditions and the following disclaimer in the | 18 | * notice, this list of conditions and the following disclaimer in the | |
19 | * documentation and/or other materials provided with the distribution. | 19 | * documentation and/or other materials provided with the distribution. | |
20 | * | 20 | * | |
21 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | 21 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | |
22 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | 22 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | |
23 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 23 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
24 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | 24 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | |
25 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | 25 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
26 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 26 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
27 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 27 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
28 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | 28 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
29 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 29 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
31 | * POSSIBILITY OF SUCH DAMAGE. | 31 | * POSSIBILITY OF SUCH DAMAGE. | |
32 | */ | 32 | */ | |
33 | 33 | |||
34 | /* | 34 | /* | |
35 | * Copyright (c) 1999 Stefan Grefen | 35 | * Copyright (c) 1999 Stefan Grefen | |
36 | * | 36 | * | |
37 | * Redistribution and use in source and binary forms, with or without | 37 | * Redistribution and use in source and binary forms, with or without | |
38 | * modification, are permitted provided that the following conditions | 38 | * modification, are permitted provided that the following conditions | |
39 | * are met: | 39 | * are met: | |
40 | * 1. Redistributions of source code must retain the above copyright | 40 | * 1. Redistributions of source code must retain the above copyright | |
41 | * notice, this list of conditions and the following disclaimer. | 41 | * notice, this list of conditions and the following disclaimer. | |
42 | * 2. Redistributions in binary form must reproduce the above copyright | 42 | * 2. Redistributions in binary form must reproduce the above copyright | |
43 | * notice, this list of conditions and the following disclaimer in the | 43 | * notice, this list of conditions and the following disclaimer in the | |
44 | * documentation and/or other materials provided with the distribution. | 44 | * documentation and/or other materials provided with the distribution. | |
45 | * 3. All advertising materials mentioning features or use of this software | 45 | * 3. All advertising materials mentioning features or use of this software | |
46 | * must display the following acknowledgement: | 46 | * must display the following acknowledgement: | |
47 | * This product includes software developed by the NetBSD | 47 | * This product includes software developed by the NetBSD | |
48 | * Foundation, Inc. and its contributors. | 48 | * Foundation, Inc. and its contributors. | |
49 | * 4. Neither the name of The NetBSD Foundation nor the names of its | 49 | * 4. Neither the name of The NetBSD Foundation nor the names of its | |
50 | * contributors may be used to endorse or promote products derived | 50 | * contributors may be used to endorse or promote products derived | |
51 | * from this software without specific prior written permission. | 51 | * from this software without specific prior written permission. | |
52 | * | 52 | * | |
53 | * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY | 53 | * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY | |
54 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | 54 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
55 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | 55 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
56 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR AND CONTRIBUTORS BE LIABLE | 56 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR AND CONTRIBUTORS BE LIABLE | |
57 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | 57 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
58 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | 58 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
59 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | 59 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
60 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | 60 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
61 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | 61 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
62 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | 62 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
63 | * SUCH DAMAGE. | 63 | * SUCH DAMAGE. | |
64 | */ | 64 | */ | |
65 | 65 | |||
66 | #ifndef _X86_CPUVAR_H_ | 66 | #ifndef _X86_CPUVAR_H_ | |
67 | #define _X86_CPUVAR_H_ | 67 | #define _X86_CPUVAR_H_ | |
68 | 68 | |||
69 | #include <sys/sysctl.h> | 69 | #include <sys/sysctl.h> | |
70 | 70 | |||
71 | struct cpu_functions { | 71 | struct cpu_functions { | |
72 | int (*start)(struct cpu_info *, paddr_t); | 72 | int (*start)(struct cpu_info *, paddr_t); | |
73 | int (*stop)(struct cpu_info *); | 73 | int (*stop)(struct cpu_info *); | |
74 | void (*cleanup)(struct cpu_info *); | 74 | void (*cleanup)(struct cpu_info *); | |
75 | }; | 75 | }; | |
76 | 76 | |||
77 | extern const struct cpu_functions mp_cpu_funcs; | 77 | extern const struct cpu_functions mp_cpu_funcs; | |
78 | 78 | |||
79 | #define CPU_ROLE_SP 0 | 79 | #define CPU_ROLE_SP 0 | |
80 | #define CPU_ROLE_BP 1 | 80 | #define CPU_ROLE_BP 1 | |
81 | #define CPU_ROLE_AP 2 | 81 | #define CPU_ROLE_AP 2 | |
82 | 82 | |||
83 | struct cpu_attach_args { | 83 | struct cpu_attach_args { | |
84 | int cpu_id; | 84 | int cpu_id; | |
85 | int cpu_number; | 85 | int cpu_number; | |
86 | int cpu_role; | 86 | int cpu_role; | |
87 | const struct cpu_functions *cpu_func; | 87 | const struct cpu_functions *cpu_func; | |
88 | }; | 88 | }; | |
89 | 89 | |||
90 | #ifdef _KERNEL | 90 | #ifdef _KERNEL | |
91 | 91 | |||
92 | #if defined(_KERNEL_OPT) | 92 | #if defined(_KERNEL_OPT) | |
93 | #include "opt_multiprocessor.h" | 93 | #include "opt_multiprocessor.h" | |
94 | #include "opt_enhanced_speedstep.h" | 94 | #include "opt_enhanced_speedstep.h" | |
95 | #ifndef XEN | 95 | #ifndef XEN | |
96 | #include "opt_intel_coretemp.h" | 96 | #include "opt_intel_coretemp.h" | |
97 | #include "opt_intel_odcm.h" | 97 | #include "opt_intel_odcm.h" | |
98 | #include "opt_via_c7temp.h" | 98 | #include "opt_via_c7temp.h" | |
99 | #endif | 99 | #endif | |
100 | #endif /* defined(_KERNEL_OPT) */ | 100 | #endif /* defined(_KERNEL_OPT) */ | |
101 | 101 | |||
102 | #ifdef MULTIPROCESSOR | 102 | #ifdef MULTIPROCESSOR | |
103 | extern uint32_t cpus_running; | 103 | extern uint32_t cpus_running; | |
104 | #endif | 104 | #endif | |
105 | 105 | |||
106 | int x86_ipi(int, int, int); | 106 | int x86_ipi(int, int, int); | |
107 | void x86_self_ipi(int); | 107 | void x86_self_ipi(int); | |
108 | int x86_ipi_init(int); | 108 | int x86_ipi_init(int); | |
109 | int x86_ipi_startup(int, int); | 109 | int x86_ipi_startup(int, int); | |
110 | void x86_errata(void); | 110 | void x86_errata(void); | |
111 | 111 | |||
112 | void identifycpu(struct cpu_info *); | 112 | void identifycpu(struct cpu_info *); | |
113 | void identifycpu_cpuids(struct cpu_info *); | 113 | void identifycpu_cpuids(struct cpu_info *); | |
114 | void cpu_init(struct cpu_info *); | 114 | void cpu_init(struct cpu_info *); | |
115 | void cpu_init_tss(struct cpu_info *); | 115 | void cpu_init_tss(struct cpu_info *); | |
116 | void cpu_init_first(void); | 116 | void cpu_init_first(void); | |
117 | 117 | |||
118 | void x86_cpu_idle_init(void); | 118 | void x86_cpu_idle_init(void); | |
119 | void x86_cpu_idle_halt(void); | 119 | void x86_cpu_idle_halt(void); | |
120 | void x86_cpu_idle_mwait(void); | 120 | void x86_cpu_idle_mwait(void); | |
121 | #ifdef XEN | 121 | #ifdef XEN | |
122 | void x86_cpu_idle_xen(void); | 122 | void x86_cpu_idle_xen(void); | |
123 | #endif | 123 | #endif | |
124 | 124 | |||
125 | #ifdef VIA_C7TEMP | 125 | #ifdef VIA_C7TEMP | |
126 | void viac7temp_register(struct cpu_info *); | 126 | void viac7temp_register(struct cpu_info *); | |
127 | #endif | 127 | #endif | |
128 | 128 | |||
129 | #ifdef INTEL_CORETEMP | 129 | #ifdef INTEL_CORETEMP | |
130 | void coretemp_register(struct cpu_info *); | 130 | void coretemp_register(struct cpu_info *); | |
131 | #endif | 131 | #endif | |
132 | 132 | |||
133 | #ifdef INTEL_ONDEMAND_CLOCKMOD | 133 | #ifdef INTEL_ONDEMAND_CLOCKMOD | |
134 | void clockmod_init(void); | 134 | void clockmod_init(void); | |
135 | #endif | 135 | #endif | |
136 | 136 | |||
137 | #ifdef ENHANCED_SPEEDSTEP | 137 | #ifdef ENHANCED_SPEEDSTEP | |
138 | void est_init(int); | 138 | void est_init(int); | |
139 | int via_get_bus_clock(struct cpu_info *); | 139 | int via_get_bus_clock(struct cpu_info *); | |
140 | int viac7_get_bus_clock(struct cpu_info *); | 140 | int viac7_get_bus_clock(struct cpu_info *); | |
141 | int p3_get_bus_clock(struct cpu_info *); | 141 | int p3_get_bus_clock(struct cpu_info *); | |
142 | int p4_get_bus_clock(struct cpu_info *); | 142 | int p4_get_bus_clock(struct cpu_info *); | |
143 | #endif | 143 | #endif | |
144 | 144 | |||
145 | extern int (*est_sysctl_get)(SYSCTLFN_PROTO); | 145 | extern int (*cpu_freq_sysctl_get)(SYSCTLFN_PROTO); | |
146 | extern int (*est_sysctl_set)(SYSCTLFN_PROTO); | 146 | extern int (*cpu_freq_sysctl_set)(SYSCTLFN_PROTO); | |
147 | extern int (*est_sysctl_all)(SYSCTLFN_PROTO); | 147 | extern int (*cpu_freq_sysctl_all)(SYSCTLFN_PROTO); | |
148 | 148 | |||
149 | void cpu_get_tsc_freq(struct cpu_info *); | 149 | void cpu_get_tsc_freq(struct cpu_info *); | |
150 | void pat_init(struct cpu_info *); | 150 | void pat_init(struct cpu_info *); | |
151 | 151 | |||
152 | extern int cpu_vendor; | 152 | extern int cpu_vendor; | |
153 | extern bool x86_mp_online; | 153 | extern bool x86_mp_online; | |
154 | 154 | |||
155 | extern uint32_t cpu_feature[5]; | 155 | extern uint32_t cpu_feature[5]; | |
156 | 156 | |||
157 | #endif /* _KERNEL */ | 157 | #endif /* _KERNEL */ | |
158 | 158 | |||
159 | #endif /* !_X86_CPUVAR_H_ */ | 159 | #endif /* !_X86_CPUVAR_H_ */ |
--- src/sys/arch/x86/x86/cpu.c 2010/08/04 10:02:12 1.74
+++ src/sys/arch/x86/x86/cpu.c 2010/08/09 04:18:48 1.75
@@ -1,1132 +1,1136 @@ | @@ -1,1132 +1,1136 @@ | |||
1 | /* $NetBSD: cpu.c,v 1.74 2010/08/04 10:02:12 jruoho Exp $ */ | 1 | /* $NetBSD: cpu.c,v 1.75 2010/08/09 04:18:48 jruoho Exp $ */ | |
2 | 2 | |||
3 | /*- | 3 | /*- | |
4 | * Copyright (c) 2000, 2006, 2007, 2008 The NetBSD Foundation, Inc. | 4 | * Copyright (c) 2000, 2006, 2007, 2008 The NetBSD Foundation, Inc. | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * This code is derived from software contributed to The NetBSD Foundation | 7 | * This code is derived from software contributed to The NetBSD Foundation | |
8 | * by Bill Sommerfeld of RedBack Networks Inc, and by Andrew Doran. | 8 | * by Bill Sommerfeld of RedBack Networks Inc, and by Andrew Doran. | |
9 | * | 9 | * | |
10 | * Redistribution and use in source and binary forms, with or without | 10 | * Redistribution and use in source and binary forms, with or without | |
11 | * modification, are permitted provided that the following conditions | 11 | * modification, are permitted provided that the following conditions | |
12 | * are met: | 12 | * are met: | |
13 | * 1. Redistributions of source code must retain the above copyright | 13 | * 1. Redistributions of source code must retain the above copyright | |
14 | * notice, this list of conditions and the following disclaimer. | 14 | * notice, this list of conditions and the following disclaimer. | |
15 | * 2. Redistributions in binary form must reproduce the above copyright | 15 | * 2. Redistributions in binary form must reproduce the above copyright | |
16 | * notice, this list of conditions and the following disclaimer in the | 16 | * notice, this list of conditions and the following disclaimer in the | |
17 | * documentation and/or other materials provided with the distribution. | 17 | * documentation and/or other materials provided with the distribution. | |
18 | * | 18 | * | |
19 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | 19 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | |
20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | 20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | |
21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | 22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | |
23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | 23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
29 | * POSSIBILITY OF SUCH DAMAGE. | 29 | * POSSIBILITY OF SUCH DAMAGE. | |
30 | */ | 30 | */ | |
31 | 31 | |||
32 | /* | 32 | /* | |
33 | * Copyright (c) 1999 Stefan Grefen | 33 | * Copyright (c) 1999 Stefan Grefen | |
34 | * | 34 | * | |
35 | * Redistribution and use in source and binary forms, with or without | 35 | * Redistribution and use in source and binary forms, with or without | |
36 | * modification, are permitted provided that the following conditions | 36 | * modification, are permitted provided that the following conditions | |
37 | * are met: | 37 | * are met: | |
38 | * 1. Redistributions of source code must retain the above copyright | 38 | * 1. Redistributions of source code must retain the above copyright | |
39 | * notice, this list of conditions and the following disclaimer. | 39 | * notice, this list of conditions and the following disclaimer. | |
40 | * 2. Redistributions in binary form must reproduce the above copyright | 40 | * 2. Redistributions in binary form must reproduce the above copyright | |
41 | * notice, this list of conditions and the following disclaimer in the | 41 | * notice, this list of conditions and the following disclaimer in the | |
42 | * documentation and/or other materials provided with the distribution. | 42 | * documentation and/or other materials provided with the distribution. | |
43 | * 3. All advertising materials mentioning features or use of this software | 43 | * 3. All advertising materials mentioning features or use of this software | |
44 | * must display the following acknowledgement: | 44 | * must display the following acknowledgement: | |
45 | * This product includes software developed by the NetBSD | 45 | * This product includes software developed by the NetBSD | |
46 | * Foundation, Inc. and its contributors. | 46 | * Foundation, Inc. and its contributors. | |
47 | * 4. Neither the name of The NetBSD Foundation nor the names of its | 47 | * 4. Neither the name of The NetBSD Foundation nor the names of its | |
48 | * contributors may be used to endorse or promote products derived | 48 | * contributors may be used to endorse or promote products derived | |
49 | * from this software without specific prior written permission. | 49 | * from this software without specific prior written permission. | |
50 | * | 50 | * | |
51 | * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY | 51 | * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY | |
52 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | 52 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
53 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | 53 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
54 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR AND CONTRIBUTORS BE LIABLE | 54 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR AND CONTRIBUTORS BE LIABLE | |
55 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | 55 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
56 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | 56 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
57 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | 57 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
58 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | 58 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
59 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | 59 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
60 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | 60 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
61 | * SUCH DAMAGE. | 61 | * SUCH DAMAGE. | |
62 | */ | 62 | */ | |
63 | 63 | |||
64 | #include <sys/cdefs.h> | 64 | #include <sys/cdefs.h> | |
65 | __KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.74 2010/08/04 10:02:12 jruoho Exp $"); | 65 | __KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.75 2010/08/09 04:18:48 jruoho Exp $"); | |
66 | 66 | |||
67 | #include "opt_ddb.h" | 67 | #include "opt_ddb.h" | |
68 | #include "opt_mpbios.h" /* for MPDEBUG */ | 68 | #include "opt_mpbios.h" /* for MPDEBUG */ | |
69 | #include "opt_mtrr.h" | 69 | #include "opt_mtrr.h" | |
70 | 70 | |||
71 | #include "lapic.h" | 71 | #include "lapic.h" | |
72 | #include "ioapic.h" | 72 | #include "ioapic.h" | |
73 | 73 | |||
74 | #ifdef i386 | 74 | #ifdef i386 | |
75 | #include "npx.h" | 75 | #include "npx.h" | |
76 | #endif | 76 | #endif | |
77 | 77 | |||
78 | #include <sys/param.h> | 78 | #include <sys/param.h> | |
79 | #include <sys/proc.h> | 79 | #include <sys/proc.h> | |
80 | #include <sys/systm.h> | 80 | #include <sys/systm.h> | |
81 | #include <sys/device.h> | 81 | #include <sys/device.h> | |
82 | #include <sys/kmem.h> | 82 | #include <sys/kmem.h> | |
83 | #include <sys/cpu.h> | 83 | #include <sys/cpu.h> | |
84 | #include <sys/atomic.h> | 84 | #include <sys/atomic.h> | |
85 | #include <sys/reboot.h> | 85 | #include <sys/reboot.h> | |
86 | 86 | |||
87 | #include <uvm/uvm_extern.h> | 87 | #include <uvm/uvm_extern.h> | |
88 | 88 | |||
89 | #include <machine/cpufunc.h> | 89 | #include <machine/cpufunc.h> | |
90 | #include <machine/cpuvar.h> | 90 | #include <machine/cpuvar.h> | |
91 | #include <machine/pmap.h> | 91 | #include <machine/pmap.h> | |
92 | #include <machine/vmparam.h> | 92 | #include <machine/vmparam.h> | |
93 | #include <machine/mpbiosvar.h> | 93 | #include <machine/mpbiosvar.h> | |
94 | #include <machine/pcb.h> | 94 | #include <machine/pcb.h> | |
95 | #include <machine/specialreg.h> | 95 | #include <machine/specialreg.h> | |
96 | #include <machine/segments.h> | 96 | #include <machine/segments.h> | |
97 | #include <machine/gdt.h> | 97 | #include <machine/gdt.h> | |
98 | #include <machine/mtrr.h> | 98 | #include <machine/mtrr.h> | |
99 | #include <machine/pio.h> | 99 | #include <machine/pio.h> | |
100 | #include <machine/cpu_counter.h> | 100 | #include <machine/cpu_counter.h> | |
101 | 101 | |||
102 | #ifdef i386 | 102 | #ifdef i386 | |
103 | #include <machine/tlog.h> | 103 | #include <machine/tlog.h> | |
104 | #endif | 104 | #endif | |
105 | 105 | |||
106 | #include <machine/apicvar.h> | 106 | #include <machine/apicvar.h> | |
107 | #include <machine/i82489reg.h> | 107 | #include <machine/i82489reg.h> | |
108 | #include <machine/i82489var.h> | 108 | #include <machine/i82489var.h> | |
109 | 109 | |||
110 | #include <dev/ic/mc146818reg.h> | 110 | #include <dev/ic/mc146818reg.h> | |
111 | #include <i386/isa/nvram.h> | 111 | #include <i386/isa/nvram.h> | |
112 | #include <dev/isa/isareg.h> | 112 | #include <dev/isa/isareg.h> | |
113 | 113 | |||
114 | #include "tsc.h" | 114 | #include "tsc.h" | |
115 | 115 | |||
116 | #if MAXCPUS > 32 | 116 | #if MAXCPUS > 32 | |
117 | #error cpu_info contains 32bit bitmasks | 117 | #error cpu_info contains 32bit bitmasks | |
118 | #endif | 118 | #endif | |
119 | 119 | |||
120 | int cpu_match(device_t, cfdata_t, void *); | 120 | int cpu_match(device_t, cfdata_t, void *); | |
121 | void cpu_attach(device_t, device_t, void *); | 121 | void cpu_attach(device_t, device_t, void *); | |
122 | 122 | |||
123 | static bool cpu_suspend(device_t, const pmf_qual_t *); | 123 | static bool cpu_suspend(device_t, const pmf_qual_t *); | |
124 | static bool cpu_resume(device_t, const pmf_qual_t *); | 124 | static bool cpu_resume(device_t, const pmf_qual_t *); | |
125 | 125 | |||
126 | struct cpu_softc { | 126 | struct cpu_softc { | |
127 | device_t sc_dev; /* device tree glue */ | 127 | device_t sc_dev; /* device tree glue */ | |
128 | struct cpu_info *sc_info; /* pointer to CPU info */ | 128 | struct cpu_info *sc_info; /* pointer to CPU info */ | |
129 | bool sc_wasonline; | 129 | bool sc_wasonline; | |
130 | }; | 130 | }; | |
131 | 131 | |||
132 | int mp_cpu_start(struct cpu_info *, paddr_t); | 132 | int mp_cpu_start(struct cpu_info *, paddr_t); | |
133 | void mp_cpu_start_cleanup(struct cpu_info *); | 133 | void mp_cpu_start_cleanup(struct cpu_info *); | |
134 | const struct cpu_functions mp_cpu_funcs = { mp_cpu_start, NULL, | 134 | const struct cpu_functions mp_cpu_funcs = { mp_cpu_start, NULL, | |
135 | mp_cpu_start_cleanup }; | 135 | mp_cpu_start_cleanup }; | |
136 | 136 | |||
137 | 137 | |||
138 | CFATTACH_DECL_NEW(cpu, sizeof(struct cpu_softc), | 138 | CFATTACH_DECL_NEW(cpu, sizeof(struct cpu_softc), | |
139 | cpu_match, cpu_attach, NULL, NULL); | 139 | cpu_match, cpu_attach, NULL, NULL); | |
140 | 140 | |||
141 | /* | 141 | /* | |
142 | * Statically-allocated CPU info for the primary CPU (or the only | 142 | * Statically-allocated CPU info for the primary CPU (or the only | |
143 | * CPU, on uniprocessors). The CPU info list is initialized to | 143 | * CPU, on uniprocessors). The CPU info list is initialized to | |
144 | * point at it. | 144 | * point at it. | |
145 | */ | 145 | */ | |
146 | #ifdef TRAPLOG | 146 | #ifdef TRAPLOG | |
147 | struct tlog tlog_primary; | 147 | struct tlog tlog_primary; | |
148 | #endif | 148 | #endif | |
149 | struct cpu_info cpu_info_primary __aligned(CACHE_LINE_SIZE) = { | 149 | struct cpu_info cpu_info_primary __aligned(CACHE_LINE_SIZE) = { | |
150 | .ci_dev = 0, | 150 | .ci_dev = 0, | |
151 | .ci_self = &cpu_info_primary, | 151 | .ci_self = &cpu_info_primary, | |
152 | .ci_idepth = -1, | 152 | .ci_idepth = -1, | |
153 | .ci_curlwp = &lwp0, | 153 | .ci_curlwp = &lwp0, | |
154 | .ci_curldt = -1, | 154 | .ci_curldt = -1, | |
155 | #ifdef TRAPLOG | 155 | #ifdef TRAPLOG | |
156 | .ci_tlog_base = &tlog_primary, | 156 | .ci_tlog_base = &tlog_primary, | |
157 | #endif /* !TRAPLOG */ | 157 | #endif /* !TRAPLOG */ | |
158 | }; | 158 | }; | |
159 | 159 | |||
160 | struct cpu_info *cpu_info_list = &cpu_info_primary; | 160 | struct cpu_info *cpu_info_list = &cpu_info_primary; | |
161 | 161 | |||
162 | static void cpu_set_tss_gates(struct cpu_info *); | 162 | static void cpu_set_tss_gates(struct cpu_info *); | |
163 | 163 | |||
164 | #ifdef i386 | 164 | #ifdef i386 | |
165 | static void tss_init(struct i386tss *, void *, void *); | 165 | static void tss_init(struct i386tss *, void *, void *); | |
166 | #endif | 166 | #endif | |
167 | 167 | |||
168 | static void cpu_init_idle_lwp(struct cpu_info *); | 168 | static void cpu_init_idle_lwp(struct cpu_info *); | |
169 | 169 | |||
170 | uint32_t cpus_attached = 0; | 170 | uint32_t cpus_attached = 0; | |
171 | uint32_t cpus_running = 0; | 171 | uint32_t cpus_running = 0; | |
172 | 172 | |||
173 | uint32_t cpu_feature[5]; /* X86 CPUID feature bits | 173 | uint32_t cpu_feature[5]; /* X86 CPUID feature bits | |
174 | * [0] basic features %edx | 174 | * [0] basic features %edx | |
175 | * [1] basic features %ecx | 175 | * [1] basic features %ecx | |
176 | * [2] extended features %edx | 176 | * [2] extended features %edx | |
177 | * [3] extended features %ecx | 177 | * [3] extended features %ecx | |
178 | * [4] VIA padlock features | 178 | * [4] VIA padlock features | |
179 | */ | 179 | */ | |
180 | 180 | |||
181 | extern char x86_64_doubleflt_stack[]; | 181 | extern char x86_64_doubleflt_stack[]; | |
182 | 182 | |||
183 | bool x86_mp_online; | 183 | bool x86_mp_online; | |
184 | paddr_t mp_trampoline_paddr = MP_TRAMPOLINE; | 184 | paddr_t mp_trampoline_paddr = MP_TRAMPOLINE; | |
185 | static vaddr_t cmos_data_mapping; | 185 | static vaddr_t cmos_data_mapping; | |
186 | struct cpu_info *cpu_starting; | 186 | struct cpu_info *cpu_starting; | |
187 | 187 | |||
188 | int (*cpu_freq_sysctl_get)(SYSCTLFN_PROTO) = NULL; | |||
189 | int (*cpu_freq_sysctl_set)(SYSCTLFN_PROTO) = NULL; | |||
190 | int (*cpu_freq_sysctl_all)(SYSCTLFN_PROTO) = NULL; | |||
191 | ||||
188 | void cpu_hatch(void *); | 192 | void cpu_hatch(void *); | |
189 | static void cpu_boot_secondary(struct cpu_info *ci); | 193 | static void cpu_boot_secondary(struct cpu_info *ci); | |
190 | static void cpu_start_secondary(struct cpu_info *ci); | 194 | static void cpu_start_secondary(struct cpu_info *ci); | |
191 | static void cpu_copy_trampoline(void); | 195 | static void cpu_copy_trampoline(void); | |
192 | 196 | |||
193 | /* | 197 | /* | |
194 | * Runs once per boot once multiprocessor goo has been detected and | 198 | * Runs once per boot once multiprocessor goo has been detected and | |
195 | * the local APIC on the boot processor has been mapped. | 199 | * the local APIC on the boot processor has been mapped. | |
196 | * | 200 | * | |
197 | * Called from lapic_boot_init() (from mpbios_scan()). | 201 | * Called from lapic_boot_init() (from mpbios_scan()). | |
198 | */ | 202 | */ | |
199 | void | 203 | void | |
200 | cpu_init_first(void) | 204 | cpu_init_first(void) | |
201 | { | 205 | { | |
202 | 206 | |||
203 | cpu_info_primary.ci_cpuid = lapic_cpu_number(); | 207 | cpu_info_primary.ci_cpuid = lapic_cpu_number(); | |
204 | cpu_copy_trampoline(); | 208 | cpu_copy_trampoline(); | |
205 | 209 | |||
206 | cmos_data_mapping = uvm_km_alloc(kernel_map, PAGE_SIZE, 0, UVM_KMF_VAONLY); | 210 | cmos_data_mapping = uvm_km_alloc(kernel_map, PAGE_SIZE, 0, UVM_KMF_VAONLY); | |
207 | if (cmos_data_mapping == 0) | 211 | if (cmos_data_mapping == 0) | |
208 | panic("No KVA for page 0"); | 212 | panic("No KVA for page 0"); | |
209 | pmap_kenter_pa(cmos_data_mapping, 0, VM_PROT_READ|VM_PROT_WRITE, 0); | 213 | pmap_kenter_pa(cmos_data_mapping, 0, VM_PROT_READ|VM_PROT_WRITE, 0); | |
210 | pmap_update(pmap_kernel()); | 214 | pmap_update(pmap_kernel()); | |
211 | } | 215 | } | |
212 | 216 | |||
213 | int | 217 | int | |
214 | cpu_match(device_t parent, cfdata_t match, void *aux) | 218 | cpu_match(device_t parent, cfdata_t match, void *aux) | |
215 | { | 219 | { | |
216 | 220 | |||
217 | return 1; | 221 | return 1; | |
218 | } | 222 | } | |
219 | 223 | |||
220 | static void | 224 | static void | |
221 | cpu_vm_init(struct cpu_info *ci) | 225 | cpu_vm_init(struct cpu_info *ci) | |
222 | { | 226 | { | |
223 | int ncolors = 2, i; | 227 | int ncolors = 2, i; | |
224 | 228 | |||
225 | for (i = CAI_ICACHE; i <= CAI_L2CACHE; i++) { | 229 | for (i = CAI_ICACHE; i <= CAI_L2CACHE; i++) { | |
226 | struct x86_cache_info *cai; | 230 | struct x86_cache_info *cai; | |
227 | int tcolors; | 231 | int tcolors; | |
228 | 232 | |||
229 | cai = &ci->ci_cinfo[i]; | 233 | cai = &ci->ci_cinfo[i]; | |
230 | 234 | |||
231 | tcolors = atop(cai->cai_totalsize); | 235 | tcolors = atop(cai->cai_totalsize); | |
232 | switch(cai->cai_associativity) { | 236 | switch(cai->cai_associativity) { | |
233 | case 0xff: | 237 | case 0xff: | |
234 | tcolors = 1; /* fully associative */ | 238 | tcolors = 1; /* fully associative */ | |
235 | break; | 239 | break; | |
236 | case 0: | 240 | case 0: | |
237 | case 1: | 241 | case 1: | |
238 | break; | 242 | break; | |
239 | default: | 243 | default: | |
240 | tcolors /= cai->cai_associativity; | 244 | tcolors /= cai->cai_associativity; | |
241 | } | 245 | } | |
242 | ncolors = max(ncolors, tcolors); | 246 | ncolors = max(ncolors, tcolors); | |
243 | /* | 247 | /* | |
244 | * If the desired number of colors is not a power of | 248 | * If the desired number of colors is not a power of | |
245 | * two, it won't be good. Find the greatest power of | 249 | * two, it won't be good. Find the greatest power of | |
246 | * two which is an even divisor of the number of colors, | 250 | * two which is an even divisor of the number of colors, | |
247 | * to preserve even coloring of pages. | 251 | * to preserve even coloring of pages. | |
248 | */ | 252 | */ | |
249 | if (ncolors & (ncolors - 1) ) { | 253 | if (ncolors & (ncolors - 1) ) { | |
250 | int try, picked = 1; | 254 | int try, picked = 1; | |
251 | for (try = 1; try < ncolors; try *= 2) { | 255 | for (try = 1; try < ncolors; try *= 2) { | |
252 | if (ncolors % try == 0) picked = try; | 256 | if (ncolors % try == 0) picked = try; | |
253 | } | 257 | } | |
254 | if (picked == 1) { | 258 | if (picked == 1) { | |
255 | panic("desired number of cache colors %d is " | 259 | panic("desired number of cache colors %d is " | |
256 | " > 1, but not even!", ncolors); | 260 | " > 1, but not even!", ncolors); | |
257 | } | 261 | } | |
258 | ncolors = picked; | 262 | ncolors = picked; | |
259 | } | 263 | } | |
260 | } | 264 | } | |
261 | 265 | |||
262 | /* | 266 | /* | |
263 | * Knowing the size of the largest cache on this CPU, re-color | 267 | * Knowing the size of the largest cache on this CPU, re-color | |
264 | * our pages. | 268 | * our pages. | |
265 | */ | 269 | */ | |
266 | if (ncolors <= uvmexp.ncolors) | 270 | if (ncolors <= uvmexp.ncolors) | |
267 | return; | 271 | return; | |
268 | aprint_debug_dev(ci->ci_dev, "%d page colors\n", ncolors); | 272 | aprint_debug_dev(ci->ci_dev, "%d page colors\n", ncolors); | |
269 | uvm_page_recolor(ncolors); | 273 | uvm_page_recolor(ncolors); | |
270 | } | 274 | } | |
271 | 275 | |||
272 | 276 | |||
273 | void | 277 | void | |
274 | cpu_attach(device_t parent, device_t self, void *aux) | 278 | cpu_attach(device_t parent, device_t self, void *aux) | |
275 | { | 279 | { | |
276 | struct cpu_softc *sc = device_private(self); | 280 | struct cpu_softc *sc = device_private(self); | |
277 | struct cpu_attach_args *caa = aux; | 281 | struct cpu_attach_args *caa = aux; | |
278 | struct cpu_info *ci; | 282 | struct cpu_info *ci; | |
279 | uintptr_t ptr; | 283 | uintptr_t ptr; | |
280 | int cpunum = caa->cpu_number; | 284 | int cpunum = caa->cpu_number; | |
281 | static bool again; | 285 | static bool again; | |
282 | 286 | |||
283 | sc->sc_dev = self; | 287 | sc->sc_dev = self; | |
284 | 288 | |||
285 | if (cpus_attached == ~0) { | 289 | if (cpus_attached == ~0) { | |
286 | aprint_error(": increase MAXCPUS\n"); | 290 | aprint_error(": increase MAXCPUS\n"); | |
287 | return; | 291 | return; | |
288 | } | 292 | } | |
289 | 293 | |||
290 | /* | 294 | /* | |
291 | * If we're an Application Processor, allocate a cpu_info | 295 | * If we're an Application Processor, allocate a cpu_info | |
292 | * structure, otherwise use the primary's. | 296 | * structure, otherwise use the primary's. | |
293 | */ | 297 | */ | |
294 | if (caa->cpu_role == CPU_ROLE_AP) { | 298 | if (caa->cpu_role == CPU_ROLE_AP) { | |
295 | if ((boothowto & RB_MD1) != 0) { | 299 | if ((boothowto & RB_MD1) != 0) { | |
296 | aprint_error(": multiprocessor boot disabled\n"); | 300 | aprint_error(": multiprocessor boot disabled\n"); | |
297 | if (!pmf_device_register(self, NULL, NULL)) | 301 | if (!pmf_device_register(self, NULL, NULL)) | |
298 | aprint_error_dev(self, | 302 | aprint_error_dev(self, | |
299 | "couldn't establish power handler\n"); | 303 | "couldn't establish power handler\n"); | |
300 | return; | 304 | return; | |
301 | } | 305 | } | |
302 | aprint_naive(": Application Processor\n"); | 306 | aprint_naive(": Application Processor\n"); | |
303 | ptr = (uintptr_t)kmem_zalloc(sizeof(*ci) + CACHE_LINE_SIZE - 1, | 307 | ptr = (uintptr_t)kmem_zalloc(sizeof(*ci) + CACHE_LINE_SIZE - 1, | |
304 | KM_SLEEP); | 308 | KM_SLEEP); | |
305 | ci = (struct cpu_info *)roundup2(ptr, CACHE_LINE_SIZE); | 309 | ci = (struct cpu_info *)roundup2(ptr, CACHE_LINE_SIZE); | |
306 | ci->ci_curldt = -1; | 310 | ci->ci_curldt = -1; | |
307 | #ifdef TRAPLOG | 311 | #ifdef TRAPLOG | |
308 | ci->ci_tlog_base = kmem_zalloc(sizeof(struct tlog), KM_SLEEP); | 312 | ci->ci_tlog_base = kmem_zalloc(sizeof(struct tlog), KM_SLEEP); | |
309 | #endif | 313 | #endif | |
310 | } else { | 314 | } else { | |
311 | aprint_naive(": %s Processor\n", | 315 | aprint_naive(": %s Processor\n", | |
312 | caa->cpu_role == CPU_ROLE_SP ? "Single" : "Boot"); | 316 | caa->cpu_role == CPU_ROLE_SP ? "Single" : "Boot"); | |
313 | ci = &cpu_info_primary; | 317 | ci = &cpu_info_primary; | |
314 | if (cpunum != lapic_cpu_number()) { | 318 | if (cpunum != lapic_cpu_number()) { | |
315 | /* XXX should be done earlier. */ | 319 | /* XXX should be done earlier. */ | |
316 | uint32_t reg; | 320 | uint32_t reg; | |
317 | aprint_verbose("\n"); | 321 | aprint_verbose("\n"); | |
318 | aprint_verbose_dev(self, "running CPU at apic %d" | 322 | aprint_verbose_dev(self, "running CPU at apic %d" | |
319 | " instead of at expected %d", lapic_cpu_number(), | 323 | " instead of at expected %d", lapic_cpu_number(), | |
320 | cpunum); | 324 | cpunum); | |
321 | reg = i82489_readreg(LAPIC_ID); | 325 | reg = i82489_readreg(LAPIC_ID); | |
322 | i82489_writereg(LAPIC_ID, (reg & ~LAPIC_ID_MASK) | | 326 | i82489_writereg(LAPIC_ID, (reg & ~LAPIC_ID_MASK) | | |
323 | (cpunum << LAPIC_ID_SHIFT)); | 327 | (cpunum << LAPIC_ID_SHIFT)); | |
324 | } | 328 | } | |
325 | if (cpunum != lapic_cpu_number()) { | 329 | if (cpunum != lapic_cpu_number()) { | |
326 | aprint_error_dev(self, "unable to reset apic id\n"); | 330 | aprint_error_dev(self, "unable to reset apic id\n"); | |
327 | } | 331 | } | |
328 | } | 332 | } | |
329 | 333 | |||
330 | ci->ci_self = ci; | 334 | ci->ci_self = ci; | |
331 | sc->sc_info = ci; | 335 | sc->sc_info = ci; | |
332 | ci->ci_dev = self; | 336 | ci->ci_dev = self; | |
333 | ci->ci_acpiid = caa->cpu_id; | 337 | ci->ci_acpiid = caa->cpu_id; | |
334 | ci->ci_cpuid = caa->cpu_number; | 338 | ci->ci_cpuid = caa->cpu_number; | |
335 | ci->ci_func = caa->cpu_func; | 339 | ci->ci_func = caa->cpu_func; | |
336 | 340 | |||
337 | /* Must be before mi_cpu_attach(). */ | 341 | /* Must be before mi_cpu_attach(). */ | |
338 | cpu_vm_init(ci); | 342 | cpu_vm_init(ci); | |
339 | 343 | |||
340 | if (caa->cpu_role == CPU_ROLE_AP) { | 344 | if (caa->cpu_role == CPU_ROLE_AP) { | |
341 | int error; | 345 | int error; | |
342 | 346 | |||
343 | error = mi_cpu_attach(ci); | 347 | error = mi_cpu_attach(ci); | |
344 | if (error != 0) { | 348 | if (error != 0) { | |
345 | aprint_normal("\n"); | 349 | aprint_normal("\n"); | |
346 | aprint_error_dev(self, | 350 | aprint_error_dev(self, | |
347 | "mi_cpu_attach failed with %d\n", error); | 351 | "mi_cpu_attach failed with %d\n", error); | |
348 | return; | 352 | return; | |
349 | } | 353 | } | |
350 | cpu_init_tss(ci); | 354 | cpu_init_tss(ci); | |
351 | } else { | 355 | } else { | |
352 | KASSERT(ci->ci_data.cpu_idlelwp != NULL); | 356 | KASSERT(ci->ci_data.cpu_idlelwp != NULL); | |
353 | } | 357 | } | |
354 | 358 | |||
355 | ci->ci_cpumask = (1 << cpu_index(ci)); | 359 | ci->ci_cpumask = (1 << cpu_index(ci)); | |
356 | pmap_reference(pmap_kernel()); | 360 | pmap_reference(pmap_kernel()); | |
357 | ci->ci_pmap = pmap_kernel(); | 361 | ci->ci_pmap = pmap_kernel(); | |
358 | ci->ci_tlbstate = TLBSTATE_STALE; | 362 | ci->ci_tlbstate = TLBSTATE_STALE; | |
359 | 363 | |||
360 | /* | 364 | /* | |
361 | * Boot processor may not be attached first, but the below | 365 | * Boot processor may not be attached first, but the below | |
362 | * must be done to allow booting other processors. | 366 | * must be done to allow booting other processors. | |
363 | */ | 367 | */ | |
364 | if (!again) { | 368 | if (!again) { | |
365 | atomic_or_32(&ci->ci_flags, CPUF_PRESENT | CPUF_PRIMARY); | 369 | atomic_or_32(&ci->ci_flags, CPUF_PRESENT | CPUF_PRIMARY); | |
366 | /* Basic init. */ | 370 | /* Basic init. */ | |
367 | cpu_intr_init(ci); | 371 | cpu_intr_init(ci); | |
368 | cpu_get_tsc_freq(ci); | 372 | cpu_get_tsc_freq(ci); | |
369 | cpu_init(ci); | 373 | cpu_init(ci); | |
370 | cpu_set_tss_gates(ci); | 374 | cpu_set_tss_gates(ci); | |
371 | pmap_cpu_init_late(ci); | 375 | pmap_cpu_init_late(ci); | |
372 | if (caa->cpu_role != CPU_ROLE_SP) { | 376 | if (caa->cpu_role != CPU_ROLE_SP) { | |
373 | /* Enable lapic. */ | 377 | /* Enable lapic. */ | |
374 | lapic_enable(); | 378 | lapic_enable(); | |
375 | lapic_set_lvt(); | 379 | lapic_set_lvt(); | |
376 | lapic_calibrate_timer(ci); | 380 | lapic_calibrate_timer(ci); | |
377 | } | 381 | } | |
378 | /* Make sure DELAY() is initialized. */ | 382 | /* Make sure DELAY() is initialized. */ | |
379 | DELAY(1); | 383 | DELAY(1); | |
380 | again = true; | 384 | again = true; | |
381 | } | 385 | } | |
382 | 386 | |||
383 | /* further PCB init done later. */ | 387 | /* further PCB init done later. */ | |
384 | 388 | |||
385 | switch (caa->cpu_role) { | 389 | switch (caa->cpu_role) { | |
386 | case CPU_ROLE_SP: | 390 | case CPU_ROLE_SP: | |
387 | atomic_or_32(&ci->ci_flags, CPUF_SP); | 391 | atomic_or_32(&ci->ci_flags, CPUF_SP); | |
388 | cpu_identify(ci); | 392 | cpu_identify(ci); | |
389 | x86_errata(); | 393 | x86_errata(); | |
390 | x86_cpu_idle_init(); | 394 | x86_cpu_idle_init(); | |
391 | break; | 395 | break; | |
392 | 396 | |||
393 | case CPU_ROLE_BP: | 397 | case CPU_ROLE_BP: | |
394 | atomic_or_32(&ci->ci_flags, CPUF_BSP); | 398 | atomic_or_32(&ci->ci_flags, CPUF_BSP); | |
395 | cpu_identify(ci); | 399 | cpu_identify(ci); | |
396 | x86_errata(); | 400 | x86_errata(); | |
397 | x86_cpu_idle_init(); | 401 | x86_cpu_idle_init(); | |
398 | break; | 402 | break; | |
399 | 403 | |||
400 | case CPU_ROLE_AP: | 404 | case CPU_ROLE_AP: | |
401 | /* | 405 | /* | |
402 | * report on an AP | 406 | * report on an AP | |
403 | */ | 407 | */ | |
404 | cpu_intr_init(ci); | 408 | cpu_intr_init(ci); | |
405 | gdt_alloc_cpu(ci); | 409 | gdt_alloc_cpu(ci); | |
406 | cpu_set_tss_gates(ci); | 410 | cpu_set_tss_gates(ci); | |
407 | pmap_cpu_init_early(ci); | 411 | pmap_cpu_init_early(ci); | |
408 | pmap_cpu_init_late(ci); | 412 | pmap_cpu_init_late(ci); | |
409 | cpu_start_secondary(ci); | 413 | cpu_start_secondary(ci); | |
410 | if (ci->ci_flags & CPUF_PRESENT) { | 414 | if (ci->ci_flags & CPUF_PRESENT) { | |
411 | struct cpu_info *tmp; | 415 | struct cpu_info *tmp; | |
412 | 416 | |||
413 | cpu_identify(ci); | 417 | cpu_identify(ci); | |
414 | tmp = cpu_info_list; | 418 | tmp = cpu_info_list; | |
415 | while (tmp->ci_next) | 419 | while (tmp->ci_next) | |
416 | tmp = tmp->ci_next; | 420 | tmp = tmp->ci_next; | |
417 | 421 | |||
418 | tmp->ci_next = ci; | 422 | tmp->ci_next = ci; | |
419 | } | 423 | } | |
420 | break; | 424 | break; | |
421 | 425 | |||
422 | default: | 426 | default: | |
423 | aprint_normal("\n"); | 427 | aprint_normal("\n"); | |
424 | panic("unknown processor type??\n"); | 428 | panic("unknown processor type??\n"); | |
425 | } | 429 | } | |
426 | 430 | |||
427 | pat_init(ci); | 431 | pat_init(ci); | |
428 | atomic_or_32(&cpus_attached, ci->ci_cpumask); | 432 | atomic_or_32(&cpus_attached, ci->ci_cpumask); | |
429 | 433 | |||
430 | if (!pmf_device_register(self, cpu_suspend, cpu_resume)) | 434 | if (!pmf_device_register(self, cpu_suspend, cpu_resume)) | |
431 | aprint_error_dev(self, "couldn't establish power handler\n"); | 435 | aprint_error_dev(self, "couldn't establish power handler\n"); | |
432 | 436 | |||
433 | if (mp_verbose) { | 437 | if (mp_verbose) { | |
434 | struct lwp *l = ci->ci_data.cpu_idlelwp; | 438 | struct lwp *l = ci->ci_data.cpu_idlelwp; | |
435 | struct pcb *pcb = lwp_getpcb(l); | 439 | struct pcb *pcb = lwp_getpcb(l); | |
436 | 440 | |||
437 | aprint_verbose_dev(self, | 441 | aprint_verbose_dev(self, | |
438 | "idle lwp at %p, idle sp at %p\n", | 442 | "idle lwp at %p, idle sp at %p\n", | |
439 | l, | 443 | l, | |
440 | #ifdef i386 | 444 | #ifdef i386 | |
441 | (void *)pcb->pcb_esp | 445 | (void *)pcb->pcb_esp | |
442 | #else | 446 | #else | |
443 | (void *)pcb->pcb_rsp | 447 | (void *)pcb->pcb_rsp | |
444 | #endif | 448 | #endif | |
445 | ); | 449 | ); | |
446 | } | 450 | } | |
447 | } | 451 | } | |
448 | 452 | |||
449 | /* | 453 | /* | |
450 | * Initialize the processor appropriately. | 454 | * Initialize the processor appropriately. | |
451 | */ | 455 | */ | |
452 | 456 | |||
453 | void | 457 | void | |
454 | cpu_init(struct cpu_info *ci) | 458 | cpu_init(struct cpu_info *ci) | |
455 | { | 459 | { | |
456 | 460 | |||
457 | lcr0(rcr0() | CR0_WP); | 461 | lcr0(rcr0() | CR0_WP); | |
458 | 462 | |||
459 | /* | 463 | /* | |
460 | * On a P6 or above, enable global TLB caching if the | 464 | * On a P6 or above, enable global TLB caching if the | |
461 | * hardware supports it. | 465 | * hardware supports it. | |
462 | */ | 466 | */ | |
463 | if (cpu_feature[0] & CPUID_PGE) | 467 | if (cpu_feature[0] & CPUID_PGE) | |
464 | lcr4(rcr4() | CR4_PGE); /* enable global TLB caching */ | 468 | lcr4(rcr4() | CR4_PGE); /* enable global TLB caching */ | |
465 | 469 | |||
466 | /* | 470 | /* | |
467 | * If we have FXSAVE/FXRESTOR, use them. | 471 | * If we have FXSAVE/FXRESTOR, use them. | |
468 | */ | 472 | */ | |
469 | if (cpu_feature[0] & CPUID_FXSR) { | 473 | if (cpu_feature[0] & CPUID_FXSR) { | |
470 | lcr4(rcr4() | CR4_OSFXSR); | 474 | lcr4(rcr4() | CR4_OSFXSR); | |
471 | 475 | |||
472 | /* | 476 | /* | |
473 | * If we have SSE/SSE2, enable XMM exceptions. | 477 | * If we have SSE/SSE2, enable XMM exceptions. | |
474 | */ | 478 | */ | |
475 | if (cpu_feature[0] & (CPUID_SSE|CPUID_SSE2)) | 479 | if (cpu_feature[0] & (CPUID_SSE|CPUID_SSE2)) | |
476 | lcr4(rcr4() | CR4_OSXMMEXCPT); | 480 | lcr4(rcr4() | CR4_OSXMMEXCPT); | |
477 | } | 481 | } | |
478 | 482 | |||
479 | #ifdef MTRR | 483 | #ifdef MTRR | |
480 | /* | 484 | /* | |
481 | * On a P6 or above, initialize MTRR's if the hardware supports them. | 485 | * On a P6 or above, initialize MTRR's if the hardware supports them. | |
482 | */ | 486 | */ | |
483 | if (cpu_feature[0] & CPUID_MTRR) { | 487 | if (cpu_feature[0] & CPUID_MTRR) { | |
484 | if ((ci->ci_flags & CPUF_AP) == 0) | 488 | if ((ci->ci_flags & CPUF_AP) == 0) | |
485 | i686_mtrr_init_first(); | 489 | i686_mtrr_init_first(); | |
486 | mtrr_init_cpu(ci); | 490 | mtrr_init_cpu(ci); | |
487 | } | 491 | } | |
488 | 492 | |||
489 | #ifdef i386 | 493 | #ifdef i386 | |
490 | if (strcmp((char *)(ci->ci_vendor), "AuthenticAMD") == 0) { | 494 | if (strcmp((char *)(ci->ci_vendor), "AuthenticAMD") == 0) { | |
491 | /* | 495 | /* | |
492 | * Must be a K6-2 Step >= 7 or a K6-III. | 496 | * Must be a K6-2 Step >= 7 or a K6-III. | |
493 | */ | 497 | */ | |
494 | if (CPUID2FAMILY(ci->ci_signature) == 5) { | 498 | if (CPUID2FAMILY(ci->ci_signature) == 5) { | |
495 | if (CPUID2MODEL(ci->ci_signature) > 8 || | 499 | if (CPUID2MODEL(ci->ci_signature) > 8 || | |
496 | (CPUID2MODEL(ci->ci_signature) == 8 && | 500 | (CPUID2MODEL(ci->ci_signature) == 8 && | |
497 | CPUID2STEPPING(ci->ci_signature) >= 7)) { | 501 | CPUID2STEPPING(ci->ci_signature) >= 7)) { | |
498 | mtrr_funcs = &k6_mtrr_funcs; | 502 | mtrr_funcs = &k6_mtrr_funcs; | |
499 | k6_mtrr_init_first(); | 503 | k6_mtrr_init_first(); | |
500 | mtrr_init_cpu(ci); | 504 | mtrr_init_cpu(ci); | |
501 | } | 505 | } | |
502 | } | 506 | } | |
503 | } | 507 | } | |
504 | #endif /* i386 */ | 508 | #endif /* i386 */ | |
505 | #endif /* MTRR */ | 509 | #endif /* MTRR */ | |
506 | 510 | |||
507 | atomic_or_32(&cpus_running, ci->ci_cpumask); | 511 | atomic_or_32(&cpus_running, ci->ci_cpumask); | |
508 | 512 | |||
509 | if (ci != &cpu_info_primary) { | 513 | if (ci != &cpu_info_primary) { | |
510 | /* Synchronize TSC again, and check for drift. */ | 514 | /* Synchronize TSC again, and check for drift. */ | |
511 | wbinvd(); | 515 | wbinvd(); | |
512 | atomic_or_32(&ci->ci_flags, CPUF_RUNNING); | 516 | atomic_or_32(&ci->ci_flags, CPUF_RUNNING); | |
513 | tsc_sync_ap(ci); | 517 | tsc_sync_ap(ci); | |
514 | } else { | 518 | } else { | |
515 | atomic_or_32(&ci->ci_flags, CPUF_RUNNING); | 519 | atomic_or_32(&ci->ci_flags, CPUF_RUNNING); | |
516 | } | 520 | } | |
517 | } | 521 | } | |
518 | 522 | |||
519 | void | 523 | void | |
520 | cpu_boot_secondary_processors(void) | 524 | cpu_boot_secondary_processors(void) | |
521 | { | 525 | { | |
522 | struct cpu_info *ci; | 526 | struct cpu_info *ci; | |
523 | u_long i; | 527 | u_long i; | |
524 | 528 | |||
525 | /* Now that we know the number of CPUs, patch the text segment. */ | 529 | /* Now that we know the number of CPUs, patch the text segment. */ | |
526 | x86_patch(false); | 530 | x86_patch(false); | |
527 | 531 | |||
528 | for (i=0; i < maxcpus; i++) { | 532 | for (i=0; i < maxcpus; i++) { | |
529 | ci = cpu_lookup(i); | 533 | ci = cpu_lookup(i); | |
530 | if (ci == NULL) | 534 | if (ci == NULL) | |
531 | continue; | 535 | continue; | |
532 | if (ci->ci_data.cpu_idlelwp == NULL) | 536 | if (ci->ci_data.cpu_idlelwp == NULL) | |
533 | continue; | 537 | continue; | |
534 | if ((ci->ci_flags & CPUF_PRESENT) == 0) | 538 | if ((ci->ci_flags & CPUF_PRESENT) == 0) | |
535 | continue; | 539 | continue; | |
536 | if (ci->ci_flags & (CPUF_BSP|CPUF_SP|CPUF_PRIMARY)) | 540 | if (ci->ci_flags & (CPUF_BSP|CPUF_SP|CPUF_PRIMARY)) | |
537 | continue; | 541 | continue; | |
538 | cpu_boot_secondary(ci); | 542 | cpu_boot_secondary(ci); | |
539 | } | 543 | } | |
540 | 544 | |||
541 | x86_mp_online = true; | 545 | x86_mp_online = true; | |
542 | 546 | |||
543 | /* Now that we know about the TSC, attach the timecounter. */ | 547 | /* Now that we know about the TSC, attach the timecounter. */ | |
544 | tsc_tc_init(); | 548 | tsc_tc_init(); | |
545 | 549 | |||
546 | /* Enable zeroing of pages in the idle loop if we have SSE2. */ | 550 | /* Enable zeroing of pages in the idle loop if we have SSE2. */ | |
547 | vm_page_zero_enable = ((cpu_feature[0] & CPUID_SSE2) != 0); | 551 | vm_page_zero_enable = ((cpu_feature[0] & CPUID_SSE2) != 0); | |
548 | } | 552 | } | |
549 | 553 | |||
550 | static void | 554 | static void | |
551 | cpu_init_idle_lwp(struct cpu_info *ci) | 555 | cpu_init_idle_lwp(struct cpu_info *ci) | |
552 | { | 556 | { | |
553 | struct lwp *l = ci->ci_data.cpu_idlelwp; | 557 | struct lwp *l = ci->ci_data.cpu_idlelwp; | |
554 | struct pcb *pcb = lwp_getpcb(l); | 558 | struct pcb *pcb = lwp_getpcb(l); | |
555 | 559 | |||
556 | pcb->pcb_cr0 = rcr0(); | 560 | pcb->pcb_cr0 = rcr0(); | |
557 | } | 561 | } | |
558 | 562 | |||
559 | void | 563 | void | |
560 | cpu_init_idle_lwps(void) | 564 | cpu_init_idle_lwps(void) | |
561 | { | 565 | { | |
562 | struct cpu_info *ci; | 566 | struct cpu_info *ci; | |
563 | u_long i; | 567 | u_long i; | |
564 | 568 | |||
565 | for (i = 0; i < maxcpus; i++) { | 569 | for (i = 0; i < maxcpus; i++) { | |
566 | ci = cpu_lookup(i); | 570 | ci = cpu_lookup(i); | |
567 | if (ci == NULL) | 571 | if (ci == NULL) | |
568 | continue; | 572 | continue; | |
569 | if (ci->ci_data.cpu_idlelwp == NULL) | 573 | if (ci->ci_data.cpu_idlelwp == NULL) | |
570 | continue; | 574 | continue; | |
571 | if ((ci->ci_flags & CPUF_PRESENT) == 0) | 575 | if ((ci->ci_flags & CPUF_PRESENT) == 0) | |
572 | continue; | 576 | continue; | |
573 | cpu_init_idle_lwp(ci); | 577 | cpu_init_idle_lwp(ci); | |
574 | } | 578 | } | |
575 | } | 579 | } | |
576 | 580 | |||
577 | void | 581 | void | |
578 | cpu_start_secondary(struct cpu_info *ci) | 582 | cpu_start_secondary(struct cpu_info *ci) | |
579 | { | 583 | { | |
580 | extern paddr_t mp_pdirpa; | 584 | extern paddr_t mp_pdirpa; | |
581 | u_long psl; | 585 | u_long psl; | |
582 | int i; | 586 | int i; | |
583 | 587 | |||
584 | mp_pdirpa = pmap_init_tmp_pgtbl(mp_trampoline_paddr); | 588 | mp_pdirpa = pmap_init_tmp_pgtbl(mp_trampoline_paddr); | |
585 | atomic_or_32(&ci->ci_flags, CPUF_AP); | 589 | atomic_or_32(&ci->ci_flags, CPUF_AP); | |
586 | ci->ci_curlwp = ci->ci_data.cpu_idlelwp; | 590 | ci->ci_curlwp = ci->ci_data.cpu_idlelwp; | |
587 | if (CPU_STARTUP(ci, mp_trampoline_paddr) != 0) { | 591 | if (CPU_STARTUP(ci, mp_trampoline_paddr) != 0) { | |
588 | return; | 592 | return; | |
589 | } | 593 | } | |
590 | 594 | |||
591 | /* | 595 | /* | |
592 | * Wait for it to become ready. Setting cpu_starting opens the | 596 | * Wait for it to become ready. Setting cpu_starting opens the | |
593 | * initial gate and allows the AP to start soft initialization. | 597 | * initial gate and allows the AP to start soft initialization. | |
594 | */ | 598 | */ | |
595 | KASSERT(cpu_starting == NULL); | 599 | KASSERT(cpu_starting == NULL); | |
596 | cpu_starting = ci; | 600 | cpu_starting = ci; | |
597 | for (i = 100000; (!(ci->ci_flags & CPUF_PRESENT)) && i > 0; i--) { | 601 | for (i = 100000; (!(ci->ci_flags & CPUF_PRESENT)) && i > 0; i--) { | |
598 | #ifdef MPDEBUG | 602 | #ifdef MPDEBUG | |
599 | extern int cpu_trace[3]; | 603 | extern int cpu_trace[3]; | |
600 | static int otrace[3]; | 604 | static int otrace[3]; | |
601 | if (memcmp(otrace, cpu_trace, sizeof(otrace)) != 0) { | 605 | if (memcmp(otrace, cpu_trace, sizeof(otrace)) != 0) { | |
602 | aprint_debug_dev(ci->ci_dev, "trace %02x %02x %02x\n", | 606 | aprint_debug_dev(ci->ci_dev, "trace %02x %02x %02x\n", | |
603 | cpu_trace[0], cpu_trace[1], cpu_trace[2]); | 607 | cpu_trace[0], cpu_trace[1], cpu_trace[2]); | |
604 | memcpy(otrace, cpu_trace, sizeof(otrace)); | 608 | memcpy(otrace, cpu_trace, sizeof(otrace)); | |
605 | } | 609 | } | |
606 | #endif | 610 | #endif | |
607 | i8254_delay(10); | 611 | i8254_delay(10); | |
608 | } | 612 | } | |
609 | 613 | |||
610 | if ((ci->ci_flags & CPUF_PRESENT) == 0) { | 614 | if ((ci->ci_flags & CPUF_PRESENT) == 0) { | |
611 | aprint_error_dev(ci->ci_dev, "failed to become ready\n"); | 615 | aprint_error_dev(ci->ci_dev, "failed to become ready\n"); | |
612 | #if defined(MPDEBUG) && defined(DDB) | 616 | #if defined(MPDEBUG) && defined(DDB) | |
613 | printf("dropping into debugger; continue from here to resume boot\n"); | 617 | printf("dropping into debugger; continue from here to resume boot\n"); | |
614 | Debugger(); | 618 | Debugger(); | |
615 | #endif | 619 | #endif | |
616 | } else { | 620 | } else { | |
617 | /* | 621 | /* | |
618 | * Synchronize time stamp counters. Invalidate cache and do | 622 | * Synchronize time stamp counters. Invalidate cache and do | |
619 | * twice to try and minimize possible cache effects. Disable | 623 | * twice to try and minimize possible cache effects. Disable | |
620 | * interrupts to try and rule out any external interference. | 624 | * interrupts to try and rule out any external interference. | |
621 | */ | 625 | */ | |
622 | psl = x86_read_psl(); | 626 | psl = x86_read_psl(); | |
623 | x86_disable_intr(); | 627 | x86_disable_intr(); | |
624 | wbinvd(); | 628 | wbinvd(); | |
625 | tsc_sync_bp(ci); | 629 | tsc_sync_bp(ci); | |
626 | x86_write_psl(psl); | 630 | x86_write_psl(psl); | |
627 | } | 631 | } | |
628 | 632 | |||
629 | CPU_START_CLEANUP(ci); | 633 | CPU_START_CLEANUP(ci); | |
630 | cpu_starting = NULL; | 634 | cpu_starting = NULL; | |
631 | } | 635 | } | |
632 | 636 | |||
633 | void | 637 | void | |
634 | cpu_boot_secondary(struct cpu_info *ci) | 638 | cpu_boot_secondary(struct cpu_info *ci) | |
635 | { | 639 | { | |
636 | int64_t drift; | 640 | int64_t drift; | |
637 | u_long psl; | 641 | u_long psl; | |
638 | int i; | 642 | int i; | |
639 | 643 | |||
640 | atomic_or_32(&ci->ci_flags, CPUF_GO); | 644 | atomic_or_32(&ci->ci_flags, CPUF_GO); | |
641 | for (i = 100000; (!(ci->ci_flags & CPUF_RUNNING)) && i > 0; i--) { | 645 | for (i = 100000; (!(ci->ci_flags & CPUF_RUNNING)) && i > 0; i--) { | |
642 | i8254_delay(10); | 646 | i8254_delay(10); | |
643 | } | 647 | } | |
644 | if ((ci->ci_flags & CPUF_RUNNING) == 0) { | 648 | if ((ci->ci_flags & CPUF_RUNNING) == 0) { | |
645 | aprint_error_dev(ci->ci_dev, "failed to start\n"); | 649 | aprint_error_dev(ci->ci_dev, "failed to start\n"); | |
646 | #if defined(MPDEBUG) && defined(DDB) | 650 | #if defined(MPDEBUG) && defined(DDB) | |
647 | printf("dropping into debugger; continue from here to resume boot\n"); | 651 | printf("dropping into debugger; continue from here to resume boot\n"); | |
648 | Debugger(); | 652 | Debugger(); | |
649 | #endif | 653 | #endif | |
650 | } else { | 654 | } else { | |
651 | /* Synchronize TSC again, check for drift. */ | 655 | /* Synchronize TSC again, check for drift. */ | |
652 | drift = ci->ci_data.cpu_cc_skew; | 656 | drift = ci->ci_data.cpu_cc_skew; | |
653 | psl = x86_read_psl(); | 657 | psl = x86_read_psl(); | |
654 | x86_disable_intr(); | 658 | x86_disable_intr(); | |
655 | wbinvd(); | 659 | wbinvd(); | |
656 | tsc_sync_bp(ci); | 660 | tsc_sync_bp(ci); | |
657 | x86_write_psl(psl); | 661 | x86_write_psl(psl); | |
658 | drift -= ci->ci_data.cpu_cc_skew; | 662 | drift -= ci->ci_data.cpu_cc_skew; | |
659 | aprint_debug_dev(ci->ci_dev, "TSC skew=%lld drift=%lld\n", | 663 | aprint_debug_dev(ci->ci_dev, "TSC skew=%lld drift=%lld\n", | |
660 | (long long)ci->ci_data.cpu_cc_skew, (long long)drift); | 664 | (long long)ci->ci_data.cpu_cc_skew, (long long)drift); | |
661 | tsc_sync_drift(drift); | 665 | tsc_sync_drift(drift); | |
662 | } | 666 | } | |
663 | } | 667 | } | |
664 | 668 | |||
665 | /* | 669 | /* | |
666 | * The CPU ends up here when its ready to run | 670 | * The CPU ends up here when its ready to run | |
667 | * This is called from code in mptramp.s; at this point, we are running | 671 | * This is called from code in mptramp.s; at this point, we are running | |
668 | * in the idle pcb/idle stack of the new CPU. When this function returns, | 672 | * in the idle pcb/idle stack of the new CPU. When this function returns, | |
669 | * this processor will enter the idle loop and start looking for work. | 673 | * this processor will enter the idle loop and start looking for work. | |
670 | */ | 674 | */ | |
671 | void | 675 | void | |
672 | cpu_hatch(void *v) | 676 | cpu_hatch(void *v) | |
673 | { | 677 | { | |
674 | struct cpu_info *ci = (struct cpu_info *)v; | 678 | struct cpu_info *ci = (struct cpu_info *)v; | |
675 | struct pcb *pcb; | 679 | struct pcb *pcb; | |
676 | int s, i; | 680 | int s, i; | |
677 | 681 | |||
678 | cpu_init_msrs(ci, true); | 682 | cpu_init_msrs(ci, true); | |
679 | cpu_probe(ci); | 683 | cpu_probe(ci); | |
680 | 684 | |||
681 | ci->ci_data.cpu_cc_freq = cpu_info_primary.ci_data.cpu_cc_freq; | 685 | ci->ci_data.cpu_cc_freq = cpu_info_primary.ci_data.cpu_cc_freq; | |
682 | /* cpu_get_tsc_freq(ci); */ | 686 | /* cpu_get_tsc_freq(ci); */ | |
683 | 687 | |||
684 | KDASSERT((ci->ci_flags & CPUF_PRESENT) == 0); | 688 | KDASSERT((ci->ci_flags & CPUF_PRESENT) == 0); | |
685 | 689 | |||
686 | /* | 690 | /* | |
687 | * Synchronize time stamp counters. Invalidate cache and do twice | 691 | * Synchronize time stamp counters. Invalidate cache and do twice | |
688 | * to try and minimize possible cache effects. Note that interrupts | 692 | * to try and minimize possible cache effects. Note that interrupts | |
689 | * are off at this point. | 693 | * are off at this point. | |
690 | */ | 694 | */ | |
691 | wbinvd(); | 695 | wbinvd(); | |
692 | atomic_or_32(&ci->ci_flags, CPUF_PRESENT); | 696 | atomic_or_32(&ci->ci_flags, CPUF_PRESENT); | |
693 | tsc_sync_ap(ci); | 697 | tsc_sync_ap(ci); | |
694 | 698 | |||
695 | /* | 699 | /* | |
696 | * Wait to be brought online. Use 'monitor/mwait' if available, | 700 | * Wait to be brought online. Use 'monitor/mwait' if available, | |
697 | * in order to make the TSC drift as much as possible. so that | 701 | * in order to make the TSC drift as much as possible. so that | |
698 | * we can detect it later. If not available, try 'pause'. | 702 | * we can detect it later. If not available, try 'pause'. | |
699 | * We'd like to use 'hlt', but we have interrupts off. | 703 | * We'd like to use 'hlt', but we have interrupts off. | |
700 | */ | 704 | */ | |
701 | while ((ci->ci_flags & CPUF_GO) == 0) { | 705 | while ((ci->ci_flags & CPUF_GO) == 0) { | |
702 | if ((cpu_feature[1] & CPUID2_MONITOR) != 0) { | 706 | if ((cpu_feature[1] & CPUID2_MONITOR) != 0) { | |
703 | x86_monitor(&ci->ci_flags, 0, 0); | 707 | x86_monitor(&ci->ci_flags, 0, 0); | |
704 | if ((ci->ci_flags & CPUF_GO) != 0) { | 708 | if ((ci->ci_flags & CPUF_GO) != 0) { | |
705 | continue; | 709 | continue; | |
706 | } | 710 | } | |
707 | x86_mwait(0, 0); | 711 | x86_mwait(0, 0); | |
708 | } else { | 712 | } else { | |
709 | for (i = 10000; i != 0; i--) { | 713 | for (i = 10000; i != 0; i--) { | |
710 | x86_pause(); | 714 | x86_pause(); | |
711 | } | 715 | } | |
712 | } | 716 | } | |
713 | } | 717 | } | |
714 | 718 | |||
715 | /* Because the text may have been patched in x86_patch(). */ | 719 | /* Because the text may have been patched in x86_patch(). */ | |
716 | wbinvd(); | 720 | wbinvd(); | |
717 | x86_flush(); | 721 | x86_flush(); | |
718 | 722 | |||
719 | KASSERT((ci->ci_flags & CPUF_RUNNING) == 0); | 723 | KASSERT((ci->ci_flags & CPUF_RUNNING) == 0); | |
720 | 724 | |||
721 | #ifdef PAE | 725 | #ifdef PAE | |
722 | pd_entry_t * l3_pd = ci->ci_pae_l3_pdir; | 726 | pd_entry_t * l3_pd = ci->ci_pae_l3_pdir; | |
723 | for (i = 0 ; i < PDP_SIZE; i++) { | 727 | for (i = 0 ; i < PDP_SIZE; i++) { | |
724 | l3_pd[i] = pmap_kernel()->pm_pdirpa[i] | PG_V; | 728 | l3_pd[i] = pmap_kernel()->pm_pdirpa[i] | PG_V; | |
725 | } | 729 | } | |
726 | lcr3(ci->ci_pae_l3_pdirpa); | 730 | lcr3(ci->ci_pae_l3_pdirpa); | |
727 | #else | 731 | #else | |
728 | lcr3(pmap_pdirpa(pmap_kernel(), 0)); | 732 | lcr3(pmap_pdirpa(pmap_kernel(), 0)); | |
729 | #endif | 733 | #endif | |
730 | 734 | |||
731 | pcb = lwp_getpcb(curlwp); | 735 | pcb = lwp_getpcb(curlwp); | |
732 | pcb->pcb_cr3 = rcr3(); | 736 | pcb->pcb_cr3 = rcr3(); | |
733 | pcb = lwp_getpcb(ci->ci_data.cpu_idlelwp); | 737 | pcb = lwp_getpcb(ci->ci_data.cpu_idlelwp); | |
734 | lcr0(pcb->pcb_cr0); | 738 | lcr0(pcb->pcb_cr0); | |
735 | 739 | |||
736 | cpu_init_idt(); | 740 | cpu_init_idt(); | |
737 | gdt_init_cpu(ci); | 741 | gdt_init_cpu(ci); | |
738 | lapic_enable(); | 742 | lapic_enable(); | |
739 | lapic_set_lvt(); | 743 | lapic_set_lvt(); | |
740 | lapic_initclocks(); | 744 | lapic_initclocks(); | |
741 | 745 | |||
742 | #ifdef i386 | 746 | #ifdef i386 | |
743 | #if NNPX > 0 | 747 | #if NNPX > 0 | |
744 | npxinit(ci); | 748 | npxinit(ci); | |
745 | #endif | 749 | #endif | |
746 | #else | 750 | #else | |
747 | fpuinit(ci); | 751 | fpuinit(ci); | |
748 | #endif | 752 | #endif | |
749 | lldt(GSYSSEL(GLDT_SEL, SEL_KPL)); | 753 | lldt(GSYSSEL(GLDT_SEL, SEL_KPL)); | |
750 | ltr(ci->ci_tss_sel); | 754 | ltr(ci->ci_tss_sel); | |
751 | 755 | |||
752 | cpu_init(ci); | 756 | cpu_init(ci); | |
753 | cpu_get_tsc_freq(ci); | 757 | cpu_get_tsc_freq(ci); | |
754 | 758 | |||
755 | s = splhigh(); | 759 | s = splhigh(); | |
756 | #ifdef i386 | 760 | #ifdef i386 | |
757 | lapic_tpr = 0; | 761 | lapic_tpr = 0; | |
758 | #else | 762 | #else | |
759 | lcr8(0); | 763 | lcr8(0); | |
760 | #endif | 764 | #endif | |
761 | x86_enable_intr(); | 765 | x86_enable_intr(); | |
762 | splx(s); | 766 | splx(s); | |
763 | x86_errata(); | 767 | x86_errata(); | |
764 | 768 | |||
765 | aprint_debug_dev(ci->ci_dev, "running\n"); | 769 | aprint_debug_dev(ci->ci_dev, "running\n"); | |
766 | } | 770 | } | |
767 | 771 | |||
768 | #if defined(DDB) | 772 | #if defined(DDB) | |
769 | 773 | |||
770 | #include <ddb/db_output.h> | 774 | #include <ddb/db_output.h> | |
771 | #include <machine/db_machdep.h> | 775 | #include <machine/db_machdep.h> | |
772 | 776 | |||
773 | /* | 777 | /* | |
774 | * Dump CPU information from ddb. | 778 | * Dump CPU information from ddb. | |
775 | */ | 779 | */ | |
776 | void | 780 | void | |
777 | cpu_debug_dump(void) | 781 | cpu_debug_dump(void) | |
778 | { | 782 | { | |
779 | struct cpu_info *ci; | 783 | struct cpu_info *ci; | |
780 | CPU_INFO_ITERATOR cii; | 784 | CPU_INFO_ITERATOR cii; | |
781 | 785 | |||
782 | db_printf("addr dev id flags ipis curlwp fpcurlwp\n"); | 786 | db_printf("addr dev id flags ipis curlwp fpcurlwp\n"); | |
783 | for (CPU_INFO_FOREACH(cii, ci)) { | 787 | for (CPU_INFO_FOREACH(cii, ci)) { | |
784 | db_printf("%p %s %ld %x %x %10p %10p\n", | 788 | db_printf("%p %s %ld %x %x %10p %10p\n", | |
785 | ci, | 789 | ci, | |
786 | ci->ci_dev == NULL ? "BOOT" : device_xname(ci->ci_dev), | 790 | ci->ci_dev == NULL ? "BOOT" : device_xname(ci->ci_dev), | |
787 | (long)ci->ci_cpuid, | 791 | (long)ci->ci_cpuid, | |
788 | ci->ci_flags, ci->ci_ipis, | 792 | ci->ci_flags, ci->ci_ipis, | |
789 | ci->ci_curlwp, | 793 | ci->ci_curlwp, | |
790 | ci->ci_fpcurlwp); | 794 | ci->ci_fpcurlwp); | |
791 | } | 795 | } | |
792 | } | 796 | } | |
793 | #endif | 797 | #endif | |
794 | 798 | |||
795 | static void | 799 | static void | |
796 | cpu_copy_trampoline(void) | 800 | cpu_copy_trampoline(void) | |
797 | { | 801 | { | |
798 | /* | 802 | /* | |
799 | * Copy boot code. | 803 | * Copy boot code. | |
800 | */ | 804 | */ | |
801 | extern u_char cpu_spinup_trampoline[]; | 805 | extern u_char cpu_spinup_trampoline[]; | |
802 | extern u_char cpu_spinup_trampoline_end[]; | 806 | extern u_char cpu_spinup_trampoline_end[]; | |
803 | 807 | |||
804 | vaddr_t mp_trampoline_vaddr; | 808 | vaddr_t mp_trampoline_vaddr; | |
805 | 809 | |||
806 | mp_trampoline_vaddr = uvm_km_alloc(kernel_map, PAGE_SIZE, 0, | 810 | mp_trampoline_vaddr = uvm_km_alloc(kernel_map, PAGE_SIZE, 0, | |
807 | UVM_KMF_VAONLY); | 811 | UVM_KMF_VAONLY); | |
808 | 812 | |||
809 | pmap_kenter_pa(mp_trampoline_vaddr, mp_trampoline_paddr, | 813 | pmap_kenter_pa(mp_trampoline_vaddr, mp_trampoline_paddr, | |
810 | VM_PROT_READ | VM_PROT_WRITE, 0); | 814 | VM_PROT_READ | VM_PROT_WRITE, 0); | |
811 | pmap_update(pmap_kernel()); | 815 | pmap_update(pmap_kernel()); | |
812 | memcpy((void *)mp_trampoline_vaddr, | 816 | memcpy((void *)mp_trampoline_vaddr, | |
813 | cpu_spinup_trampoline, | 817 | cpu_spinup_trampoline, | |
814 | cpu_spinup_trampoline_end - cpu_spinup_trampoline); | 818 | cpu_spinup_trampoline_end - cpu_spinup_trampoline); | |
815 | 819 | |||
816 | pmap_kremove(mp_trampoline_vaddr, PAGE_SIZE); | 820 | pmap_kremove(mp_trampoline_vaddr, PAGE_SIZE); | |
817 | pmap_update(pmap_kernel()); | 821 | pmap_update(pmap_kernel()); | |
818 | uvm_km_free(kernel_map, mp_trampoline_vaddr, PAGE_SIZE, UVM_KMF_VAONLY); | 822 | uvm_km_free(kernel_map, mp_trampoline_vaddr, PAGE_SIZE, UVM_KMF_VAONLY); | |
819 | } | 823 | } | |
820 | 824 | |||
821 | #ifdef i386 | 825 | #ifdef i386 | |
822 | static void | 826 | static void | |
823 | tss_init(struct i386tss *tss, void *stack, void *func) | 827 | tss_init(struct i386tss *tss, void *stack, void *func) | |
824 | { | 828 | { | |
825 | KASSERT(curcpu()->ci_pmap == pmap_kernel()); | 829 | KASSERT(curcpu()->ci_pmap == pmap_kernel()); | |
826 | 830 | |||
827 | memset(tss, 0, sizeof *tss); | 831 | memset(tss, 0, sizeof *tss); | |
828 | tss->tss_esp0 = tss->tss_esp = (int)((char *)stack + USPACE - 16); | 832 | tss->tss_esp0 = tss->tss_esp = (int)((char *)stack + USPACE - 16); | |
829 | tss->tss_ss0 = GSEL(GDATA_SEL, SEL_KPL); | 833 | tss->tss_ss0 = GSEL(GDATA_SEL, SEL_KPL); | |
830 | tss->__tss_cs = GSEL(GCODE_SEL, SEL_KPL); | 834 | tss->__tss_cs = GSEL(GCODE_SEL, SEL_KPL); | |
831 | tss->tss_fs = GSEL(GCPU_SEL, SEL_KPL); | 835 | tss->tss_fs = GSEL(GCPU_SEL, SEL_KPL); | |
832 | tss->tss_gs = tss->__tss_es = tss->__tss_ds = | 836 | tss->tss_gs = tss->__tss_es = tss->__tss_ds = | |
833 | tss->__tss_ss = GSEL(GDATA_SEL, SEL_KPL); | 837 | tss->__tss_ss = GSEL(GDATA_SEL, SEL_KPL); | |
834 | /* %cr3 contains the value associated to pmap_kernel */ | 838 | /* %cr3 contains the value associated to pmap_kernel */ | |
835 | tss->tss_cr3 = rcr3(); | 839 | tss->tss_cr3 = rcr3(); | |
836 | tss->tss_esp = (int)((char *)stack + USPACE - 16); | 840 | tss->tss_esp = (int)((char *)stack + USPACE - 16); | |
837 | tss->tss_ldt = GSEL(GLDT_SEL, SEL_KPL); | 841 | tss->tss_ldt = GSEL(GLDT_SEL, SEL_KPL); | |
838 | tss->__tss_eflags = PSL_MBO | PSL_NT; /* XXX not needed? */ | 842 | tss->__tss_eflags = PSL_MBO | PSL_NT; /* XXX not needed? */ | |
839 | tss->__tss_eip = (int)func; | 843 | tss->__tss_eip = (int)func; | |
840 | } | 844 | } | |
841 | 845 | |||
842 | /* XXX */ | 846 | /* XXX */ | |
843 | #define IDTVEC(name) __CONCAT(X, name) | 847 | #define IDTVEC(name) __CONCAT(X, name) | |
844 | typedef void (vector)(void); | 848 | typedef void (vector)(void); | |
845 | extern vector IDTVEC(tss_trap08); | 849 | extern vector IDTVEC(tss_trap08); | |
846 | #ifdef DDB | 850 | #ifdef DDB | |
847 | extern vector Xintrddbipi; | 851 | extern vector Xintrddbipi; | |
848 | extern int ddb_vec; | 852 | extern int ddb_vec; | |
849 | #endif | 853 | #endif | |
850 | 854 | |||
851 | static void | 855 | static void | |
852 | cpu_set_tss_gates(struct cpu_info *ci) | 856 | cpu_set_tss_gates(struct cpu_info *ci) | |
853 | { | 857 | { | |
854 | struct segment_descriptor sd; | 858 | struct segment_descriptor sd; | |
855 | 859 | |||
856 | ci->ci_doubleflt_stack = (char *)uvm_km_alloc(kernel_map, USPACE, 0, | 860 | ci->ci_doubleflt_stack = (char *)uvm_km_alloc(kernel_map, USPACE, 0, | |
857 | UVM_KMF_WIRED); | 861 | UVM_KMF_WIRED); | |
858 | tss_init(&ci->ci_doubleflt_tss, ci->ci_doubleflt_stack, | 862 | tss_init(&ci->ci_doubleflt_tss, ci->ci_doubleflt_stack, | |
859 | IDTVEC(tss_trap08)); | 863 | IDTVEC(tss_trap08)); | |
860 | setsegment(&sd, &ci->ci_doubleflt_tss, sizeof(struct i386tss) - 1, | 864 | setsegment(&sd, &ci->ci_doubleflt_tss, sizeof(struct i386tss) - 1, | |
861 | SDT_SYS386TSS, SEL_KPL, 0, 0); | 865 | SDT_SYS386TSS, SEL_KPL, 0, 0); | |
862 | ci->ci_gdt[GTRAPTSS_SEL].sd = sd; | 866 | ci->ci_gdt[GTRAPTSS_SEL].sd = sd; | |
863 | setgate(&idt[8], NULL, 0, SDT_SYSTASKGT, SEL_KPL, | 867 | setgate(&idt[8], NULL, 0, SDT_SYSTASKGT, SEL_KPL, | |
864 | GSEL(GTRAPTSS_SEL, SEL_KPL)); | 868 | GSEL(GTRAPTSS_SEL, SEL_KPL)); | |
865 | 869 | |||
866 | #if defined(DDB) | 870 | #if defined(DDB) | |
867 | /* | 871 | /* | |
868 | * Set up separate handler for the DDB IPI, so that it doesn't | 872 | * Set up separate handler for the DDB IPI, so that it doesn't | |
869 | * stomp on a possibly corrupted stack. | 873 | * stomp on a possibly corrupted stack. | |
870 | * | 874 | * | |
871 | * XXX overwriting the gate set in db_machine_init. | 875 | * XXX overwriting the gate set in db_machine_init. | |
872 | * Should rearrange the code so that it's set only once. | 876 | * Should rearrange the code so that it's set only once. | |
873 | */ | 877 | */ | |
874 | ci->ci_ddbipi_stack = (char *)uvm_km_alloc(kernel_map, USPACE, 0, | 878 | ci->ci_ddbipi_stack = (char *)uvm_km_alloc(kernel_map, USPACE, 0, | |
875 | UVM_KMF_WIRED); | 879 | UVM_KMF_WIRED); | |
876 | tss_init(&ci->ci_ddbipi_tss, ci->ci_ddbipi_stack, Xintrddbipi); | 880 | tss_init(&ci->ci_ddbipi_tss, ci->ci_ddbipi_stack, Xintrddbipi); | |
877 | 881 | |||
878 | setsegment(&sd, &ci->ci_ddbipi_tss, sizeof(struct i386tss) - 1, | 882 | setsegment(&sd, &ci->ci_ddbipi_tss, sizeof(struct i386tss) - 1, | |
879 | SDT_SYS386TSS, SEL_KPL, 0, 0); | 883 | SDT_SYS386TSS, SEL_KPL, 0, 0); | |
880 | ci->ci_gdt[GIPITSS_SEL].sd = sd; | 884 | ci->ci_gdt[GIPITSS_SEL].sd = sd; | |
881 | 885 | |||
882 | setgate(&idt[ddb_vec], NULL, 0, SDT_SYSTASKGT, SEL_KPL, | 886 | setgate(&idt[ddb_vec], NULL, 0, SDT_SYSTASKGT, SEL_KPL, | |
883 | GSEL(GIPITSS_SEL, SEL_KPL)); | 887 | GSEL(GIPITSS_SEL, SEL_KPL)); | |
884 | #endif | 888 | #endif | |
885 | } | 889 | } | |
886 | #else | 890 | #else | |
887 | static void | 891 | static void | |
888 | cpu_set_tss_gates(struct cpu_info *ci) | 892 | cpu_set_tss_gates(struct cpu_info *ci) | |
889 | { | 893 | { | |
890 | 894 | |||
891 | } | 895 | } | |
892 | #endif /* i386 */ | 896 | #endif /* i386 */ | |
893 | 897 | |||
894 | int | 898 | int | |
895 | mp_cpu_start(struct cpu_info *ci, paddr_t target) | 899 | mp_cpu_start(struct cpu_info *ci, paddr_t target) | |
896 | { | 900 | { | |
897 | unsigned short dwordptr[2]; | 901 | unsigned short dwordptr[2]; | |
898 | int error; | 902 | int error; | |
899 | 903 | |||
900 | /* | 904 | /* | |
901 | * Bootstrap code must be addressable in real mode | 905 | * Bootstrap code must be addressable in real mode | |
902 | * and it must be page aligned. | 906 | * and it must be page aligned. | |
903 | */ | 907 | */ | |
904 | KASSERT(target < 0x10000 && target % PAGE_SIZE == 0); | 908 | KASSERT(target < 0x10000 && target % PAGE_SIZE == 0); | |
905 | 909 | |||
906 | /* | 910 | /* | |
907 | * "The BSP must initialize CMOS shutdown code to 0Ah ..." | 911 | * "The BSP must initialize CMOS shutdown code to 0Ah ..." | |
908 | */ | 912 | */ | |
909 | 913 | |||
910 | outb(IO_RTC, NVRAM_RESET); | 914 | outb(IO_RTC, NVRAM_RESET); | |
911 | outb(IO_RTC+1, NVRAM_RESET_JUMP); | 915 | outb(IO_RTC+1, NVRAM_RESET_JUMP); | |
912 | 916 | |||
913 | /* | 917 | /* | |
914 | * "and the warm reset vector (DWORD based at 40:67) to point | 918 | * "and the warm reset vector (DWORD based at 40:67) to point | |
915 | * to the AP startup code ..." | 919 | * to the AP startup code ..." | |
916 | */ | 920 | */ | |
917 | 921 | |||
918 | dwordptr[0] = 0; | 922 | dwordptr[0] = 0; | |
919 | dwordptr[1] = target >> 4; | 923 | dwordptr[1] = target >> 4; | |
920 | 924 | |||
921 | memcpy((uint8_t *)cmos_data_mapping + 0x467, dwordptr, 4); | 925 | memcpy((uint8_t *)cmos_data_mapping + 0x467, dwordptr, 4); | |
922 | 926 | |||
923 | if ((cpu_feature[0] & CPUID_APIC) == 0) { | 927 | if ((cpu_feature[0] & CPUID_APIC) == 0) { | |
924 | aprint_error("mp_cpu_start: CPU does not have APIC\n"); | 928 | aprint_error("mp_cpu_start: CPU does not have APIC\n"); | |
925 | return ENODEV; | 929 | return ENODEV; | |
926 | } | 930 | } | |
927 | 931 | |||
928 | /* | 932 | /* | |
929 | * ... prior to executing the following sequence:". We'll also add in | 933 | * ... prior to executing the following sequence:". We'll also add in | |
930 | * local cache flush, in case the BIOS has left the AP with its cache | 934 | * local cache flush, in case the BIOS has left the AP with its cache | |
931 | * disabled. It may not be able to cope with MP coherency. | 935 | * disabled. It may not be able to cope with MP coherency. | |
932 | */ | 936 | */ | |
933 | wbinvd(); | 937 | wbinvd(); | |
934 | 938 | |||
935 | if (ci->ci_flags & CPUF_AP) { | 939 | if (ci->ci_flags & CPUF_AP) { | |
936 | error = x86_ipi_init(ci->ci_cpuid); | 940 | error = x86_ipi_init(ci->ci_cpuid); | |
937 | if (error != 0) { | 941 | if (error != 0) { | |
938 | aprint_error_dev(ci->ci_dev, "%s: IPI not taken (1)\n", | 942 | aprint_error_dev(ci->ci_dev, "%s: IPI not taken (1)\n", | |
939 | __func__); | 943 | __func__); | |
940 | return error; | 944 | return error; | |
941 | } | 945 | } | |
942 | i8254_delay(10000); | 946 | i8254_delay(10000); | |
943 | 947 | |||
944 | error = x86_ipi_startup(ci->ci_cpuid, target / PAGE_SIZE); | 948 | error = x86_ipi_startup(ci->ci_cpuid, target / PAGE_SIZE); | |
945 | if (error != 0) { | 949 | if (error != 0) { | |
946 | aprint_error_dev(ci->ci_dev, "%s: IPI not taken (2)\n", | 950 | aprint_error_dev(ci->ci_dev, "%s: IPI not taken (2)\n", | |
947 | __func__); | 951 | __func__); | |
948 | return error; | 952 | return error; | |
949 | } | 953 | } | |
950 | i8254_delay(200); | 954 | i8254_delay(200); | |
951 | 955 | |||
952 | error = x86_ipi_startup(ci->ci_cpuid, target / PAGE_SIZE); | 956 | error = x86_ipi_startup(ci->ci_cpuid, target / PAGE_SIZE); | |
953 | if (error != 0) { | 957 | if (error != 0) { | |
954 | aprint_error_dev(ci->ci_dev, "%s: IPI not taken (3)\n", | 958 | aprint_error_dev(ci->ci_dev, "%s: IPI not taken (3)\n", | |
955 | __func__); | 959 | __func__); | |
956 | return error; | 960 | return error; | |
957 | } | 961 | } | |
958 | i8254_delay(200); | 962 | i8254_delay(200); | |
959 | } | 963 | } | |
960 | 964 | |||
961 | return 0; | 965 | return 0; | |
962 | } | 966 | } | |
963 | 967 | |||
964 | void | 968 | void | |
965 | mp_cpu_start_cleanup(struct cpu_info *ci) | 969 | mp_cpu_start_cleanup(struct cpu_info *ci) | |
966 | { | 970 | { | |
967 | /* | 971 | /* | |
968 | * Ensure the NVRAM reset byte contains something vaguely sane. | 972 | * Ensure the NVRAM reset byte contains something vaguely sane. | |
969 | */ | 973 | */ | |
970 | 974 | |||
971 | outb(IO_RTC, NVRAM_RESET); | 975 | outb(IO_RTC, NVRAM_RESET); | |
972 | outb(IO_RTC+1, NVRAM_RESET_RST); | 976 | outb(IO_RTC+1, NVRAM_RESET_RST); | |
973 | } | 977 | } | |
974 | 978 | |||
975 | #ifdef __x86_64__ | 979 | #ifdef __x86_64__ | |
976 | typedef void (vector)(void); | 980 | typedef void (vector)(void); | |
977 | extern vector Xsyscall, Xsyscall32; | 981 | extern vector Xsyscall, Xsyscall32; | |
978 | #endif | 982 | #endif | |
979 | 983 | |||
980 | void | 984 | void | |
981 | cpu_init_msrs(struct cpu_info *ci, bool full) | 985 | cpu_init_msrs(struct cpu_info *ci, bool full) | |
982 | { | 986 | { | |
983 | #ifdef __x86_64__ | 987 | #ifdef __x86_64__ | |
984 | wrmsr(MSR_STAR, | 988 | wrmsr(MSR_STAR, | |
985 | ((uint64_t)GSEL(GCODE_SEL, SEL_KPL) << 32) | | 989 | ((uint64_t)GSEL(GCODE_SEL, SEL_KPL) << 32) | | |
986 | ((uint64_t)LSEL(LSYSRETBASE_SEL, SEL_UPL) << 48)); | 990 | ((uint64_t)LSEL(LSYSRETBASE_SEL, SEL_UPL) << 48)); | |
987 | wrmsr(MSR_LSTAR, (uint64_t)Xsyscall); | 991 | wrmsr(MSR_LSTAR, (uint64_t)Xsyscall); | |
988 | wrmsr(MSR_CSTAR, (uint64_t)Xsyscall32); | 992 | wrmsr(MSR_CSTAR, (uint64_t)Xsyscall32); | |
989 | wrmsr(MSR_SFMASK, PSL_NT|PSL_T|PSL_I|PSL_C); | 993 | wrmsr(MSR_SFMASK, PSL_NT|PSL_T|PSL_I|PSL_C); | |
990 | 994 | |||
991 | if (full) { | 995 | if (full) { | |
992 | wrmsr(MSR_FSBASE, 0); | 996 | wrmsr(MSR_FSBASE, 0); | |
993 | wrmsr(MSR_GSBASE, (uint64_t)ci); | 997 | wrmsr(MSR_GSBASE, (uint64_t)ci); | |
994 | wrmsr(MSR_KERNELGSBASE, 0); | 998 | wrmsr(MSR_KERNELGSBASE, 0); | |
995 | } | 999 | } | |
996 | #endif /* __x86_64__ */ | 1000 | #endif /* __x86_64__ */ | |
997 | 1001 | |||
998 | if (cpu_feature[2] & CPUID_NOX) | 1002 | if (cpu_feature[2] & CPUID_NOX) | |
999 | wrmsr(MSR_EFER, rdmsr(MSR_EFER) | EFER_NXE); | 1003 | wrmsr(MSR_EFER, rdmsr(MSR_EFER) | EFER_NXE); | |
1000 | } | 1004 | } | |
1001 | 1005 | |||
1002 | void | 1006 | void | |
1003 | cpu_offline_md(void) | 1007 | cpu_offline_md(void) | |
1004 | { | 1008 | { | |
1005 | int s; | 1009 | int s; | |
1006 | 1010 | |||
1007 | s = splhigh(); | 1011 | s = splhigh(); | |
1008 | #ifdef i386 | 1012 | #ifdef i386 | |
1009 | #if NNPX > 0 | 1013 | #if NNPX > 0 | |
1010 | npxsave_cpu(true); | 1014 | npxsave_cpu(true); | |
1011 | #endif | 1015 | #endif | |
1012 | #else | 1016 | #else | |
1013 | fpusave_cpu(true); | 1017 | fpusave_cpu(true); | |
1014 | #endif | 1018 | #endif | |
1015 | splx(s); | 1019 | splx(s); | |
1016 | } | 1020 | } | |
1017 | 1021 | |||
1018 | /* XXX joerg restructure and restart CPUs individually */ | 1022 | /* XXX joerg restructure and restart CPUs individually */ | |
1019 | static bool | 1023 | static bool | |
1020 | cpu_suspend(device_t dv, const pmf_qual_t *qual) | 1024 | cpu_suspend(device_t dv, const pmf_qual_t *qual) | |
1021 | { | 1025 | { | |
1022 | struct cpu_softc *sc = device_private(dv); | 1026 | struct cpu_softc *sc = device_private(dv); | |
1023 | struct cpu_info *ci = sc->sc_info; | 1027 | struct cpu_info *ci = sc->sc_info; | |
1024 | int err; | 1028 | int err; | |
1025 | 1029 | |||
1026 | if (ci->ci_flags & CPUF_PRIMARY) | 1030 | if (ci->ci_flags & CPUF_PRIMARY) | |
1027 | return true; | 1031 | return true; | |
1028 | if (ci->ci_data.cpu_idlelwp == NULL) | 1032 | if (ci->ci_data.cpu_idlelwp == NULL) | |
1029 | return true; | 1033 | return true; | |
1030 | if ((ci->ci_flags & CPUF_PRESENT) == 0) | 1034 | if ((ci->ci_flags & CPUF_PRESENT) == 0) | |
1031 | return true; | 1035 | return true; | |
1032 | 1036 | |||
1033 | sc->sc_wasonline = !(ci->ci_schedstate.spc_flags & SPCF_OFFLINE); | 1037 | sc->sc_wasonline = !(ci->ci_schedstate.spc_flags & SPCF_OFFLINE); | |
1034 | 1038 | |||
1035 | if (sc->sc_wasonline) { | 1039 | if (sc->sc_wasonline) { | |
1036 | mutex_enter(&cpu_lock); | 1040 | mutex_enter(&cpu_lock); | |
1037 | err = cpu_setstate(ci, false); | 1041 | err = cpu_setstate(ci, false); | |
1038 | mutex_exit(&cpu_lock); | 1042 | mutex_exit(&cpu_lock); | |
1039 | 1043 | |||
1040 | if (err) | 1044 | if (err) | |
1041 | return false; | 1045 | return false; | |
1042 | } | 1046 | } | |
1043 | 1047 | |||
1044 | return true; | 1048 | return true; | |
1045 | } | 1049 | } | |
1046 | 1050 | |||
1047 | static bool | 1051 | static bool | |
1048 | cpu_resume(device_t dv, const pmf_qual_t *qual) | 1052 | cpu_resume(device_t dv, const pmf_qual_t *qual) | |
1049 | { | 1053 | { | |
1050 | struct cpu_softc *sc = device_private(dv); | 1054 | struct cpu_softc *sc = device_private(dv); | |
1051 | struct cpu_info *ci = sc->sc_info; | 1055 | struct cpu_info *ci = sc->sc_info; | |
1052 | int err = 0; | 1056 | int err = 0; | |
1053 | 1057 | |||
1054 | if (ci->ci_flags & CPUF_PRIMARY) | 1058 | if (ci->ci_flags & CPUF_PRIMARY) | |
1055 | return true; | 1059 | return true; | |
1056 | if (ci->ci_data.cpu_idlelwp == NULL) | 1060 | if (ci->ci_data.cpu_idlelwp == NULL) | |
1057 | return true; | 1061 | return true; | |
1058 | if ((ci->ci_flags & CPUF_PRESENT) == 0) | 1062 | if ((ci->ci_flags & CPUF_PRESENT) == 0) | |
1059 | return true; | 1063 | return true; | |
1060 | 1064 | |||
1061 | if (sc->sc_wasonline) { | 1065 | if (sc->sc_wasonline) { | |
1062 | mutex_enter(&cpu_lock); | 1066 | mutex_enter(&cpu_lock); | |
1063 | err = cpu_setstate(ci, true); | 1067 | err = cpu_setstate(ci, true); | |
1064 | mutex_exit(&cpu_lock); | 1068 | mutex_exit(&cpu_lock); | |
1065 | } | 1069 | } | |
1066 | 1070 | |||
1067 | return err == 0; | 1071 | return err == 0; | |
1068 | } | 1072 | } | |
1069 | 1073 | |||
1070 | void | 1074 | void | |
1071 | cpu_get_tsc_freq(struct cpu_info *ci) | 1075 | cpu_get_tsc_freq(struct cpu_info *ci) | |
1072 | { | 1076 | { | |
1073 | uint64_t last_tsc; | 1077 | uint64_t last_tsc; | |
1074 | 1078 | |||
1075 | if (cpu_hascounter()) { | 1079 | if (cpu_hascounter()) { | |
1076 | last_tsc = rdmsr(MSR_TSC); | 1080 | last_tsc = rdmsr(MSR_TSC); | |
1077 | i8254_delay(100000); | 1081 | i8254_delay(100000); | |
1078 | ci->ci_data.cpu_cc_freq = (rdmsr(MSR_TSC) - last_tsc) * 10; | 1082 | ci->ci_data.cpu_cc_freq = (rdmsr(MSR_TSC) - last_tsc) * 10; | |
1079 | } | 1083 | } | |
1080 | } | 1084 | } | |
1081 | 1085 | |||
1082 | void | 1086 | void | |
1083 | x86_cpu_idle_mwait(void) | 1087 | x86_cpu_idle_mwait(void) | |
1084 | { | 1088 | { | |
1085 | struct cpu_info *ci = curcpu(); | 1089 | struct cpu_info *ci = curcpu(); | |
1086 | 1090 | |||
1087 | KASSERT(ci->ci_ilevel == IPL_NONE); | 1091 | KASSERT(ci->ci_ilevel == IPL_NONE); | |
1088 | 1092 | |||
1089 | x86_monitor(&ci->ci_want_resched, 0, 0); | 1093 | x86_monitor(&ci->ci_want_resched, 0, 0); | |
1090 | if (__predict_false(ci->ci_want_resched)) { | 1094 | if (__predict_false(ci->ci_want_resched)) { | |
1091 | return; | 1095 | return; | |
1092 | } | 1096 | } | |
1093 | x86_mwait(0, 0); | 1097 | x86_mwait(0, 0); | |
1094 | } | 1098 | } | |
1095 | 1099 | |||
1096 | void | 1100 | void | |
1097 | x86_cpu_idle_halt(void) | 1101 | x86_cpu_idle_halt(void) | |
1098 | { | 1102 | { | |
1099 | struct cpu_info *ci = curcpu(); | 1103 | struct cpu_info *ci = curcpu(); | |
1100 | 1104 | |||
1101 | KASSERT(ci->ci_ilevel == IPL_NONE); | 1105 | KASSERT(ci->ci_ilevel == IPL_NONE); | |
1102 | 1106 | |||
1103 | x86_disable_intr(); | 1107 | x86_disable_intr(); | |
1104 | if (!__predict_false(ci->ci_want_resched)) { | 1108 | if (!__predict_false(ci->ci_want_resched)) { | |
1105 | x86_stihlt(); | 1109 | x86_stihlt(); | |
1106 | } else { | 1110 | } else { | |
1107 | x86_enable_intr(); | 1111 | x86_enable_intr(); | |
1108 | } | 1112 | } | |
1109 | } | 1113 | } | |
1110 | 1114 | |||
1111 | /* | 1115 | /* | |
1112 | * Loads pmap for the current CPU. | 1116 | * Loads pmap for the current CPU. | |
1113 | */ | 1117 | */ | |
1114 | void | 1118 | void | |
1115 | cpu_load_pmap(struct pmap *pmap) | 1119 | cpu_load_pmap(struct pmap *pmap) | |
1116 | { | 1120 | { | |
1117 | #ifdef PAE | 1121 | #ifdef PAE | |
1118 | int i, s; | 1122 | int i, s; | |
1119 | struct cpu_info *ci; | 1123 | struct cpu_info *ci; | |
1120 | 1124 | |||
1121 | s = splvm(); /* just to be safe */ | 1125 | s = splvm(); /* just to be safe */ | |
1122 | ci = curcpu(); | 1126 | ci = curcpu(); | |
1123 | pd_entry_t *l3_pd = ci->ci_pae_l3_pdir; | 1127 | pd_entry_t *l3_pd = ci->ci_pae_l3_pdir; | |
1124 | for (i = 0 ; i < PDP_SIZE; i++) { | 1128 | for (i = 0 ; i < PDP_SIZE; i++) { | |
1125 | l3_pd[i] = pmap->pm_pdirpa[i] | PG_V; | 1129 | l3_pd[i] = pmap->pm_pdirpa[i] | PG_V; | |
1126 | } | 1130 | } | |
1127 | splx(s); | 1131 | splx(s); | |
1128 | tlbflush(); | 1132 | tlbflush(); | |
1129 | #else /* PAE */ | 1133 | #else /* PAE */ | |
1130 | lcr3(pmap_pdirpa(pmap, 0)); | 1134 | lcr3(pmap_pdirpa(pmap, 0)); | |
1131 | #endif /* PAE */ | 1135 | #endif /* PAE */ | |
1132 | } | 1136 | } |
--- src/sys/arch/x86/x86/est.c 2010/08/08 16:58:42 1.16
+++ src/sys/arch/x86/x86/est.c 2010/08/09 04:18:49 1.17
@@ -1,1359 +1,1355 @@ | @@ -1,1359 +1,1355 @@ | |||
1 | /* $NetBSD: est.c,v 1.16 2010/08/08 16:58:42 jruoho Exp $ */ | 1 | /* $NetBSD: est.c,v 1.17 2010/08/09 04:18:49 jruoho Exp $ */ | |
2 | /* | 2 | /* | |
3 | * Copyright (c) 2003 Michael Eriksson. | 3 | * Copyright (c) 2003 Michael Eriksson. | |
4 | * All rights reserved. | 4 | * All rights reserved. | |
5 | * | 5 | * | |
6 | * Redistribution and use in source and binary forms, with or without | 6 | * Redistribution and use in source and binary forms, with or without | |
7 | * modification, are permitted provided that the following conditions | 7 | * modification, are permitted provided that the following conditions | |
8 | * are met: | 8 | * are met: | |
9 | * 1. Redistributions of source code must retain the above copyright | 9 | * 1. Redistributions of source code must retain the above copyright | |
10 | * notice, this list of conditions and the following disclaimer. | 10 | * notice, this list of conditions and the following disclaimer. | |
11 | * 2. Redistributions in binary form must reproduce the above copyright | 11 | * 2. Redistributions in binary form must reproduce the above copyright | |
12 | * notice, this list of conditions and the following disclaimer in the | 12 | * notice, this list of conditions and the following disclaimer in the | |
13 | * documentation and/or other materials provided with the distribution. | 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 | 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. | 15 | * derived from this software without specific prior written permission. | |
16 | * | 16 | * | |
17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | 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 | 18 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |
19 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | 19 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | |
20 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | 20 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | |
21 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | 21 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | |
22 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 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 | 23 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
24 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 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 | 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. | 26 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
27 | */ | 27 | */ | |
28 | /*- | 28 | /*- | |
29 | * Copyright (c) 2004 The NetBSD Foundation, Inc. | 29 | * Copyright (c) 2004 The NetBSD Foundation, Inc. | |
30 | * All rights reserved. | 30 | * All rights reserved. | |
31 | * | 31 | * | |
32 | * Redistribution and use in source and binary forms, with or without | 32 | * Redistribution and use in source and binary forms, with or without | |
33 | * modification, are permitted provided that the following conditions | 33 | * modification, are permitted provided that the following conditions | |
34 | * are met: | 34 | * are met: | |
35 | * 1. Redistributions of source code must retain the above copyright | 35 | * 1. Redistributions of source code must retain the above copyright | |
36 | * notice, this list of conditions and the following disclaimer. | 36 | * notice, this list of conditions and the following disclaimer. | |
37 | * 2. Redistributions in binary form must reproduce the above copyright | 37 | * 2. Redistributions in binary form must reproduce the above copyright | |
38 | * notice, this list of conditions and the following disclaimer in the | 38 | * notice, this list of conditions and the following disclaimer in the | |
39 | * documentation and/or other materials provided with the distribution. | 39 | * documentation and/or other materials provided with the distribution. | |
40 | * | 40 | * | |
41 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | 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 | 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 | 43 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
44 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | 44 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | |
45 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | 45 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
46 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 46 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
47 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 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 | 48 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
49 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 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 | 50 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
51 | * POSSIBILITY OF SUCH DAMAGE. | 51 | * POSSIBILITY OF SUCH DAMAGE. | |
52 | */ | 52 | */ | |
53 | 53 | |||
54 | /* | 54 | /* | |
55 | * This is a driver for Intel's Enhanced SpeedStep Technology (EST), | 55 | * This is a driver for Intel's Enhanced SpeedStep Technology (EST), | |
56 | * as implemented in Pentium M processors. | 56 | * as implemented in Pentium M processors. | |
57 | * | 57 | * | |
58 | * Reference documentation: | 58 | * Reference documentation: | |
59 | * | 59 | * | |
60 | * - IA-32 Intel Architecture Software Developer's Manual, Volume 3: | 60 | * - IA-32 Intel Architecture Software Developer's Manual, Volume 3: | |
61 | * System Programming Guide. | 61 | * System Programming Guide. | |
62 | * Section 13.14, Enhanced Intel SpeedStep technology. | 62 | * Section 13.14, Enhanced Intel SpeedStep technology. | |
63 | * Table B-2, MSRs in Pentium M Processors. | 63 | * Table B-2, MSRs in Pentium M Processors. | |
64 | * http://www.intel.com/design/pentium4/manuals/253668.htm | 64 | * http://www.intel.com/design/pentium4/manuals/253668.htm | |
65 | * | 65 | * | |
66 | * - Intel Pentium M Processor Datasheet. | 66 | * - Intel Pentium M Processor Datasheet. | |
67 | * Table 5, Voltage and Current Specifications. | 67 | * Table 5, Voltage and Current Specifications. | |
68 | * http://www.intel.com/design/mobile/datashts/252612.htm | 68 | * http://www.intel.com/design/mobile/datashts/252612.htm | |
69 | * | 69 | * | |
70 | * - Intel Pentium M Processor on 90 nm Process with 2-MB L2 Cache Datasheet | 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. | 71 | * Table 3-4, 3-5, 3-6, Voltage and Current Specifications. | |
72 | * http://www.intel.com/design/mobile/datashts/302189.htm | 72 | * http://www.intel.com/design/mobile/datashts/302189.htm | |
73 | * | 73 | * | |
74 | * - Linux cpufreq patches, speedstep-centrino.c. | 74 | * - Linux cpufreq patches, speedstep-centrino.c. | |
75 | * Encoding of MSR_PERF_CTL and MSR_PERF_STATUS. | 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 | 76 | * http://www.codemonkey.org.uk/projects/cpufreq/cpufreq-2.4.22-pre6-1.gz | |
77 | * | 77 | * | |
78 | * ACPI objects: _PCT is MSR location, _PSS is freq/voltage, _PPC is caps. | 78 | * ACPI objects: _PCT is MSR location, _PSS is freq/voltage, _PPC is caps. | |
79 | */ | 79 | */ | |
80 | 80 | |||
81 | /* #define EST_DEBUG */ | 81 | /* #define EST_DEBUG */ | |
82 | 82 | |||
83 | #include <sys/cdefs.h> | 83 | #include <sys/cdefs.h> | |
84 | __KERNEL_RCSID(0, "$NetBSD: est.c,v 1.16 2010/08/08 16:58:42 jruoho Exp $"); | 84 | __KERNEL_RCSID(0, "$NetBSD: est.c,v 1.17 2010/08/09 04:18:49 jruoho Exp $"); | |
85 | 85 | |||
86 | #include <sys/param.h> | 86 | #include <sys/param.h> | |
87 | #include <sys/systm.h> | 87 | #include <sys/systm.h> | |
88 | #include <sys/device.h> | 88 | #include <sys/device.h> | |
89 | #include <sys/malloc.h> | 89 | #include <sys/malloc.h> | |
90 | #include <sys/sysctl.h> | 90 | #include <sys/sysctl.h> | |
91 | #include <sys/once.h> | 91 | #include <sys/once.h> | |
92 | #include <sys/xcall.h> | 92 | #include <sys/xcall.h> | |
93 | 93 | |||
94 | #include <x86/cpuvar.h> | 94 | #include <x86/cpuvar.h> | |
95 | #include <x86/cputypes.h> | 95 | #include <x86/cputypes.h> | |
96 | #include <x86/cpu_msr.h> | 96 | #include <x86/cpu_msr.h> | |
97 | 97 | |||
98 | #include <machine/cpu.h> | 98 | #include <machine/cpu.h> | |
99 | #include <machine/specialreg.h> | 99 | #include <machine/specialreg.h> | |
100 | 100 | |||
101 | #include "opt_est.h" | 101 | #include "opt_est.h" | |
102 | #ifdef EST_FREQ_USERWRITE | 102 | #ifdef EST_FREQ_USERWRITE | |
103 | #define EST_TARGET_CTLFLAG (CTLFLAG_READWRITE | CTLFLAG_ANYWRITE) | 103 | #define EST_TARGET_CTLFLAG (CTLFLAG_READWRITE | CTLFLAG_ANYWRITE) | |
104 | #else | 104 | #else | |
105 | #define EST_TARGET_CTLFLAG CTLFLAG_READWRITE | 105 | #define EST_TARGET_CTLFLAG CTLFLAG_READWRITE | |
106 | #endif | 106 | #endif | |
107 | 107 | |||
108 | /* Convert MHz and mV into IDs for passing to the MSR. */ | 108 | /* Convert MHz and mV into IDs for passing to the MSR. */ | |
109 | #define ID16(MHz, mV, bus_clk) \ | 109 | #define ID16(MHz, mV, bus_clk) \ | |
110 | ((((MHz * 100 + 50) / bus_clk) << 8) | ((mV ? mV - 700 : 0) >> 4)) | 110 | ((((MHz * 100 + 50) / bus_clk) << 8) | ((mV ? mV - 700 : 0) >> 4)) | |
111 | 111 | |||
112 | /* Possible bus speeds (multiplied by 100 for rounding) */ | 112 | /* Possible bus speeds (multiplied by 100 for rounding) */ | |
113 | enum { BUS100 = 10000, BUS133 = 13333, BUS166 = 16666, BUS200 = 20000 }; | 113 | enum { BUS100 = 10000, BUS133 = 13333, BUS166 = 16666, BUS200 = 20000 }; | |
114 | 114 | |||
115 | /* Ultra Low Voltage Intel Pentium M processor 900 MHz */ | 115 | /* Ultra Low Voltage Intel Pentium M processor 900 MHz */ | |
116 | static const uint16_t pm130_900_ulv[] = { | 116 | static const uint16_t pm130_900_ulv[] = { | |
117 | ID16( 900, 1004, BUS100), | 117 | ID16( 900, 1004, BUS100), | |
118 | ID16( 800, 988, BUS100), | 118 | ID16( 800, 988, BUS100), | |
119 | ID16( 600, 844, BUS100), | 119 | ID16( 600, 844, BUS100), | |
120 | }; | 120 | }; | |
121 | 121 | |||
122 | /* Ultra Low Voltage Intel Pentium M processor 1.00 GHz */ | 122 | /* Ultra Low Voltage Intel Pentium M processor 1.00 GHz */ | |
123 | static const uint16_t pm130_1000_ulv[] = { | 123 | static const uint16_t pm130_1000_ulv[] = { | |
124 | ID16(1000, 1004, BUS100), | 124 | ID16(1000, 1004, BUS100), | |
125 | ID16( 900, 988, BUS100), | 125 | ID16( 900, 988, BUS100), | |
126 | ID16( 800, 972, BUS100), | 126 | ID16( 800, 972, BUS100), | |
127 | ID16( 600, 844, BUS100), | 127 | ID16( 600, 844, BUS100), | |
128 | }; | 128 | }; | |
129 | 129 | |||
130 | /* Ultra Low Voltage Intel Pentium M processor 1.10 GHz */ | 130 | /* Ultra Low Voltage Intel Pentium M processor 1.10 GHz */ | |
131 | static const uint16_t pm130_1100_ulv[] = { | 131 | static const uint16_t pm130_1100_ulv[] = { | |
132 | ID16(1100, 1004, BUS100), | 132 | ID16(1100, 1004, BUS100), | |
133 | ID16(1000, 988, BUS100), | 133 | ID16(1000, 988, BUS100), | |
134 | ID16( 900, 972, BUS100), | 134 | ID16( 900, 972, BUS100), | |
135 | ID16( 800, 956, BUS100), | 135 | ID16( 800, 956, BUS100), | |
136 | ID16( 600, 844, BUS100), | 136 | ID16( 600, 844, BUS100), | |
137 | }; | 137 | }; | |
138 | 138 | |||
139 | /* Low Voltage Intel Pentium M processor 1.10 GHz */ | 139 | /* Low Voltage Intel Pentium M processor 1.10 GHz */ | |
140 | static const uint16_t pm130_1100_lv[] = { | 140 | static const uint16_t pm130_1100_lv[] = { | |
141 | ID16(1100, 1180, BUS100), | 141 | ID16(1100, 1180, BUS100), | |
142 | ID16(1000, 1164, BUS100), | 142 | ID16(1000, 1164, BUS100), | |
143 | ID16( 900, 1100, BUS100), | 143 | ID16( 900, 1100, BUS100), | |
144 | ID16( 800, 1020, BUS100), | 144 | ID16( 800, 1020, BUS100), | |
145 | ID16( 600, 956, BUS100), | 145 | ID16( 600, 956, BUS100), | |
146 | }; | 146 | }; | |
147 | 147 | |||
148 | /* Low Voltage Intel Pentium M processor 1.20 GHz */ | 148 | /* Low Voltage Intel Pentium M processor 1.20 GHz */ | |
149 | static const uint16_t pm130_1200_lv[] = { | 149 | static const uint16_t pm130_1200_lv[] = { | |
150 | ID16(1200, 1180, BUS100), | 150 | ID16(1200, 1180, BUS100), | |
151 | ID16(1100, 1164, BUS100), | 151 | ID16(1100, 1164, BUS100), | |
152 | ID16(1000, 1100, BUS100), | 152 | ID16(1000, 1100, BUS100), | |
153 | ID16( 900, 1020, BUS100), | 153 | ID16( 900, 1020, BUS100), | |
154 | ID16( 800, 1004, BUS100), | 154 | ID16( 800, 1004, BUS100), | |
155 | ID16( 600, 956, BUS100), | 155 | ID16( 600, 956, BUS100), | |
156 | }; | 156 | }; | |
157 | 157 | |||
158 | /* Low Voltage Intel Pentium M processor 1.30 GHz */ | 158 | /* Low Voltage Intel Pentium M processor 1.30 GHz */ | |
159 | static const uint16_t pm130_1300_lv[] = { | 159 | static const uint16_t pm130_1300_lv[] = { | |
160 | ID16(1300, 1180, BUS100), | 160 | ID16(1300, 1180, BUS100), | |
161 | ID16(1200, 1164, BUS100), | 161 | ID16(1200, 1164, BUS100), | |
162 | ID16(1100, 1100, BUS100), | 162 | ID16(1100, 1100, BUS100), | |
163 | ID16(1000, 1020, BUS100), | 163 | ID16(1000, 1020, BUS100), | |
164 | ID16( 900, 1004, BUS100), | 164 | ID16( 900, 1004, BUS100), | |
165 | ID16( 800, 988, BUS100), | 165 | ID16( 800, 988, BUS100), | |
166 | ID16( 600, 956, BUS100), | 166 | ID16( 600, 956, BUS100), | |
167 | }; | 167 | }; | |
168 | 168 | |||
169 | /* Intel Pentium M processor 1.30 GHz */ | 169 | /* Intel Pentium M processor 1.30 GHz */ | |
170 | static const uint16_t pm130_1300[] = { | 170 | static const uint16_t pm130_1300[] = { | |
171 | ID16(1300, 1388, BUS100), | 171 | ID16(1300, 1388, BUS100), | |
172 | ID16(1200, 1356, BUS100), | 172 | ID16(1200, 1356, BUS100), | |
173 | ID16(1000, 1292, BUS100), | 173 | ID16(1000, 1292, BUS100), | |
174 | ID16( 800, 1260, BUS100), | 174 | ID16( 800, 1260, BUS100), | |
175 | ID16( 600, 956, BUS100), | 175 | ID16( 600, 956, BUS100), | |
176 | }; | 176 | }; | |
177 | 177 | |||
178 | /* Intel Pentium M processor 1.40 GHz */ | 178 | /* Intel Pentium M processor 1.40 GHz */ | |
179 | static const uint16_t pm130_1400[] = { | 179 | static const uint16_t pm130_1400[] = { | |
180 | ID16(1400, 1484, BUS100), | 180 | ID16(1400, 1484, BUS100), | |
181 | ID16(1200, 1436, BUS100), | 181 | ID16(1200, 1436, BUS100), | |
182 | ID16(1000, 1308, BUS100), | 182 | ID16(1000, 1308, BUS100), | |
183 | ID16( 800, 1180, BUS100), | 183 | ID16( 800, 1180, BUS100), | |
184 | ID16( 600, 956, BUS100), | 184 | ID16( 600, 956, BUS100), | |
185 | }; | 185 | }; | |
186 | 186 | |||
187 | /* Intel Pentium M processor 1.50 GHz */ | 187 | /* Intel Pentium M processor 1.50 GHz */ | |
188 | static const uint16_t pm130_1500[] = { | 188 | static const uint16_t pm130_1500[] = { | |
189 | ID16(1500, 1484, BUS100), | 189 | ID16(1500, 1484, BUS100), | |
190 | ID16(1400, 1452, BUS100), | 190 | ID16(1400, 1452, BUS100), | |
191 | ID16(1200, 1356, BUS100), | 191 | ID16(1200, 1356, BUS100), | |
192 | ID16(1000, 1228, BUS100), | 192 | ID16(1000, 1228, BUS100), | |
193 | ID16( 800, 1116, BUS100), | 193 | ID16( 800, 1116, BUS100), | |
194 | ID16( 600, 956, BUS100), | 194 | ID16( 600, 956, BUS100), | |
195 | }; | 195 | }; | |
196 | 196 | |||
197 | /* Intel Pentium M processor 1.60 GHz */ | 197 | /* Intel Pentium M processor 1.60 GHz */ | |
198 | static const uint16_t pm130_1600[] = { | 198 | static const uint16_t pm130_1600[] = { | |
199 | ID16(1600, 1484, BUS100), | 199 | ID16(1600, 1484, BUS100), | |
200 | ID16(1400, 1420, BUS100), | 200 | ID16(1400, 1420, BUS100), | |
201 | ID16(1200, 1276, BUS100), | 201 | ID16(1200, 1276, BUS100), | |
202 | ID16(1000, 1164, BUS100), | 202 | ID16(1000, 1164, BUS100), | |
203 | ID16( 800, 1036, BUS100), | 203 | ID16( 800, 1036, BUS100), | |
204 | ID16( 600, 956, BUS100), | 204 | ID16( 600, 956, BUS100), | |
205 | }; | 205 | }; | |
206 | 206 | |||
207 | /* Intel Pentium M processor 1.70 GHz */ | 207 | /* Intel Pentium M processor 1.70 GHz */ | |
208 | static const uint16_t pm130_1700[] = { | 208 | static const uint16_t pm130_1700[] = { | |
209 | ID16(1700, 1484, BUS100), | 209 | ID16(1700, 1484, BUS100), | |
210 | ID16(1400, 1308, BUS100), | 210 | ID16(1400, 1308, BUS100), | |
211 | ID16(1200, 1228, BUS100), | 211 | ID16(1200, 1228, BUS100), | |
212 | ID16(1000, 1116, BUS100), | 212 | ID16(1000, 1116, BUS100), | |
213 | ID16( 800, 1004, BUS100), | 213 | ID16( 800, 1004, BUS100), | |
214 | ID16( 600, 956, BUS100), | 214 | ID16( 600, 956, BUS100), | |
215 | }; | 215 | }; | |
216 | 216 | |||
217 | /* Intel Pentium M processor 723 1.0 GHz */ | 217 | /* Intel Pentium M processor 723 1.0 GHz */ | |
218 | static const uint16_t pm90_n723[] = { | 218 | static const uint16_t pm90_n723[] = { | |
219 | ID16(1000, 940, BUS100), | 219 | ID16(1000, 940, BUS100), | |
220 | ID16( 900, 908, BUS100), | 220 | ID16( 900, 908, BUS100), | |
221 | ID16( 800, 876, BUS100), | 221 | ID16( 800, 876, BUS100), | |
222 | ID16( 600, 812, BUS100), | 222 | ID16( 600, 812, BUS100), | |
223 | }; | 223 | }; | |
224 | 224 | |||
225 | /* Intel Pentium M processor 733 1.1 GHz, VID #G */ | 225 | /* Intel Pentium M processor 733 1.1 GHz, VID #G */ | |
226 | static const uint16_t pm90_n733g[] = { | 226 | static const uint16_t pm90_n733g[] = { | |
227 | ID16(1100, 956, BUS100), | 227 | ID16(1100, 956, BUS100), | |
228 | ID16(1000, 940, BUS100), | 228 | ID16(1000, 940, BUS100), | |
229 | ID16( 900, 908, BUS100), | 229 | ID16( 900, 908, BUS100), | |
230 | ID16( 800, 876, BUS100), | 230 | ID16( 800, 876, BUS100), | |
231 | ID16( 600, 812, BUS100), | 231 | ID16( 600, 812, BUS100), | |
232 | }; | 232 | }; | |
233 | 233 | |||
234 | /* Intel Pentium M processor 733 1.1 GHz, VID #H */ | 234 | /* Intel Pentium M processor 733 1.1 GHz, VID #H */ | |
235 | static const uint16_t pm90_n733h[] = { | 235 | static const uint16_t pm90_n733h[] = { | |
236 | ID16(1100, 940, BUS100), | 236 | ID16(1100, 940, BUS100), | |
237 | ID16(1000, 924, BUS100), | 237 | ID16(1000, 924, BUS100), | |
238 | ID16( 900, 892, BUS100), | 238 | ID16( 900, 892, BUS100), | |
239 | ID16( 800, 876, BUS100), | 239 | ID16( 800, 876, BUS100), | |
240 | ID16( 600, 812, BUS100), | 240 | ID16( 600, 812, BUS100), | |
241 | }; | 241 | }; | |
242 | 242 | |||
243 | /* Intel Pentium M processor 733 1.1 GHz, VID #I */ | 243 | /* Intel Pentium M processor 733 1.1 GHz, VID #I */ | |
244 | static const uint16_t pm90_n733i[] = { | 244 | static const uint16_t pm90_n733i[] = { | |
245 | ID16(1100, 924, BUS100), | 245 | ID16(1100, 924, BUS100), | |
246 | ID16(1000, 908, BUS100), | 246 | ID16(1000, 908, BUS100), | |
247 | ID16( 900, 892, BUS100), | 247 | ID16( 900, 892, BUS100), | |
248 | ID16( 800, 860, BUS100), | 248 | ID16( 800, 860, BUS100), | |
249 | ID16( 600, 812, BUS100), | 249 | ID16( 600, 812, BUS100), | |
250 | }; | 250 | }; | |
251 | 251 | |||
252 | /* Intel Pentium M processor 733 1.1 GHz, VID #J */ | 252 | /* Intel Pentium M processor 733 1.1 GHz, VID #J */ | |
253 | static const uint16_t pm90_n733j[] = { | 253 | static const uint16_t pm90_n733j[] = { | |
254 | ID16(1100, 908, BUS100), | 254 | ID16(1100, 908, BUS100), | |
255 | ID16(1000, 892, BUS100), | 255 | ID16(1000, 892, BUS100), | |
256 | ID16( 900, 876, BUS100), | 256 | ID16( 900, 876, BUS100), | |
257 | ID16( 800, 860, BUS100), | 257 | ID16( 800, 860, BUS100), | |
258 | ID16( 600, 812, BUS100), | 258 | ID16( 600, 812, BUS100), | |
259 | }; | 259 | }; | |
260 | 260 | |||
261 | /* Intel Pentium M processor 733 1.1 GHz, VID #K */ | 261 | /* Intel Pentium M processor 733 1.1 GHz, VID #K */ | |
262 | static const uint16_t pm90_n733k[] = { | 262 | static const uint16_t pm90_n733k[] = { | |
263 | ID16(1100, 892, BUS100), | 263 | ID16(1100, 892, BUS100), | |
264 | ID16(1000, 876, BUS100), | 264 | ID16(1000, 876, BUS100), | |
265 | ID16( 900, 860, BUS100), | 265 | ID16( 900, 860, BUS100), | |
266 | ID16( 800, 844, BUS100), | 266 | ID16( 800, 844, BUS100), | |
267 | ID16( 600, 812, BUS100), | 267 | ID16( 600, 812, BUS100), | |
268 | }; | 268 | }; | |
269 | 269 | |||
270 | /* Intel Pentium M processor 733 1.1 GHz, VID #L */ | 270 | /* Intel Pentium M processor 733 1.1 GHz, VID #L */ | |
271 | static const uint16_t pm90_n733l[] = { | 271 | static const uint16_t pm90_n733l[] = { | |
272 | ID16(1100, 876, BUS100), | 272 | ID16(1100, 876, BUS100), | |
273 | ID16(1000, 876, BUS100), | 273 | ID16(1000, 876, BUS100), | |
274 | ID16( 900, 860, BUS100), | 274 | ID16( 900, 860, BUS100), | |
275 | ID16( 800, 844, BUS100), | 275 | ID16( 800, 844, BUS100), | |
276 | ID16( 600, 812, BUS100), | 276 | ID16( 600, 812, BUS100), | |
277 | }; | 277 | }; | |
278 | 278 | |||
279 | /* Intel Pentium M processor 753 1.2 GHz, VID #G */ | 279 | /* Intel Pentium M processor 753 1.2 GHz, VID #G */ | |
280 | static const uint16_t pm90_n753g[] = { | 280 | static const uint16_t pm90_n753g[] = { | |
281 | ID16(1200, 956, BUS100), | 281 | ID16(1200, 956, BUS100), | |
282 | ID16(1100, 940, BUS100), | 282 | ID16(1100, 940, BUS100), | |
283 | ID16(1000, 908, BUS100), | 283 | ID16(1000, 908, BUS100), | |
284 | ID16( 900, 892, BUS100), | 284 | ID16( 900, 892, BUS100), | |
285 | ID16( 800, 860, BUS100), | 285 | ID16( 800, 860, BUS100), | |
286 | ID16( 600, 812, BUS100), | 286 | ID16( 600, 812, BUS100), | |
287 | }; | 287 | }; | |
288 | 288 | |||
289 | /* Intel Pentium M processor 753 1.2 GHz, VID #H */ | 289 | /* Intel Pentium M processor 753 1.2 GHz, VID #H */ | |
290 | static const uint16_t pm90_n753h[] = { | 290 | static const uint16_t pm90_n753h[] = { | |
291 | ID16(1200, 940, BUS100), | 291 | ID16(1200, 940, BUS100), | |
292 | ID16(1100, 924, BUS100), | 292 | ID16(1100, 924, BUS100), | |
293 | ID16(1000, 908, BUS100), | 293 | ID16(1000, 908, BUS100), | |
294 | ID16( 900, 876, BUS100), | 294 | ID16( 900, 876, BUS100), | |
295 | ID16( 800, 860, BUS100), | 295 | ID16( 800, 860, BUS100), | |
296 | ID16( 600, 812, BUS100), | 296 | ID16( 600, 812, BUS100), | |
297 | }; | 297 | }; | |
298 | 298 | |||
299 | /* Intel Pentium M processor 753 1.2 GHz, VID #I */ | 299 | /* Intel Pentium M processor 753 1.2 GHz, VID #I */ | |
300 | static const uint16_t pm90_n753i[] = { | 300 | static const uint16_t pm90_n753i[] = { | |
301 | ID16(1200, 924, BUS100), | 301 | ID16(1200, 924, BUS100), | |
302 | ID16(1100, 908, BUS100), | 302 | ID16(1100, 908, BUS100), | |
303 | ID16(1000, 892, BUS100), | 303 | ID16(1000, 892, BUS100), | |
304 | ID16( 900, 876, BUS100), | 304 | ID16( 900, 876, BUS100), | |
305 | ID16( 800, 860, BUS100), | 305 | ID16( 800, 860, BUS100), | |
306 | ID16( 600, 812, BUS100), | 306 | ID16( 600, 812, BUS100), | |
307 | }; | 307 | }; | |
308 | 308 | |||
309 | /* Intel Pentium M processor 753 1.2 GHz, VID #J */ | 309 | /* Intel Pentium M processor 753 1.2 GHz, VID #J */ | |
310 | static const uint16_t pm90_n753j[] = { | 310 | static const uint16_t pm90_n753j[] = { | |
311 | ID16(1200, 908, BUS100), | 311 | ID16(1200, 908, BUS100), | |
312 | ID16(1100, 892, BUS100), | 312 | ID16(1100, 892, BUS100), | |
313 | ID16(1000, 876, BUS100), | 313 | ID16(1000, 876, BUS100), | |
314 | ID16( 900, 860, BUS100), | 314 | ID16( 900, 860, BUS100), | |
315 | ID16( 800, 844, BUS100), | 315 | ID16( 800, 844, BUS100), | |
316 | ID16( 600, 812, BUS100), | 316 | ID16( 600, 812, BUS100), | |
317 | }; | 317 | }; | |
318 | 318 | |||
319 | /* Intel Pentium M processor 753 1.2 GHz, VID #K */ | 319 | /* Intel Pentium M processor 753 1.2 GHz, VID #K */ | |
320 | static const uint16_t pm90_n753k[] = { | 320 | static const uint16_t pm90_n753k[] = { | |
321 | ID16(1200, 892, BUS100), | 321 | ID16(1200, 892, BUS100), | |
322 | ID16(1100, 892, BUS100), | 322 | ID16(1100, 892, BUS100), | |
323 | ID16(1000, 876, BUS100), | 323 | ID16(1000, 876, BUS100), | |
324 | ID16( 900, 860, BUS100), | 324 | ID16( 900, 860, BUS100), | |
325 | ID16( 800, 844, BUS100), | 325 | ID16( 800, 844, BUS100), | |
326 | ID16( 600, 812, BUS100), | 326 | ID16( 600, 812, BUS100), | |
327 | }; | 327 | }; | |
328 | 328 | |||
329 | /* Intel Pentium M processor 753 1.2 GHz, VID #L */ | 329 | /* Intel Pentium M processor 753 1.2 GHz, VID #L */ | |
330 | static const uint16_t pm90_n753l[] = { | 330 | static const uint16_t pm90_n753l[] = { | |
331 | ID16(1200, 876, BUS100), | 331 | ID16(1200, 876, BUS100), | |
332 | ID16(1100, 876, BUS100), | 332 | ID16(1100, 876, BUS100), | |
333 | ID16(1000, 860, BUS100), | 333 | ID16(1000, 860, BUS100), | |
334 | ID16( 900, 844, BUS100), | 334 | ID16( 900, 844, BUS100), | |
335 | ID16( 800, 844, BUS100), | 335 | ID16( 800, 844, BUS100), | |
336 | ID16( 600, 812, BUS100), | 336 | ID16( 600, 812, BUS100), | |
337 | }; | 337 | }; | |
338 | 338 | |||
339 | /* Intel Pentium M processor 773 1.3 GHz, VID #G */ | 339 | /* Intel Pentium M processor 773 1.3 GHz, VID #G */ | |
340 | static const uint16_t pm90_n773g[] = { | 340 | static const uint16_t pm90_n773g[] = { | |
341 | ID16(1300, 956, BUS100), | 341 | ID16(1300, 956, BUS100), | |
342 | ID16(1200, 940, BUS100), | 342 | ID16(1200, 940, BUS100), | |
343 | ID16(1100, 924, BUS100), | 343 | ID16(1100, 924, BUS100), | |
344 | ID16(1000, 908, BUS100), | 344 | ID16(1000, 908, BUS100), | |
345 | ID16( 900, 876, BUS100), | 345 | ID16( 900, 876, BUS100), | |
346 | ID16( 800, 860, BUS100), | 346 | ID16( 800, 860, BUS100), | |
347 | ID16( 600, 812, BUS100), | 347 | ID16( 600, 812, BUS100), | |
348 | }; | 348 | }; | |
349 | 349 | |||
350 | /* Intel Pentium M processor 773 1.3 GHz, VID #H */ | 350 | /* Intel Pentium M processor 773 1.3 GHz, VID #H */ | |
351 | static const uint16_t pm90_n773h[] = { | 351 | static const uint16_t pm90_n773h[] = { | |
352 | ID16(1300, 940, BUS100), | 352 | ID16(1300, 940, BUS100), | |
353 | ID16(1200, 924, BUS100), | 353 | ID16(1200, 924, BUS100), | |
354 | ID16(1100, 908, BUS100), | 354 | ID16(1100, 908, BUS100), | |
355 | ID16(1000, 892, BUS100), | 355 | ID16(1000, 892, BUS100), | |
356 | ID16( 900, 876, BUS100), | 356 | ID16( 900, 876, BUS100), | |
357 | ID16( 800, 860, BUS100), | 357 | ID16( 800, 860, BUS100), | |
358 | ID16( 600, 812, BUS100), | 358 | ID16( 600, 812, BUS100), | |
359 | }; | 359 | }; | |
360 | 360 | |||
361 | /* Intel Pentium M processor 773 1.3 GHz, VID #I */ | 361 | /* Intel Pentium M processor 773 1.3 GHz, VID #I */ | |
362 | static const uint16_t pm90_n773i[] = { | 362 | static const uint16_t pm90_n773i[] = { | |
363 | ID16(1300, 924, BUS100), | 363 | ID16(1300, 924, BUS100), | |
364 | ID16(1200, 908, BUS100), | 364 | ID16(1200, 908, BUS100), | |
365 | ID16(1100, 892, BUS100), | 365 | ID16(1100, 892, BUS100), | |
366 | ID16(1000, 876, BUS100), | 366 | ID16(1000, 876, BUS100), | |
367 | ID16( 900, 860, BUS100), | 367 | ID16( 900, 860, BUS100), | |
368 | ID16( 800, 844, BUS100), | 368 | ID16( 800, 844, BUS100), | |
369 | ID16( 600, 812, BUS100), | 369 | ID16( 600, 812, BUS100), | |
370 | }; | 370 | }; | |
371 | 371 | |||
372 | /* Intel Pentium M processor 773 1.3 GHz, VID #J */ | 372 | /* Intel Pentium M processor 773 1.3 GHz, VID #J */ | |
373 | static const uint16_t pm90_n773j[] = { | 373 | static const uint16_t pm90_n773j[] = { | |
374 | ID16(1300, 908, BUS100), | 374 | ID16(1300, 908, BUS100), | |
375 | ID16(1200, 908, BUS100), | 375 | ID16(1200, 908, BUS100), | |
376 | ID16(1100, 892, BUS100), | 376 | ID16(1100, 892, BUS100), | |
377 | ID16(1000, 876, BUS100), | 377 | ID16(1000, 876, BUS100), | |
378 | ID16( 900, 860, BUS100), | 378 | ID16( 900, 860, BUS100), | |
379 | ID16( 800, 844, BUS100), | 379 | ID16( 800, 844, BUS100), | |
380 | ID16( 600, 812, BUS100), | 380 | ID16( 600, 812, BUS100), | |
381 | }; | 381 | }; | |
382 | 382 | |||
383 | /* Intel Pentium M processor 773 1.3 GHz, VID #K */ | 383 | /* Intel Pentium M processor 773 1.3 GHz, VID #K */ | |
384 | static const uint16_t pm90_n773k[] = { | 384 | static const uint16_t pm90_n773k[] = { | |
385 | ID16(1300, 892, BUS100), | 385 | ID16(1300, 892, BUS100), | |
386 | ID16(1200, 892, BUS100), | 386 | ID16(1200, 892, BUS100), | |
387 | ID16(1100, 876, BUS100), | 387 | ID16(1100, 876, BUS100), | |
388 | ID16(1000, 860, BUS100), | 388 | ID16(1000, 860, BUS100), | |
389 | ID16( 900, 860, BUS100), | 389 | ID16( 900, 860, BUS100), | |
390 | ID16( 800, 844, BUS100), | 390 | ID16( 800, 844, BUS100), | |
391 | ID16( 600, 812, BUS100), | 391 | ID16( 600, 812, BUS100), | |
392 | }; | 392 | }; | |
393 | 393 | |||
394 | /* Intel Pentium M processor 773 1.3 GHz, VID #L */ | 394 | /* Intel Pentium M processor 773 1.3 GHz, VID #L */ | |
395 | static const uint16_t pm90_n773l[] = { | 395 | static const uint16_t pm90_n773l[] = { | |
396 | ID16(1300, 876, BUS100), | 396 | ID16(1300, 876, BUS100), | |
397 | ID16(1200, 876, BUS100), | 397 | ID16(1200, 876, BUS100), | |
398 | ID16(1100, 860, BUS100), | 398 | ID16(1100, 860, BUS100), | |
399 | ID16(1000, 860, BUS100), | 399 | ID16(1000, 860, BUS100), | |
400 | ID16( 900, 844, BUS100), | 400 | ID16( 900, 844, BUS100), | |
401 | ID16( 800, 844, BUS100), | 401 | ID16( 800, 844, BUS100), | |
402 | ID16( 600, 812, BUS100), | 402 | ID16( 600, 812, BUS100), | |
403 | }; | 403 | }; | |
404 | 404 | |||
405 | /* Intel Pentium M processor 738 1.4 GHz */ | 405 | /* Intel Pentium M processor 738 1.4 GHz */ | |
406 | static const uint16_t pm90_n738[] = { | 406 | static const uint16_t pm90_n738[] = { | |
407 | ID16(1400, 1116, BUS100), | 407 | ID16(1400, 1116, BUS100), | |
408 | ID16(1300, 1116, BUS100), | 408 | ID16(1300, 1116, BUS100), | |
409 | ID16(1200, 1100, BUS100), | 409 | ID16(1200, 1100, BUS100), | |
410 | ID16(1100, 1068, BUS100), | 410 | ID16(1100, 1068, BUS100), | |
411 | ID16(1000, 1052, BUS100), | 411 | ID16(1000, 1052, BUS100), | |
412 | ID16( 900, 1036, BUS100), | 412 | ID16( 900, 1036, BUS100), | |
413 | ID16( 800, 1020, BUS100), | 413 | ID16( 800, 1020, BUS100), | |
414 | ID16( 600, 988, BUS100), | 414 | ID16( 600, 988, BUS100), | |
415 | }; | 415 | }; | |
416 | 416 | |||
417 | /* Intel Pentium M processor 758 1.5 GHz */ | 417 | /* Intel Pentium M processor 758 1.5 GHz */ | |
418 | static const uint16_t pm90_n758[] = { | 418 | static const uint16_t pm90_n758[] = { | |
419 | ID16(1500, 1116, BUS100), | 419 | ID16(1500, 1116, BUS100), | |
420 | ID16(1400, 1116, BUS100), | 420 | ID16(1400, 1116, BUS100), | |
421 | ID16(1300, 1100, BUS100), | 421 | ID16(1300, 1100, BUS100), | |
422 | ID16(1200, 1084, BUS100), | 422 | ID16(1200, 1084, BUS100), | |
423 | ID16(1100, 1068, BUS100), | 423 | ID16(1100, 1068, BUS100), | |
424 | ID16(1000, 1052, BUS100), | 424 | ID16(1000, 1052, BUS100), | |
425 | ID16( 900, 1036, BUS100), | 425 | ID16( 900, 1036, BUS100), | |
426 | ID16( 800, 1020, BUS100), | 426 | ID16( 800, 1020, BUS100), | |
427 | ID16( 600, 988, BUS100), | 427 | ID16( 600, 988, BUS100), | |
428 | }; | 428 | }; | |
429 | 429 | |||
430 | /* Intel Pentium M processor 778 1.6 GHz */ | 430 | /* Intel Pentium M processor 778 1.6 GHz */ | |
431 | static const uint16_t pm90_n778[] = { | 431 | static const uint16_t pm90_n778[] = { | |
432 | ID16(1600, 1116, BUS100), | 432 | ID16(1600, 1116, BUS100), | |
433 | ID16(1500, 1116, BUS100), | 433 | ID16(1500, 1116, BUS100), | |
434 | ID16(1400, 1100, BUS100), | 434 | ID16(1400, 1100, BUS100), | |
435 | ID16(1300, 1184, BUS100), | 435 | ID16(1300, 1184, BUS100), | |
436 | ID16(1200, 1068, BUS100), | 436 | ID16(1200, 1068, BUS100), | |
437 | ID16(1100, 1052, BUS100), | 437 | ID16(1100, 1052, BUS100), | |
438 | ID16(1000, 1052, BUS100), | 438 | ID16(1000, 1052, BUS100), | |
439 | ID16( 900, 1036, BUS100), | 439 | ID16( 900, 1036, BUS100), | |
440 | ID16( 800, 1020, BUS100), | 440 | ID16( 800, 1020, BUS100), | |
441 | ID16( 600, 988, BUS100), | 441 | ID16( 600, 988, BUS100), | |
442 | }; | 442 | }; | |
443 | 443 | |||
444 | /* Intel Pentium M processor 710 1.4 GHz, 533 MHz FSB */ | 444 | /* Intel Pentium M processor 710 1.4 GHz, 533 MHz FSB */ | |
445 | static const uint16_t pm90_n710[] = { | 445 | static const uint16_t pm90_n710[] = { | |
446 | ID16(1400, 1340, BUS133), | 446 | ID16(1400, 1340, BUS133), | |
447 | ID16(1200, 1228, BUS133), | 447 | ID16(1200, 1228, BUS133), | |
448 | ID16(1000, 1148, BUS133), | 448 | ID16(1000, 1148, BUS133), | |
449 | ID16( 800, 1068, BUS133), | 449 | ID16( 800, 1068, BUS133), | |
450 | ID16( 600, 998, BUS133), | 450 | ID16( 600, 998, BUS133), | |
451 | }; | 451 | }; | |
452 | 452 | |||
453 | /* Intel Pentium M processor 715 1.5 GHz, VID #A */ | 453 | /* Intel Pentium M processor 715 1.5 GHz, VID #A */ | |
454 | static const uint16_t pm90_n715a[] = { | 454 | static const uint16_t pm90_n715a[] = { | |
455 | ID16(1500, 1340, BUS100), | 455 | ID16(1500, 1340, BUS100), | |
456 | ID16(1200, 1228, BUS100), | 456 | ID16(1200, 1228, BUS100), | |
457 | ID16(1000, 1148, BUS100), | 457 | ID16(1000, 1148, BUS100), | |
458 | ID16( 800, 1068, BUS100), | 458 | ID16( 800, 1068, BUS100), | |
459 | ID16( 600, 988, BUS100), | 459 | ID16( 600, 988, BUS100), | |
460 | }; | 460 | }; | |
461 | 461 | |||
462 | /* Intel Pentium M processor 715 1.5 GHz, VID #B */ | 462 | /* Intel Pentium M processor 715 1.5 GHz, VID #B */ | |
463 | static const uint16_t pm90_n715b[] = { | 463 | static const uint16_t pm90_n715b[] = { | |
464 | ID16(1500, 1324, BUS100), | 464 | ID16(1500, 1324, BUS100), | |
465 | ID16(1200, 1212, BUS100), | 465 | ID16(1200, 1212, BUS100), | |
466 | ID16(1000, 1148, BUS100), | 466 | ID16(1000, 1148, BUS100), | |
467 | ID16( 800, 1068, BUS100), | 467 | ID16( 800, 1068, BUS100), | |
468 | ID16( 600, 988, BUS100), | 468 | ID16( 600, 988, BUS100), | |
469 | }; | 469 | }; | |
470 | 470 | |||
471 | /* Intel Pentium M processor 715 1.5 GHz, VID #C */ | 471 | /* Intel Pentium M processor 715 1.5 GHz, VID #C */ | |
472 | static const uint16_t pm90_n715c[] = { | 472 | static const uint16_t pm90_n715c[] = { | |
473 | ID16(1500, 1308, BUS100), | 473 | ID16(1500, 1308, BUS100), | |
474 | ID16(1200, 1212, BUS100), | 474 | ID16(1200, 1212, BUS100), | |
475 | ID16(1000, 1132, BUS100), | 475 | ID16(1000, 1132, BUS100), | |
476 | ID16( 800, 1068, BUS100), | 476 | ID16( 800, 1068, BUS100), | |
477 | ID16( 600, 988, BUS100), | 477 | ID16( 600, 988, BUS100), | |
478 | }; | 478 | }; | |
479 | 479 | |||
480 | /* Intel Pentium M processor 715 1.5 GHz, VID #D */ | 480 | /* Intel Pentium M processor 715 1.5 GHz, VID #D */ | |
481 | static const uint16_t pm90_n715d[] = { | 481 | static const uint16_t pm90_n715d[] = { | |
482 | ID16(1500, 1276, BUS100), | 482 | ID16(1500, 1276, BUS100), | |
483 | ID16(1200, 1180, BUS100), | 483 | ID16(1200, 1180, BUS100), | |
484 | ID16(1000, 1116, BUS100), | 484 | ID16(1000, 1116, BUS100), | |
485 | ID16( 800, 1052, BUS100), | 485 | ID16( 800, 1052, BUS100), | |
486 | ID16( 600, 988, BUS100), | 486 | ID16( 600, 988, BUS100), | |
487 | }; | 487 | }; | |
488 | 488 | |||
489 | /* Intel Pentium M processor 725 1.6 GHz, VID #A */ | 489 | /* Intel Pentium M processor 725 1.6 GHz, VID #A */ | |
490 | static const uint16_t pm90_n725a[] = { | 490 | static const uint16_t pm90_n725a[] = { | |
491 | ID16(1600, 1340, BUS100), | 491 | ID16(1600, 1340, BUS100), | |
492 | ID16(1400, 1276, BUS100), | 492 | ID16(1400, 1276, BUS100), | |
493 | ID16(1200, 1212, BUS100), | 493 | ID16(1200, 1212, BUS100), | |
494 | ID16(1000, 1132, BUS100), | 494 | ID16(1000, 1132, BUS100), | |
495 | ID16( 800, 1068, BUS100), | 495 | ID16( 800, 1068, BUS100), | |
496 | ID16( 600, 988, BUS100), | 496 | ID16( 600, 988, BUS100), | |
497 | }; | 497 | }; | |
498 | 498 | |||
499 | /* Intel Pentium M processor 725 1.6 GHz, VID #B */ | 499 | /* Intel Pentium M processor 725 1.6 GHz, VID #B */ | |
500 | static const uint16_t pm90_n725b[] = { | 500 | static const uint16_t pm90_n725b[] = { | |
501 | ID16(1600, 1324, BUS100), | 501 | ID16(1600, 1324, BUS100), | |
502 | ID16(1400, 1260, BUS100), | 502 | ID16(1400, 1260, BUS100), | |
503 | ID16(1200, 1196, BUS100), | 503 | ID16(1200, 1196, BUS100), | |
504 | ID16(1000, 1132, BUS100), | 504 | ID16(1000, 1132, BUS100), | |
505 | ID16( 800, 1068, BUS100), | 505 | ID16( 800, 1068, BUS100), | |
506 | ID16( 600, 988, BUS100), | 506 | ID16( 600, 988, BUS100), | |
507 | }; | 507 | }; | |
508 | 508 | |||
509 | /* Intel Pentium M processor 725 1.6 GHz, VID #C */ | 509 | /* Intel Pentium M processor 725 1.6 GHz, VID #C */ | |
510 | static const uint16_t pm90_n725c[] = { | 510 | static const uint16_t pm90_n725c[] = { | |
511 | ID16(1600, 1308, BUS100), | 511 | ID16(1600, 1308, BUS100), | |
512 | ID16(1400, 1244, BUS100), | 512 | ID16(1400, 1244, BUS100), | |
513 | ID16(1200, 1180, BUS100), | 513 | ID16(1200, 1180, BUS100), | |
514 | ID16(1000, 1116, BUS100), | 514 | ID16(1000, 1116, BUS100), | |
515 | ID16( 800, 1052, BUS100), | 515 | ID16( 800, 1052, BUS100), | |
516 | ID16( 600, 988, BUS100), | 516 | ID16( 600, 988, BUS100), | |
517 | }; | 517 | }; | |
518 | 518 | |||
519 | /* Intel Pentium M processor 725 1.6 GHz, VID #D */ | 519 | /* Intel Pentium M processor 725 1.6 GHz, VID #D */ | |
520 | static const uint16_t pm90_n725d[] = { | 520 | static const uint16_t pm90_n725d[] = { | |
521 | ID16(1600, 1276, BUS100), | 521 | ID16(1600, 1276, BUS100), | |
522 | ID16(1400, 1228, BUS100), | 522 | ID16(1400, 1228, BUS100), | |
523 | ID16(1200, 1164, BUS100), | 523 | ID16(1200, 1164, BUS100), | |
524 | ID16(1000, 1116, BUS100), | 524 | ID16(1000, 1116, BUS100), | |
525 | ID16( 800, 1052, BUS100), | 525 | ID16( 800, 1052, BUS100), | |
526 | ID16( 600, 988, BUS100), | 526 | ID16( 600, 988, BUS100), | |
527 | }; | 527 | }; | |
528 | 528 | |||
529 | /* Intel Pentium M processor 730 1.6 GHz, 533 MHz FSB */ | 529 | /* Intel Pentium M processor 730 1.6 GHz, 533 MHz FSB */ | |
530 | static const uint16_t pm90_n730[] = { | 530 | static const uint16_t pm90_n730[] = { | |
531 | ID16(1600, 1308, BUS133), | 531 | ID16(1600, 1308, BUS133), | |
532 | ID16(1333, 1260, BUS133), | 532 | ID16(1333, 1260, BUS133), | |
533 | ID16(1200, 1212, BUS133), | 533 | ID16(1200, 1212, BUS133), | |
534 | ID16(1067, 1180, BUS133), | 534 | ID16(1067, 1180, BUS133), | |
535 | ID16( 800, 988, BUS133), | 535 | ID16( 800, 988, BUS133), | |
536 | }; | 536 | }; | |
537 | 537 | |||
538 | /* Intel Pentium M processor 735 1.7 GHz, VID #A */ | 538 | /* Intel Pentium M processor 735 1.7 GHz, VID #A */ | |
539 | static const uint16_t pm90_n735a[] = { | 539 | static const uint16_t pm90_n735a[] = { | |
540 | ID16(1700, 1340, BUS100), | 540 | ID16(1700, 1340, BUS100), | |
541 | ID16(1400, 1244, BUS100), | 541 | ID16(1400, 1244, BUS100), | |
542 | ID16(1200, 1180, BUS100), | 542 | ID16(1200, 1180, BUS100), | |
543 | ID16(1000, 1116, BUS100), | 543 | ID16(1000, 1116, BUS100), | |
544 | ID16( 800, 1052, BUS100), | 544 | ID16( 800, 1052, BUS100), | |
545 | ID16( 600, 988, BUS100), | 545 | ID16( 600, 988, BUS100), | |
546 | }; | 546 | }; | |
547 | 547 | |||
548 | /* Intel Pentium M processor 735 1.7 GHz, VID #B */ | 548 | /* Intel Pentium M processor 735 1.7 GHz, VID #B */ | |
549 | static const uint16_t pm90_n735b[] = { | 549 | static const uint16_t pm90_n735b[] = { | |
550 | ID16(1700, 1324, BUS100), | 550 | ID16(1700, 1324, BUS100), | |
551 | ID16(1400, 1244, BUS100), | 551 | ID16(1400, 1244, BUS100), | |
552 | ID16(1200, 1180, BUS100), | 552 | ID16(1200, 1180, BUS100), | |
553 | ID16(1000, 1116, BUS100), | 553 | ID16(1000, 1116, BUS100), | |
554 | ID16( 800, 1052, BUS100), | 554 | ID16( 800, 1052, BUS100), | |
555 | ID16( 600, 988, BUS100), | 555 | ID16( 600, 988, BUS100), | |
556 | }; | 556 | }; | |
557 | 557 | |||
558 | /* Intel Pentium M processor 735 1.7 GHz, VID #C */ | 558 | /* Intel Pentium M processor 735 1.7 GHz, VID #C */ | |
559 | static const uint16_t pm90_n735c[] = { | 559 | static const uint16_t pm90_n735c[] = { | |
560 | ID16(1700, 1308, BUS100), | 560 | ID16(1700, 1308, BUS100), | |
561 | ID16(1400, 1228, BUS100), | 561 | ID16(1400, 1228, BUS100), | |
562 | ID16(1200, 1164, BUS100), | 562 | ID16(1200, 1164, BUS100), | |
563 | ID16(1000, 1116, BUS100), | 563 | ID16(1000, 1116, BUS100), | |
564 | ID16( 800, 1052, BUS100), | 564 | ID16( 800, 1052, BUS100), | |
565 | ID16( 600, 988, BUS100), | 565 | ID16( 600, 988, BUS100), | |
566 | }; | 566 | }; | |
567 | 567 | |||
568 | /* Intel Pentium M processor 735 1.7 GHz, VID #D */ | 568 | /* Intel Pentium M processor 735 1.7 GHz, VID #D */ | |
569 | static const uint16_t pm90_n735d[] = { | 569 | static const uint16_t pm90_n735d[] = { | |
570 | ID16(1700, 1276, BUS100), | 570 | ID16(1700, 1276, BUS100), | |
571 | ID16(1400, 1212, BUS100), | 571 | ID16(1400, 1212, BUS100), | |
572 | ID16(1200, 1148, BUS100), | 572 | ID16(1200, 1148, BUS100), | |
573 | ID16(1000, 1100, BUS100), | 573 | ID16(1000, 1100, BUS100), | |
574 | ID16( 800, 1052, BUS100), | 574 | ID16( 800, 1052, BUS100), | |
575 | ID16( 600, 988, BUS100), | 575 | ID16( 600, 988, BUS100), | |
576 | }; | 576 | }; | |
577 | 577 | |||
578 | /* Intel Pentium M processor 740 1.73 GHz, 533 MHz FSB */ | 578 | /* Intel Pentium M processor 740 1.73 GHz, 533 MHz FSB */ | |
579 | static const uint16_t pm90_n740[] = { | 579 | static const uint16_t pm90_n740[] = { | |
580 | ID16(1733, 1356, BUS133), | 580 | ID16(1733, 1356, BUS133), | |
581 | ID16(1333, 1212, BUS133), | 581 | ID16(1333, 1212, BUS133), | |
582 | ID16(1067, 1100, BUS133), | 582 | ID16(1067, 1100, BUS133), | |
583 | ID16( 800, 988, BUS133), | 583 | ID16( 800, 988, BUS133), | |
584 | }; | 584 | }; | |
585 | 585 | |||
586 | /* Intel Pentium M processor 745 1.8 GHz, VID #A */ | 586 | /* Intel Pentium M processor 745 1.8 GHz, VID #A */ | |
587 | static const uint16_t pm90_n745a[] = { | 587 | static const uint16_t pm90_n745a[] = { | |
588 | ID16(1800, 1340, BUS100), | 588 | ID16(1800, 1340, BUS100), | |
589 | ID16(1600, 1292, BUS100), | 589 | ID16(1600, 1292, BUS100), | |
590 | ID16(1400, 1228, BUS100), | 590 | ID16(1400, 1228, BUS100), | |
591 | ID16(1200, 1164, BUS100), | 591 | ID16(1200, 1164, BUS100), | |
592 | ID16(1000, 1116, BUS100), | 592 | ID16(1000, 1116, BUS100), | |
593 | ID16( 800, 1052, BUS100), | 593 | ID16( 800, 1052, BUS100), | |
594 | ID16( 600, 988, BUS100), | 594 | ID16( 600, 988, BUS100), | |
595 | }; | 595 | }; | |
596 | 596 | |||
597 | /* Intel Pentium M processor 745 1.8 GHz, VID #B */ | 597 | /* Intel Pentium M processor 745 1.8 GHz, VID #B */ | |
598 | static const uint16_t pm90_n745b[] = { | 598 | static const uint16_t pm90_n745b[] = { | |
599 | ID16(1800, 1324, BUS100), | 599 | ID16(1800, 1324, BUS100), | |
600 | ID16(1600, 1276, BUS100), | 600 | ID16(1600, 1276, BUS100), | |
601 | ID16(1400, 1212, BUS100), | 601 | ID16(1400, 1212, BUS100), | |
602 | ID16(1200, 1164, BUS100), | 602 | ID16(1200, 1164, BUS100), | |
603 | ID16(1000, 1116, BUS100), | 603 | ID16(1000, 1116, BUS100), | |
604 | ID16( 800, 1052, BUS100), | 604 | ID16( 800, 1052, BUS100), | |
605 | ID16( 600, 988, BUS100), | 605 | ID16( 600, 988, BUS100), | |
606 | }; | 606 | }; | |
607 | 607 | |||
608 | /* Intel Pentium M processor 745 1.8 GHz, VID #C */ | 608 | /* Intel Pentium M processor 745 1.8 GHz, VID #C */ | |
609 | static const uint16_t pm90_n745c[] = { | 609 | static const uint16_t pm90_n745c[] = { | |
610 | ID16(1800, 1308, BUS100), | 610 | ID16(1800, 1308, BUS100), | |
611 | ID16(1600, 1260, BUS100), | 611 | ID16(1600, 1260, BUS100), | |
612 | ID16(1400, 1212, BUS100), | 612 | ID16(1400, 1212, BUS100), | |
613 | ID16(1200, 1148, BUS100), | 613 | ID16(1200, 1148, BUS100), | |
614 | ID16(1000, 1100, BUS100), | 614 | ID16(1000, 1100, BUS100), | |
615 | ID16( 800, 1052, BUS100), | 615 | ID16( 800, 1052, BUS100), | |
616 | ID16( 600, 988, BUS100), | 616 | ID16( 600, 988, BUS100), | |
617 | }; | 617 | }; | |
618 | 618 | |||
619 | /* Intel Pentium M processor 745 1.8 GHz, VID #D */ | 619 | /* Intel Pentium M processor 745 1.8 GHz, VID #D */ | |
620 | static const uint16_t pm90_n745d[] = { | 620 | static const uint16_t pm90_n745d[] = { | |
621 | ID16(1800, 1276, BUS100), | 621 | ID16(1800, 1276, BUS100), | |
622 | ID16(1600, 1228, BUS100), | 622 | ID16(1600, 1228, BUS100), | |
623 | ID16(1400, 1180, BUS100), | 623 | ID16(1400, 1180, BUS100), | |
624 | ID16(1200, 1132, BUS100), | 624 | ID16(1200, 1132, BUS100), | |
625 | ID16(1000, 1084, BUS100), | 625 | ID16(1000, 1084, BUS100), | |
626 | ID16( 800, 1036, BUS100), | 626 | ID16( 800, 1036, BUS100), | |
627 | ID16( 600, 988, BUS100), | 627 | ID16( 600, 988, BUS100), | |
628 | }; | 628 | }; | |
629 | 629 | |||
630 | /* Intel Pentium M processor 750 1.86 GHz, 533 MHz FSB */ | 630 | /* Intel Pentium M processor 750 1.86 GHz, 533 MHz FSB */ | |
631 | /* values extracted from \_PR\NPSS (via _PSS) SDST ACPI table */ | 631 | /* values extracted from \_PR\NPSS (via _PSS) SDST ACPI table */ | |
632 | static const uint16_t pm90_n750[] = { | 632 | static const uint16_t pm90_n750[] = { | |
633 | ID16(1867, 1308, BUS133), | 633 | ID16(1867, 1308, BUS133), | |
634 | ID16(1600, 1228, BUS133), | 634 | ID16(1600, 1228, BUS133), | |
635 | ID16(1333, 1148, BUS133), | 635 | ID16(1333, 1148, BUS133), | |
636 | ID16(1067, 1068, BUS133), | 636 | ID16(1067, 1068, BUS133), | |
637 | ID16( 800, 988, BUS133), | 637 | ID16( 800, 988, BUS133), | |
638 | }; | 638 | }; | |
639 | 639 | |||
640 | /* Intel Pentium M processor 755 2.0 GHz, VID #A */ | 640 | /* Intel Pentium M processor 755 2.0 GHz, VID #A */ | |
641 | static const uint16_t pm90_n755a[] = { | 641 | static const uint16_t pm90_n755a[] = { | |
642 | ID16(2000, 1340, BUS100), | 642 | ID16(2000, 1340, BUS100), | |
643 | ID16(1800, 1292, BUS100), | 643 | ID16(1800, 1292, BUS100), | |
644 | ID16(1600, 1244, BUS100), | 644 | ID16(1600, 1244, BUS100), | |
645 | ID16(1400, 1196, BUS100), | 645 | ID16(1400, 1196, BUS100), | |
646 | ID16(1200, 1148, BUS100), | 646 | ID16(1200, 1148, BUS100), | |
647 | ID16(1000, 1100, BUS100), | 647 | ID16(1000, 1100, BUS100), | |
648 | ID16( 800, 1052, BUS100), | 648 | ID16( 800, 1052, BUS100), | |
649 | ID16( 600, 988, BUS100), | 649 | ID16( 600, 988, BUS100), | |
650 | }; | 650 | }; | |
651 | 651 | |||
652 | /* Intel Pentium M processor 755 2.0 GHz, VID #B */ | 652 | /* Intel Pentium M processor 755 2.0 GHz, VID #B */ | |
653 | static const uint16_t pm90_n755b[] = { | 653 | static const uint16_t pm90_n755b[] = { | |
654 | ID16(2000, 1324, BUS100), | 654 | ID16(2000, 1324, BUS100), | |
655 | ID16(1800, 1276, BUS100), | 655 | ID16(1800, 1276, BUS100), | |
656 | ID16(1600, 1228, BUS100), | 656 | ID16(1600, 1228, BUS100), | |
657 | ID16(1400, 1180, BUS100), | 657 | ID16(1400, 1180, BUS100), | |
658 | ID16(1200, 1132, BUS100), | 658 | ID16(1200, 1132, BUS100), | |
659 | ID16(1000, 1084, BUS100), | 659 | ID16(1000, 1084, BUS100), | |
660 | ID16( 800, 1036, BUS100), | 660 | ID16( 800, 1036, BUS100), | |
661 | ID16( 600, 988, BUS100), | 661 | ID16( 600, 988, BUS100), | |
662 | }; | 662 | }; | |
663 | 663 | |||
664 | /* Intel Pentium M processor 755 2.0 GHz, VID #C */ | 664 | /* Intel Pentium M processor 755 2.0 GHz, VID #C */ | |
665 | static const uint16_t pm90_n755c[] = { | 665 | static const uint16_t pm90_n755c[] = { | |
666 | ID16(2000, 1308, BUS100), | 666 | ID16(2000, 1308, BUS100), | |
667 | ID16(1800, 1276, BUS100), | 667 | ID16(1800, 1276, BUS100), | |
668 | ID16(1600, 1228, BUS100), | 668 | ID16(1600, 1228, BUS100), | |
669 | ID16(1400, 1180, BUS100), | 669 | ID16(1400, 1180, BUS100), | |
670 | ID16(1200, 1132, BUS100), | 670 | ID16(1200, 1132, BUS100), | |
671 | ID16(1000, 1084, BUS100), | 671 | ID16(1000, 1084, BUS100), | |
672 | ID16( 800, 1036, BUS100), | 672 | ID16( 800, 1036, BUS100), | |
673 | ID16( 600, 988, BUS100), | 673 | ID16( 600, 988, BUS100), | |
674 | }; | 674 | }; | |
675 | 675 | |||
676 | /* Intel Pentium M processor 755 2.0 GHz, VID #D */ | 676 | /* Intel Pentium M processor 755 2.0 GHz, VID #D */ | |
677 | static const uint16_t pm90_n755d[] = { | 677 | static const uint16_t pm90_n755d[] = { | |
678 | ID16(2000, 1276, BUS100), | 678 | ID16(2000, 1276, BUS100), | |
679 | ID16(1800, 1244, BUS100), | 679 | ID16(1800, 1244, BUS100), | |
680 | ID16(1600, 1196, BUS100), | 680 | ID16(1600, 1196, BUS100), | |
681 | ID16(1400, 1164, BUS100), | 681 | ID16(1400, 1164, BUS100), | |
682 | ID16(1200, 1116, BUS100), | 682 | ID16(1200, 1116, BUS100), | |
683 | ID16(1000, 1084, BUS100), | 683 | ID16(1000, 1084, BUS100), | |
684 | ID16( 800, 1036, BUS100), | 684 | ID16( 800, 1036, BUS100), | |
685 | ID16( 600, 988, BUS100), | 685 | ID16( 600, 988, BUS100), | |
686 | }; | 686 | }; | |
687 | 687 | |||
688 | /* Intel Pentium M processor 760 2.0 GHz, 533 MHz FSB */ | 688 | /* Intel Pentium M processor 760 2.0 GHz, 533 MHz FSB */ | |
689 | static const uint16_t pm90_n760[] = { | 689 | static const uint16_t pm90_n760[] = { | |
690 | ID16(2000, 1356, BUS133), | 690 | ID16(2000, 1356, BUS133), | |
691 | ID16(1600, 1244, BUS133), | 691 | ID16(1600, 1244, BUS133), | |
692 | ID16(1333, 1164, BUS133), | 692 | ID16(1333, 1164, BUS133), | |
693 | ID16(1067, 1084, BUS133), | 693 | ID16(1067, 1084, BUS133), | |
694 | ID16( 800, 988, BUS133), | 694 | ID16( 800, 988, BUS133), | |
695 | }; | 695 | }; | |
696 | 696 | |||
697 | /* Intel Pentium M processor 765 2.1 GHz, VID #A */ | 697 | /* Intel Pentium M processor 765 2.1 GHz, VID #A */ | |
698 | static const uint16_t pm90_n765a[] = { | 698 | static const uint16_t pm90_n765a[] = { | |
699 | ID16(2100, 1340, BUS100), | 699 | ID16(2100, 1340, BUS100), | |
700 | ID16(1800, 1276, BUS100), | 700 | ID16(1800, 1276, BUS100), | |
701 | ID16(1600, 1228, BUS100), | 701 | ID16(1600, 1228, BUS100), | |
702 | ID16(1400, 1180, BUS100), | 702 | ID16(1400, 1180, BUS100), | |
703 | ID16(1200, 1132, BUS100), | 703 | ID16(1200, 1132, BUS100), | |
704 | ID16(1000, 1084, BUS100), | 704 | ID16(1000, 1084, BUS100), | |
705 | ID16( 800, 1036, BUS100), | 705 | ID16( 800, 1036, BUS100), | |
706 | ID16( 600, 988, BUS100), | 706 | ID16( 600, 988, BUS100), | |
707 | }; | 707 | }; | |
708 | 708 | |||
709 | /* Intel Pentium M processor 765 2.1 GHz, VID #B */ | 709 | /* Intel Pentium M processor 765 2.1 GHz, VID #B */ | |
710 | static const uint16_t pm90_n765b[] = { | 710 | static const uint16_t pm90_n765b[] = { | |
711 | ID16(2100, 1324, BUS100), | 711 | ID16(2100, 1324, BUS100), | |
712 | ID16(1800, 1260, BUS100), | 712 | ID16(1800, 1260, BUS100), | |
713 | ID16(1600, 1212, BUS100), | 713 | ID16(1600, 1212, BUS100), | |
714 | ID16(1400, 1180, BUS100), | 714 | ID16(1400, 1180, BUS100), | |
715 | ID16(1200, 1132, BUS100), | 715 | ID16(1200, 1132, BUS100), | |
716 | ID16(1000, 1084, BUS100), | 716 | ID16(1000, 1084, BUS100), | |
717 | ID16( 800, 1036, BUS100), | 717 | ID16( 800, 1036, BUS100), | |
718 | ID16( 600, 988, BUS100), | 718 | ID16( 600, 988, BUS100), | |
719 | }; | 719 | }; | |
720 | 720 | |||
721 | /* Intel Pentium M processor 765 2.1 GHz, VID #C */ | 721 | /* Intel Pentium M processor 765 2.1 GHz, VID #C */ | |
722 | static const uint16_t pm90_n765c[] = { | 722 | static const uint16_t pm90_n765c[] = { | |
723 | ID16(2100, 1308, BUS100), | 723 | ID16(2100, 1308, BUS100), | |
724 | ID16(1800, 1244, BUS100), | 724 | ID16(1800, 1244, BUS100), | |
725 | ID16(1600, 1212, BUS100), | 725 | ID16(1600, 1212, BUS100), | |
726 | ID16(1400, 1164, BUS100), | 726 | ID16(1400, 1164, BUS100), | |
727 | ID16(1200, 1116, BUS100), | 727 | ID16(1200, 1116, BUS100), | |
728 | ID16(1000, 1084, BUS100), | 728 | ID16(1000, 1084, BUS100), | |
729 | ID16( 800, 1036, BUS100), | 729 | ID16( 800, 1036, BUS100), | |
730 | ID16( 600, 988, BUS100), | 730 | ID16( 600, 988, BUS100), | |
731 | }; | 731 | }; | |
732 | 732 | |||
733 | /* Intel Pentium M processor 765 2.1 GHz, VID #E */ | 733 | /* Intel Pentium M processor 765 2.1 GHz, VID #E */ | |
734 | static const uint16_t pm90_n765e[] = { | 734 | static const uint16_t pm90_n765e[] = { | |
735 | ID16(2100, 1356, BUS100), | 735 | ID16(2100, 1356, BUS100), | |
736 | ID16(1800, 1292, BUS100), | 736 | ID16(1800, 1292, BUS100), | |
737 | ID16(1600, 1244, BUS100), | 737 | ID16(1600, 1244, BUS100), | |
738 | ID16(1400, 1196, BUS100), | 738 | ID16(1400, 1196, BUS100), | |
739 | ID16(1200, 1148, BUS100), | 739 | ID16(1200, 1148, BUS100), | |
740 | ID16(1000, 1100, BUS100), | 740 | ID16(1000, 1100, BUS100), | |
741 | ID16( 800, 1052, BUS100), | 741 | ID16( 800, 1052, BUS100), | |
742 | ID16( 600, 988, BUS100), | 742 | ID16( 600, 988, BUS100), | |
743 | }; | 743 | }; | |
744 | 744 | |||
745 | /* Intel Pentium M processor 770 2.13 GHz */ | 745 | /* Intel Pentium M processor 770 2.13 GHz */ | |
746 | static const uint16_t pm90_n770[] = { | 746 | static const uint16_t pm90_n770[] = { | |
747 | ID16(2133, 1356, BUS133), | 747 | ID16(2133, 1356, BUS133), | |
748 | ID16(1867, 1292, BUS133), | 748 | ID16(1867, 1292, BUS133), | |
749 | ID16(1600, 1212, BUS133), | 749 | ID16(1600, 1212, BUS133), | |
750 | ID16(1333, 1148, BUS133), | 750 | ID16(1333, 1148, BUS133), | |
751 | ID16(1067, 1068, BUS133), | 751 | ID16(1067, 1068, BUS133), | |
752 | ID16( 800, 988, BUS133), | 752 | ID16( 800, 988, BUS133), | |
753 | }; | 753 | }; | |
754 | 754 | |||
755 | /* Intel Pentium M processor 780 2.26 GHz */ | 755 | /* Intel Pentium M processor 780 2.26 GHz */ | |
756 | static const uint16_t pm90_n780[] = { | 756 | static const uint16_t pm90_n780[] = { | |
757 | ID16(2267, 1388, BUS133), | 757 | ID16(2267, 1388, BUS133), | |
758 | ID16(1867, 1292, BUS133), | 758 | ID16(1867, 1292, BUS133), | |
759 | ID16(1600, 1212, BUS133), | 759 | ID16(1600, 1212, BUS133), | |
760 | ID16(1333, 1148, BUS133), | 760 | ID16(1333, 1148, BUS133), | |
761 | ID16(1067, 1068, BUS133), | 761 | ID16(1067, 1068, BUS133), | |
762 | ID16( 800, 988, BUS133), | 762 | ID16( 800, 988, BUS133), | |
763 | }; | 763 | }; | |
764 | 764 | |||
765 | /* | 765 | /* | |
766 | * VIA C7-M 500 MHz FSB, 400 MHz FSB, and ULV variants. | 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. | 767 | * Data from the "VIA C7-M Processor BIOS Writer's Guide (v2.17)" datasheet. | |
768 | */ | 768 | */ | |
769 | 769 | |||
770 | /* 1.00GHz Centaur C7-M ULV */ | 770 | /* 1.00GHz Centaur C7-M ULV */ | |
771 | static const uint16_t C7M_770_ULV[] = { | 771 | static const uint16_t C7M_770_ULV[] = { | |
772 | ID16(1000, 844, BUS100), | 772 | ID16(1000, 844, BUS100), | |
773 | ID16( 800, 796, BUS100), | 773 | ID16( 800, 796, BUS100), | |
774 | ID16( 600, 796, BUS100), | 774 | ID16( 600, 796, BUS100), | |
775 | ID16( 400, 796, BUS100), | 775 | ID16( 400, 796, BUS100), | |
776 | }; | 776 | }; | |
777 | 777 | |||
778 | /* 1.00GHz Centaur C7-M ULV */ | 778 | /* 1.00GHz Centaur C7-M ULV */ | |
779 | static const uint16_t C7M_779_ULV[] = { | 779 | static const uint16_t C7M_779_ULV[] = { | |
780 | ID16(1000, 796, BUS100), | 780 | ID16(1000, 796, BUS100), | |
781 | ID16( 800, 796, BUS100), | 781 | ID16( 800, 796, BUS100), | |
782 | ID16( 600, 796, BUS100), | 782 | ID16( 600, 796, BUS100), | |
783 | ID16( 400, 796, BUS100), | 783 | ID16( 400, 796, BUS100), | |
784 | }; | 784 | }; | |
785 | 785 | |||
786 | /* 1.20GHz Centaur C7-M ULV */ | 786 | /* 1.20GHz Centaur C7-M ULV */ | |
787 | static const uint16_t C7M_772_ULV[] = { | 787 | static const uint16_t C7M_772_ULV[] = { | |
788 | ID16(1200, 844, BUS100), | 788 | ID16(1200, 844, BUS100), | |
789 | ID16(1000, 844, BUS100), | 789 | ID16(1000, 844, BUS100), | |
790 | ID16( 800, 828, BUS100), | 790 | ID16( 800, 828, BUS100), | |
791 | ID16( 600, 796, BUS100), | 791 | ID16( 600, 796, BUS100), | |
792 | ID16( 400, 796, BUS100), | 792 | ID16( 400, 796, BUS100), | |
793 | }; | 793 | }; | |
794 | 794 | |||
795 | /* 1.50GHz Centaur C7-M ULV */ | 795 | /* 1.50GHz Centaur C7-M ULV */ | |
796 | static const uint16_t C7M_775_ULV[] = { | 796 | static const uint16_t C7M_775_ULV[] = { | |
797 | ID16(1500, 956, BUS100), | 797 | ID16(1500, 956, BUS100), | |
798 | ID16(1400, 940, BUS100), | 798 | ID16(1400, 940, BUS100), | |
799 | ID16(1000, 860, BUS100), | 799 | ID16(1000, 860, BUS100), | |
800 | ID16( 800, 828, BUS100), | 800 | ID16( 800, 828, BUS100), | |
801 | ID16( 600, 796, BUS100), | 801 | ID16( 600, 796, BUS100), | |
802 | ID16( 400, 796, BUS100), | 802 | ID16( 400, 796, BUS100), | |
803 | }; | 803 | }; | |
804 | 804 | |||
805 | /* 1.20GHz Centaur C7-M 400 MHz FSB */ | 805 | /* 1.20GHz Centaur C7-M 400 MHz FSB */ | |
806 | static const uint16_t C7M_771[] = { | 806 | static const uint16_t C7M_771[] = { | |
807 | ID16(1200, 860, BUS100), | 807 | ID16(1200, 860, BUS100), | |
808 | ID16(1000, 860, BUS100), | 808 | ID16(1000, 860, BUS100), | |
809 | ID16( 800, 844, BUS100), | 809 | ID16( 800, 844, BUS100), | |
810 | ID16( 600, 844, BUS100), | 810 | ID16( 600, 844, BUS100), | |
811 | ID16( 400, 844, BUS100), | 811 | ID16( 400, 844, BUS100), | |
812 | }; | 812 | }; | |
813 | 813 | |||
814 | /* 1.50GHz Centaur C7-M 400 MHz FSB */ | 814 | /* 1.50GHz Centaur C7-M 400 MHz FSB */ | |
815 | static const uint16_t C7M_754[] = { | 815 | static const uint16_t C7M_754[] = { | |
816 | ID16(1500, 1004, BUS100), | 816 | ID16(1500, 1004, BUS100), | |
817 | ID16(1400, 988, BUS100), | 817 | ID16(1400, 988, BUS100), | |
818 | ID16(1000, 940, BUS100), | 818 | ID16(1000, 940, BUS100), | |
819 | ID16( 800, 844, BUS100), | 819 | ID16( 800, 844, BUS100), | |
820 | ID16( 600, 844, BUS100), | 820 | ID16( 600, 844, BUS100), | |
821 | ID16( 400, 844, BUS100), | 821 | ID16( 400, 844, BUS100), | |
822 | }; | 822 | }; | |
823 | 823 | |||
824 | /* 1.60GHz Centaur C7-M 400 MHz FSB */ | 824 | /* 1.60GHz Centaur C7-M 400 MHz FSB */ | |
825 | static const uint16_t C7M_764[] = { | 825 | static const uint16_t C7M_764[] = { | |
826 | ID16(1600, 1084, BUS100), | 826 | ID16(1600, 1084, BUS100), | |
827 | ID16(1400, 1052, BUS100), | 827 | ID16(1400, 1052, BUS100), | |
828 | ID16(1000, 1004, BUS100), | 828 | ID16(1000, 1004, BUS100), | |
829 | ID16( 800, 844, BUS100), | 829 | ID16( 800, 844, BUS100), | |
830 | ID16( 600, 844, BUS100), | 830 | ID16( 600, 844, BUS100), | |
831 | ID16( 400, 844, BUS100), | 831 | ID16( 400, 844, BUS100), | |
832 | }; | 832 | }; | |
833 | 833 | |||
834 | /* 1.80GHz Centaur C7-M 400 MHz FSB */ | 834 | /* 1.80GHz Centaur C7-M 400 MHz FSB */ | |
835 | static const uint16_t C7M_784[] = { | 835 | static const uint16_t C7M_784[] = { | |
836 | ID16(1800, 1148, BUS100), | 836 | ID16(1800, 1148, BUS100), | |
837 | ID16(1600, 1100, BUS100), | 837 | ID16(1600, 1100, BUS100), | |
838 | ID16(1400, 1052, BUS100), | 838 | ID16(1400, 1052, BUS100), | |
839 | ID16(1000, 1004, BUS100), | 839 | ID16(1000, 1004, BUS100), | |
840 | ID16( 800, 844, BUS100), | 840 | ID16( 800, 844, BUS100), | |
841 | ID16( 600, 844, BUS100), | 841 | ID16( 600, 844, BUS100), | |
842 | ID16( 400, 844, BUS100), | 842 | ID16( 400, 844, BUS100), | |
843 | }; | 843 | }; | |
844 | 844 | |||
845 | /* 2.00GHz Centaur C7-M 400 MHz FSB */ | 845 | /* 2.00GHz Centaur C7-M 400 MHz FSB */ | |
846 | static const uint16_t C7M_794[] = { | 846 | static const uint16_t C7M_794[] = { | |
847 | ID16(2000, 1148, BUS100), | 847 | ID16(2000, 1148, BUS100), | |
848 | ID16(1800, 1132, BUS100), | 848 | ID16(1800, 1132, BUS100), | |
849 | ID16(1600, 1100, BUS100), | 849 | ID16(1600, 1100, BUS100), | |
850 | ID16(1400, 1052, BUS100), | 850 | ID16(1400, 1052, BUS100), | |
851 | ID16(1000, 1004, BUS100), | 851 | ID16(1000, 1004, BUS100), | |
852 | ID16( 800, 844, BUS100), | 852 | ID16( 800, 844, BUS100), | |
853 | ID16( 600, 844, BUS100), | 853 | ID16( 600, 844, BUS100), | |
854 | ID16( 400, 844, BUS100), | 854 | ID16( 400, 844, BUS100), | |
855 | }; | 855 | }; | |
856 | 856 | |||
857 | /* 1.60GHz Centaur C7-M 533 MHz FSB */ | 857 | /* 1.60GHz Centaur C7-M 533 MHz FSB */ | |
858 | static const uint16_t C7M_765[] = { | 858 | static const uint16_t C7M_765[] = { | |
859 | ID16(1600, 1084, BUS133), | 859 | ID16(1600, 1084, BUS133), | |
860 | ID16(1467, 1052, BUS133), | 860 | ID16(1467, 1052, BUS133), | |
861 | ID16(1200, 1004, BUS133), | 861 | ID16(1200, 1004, BUS133), | |
862 | ID16( 800, 844, BUS133), | 862 | ID16( 800, 844, BUS133), | |
863 | ID16( 667, 844, BUS133), | 863 | ID16( 667, 844, BUS133), | |
864 | ID16( 533, 844, BUS133), | 864 | ID16( 533, 844, BUS133), | |
865 | }; | 865 | }; | |
866 | 866 | |||
867 | /* 2.00GHz Centaur C7-M 533 MHz FSB */ | 867 | /* 2.00GHz Centaur C7-M 533 MHz FSB */ | |
868 | static const uint16_t C7M_785[] = { | 868 | static const uint16_t C7M_785[] = { | |
869 | ID16(1867, 1148, BUS133), | 869 | ID16(1867, 1148, BUS133), | |
870 | ID16(1600, 1100, BUS133), | 870 | ID16(1600, 1100, BUS133), | |
871 | ID16(1467, 1052, BUS133), | 871 | ID16(1467, 1052, BUS133), | |
872 | ID16(1200, 1004, BUS133), | 872 | ID16(1200, 1004, BUS133), | |
873 | ID16( 800, 844, BUS133), | 873 | ID16( 800, 844, BUS133), | |
874 | ID16( 667, 844, BUS133), | 874 | ID16( 667, 844, BUS133), | |
875 | ID16( 533, 844, BUS133), | 875 | ID16( 533, 844, BUS133), | |
876 | }; | 876 | }; | |
877 | 877 | |||
878 | /* 2.00GHz Centaur C7-M 533 MHz FSB */ | 878 | /* 2.00GHz Centaur C7-M 533 MHz FSB */ | |
879 | static const uint16_t C7M_795[] = { | 879 | static const uint16_t C7M_795[] = { | |
880 | ID16(2000, 1148, BUS133), | 880 | ID16(2000, 1148, BUS133), | |
881 | ID16(1867, 1132, BUS133), | 881 | ID16(1867, 1132, BUS133), | |
882 | ID16(1600, 1100, BUS133), | 882 | ID16(1600, 1100, BUS133), | |
883 | ID16(1467, 1052, BUS133), | 883 | ID16(1467, 1052, BUS133), | |
884 | ID16(1200, 1004, BUS133), | 884 | ID16(1200, 1004, BUS133), | |
885 | ID16( 800, 844, BUS133), | 885 | ID16( 800, 844, BUS133), | |
886 | ID16( 667, 844, BUS133), | 886 | ID16( 667, 844, BUS133), | |
887 | ID16( 533, 844, BUS133), | 887 | ID16( 533, 844, BUS133), | |
888 | }; | 888 | }; | |
889 | 889 | |||
890 | /* 1.00GHz VIA Eden 90nm 'Esther' */ | 890 | /* 1.00GHz VIA Eden 90nm 'Esther' */ | |
891 | static const uint16_t eden90_1000[] = { | 891 | static const uint16_t eden90_1000[] = { | |
892 | ID16(1000, 844, BUS100), | 892 | ID16(1000, 844, BUS100), | |
893 | ID16( 800, 844, BUS100), | 893 | ID16( 800, 844, BUS100), | |
894 | ID16( 600, 844, BUS100), | 894 | ID16( 600, 844, BUS100), | |
895 | ID16( 400, 844, BUS100), | 895 | ID16( 400, 844, BUS100), | |
896 | }; | 896 | }; | |
897 | 897 | |||
898 | struct fqlist { | 898 | struct fqlist { | |
899 | int vendor; | 899 | int vendor; | |
900 | unsigned bus_clk; | 900 | unsigned bus_clk; | |
901 | unsigned n; | 901 | unsigned n; | |
902 | const uint16_t *table; | 902 | const uint16_t *table; | |
903 | }; | 903 | }; | |
904 | 904 | |||
905 | #define ENTRY(ven, bus_clk, tab) \ | 905 | #define ENTRY(ven, bus_clk, tab) \ | |
906 | { CPUVENDOR_##ven, bus_clk == BUS133 ? 1 : 0, __arraycount(tab), tab } | 906 | { CPUVENDOR_##ven, bus_clk == BUS133 ? 1 : 0, __arraycount(tab), tab } | |
907 | 907 | |||
908 | #define BUS_CLK(fqp) ((fqp)->bus_clk ? BUS133 : BUS100) | 908 | #define BUS_CLK(fqp) ((fqp)->bus_clk ? BUS133 : BUS100) | |
909 | 909 | |||
910 | static const struct fqlist est_cpus[] = { | 910 | static const struct fqlist est_cpus[] = { | |
911 | ENTRY(INTEL, BUS100, pm130_900_ulv), | 911 | ENTRY(INTEL, BUS100, pm130_900_ulv), | |
912 | ENTRY(INTEL, BUS100, pm130_1000_ulv), | 912 | ENTRY(INTEL, BUS100, pm130_1000_ulv), | |
913 | ENTRY(INTEL, BUS100, pm130_1100_ulv), | 913 | ENTRY(INTEL, BUS100, pm130_1100_ulv), | |
914 | ENTRY(INTEL, BUS100, pm130_1100_lv), | 914 | ENTRY(INTEL, BUS100, pm130_1100_lv), | |
915 | ENTRY(INTEL, BUS100, pm130_1200_lv), | 915 | ENTRY(INTEL, BUS100, pm130_1200_lv), | |
916 | ENTRY(INTEL, BUS100, pm130_1300_lv), | 916 | ENTRY(INTEL, BUS100, pm130_1300_lv), | |
917 | ENTRY(INTEL, BUS100, pm130_1300), | 917 | ENTRY(INTEL, BUS100, pm130_1300), | |
918 | ENTRY(INTEL, BUS100, pm130_1400), | 918 | ENTRY(INTEL, BUS100, pm130_1400), | |
919 | ENTRY(INTEL, BUS100, pm130_1500), | 919 | ENTRY(INTEL, BUS100, pm130_1500), | |
920 | ENTRY(INTEL, BUS100, pm130_1600), | 920 | ENTRY(INTEL, BUS100, pm130_1600), | |
921 | ENTRY(INTEL, BUS100, pm130_1700), | 921 | ENTRY(INTEL, BUS100, pm130_1700), | |
922 | ENTRY(INTEL, BUS100, pm90_n723), | 922 | ENTRY(INTEL, BUS100, pm90_n723), | |
923 | ENTRY(INTEL, BUS100, pm90_n733g), | 923 | ENTRY(INTEL, BUS100, pm90_n733g), | |
924 | ENTRY(INTEL, BUS100, pm90_n733h), | 924 | ENTRY(INTEL, BUS100, pm90_n733h), | |
925 | ENTRY(INTEL, BUS100, pm90_n733i), | 925 | ENTRY(INTEL, BUS100, pm90_n733i), | |
926 | ENTRY(INTEL, BUS100, pm90_n733j), | 926 | ENTRY(INTEL, BUS100, pm90_n733j), | |
927 | ENTRY(INTEL, BUS100, pm90_n733k), | 927 | ENTRY(INTEL, BUS100, pm90_n733k), | |
928 | ENTRY(INTEL, BUS100, pm90_n733l), | 928 | ENTRY(INTEL, BUS100, pm90_n733l), | |
929 | ENTRY(INTEL, BUS100, pm90_n753g), | 929 | ENTRY(INTEL, BUS100, pm90_n753g), | |
930 | ENTRY(INTEL, BUS100, pm90_n753h), | 930 | ENTRY(INTEL, BUS100, pm90_n753h), | |
931 | ENTRY(INTEL, BUS100, pm90_n753i), | 931 | ENTRY(INTEL, BUS100, pm90_n753i), | |
932 | ENTRY(INTEL, BUS100, pm90_n753j), | 932 | ENTRY(INTEL, BUS100, pm90_n753j), | |
933 | ENTRY(INTEL, BUS100, pm90_n753k), | 933 | ENTRY(INTEL, BUS100, pm90_n753k), | |
934 | ENTRY(INTEL, BUS100, pm90_n753l), | 934 | ENTRY(INTEL, BUS100, pm90_n753l), | |
935 | ENTRY(INTEL, BUS100, pm90_n773g), | 935 | ENTRY(INTEL, BUS100, pm90_n773g), | |
936 | ENTRY(INTEL, BUS100, pm90_n773h), | 936 | ENTRY(INTEL, BUS100, pm90_n773h), | |
937 | ENTRY(INTEL, BUS100, pm90_n773i), | 937 | ENTRY(INTEL, BUS100, pm90_n773i), | |
938 | ENTRY(INTEL, BUS100, pm90_n773j), | 938 | ENTRY(INTEL, BUS100, pm90_n773j), | |
939 | ENTRY(INTEL, BUS100, pm90_n773k), | 939 | ENTRY(INTEL, BUS100, pm90_n773k), | |
940 | ENTRY(INTEL, BUS100, pm90_n773l), | 940 | ENTRY(INTEL, BUS100, pm90_n773l), | |
941 | ENTRY(INTEL, BUS100, pm90_n738), | 941 | ENTRY(INTEL, BUS100, pm90_n738), | |
942 | ENTRY(INTEL, BUS100, pm90_n758), | 942 | ENTRY(INTEL, BUS100, pm90_n758), | |
943 | ENTRY(INTEL, BUS100, pm90_n778), | 943 | ENTRY(INTEL, BUS100, pm90_n778), | |
944 | 944 | |||
945 | ENTRY(INTEL, BUS133, pm90_n710), | 945 | ENTRY(INTEL, BUS133, pm90_n710), | |
946 | ENTRY(INTEL, BUS100, pm90_n715a), | 946 | ENTRY(INTEL, BUS100, pm90_n715a), | |
947 | ENTRY(INTEL, BUS100, pm90_n715b), | 947 | ENTRY(INTEL, BUS100, pm90_n715b), | |
948 | ENTRY(INTEL, BUS100, pm90_n715c), | 948 | ENTRY(INTEL, BUS100, pm90_n715c), | |
949 | ENTRY(INTEL, BUS100, pm90_n715d), | 949 | ENTRY(INTEL, BUS100, pm90_n715d), | |
950 | ENTRY(INTEL, BUS100, pm90_n725a), | 950 | ENTRY(INTEL, BUS100, pm90_n725a), | |
951 | ENTRY(INTEL, BUS100, pm90_n725b), | 951 | ENTRY(INTEL, BUS100, pm90_n725b), | |
952 | ENTRY(INTEL, BUS100, pm90_n725c), | 952 | ENTRY(INTEL, BUS100, pm90_n725c), | |
953 | ENTRY(INTEL, BUS100, pm90_n725d), | 953 | ENTRY(INTEL, BUS100, pm90_n725d), | |
954 | ENTRY(INTEL, BUS133, pm90_n730), | 954 | ENTRY(INTEL, BUS133, pm90_n730), | |
955 | ENTRY(INTEL, BUS100, pm90_n735a), | 955 | ENTRY(INTEL, BUS100, pm90_n735a), | |
956 | ENTRY(INTEL, BUS100, pm90_n735b), | 956 | ENTRY(INTEL, BUS100, pm90_n735b), | |
957 | ENTRY(INTEL, BUS100, pm90_n735c), | 957 | ENTRY(INTEL, BUS100, pm90_n735c), | |
958 | ENTRY(INTEL, BUS100, pm90_n735d), | 958 | ENTRY(INTEL, BUS100, pm90_n735d), | |
959 | ENTRY(INTEL, BUS133, pm90_n740), | 959 | ENTRY(INTEL, BUS133, pm90_n740), | |
960 | ENTRY(INTEL, BUS100, pm90_n745a), | 960 | ENTRY(INTEL, BUS100, pm90_n745a), | |
961 | ENTRY(INTEL, BUS100, pm90_n745b), | 961 | ENTRY(INTEL, BUS100, pm90_n745b), | |
962 | ENTRY(INTEL, BUS100, pm90_n745c), | 962 | ENTRY(INTEL, BUS100, pm90_n745c), | |
963 | ENTRY(INTEL, BUS100, pm90_n745d), | 963 | ENTRY(INTEL, BUS100, pm90_n745d), | |
964 | ENTRY(INTEL, BUS133, pm90_n750), | 964 | ENTRY(INTEL, BUS133, pm90_n750), | |
965 | ENTRY(INTEL, BUS100, pm90_n755a), | 965 | ENTRY(INTEL, BUS100, pm90_n755a), | |
966 | ENTRY(INTEL, BUS100, pm90_n755b), | 966 | ENTRY(INTEL, BUS100, pm90_n755b), | |
967 | ENTRY(INTEL, BUS100, pm90_n755c), | 967 | ENTRY(INTEL, BUS100, pm90_n755c), | |
968 | ENTRY(INTEL, BUS100, pm90_n755d), | 968 | ENTRY(INTEL, BUS100, pm90_n755d), | |
969 | ENTRY(INTEL, BUS133, pm90_n760), | 969 | ENTRY(INTEL, BUS133, pm90_n760), | |
970 | ENTRY(INTEL, BUS100, pm90_n765a), | 970 | ENTRY(INTEL, BUS100, pm90_n765a), | |
971 | ENTRY(INTEL, BUS100, pm90_n765b), | 971 | ENTRY(INTEL, BUS100, pm90_n765b), | |
972 | ENTRY(INTEL, BUS100, pm90_n765c), | 972 | ENTRY(INTEL, BUS100, pm90_n765c), | |
973 | ENTRY(INTEL, BUS100, pm90_n765e), | 973 | ENTRY(INTEL, BUS100, pm90_n765e), | |
974 | ENTRY(INTEL, BUS133, pm90_n770), | 974 | ENTRY(INTEL, BUS133, pm90_n770), | |
975 | ENTRY(INTEL, BUS133, pm90_n780), | 975 | ENTRY(INTEL, BUS133, pm90_n780), | |
976 | 976 | |||
977 | ENTRY(IDT, BUS100, C7M_770_ULV), | 977 | ENTRY(IDT, BUS100, C7M_770_ULV), | |
978 | ENTRY(IDT, BUS100, C7M_779_ULV), | 978 | ENTRY(IDT, BUS100, C7M_779_ULV), | |
979 | ENTRY(IDT, BUS100, C7M_772_ULV), | 979 | ENTRY(IDT, BUS100, C7M_772_ULV), | |
980 | ENTRY(IDT, BUS100, C7M_771), | 980 | ENTRY(IDT, BUS100, C7M_771), | |
981 | ENTRY(IDT, BUS100, C7M_775_ULV), | 981 | ENTRY(IDT, BUS100, C7M_775_ULV), | |
982 | ENTRY(IDT, BUS100, C7M_754), | 982 | ENTRY(IDT, BUS100, C7M_754), | |
983 | ENTRY(IDT, BUS100, C7M_764), | 983 | ENTRY(IDT, BUS100, C7M_764), | |
984 | ENTRY(IDT, BUS133, C7M_765), | 984 | ENTRY(IDT, BUS133, C7M_765), | |
985 | ENTRY(IDT, BUS100, C7M_784), | 985 | ENTRY(IDT, BUS100, C7M_784), | |
986 | ENTRY(IDT, BUS133, C7M_785), | 986 | ENTRY(IDT, BUS133, C7M_785), | |
987 | ENTRY(IDT, BUS100, C7M_794), | 987 | ENTRY(IDT, BUS100, C7M_794), | |
988 | ENTRY(IDT, BUS133, C7M_795), | 988 | ENTRY(IDT, BUS133, C7M_795), | |
989 | 989 | |||
990 | ENTRY(IDT, BUS100, eden90_1000) | 990 | ENTRY(IDT, BUS100, eden90_1000) | |
991 | }; | 991 | }; | |
992 | 992 | |||
993 | #define MSR2FREQINC(msr) (((int) (msr) >> 8) & 0xff) | 993 | #define MSR2FREQINC(msr) (((int) (msr) >> 8) & 0xff) | |
994 | #define MSR2VOLTINC(msr) ((int) (msr) & 0xff) | 994 | #define MSR2VOLTINC(msr) ((int) (msr) & 0xff) | |
995 | 995 | |||
996 | #define MSR2MHZ(msr, bus) ((MSR2FREQINC((msr)) * (bus) + 50) / 100) | 996 | #define MSR2MHZ(msr, bus) ((MSR2FREQINC((msr)) * (bus) + 50) / 100) | |
997 | #define MSR2MV(msr) (MSR2VOLTINC(msr) * 16 + 700) | 997 | #define MSR2MV(msr) (MSR2VOLTINC(msr) * 16 + 700) | |
998 | 998 | |||
999 | static const struct fqlist *est_fqlist; /* not NULL if functional */ | 999 | static const struct fqlist *est_fqlist; /* not NULL if functional */ | |
1000 | static uint16_t *fake_table; /* guessed est_cpu table */ | 1000 | static uint16_t *fake_table; /* guessed est_cpu table */ | |
1001 | static char *freq_names; | 1001 | static char *freq_names; | |
1002 | static struct fqlist fake_fqlist; | 1002 | static struct fqlist fake_fqlist; | |
1003 | static int est_node_target, est_node_current; | 1003 | static int est_node_target, est_node_current; | |
1004 | static const char est_desc[] = "Enhanced SpeedStep"; | 1004 | static const char est_desc[] = "Enhanced SpeedStep"; | |
1005 | static int lvendor, bus_clock; | 1005 | static int lvendor, bus_clock; | |
1006 | 1006 | |||
1007 | static int est_init_once(void); | 1007 | static int est_init_once(void); | |
1008 | static void est_init_main(int); | 1008 | static void est_init_main(int); | |
1009 | 1009 | |||
1010 | static int est_sysctl_helper(SYSCTLFN_PROTO); | 1010 | static int est_sysctl_helper(SYSCTLFN_PROTO); | |
1011 | static int est_sysctl_helper_get(SYSCTLFN_PROTO); | 1011 | static int est_sysctl_helper_get(SYSCTLFN_PROTO); | |
1012 | static int est_sysctl_helper_set(SYSCTLFN_PROTO); | 1012 | static int est_sysctl_helper_set(SYSCTLFN_PROTO); | |
1013 | static int est_sysctl_helper_all(SYSCTLFN_PROTO); | 1013 | static int est_sysctl_helper_all(SYSCTLFN_PROTO); | |
1014 | 1014 | |||
1015 | int (*est_sysctl_get)(SYSCTLFN_PROTO) = NULL; | |||
1016 | int (*est_sysctl_set)(SYSCTLFN_PROTO) = NULL; | |||
1017 | int (*est_sysctl_all)(SYSCTLFN_PROTO) = NULL; | |||
1018 | ||||
1019 | static int | 1015 | static int | |
1020 | est_sysctl_helper_get(SYSCTLFN_ARGS) | 1016 | est_sysctl_helper_get(SYSCTLFN_ARGS) | |
1021 | { | 1017 | { | |
1022 | 1018 | |||
1023 | if (est_sysctl_get != NULL) | 1019 | if (cpu_freq_sysctl_get != NULL) | |
1024 | return (*est_sysctl_get)(SYSCTLFN_CALL(rnode)); | 1020 | return (*cpu_freq_sysctl_get)(SYSCTLFN_CALL(rnode)); | |
1025 | 1021 | |||
1026 | return est_sysctl_helper(SYSCTLFN_CALL(rnode)); | 1022 | return est_sysctl_helper(SYSCTLFN_CALL(rnode)); | |
1027 | } | 1023 | } | |
1028 | 1024 | |||
1029 | static int | 1025 | static int | |
1030 | est_sysctl_helper_set(SYSCTLFN_ARGS) | 1026 | est_sysctl_helper_set(SYSCTLFN_ARGS) | |
1031 | { | 1027 | { | |
1032 | 1028 | |||
1033 | if (est_sysctl_set != NULL) | 1029 | if (cpu_freq_sysctl_set != NULL) | |
1034 | return (*est_sysctl_set)(SYSCTLFN_CALL(rnode)); | 1030 | return (*cpu_freq_sysctl_set)(SYSCTLFN_CALL(rnode)); | |
1035 | 1031 | |||
1036 | return est_sysctl_helper(SYSCTLFN_CALL(rnode)); | 1032 | return est_sysctl_helper(SYSCTLFN_CALL(rnode)); | |
1037 | } | 1033 | } | |
1038 | 1034 | |||
1039 | static int | 1035 | static int | |
1040 | est_sysctl_helper_all(SYSCTLFN_ARGS) | 1036 | est_sysctl_helper_all(SYSCTLFN_ARGS) | |
1041 | { | 1037 | { | |
1042 | struct sysctlnode node; | 1038 | struct sysctlnode node; | |
1043 | int err; | 1039 | int err; | |
1044 | 1040 | |||
1045 | if (est_sysctl_all != NULL) | 1041 | if (cpu_freq_sysctl_all != NULL) | |
1046 | return (*est_sysctl_all)(SYSCTLFN_CALL(rnode)); | 1042 | return (*cpu_freq_sysctl_all)(SYSCTLFN_CALL(rnode)); | |
1047 | 1043 | |||
1048 | if (freq_names == NULL) | 1044 | if (freq_names == NULL) | |
1049 | return ENXIO; | 1045 | return ENXIO; | |
1050 | 1046 | |||
1051 | node = *rnode; | 1047 | node = *rnode; | |
1052 | node.sysctl_data = freq_names; | 1048 | node.sysctl_data = freq_names; | |
1053 | 1049 | |||
1054 | err = sysctl_lookup(SYSCTLFN_CALL(&node)); | 1050 | err = sysctl_lookup(SYSCTLFN_CALL(&node)); | |
1055 | 1051 | |||
1056 | if (err != 0 || newp == NULL) | 1052 | if (err != 0 || newp == NULL) | |
1057 | return err; | 1053 | return err; | |
1058 | 1054 | |||
1059 | return 0; | 1055 | return 0; | |
1060 | } | 1056 | } | |
1061 | 1057 | |||
1062 | static int | 1058 | static int | |
1063 | est_sysctl_helper(SYSCTLFN_ARGS) | 1059 | est_sysctl_helper(SYSCTLFN_ARGS) | |
1064 | { | 1060 | { | |
1065 | struct sysctlnode node; | 1061 | struct sysctlnode node; | |
1066 | int fq, oldfq, error; | 1062 | int fq, oldfq, error; | |
1067 | 1063 | |||
1068 | if (freq_names == NULL) | 1064 | if (freq_names == NULL) | |
1069 | return ENXIO; | 1065 | return ENXIO; | |
1070 | 1066 | |||
1071 | if (est_fqlist == NULL) | 1067 | if (est_fqlist == NULL) | |
1072 | return EOPNOTSUPP; | 1068 | return EOPNOTSUPP; | |
1073 | 1069 | |||
1074 | node = *rnode; | 1070 | node = *rnode; | |
1075 | node.sysctl_data = &fq; | 1071 | node.sysctl_data = &fq; | |
1076 | 1072 | |||
1077 | oldfq = 0; | 1073 | oldfq = 0; | |
1078 | if (rnode->sysctl_num == est_node_target) | 1074 | if (rnode->sysctl_num == est_node_target) | |
1079 | fq = oldfq = MSR2MHZ(rdmsr(MSR_PERF_CTL), bus_clock); | 1075 | fq = oldfq = MSR2MHZ(rdmsr(MSR_PERF_CTL), bus_clock); | |
1080 | else if (rnode->sysctl_num == est_node_current) | 1076 | else if (rnode->sysctl_num == est_node_current) | |
1081 | fq = MSR2MHZ(rdmsr(MSR_PERF_STATUS), bus_clock); | 1077 | fq = MSR2MHZ(rdmsr(MSR_PERF_STATUS), bus_clock); | |
1082 | else | 1078 | else | |
1083 | return EOPNOTSUPP; | 1079 | return EOPNOTSUPP; | |
1084 | 1080 | |||
1085 | error = sysctl_lookup(SYSCTLFN_CALL(&node)); | 1081 | error = sysctl_lookup(SYSCTLFN_CALL(&node)); | |
1086 | if (error || newp == NULL) | 1082 | if (error || newp == NULL) | |
1087 | return error; | 1083 | return error; | |
1088 | 1084 | |||
1089 | /* support writing to ...frequency.target */ | 1085 | /* support writing to ...frequency.target */ | |
1090 | if (rnode->sysctl_num == est_node_target && fq != oldfq) { | 1086 | if (rnode->sysctl_num == est_node_target && fq != oldfq) { | |
1091 | struct msr_rw_info msr; | 1087 | struct msr_rw_info msr; | |
1092 | uint64_t where; | 1088 | uint64_t where; | |
1093 | int i; | 1089 | int i; | |
1094 | 1090 | |||
1095 | for (i = est_fqlist->n - 1; i > 0; i--) | 1091 | for (i = est_fqlist->n - 1; i > 0; i--) | |
1096 | if (MSR2MHZ(est_fqlist->table[i], bus_clock) >= fq) | 1092 | if (MSR2MHZ(est_fqlist->table[i], bus_clock) >= fq) | |
1097 | break; | 1093 | break; | |
1098 | fq = MSR2MHZ(est_fqlist->table[i], bus_clock); | 1094 | fq = MSR2MHZ(est_fqlist->table[i], bus_clock); | |
1099 | 1095 | |||
1100 | msr.msr_read = true; | 1096 | msr.msr_read = true; | |
1101 | msr.msr_type = MSR_PERF_CTL; | 1097 | msr.msr_type = MSR_PERF_CTL; | |
1102 | msr.msr_mask = 0xffffULL; | 1098 | msr.msr_mask = 0xffffULL; | |
1103 | msr.msr_value = est_fqlist->table[i]; | 1099 | msr.msr_value = est_fqlist->table[i]; | |
1104 | 1100 | |||
1105 | where = xc_broadcast(0, (xcfunc_t)x86_msr_xcall, &msr, NULL); | 1101 | where = xc_broadcast(0, (xcfunc_t)x86_msr_xcall, &msr, NULL); | |
1106 | xc_wait(where); | 1102 | xc_wait(where); | |
1107 | } | 1103 | } | |
1108 | 1104 | |||
1109 | return 0; | 1105 | return 0; | |
1110 | } | 1106 | } | |
1111 | 1107 | |||
1112 | static int | 1108 | static int | |
1113 | est_init_once(void) | 1109 | est_init_once(void) | |
1114 | { | 1110 | { | |
1115 | est_init_main(lvendor); | 1111 | est_init_main(lvendor); | |
1116 | return 0; | 1112 | return 0; | |
1117 | } | 1113 | } | |
1118 | 1114 | |||
1119 | void | 1115 | void | |
1120 | est_init(int vendor) | 1116 | est_init(int vendor) | |
1121 | { | 1117 | { | |
1122 | int error; | 1118 | int error; | |
1123 | static ONCE_DECL(est_initialized); | 1119 | static ONCE_DECL(est_initialized); | |
1124 | 1120 | |||
1125 | lvendor = vendor; | 1121 | lvendor = vendor; | |
1126 | 1122 | |||
1127 | error = RUN_ONCE(&est_initialized, est_init_once); | 1123 | error = RUN_ONCE(&est_initialized, est_init_once); | |
1128 | if (__predict_false(error != 0)) | 1124 | if (__predict_false(error != 0)) | |
1129 | return; | 1125 | return; | |
1130 | } | 1126 | } | |
1131 | 1127 | |||
1132 | static void | 1128 | static void | |
1133 | est_init_main(int vendor) | 1129 | est_init_main(int vendor) | |
1134 | { | 1130 | { | |
1135 | #ifdef __i386__ | 1131 | #ifdef __i386__ | |
1136 | const struct fqlist *fql; | 1132 | const struct fqlist *fql; | |
1137 | #endif | 1133 | #endif | |
1138 | const struct sysctlnode *node, *estnode, *freqnode; | 1134 | const struct sysctlnode *node, *estnode, *freqnode; | |
1139 | uint64_t msr; | 1135 | uint64_t msr; | |
1140 | uint16_t cur, idhi, idlo; | 1136 | uint16_t cur, idhi, idlo; | |
1141 | uint8_t crhi, crlo, crcur; | 1137 | uint8_t crhi, crlo, crcur; | |
1142 | int i, mv, rc; | 1138 | int i, mv, rc; | |
1143 | size_t len, freq_len; | 1139 | size_t len, freq_len; | |
1144 | 1140 | |||
1145 | if (CPUID2FAMILY(curcpu()->ci_signature) == 15) | 1141 | if (CPUID2FAMILY(curcpu()->ci_signature) == 15) | |
1146 | bus_clock = p4_get_bus_clock(curcpu()); | 1142 | bus_clock = p4_get_bus_clock(curcpu()); | |
1147 | else if (CPUID2FAMILY(curcpu()->ci_signature) == 6) { | 1143 | else if (CPUID2FAMILY(curcpu()->ci_signature) == 6) { | |
1148 | if (vendor == CPUVENDOR_IDT) { | 1144 | if (vendor == CPUVENDOR_IDT) { | |
1149 | switch (CPUID2MODEL(curcpu()->ci_signature)) { | 1145 | switch (CPUID2MODEL(curcpu()->ci_signature)) { | |
1150 | case 0xa: /* C7 Esther */ | 1146 | case 0xa: /* C7 Esther */ | |
1151 | case 0xd: /* C7 Esther */ | 1147 | case 0xd: /* C7 Esther */ | |
1152 | bus_clock = viac7_get_bus_clock(curcpu()); | 1148 | bus_clock = viac7_get_bus_clock(curcpu()); | |
1153 | break; | 1149 | break; | |
1154 | default: | 1150 | default: | |
1155 | bus_clock = via_get_bus_clock(curcpu()); | 1151 | bus_clock = via_get_bus_clock(curcpu()); | |
1156 | break; | 1152 | break; | |
1157 | } | 1153 | } | |
1158 | } else | 1154 | } else | |
1159 | bus_clock = p3_get_bus_clock(curcpu()); | 1155 | bus_clock = p3_get_bus_clock(curcpu()); | |
1160 | } | 1156 | } | |
1161 | 1157 | |||
1162 | if (bus_clock == 0) { | 1158 | if (bus_clock == 0) { | |
1163 | aprint_debug("%s: unknown system bus clock\n", __func__); | 1159 | aprint_debug("%s: unknown system bus clock\n", __func__); | |
1164 | return; | 1160 | return; | |
1165 | } | 1161 | } | |
1166 | 1162 | |||
1167 | msr = rdmsr(MSR_PERF_STATUS); | 1163 | msr = rdmsr(MSR_PERF_STATUS); | |
1168 | idhi = (msr >> 32) & 0xffff; | 1164 | idhi = (msr >> 32) & 0xffff; | |
1169 | idlo = (msr >> 48) & 0xffff; | 1165 | idlo = (msr >> 48) & 0xffff; | |
1170 | cur = msr & 0xffff; | 1166 | cur = msr & 0xffff; | |
1171 | crhi = (idhi >> 8) & 0xff; | 1167 | crhi = (idhi >> 8) & 0xff; | |
1172 | crlo = (idlo >> 8) & 0xff; | 1168 | crlo = (idlo >> 8) & 0xff; | |
1173 | crcur = (cur >> 8) & 0xff; | 1169 | crcur = (cur >> 8) & 0xff; | |
1174 | 1170 | |||
1175 | #ifdef __i386__ | 1171 | #ifdef __i386__ | |
1176 | if (idhi == 0 || idlo == 0 || cur == 0 || | 1172 | if (idhi == 0 || idlo == 0 || cur == 0 || | |
1177 | ((cur >> 8) & 0xff) < ((idlo >> 8) & 0xff) || | 1173 | ((cur >> 8) & 0xff) < ((idlo >> 8) & 0xff) || | |
1178 | ((cur >> 8) & 0xff) > ((idhi >> 8) & 0xff)) { | 1174 | ((cur >> 8) & 0xff) > ((idhi >> 8) & 0xff)) { | |
1179 | aprint_debug("%s: strange msr value 0x%016llx\n", | 1175 | aprint_debug("%s: strange msr value 0x%016llx\n", | |
1180 | __func__, msr); | 1176 | __func__, msr); | |
1181 | return; | 1177 | return; | |
1182 | } | 1178 | } | |
1183 | #endif | 1179 | #endif | |
1184 | 1180 | |||
1185 | #ifdef __amd64__ | 1181 | #ifdef __amd64__ | |
1186 | if (crlo == 0 || crhi == 0 || crcur == 0 || crhi == crlo || | 1182 | if (crlo == 0 || crhi == 0 || crcur == 0 || crhi == crlo || | |
1187 | crlo > crhi || crcur < crlo || crcur > crhi) { | 1183 | crlo > crhi || crcur < crlo || crcur > crhi) { | |
1188 | /* | 1184 | /* | |
1189 | * Do complain about other weirdness, because we first want to | 1185 | * Do complain about other weirdness, because we first want to | |
1190 | * know about it, before we decide what to do with it | 1186 | * know about it, before we decide what to do with it | |
1191 | */ | 1187 | */ | |
1192 | aprint_debug("%s: strange msr value 0x%" PRIu64 "\n", | 1188 | aprint_debug("%s: strange msr value 0x%" PRIu64 "\n", | |
1193 | __func__, msr); | 1189 | __func__, msr); | |
1194 | aprint_debug("%s: crhi=%" PRIu8 ", crlo=%" PRIu8 ", crcur=%" | 1190 | aprint_debug("%s: crhi=%" PRIu8 ", crlo=%" PRIu8 ", crcur=%" | |
1195 | PRIu8 "\n", __func__, crhi, crlo, crcur); | 1191 | PRIu8 "\n", __func__, crhi, crlo, crcur); | |
1196 | return; | 1192 | return; | |
1197 | } | 1193 | } | |
1198 | #endif | 1194 | #endif | |
1199 | 1195 | |||
1200 | msr = rdmsr(MSR_PERF_STATUS); | 1196 | msr = rdmsr(MSR_PERF_STATUS); | |
1201 | mv = MSR2MV(msr); | 1197 | mv = MSR2MV(msr); | |
1202 | 1198 | |||
1203 | #ifdef __i386__ | 1199 | #ifdef __i386__ | |
1204 | /* | 1200 | /* | |
1205 | * Find an entry which matches (vendor, bus_clock, idhi, idlo) | 1201 | * Find an entry which matches (vendor, bus_clock, idhi, idlo) | |
1206 | */ | 1202 | */ | |
1207 | est_fqlist = NULL; | 1203 | est_fqlist = NULL; | |
1208 | for (i = 0; i < __arraycount(est_cpus); i++) { | 1204 | for (i = 0; i < __arraycount(est_cpus); i++) { | |
1209 | fql = &est_cpus[i]; | 1205 | fql = &est_cpus[i]; | |
1210 | if (vendor == fql->vendor && bus_clock == BUS_CLK(fql) && | 1206 | if (vendor == fql->vendor && bus_clock == BUS_CLK(fql) && | |
1211 | idhi == fql->table[0] && idlo == fql->table[fql->n - 1]) { | 1207 | idhi == fql->table[0] && idlo == fql->table[fql->n - 1]) { | |
1212 | est_fqlist = fql; | 1208 | est_fqlist = fql; | |
1213 | break; | 1209 | break; | |
1214 | } | 1210 | } | |
1215 | } | 1211 | } | |
1216 | #endif | 1212 | #endif | |
1217 | 1213 | |||
1218 | if (est_fqlist == NULL) { | 1214 | if (est_fqlist == NULL) { | |
1219 | int j, tablesize, freq, volt; | 1215 | int j, tablesize, freq, volt; | |
1220 | int minfreq, minvolt, maxfreq, maxvolt, freqinc, voltinc; | 1216 | int minfreq, minvolt, maxfreq, maxvolt, freqinc, voltinc; | |
1221 | 1217 | |||
1222 | /* | 1218 | /* | |
1223 | * Some CPUs report the same frequency in idhi and idlo, | 1219 | * Some CPUs report the same frequency in idhi and idlo, | |
1224 | * so do not run est on them. | 1220 | * so do not run est on them. | |
1225 | */ | 1221 | */ | |
1226 | if (idhi == idlo) { | 1222 | if (idhi == idlo) { | |
1227 | aprint_debug("%s: idhi == idlo\n", __func__); | 1223 | aprint_debug("%s: idhi == idlo\n", __func__); | |
1228 | return; | 1224 | return; | |
1229 | } | 1225 | } | |
1230 | 1226 | |||
1231 | #ifdef EST_DEBUG | 1227 | #ifdef EST_DEBUG | |
1232 | printf("%s: bus_clock = %d\n", __func__, bus_clock); | 1228 | printf("%s: bus_clock = %d\n", __func__, bus_clock); | |
1233 | printf("%s: idlo = 0x%x\n", __func__, idlo); | 1229 | printf("%s: idlo = 0x%x\n", __func__, idlo); | |
1234 | printf("%s: lo %4d mV, %4d MHz\n", __func__, | 1230 | printf("%s: lo %4d mV, %4d MHz\n", __func__, | |
1235 | MSR2MV(idlo), MSR2MHZ(idlo, bus_clock)); | 1231 | MSR2MV(idlo), MSR2MHZ(idlo, bus_clock)); | |
1236 | printf("%s: raw %4d , %4d \n", __func__, | 1232 | printf("%s: raw %4d , %4d \n", __func__, | |
1237 | (idlo & 0xff), ((idlo >> 8) & 0xff)); | 1233 | (idlo & 0xff), ((idlo >> 8) & 0xff)); | |
1238 | printf("%s: idhi = 0x%x\n", __func__, idhi); | 1234 | printf("%s: idhi = 0x%x\n", __func__, idhi); | |
1239 | printf("%s: hi %4d mV, %4d MHz\n", __func__, | 1235 | printf("%s: hi %4d mV, %4d MHz\n", __func__, | |
1240 | MSR2MV(idhi), MSR2MHZ(idhi, bus_clock)); | 1236 | MSR2MV(idhi), MSR2MHZ(idhi, bus_clock)); | |
1241 | printf("%s: raw %4d , %4d \n", __func__, | 1237 | printf("%s: raw %4d , %4d \n", __func__, | |
1242 | (idhi & 0xff), ((idhi >> 8) & 0xff)); | 1238 | (idhi & 0xff), ((idhi >> 8) & 0xff)); | |
1243 | printf("%s: cur = 0x%x\n", __func__, cur); | 1239 | printf("%s: cur = 0x%x\n", __func__, cur); | |
1244 | #endif | 1240 | #endif | |
1245 | 1241 | |||
1246 | /* | 1242 | /* | |
1247 | * Generate a fake table with the power states we know, | 1243 | * Generate a fake table with the power states we know, | |
1248 | * interpolating the voltages and frequencies between the | 1244 | * interpolating the voltages and frequencies between the | |
1249 | * high and low values. The (milli)voltages are always | 1245 | * high and low values. The (milli)voltages are always | |
1250 | * rounded up when computing the table. | 1246 | * rounded up when computing the table. | |
1251 | */ | 1247 | */ | |
1252 | minfreq = MSR2FREQINC(idlo); | 1248 | minfreq = MSR2FREQINC(idlo); | |
1253 | maxfreq = MSR2FREQINC(idhi); | 1249 | maxfreq = MSR2FREQINC(idhi); | |
1254 | minvolt = MSR2VOLTINC(idlo); | 1250 | minvolt = MSR2VOLTINC(idlo); | |
1255 | maxvolt = MSR2VOLTINC(idhi); | 1251 | maxvolt = MSR2VOLTINC(idhi); | |
1256 | freqinc = maxfreq - minfreq; | 1252 | freqinc = maxfreq - minfreq; | |
1257 | voltinc = maxvolt - minvolt; | 1253 | voltinc = maxvolt - minvolt; | |
1258 | 1254 | |||
1259 | /* Avoid diving by zero. */ | 1255 | /* Avoid diving by zero. */ | |
1260 | if (freqinc == 0) | 1256 | if (freqinc == 0) | |
1261 | return; | 1257 | return; | |
1262 | 1258 | |||
1263 | if (freqinc < voltinc || voltinc == 0) { | 1259 | if (freqinc < voltinc || voltinc == 0) { | |
1264 | tablesize = maxfreq - minfreq + 1; | 1260 | tablesize = maxfreq - minfreq + 1; | |
1265 | if (voltinc != 0) | 1261 | if (voltinc != 0) | |
1266 | voltinc = voltinc * 100 / freqinc - 1; | 1262 | voltinc = voltinc * 100 / freqinc - 1; | |
1267 | freqinc = 100; | 1263 | freqinc = 100; | |
1268 | } else { | 1264 | } else { | |
1269 | tablesize = maxvolt - minvolt + 1; | 1265 | tablesize = maxvolt - minvolt + 1; | |
1270 | freqinc = freqinc * 100 / voltinc - 1; | 1266 | freqinc = freqinc * 100 / voltinc - 1; | |
1271 | voltinc = 100; | 1267 | voltinc = 100; | |
1272 | } | 1268 | } | |
1273 | 1269 | |||
1274 | fake_table = malloc(tablesize * sizeof(uint16_t), M_DEVBUF, | 1270 | fake_table = malloc(tablesize * sizeof(uint16_t), M_DEVBUF, | |
1275 | M_WAITOK); | 1271 | M_WAITOK); | |
1276 | fake_fqlist.n = tablesize; | 1272 | fake_fqlist.n = tablesize; | |
1277 | 1273 | |||
1278 | /* The frequency/voltage table is highest frequency first */ | 1274 | /* The frequency/voltage table is highest frequency first */ | |
1279 | freq = maxfreq * 100; | 1275 | freq = maxfreq * 100; | |
1280 | volt = maxvolt * 100; | 1276 | volt = maxvolt * 100; | |
1281 | for (j = 0; j < tablesize; j++) { | 1277 | for (j = 0; j < tablesize; j++) { | |
1282 | fake_table[j] = (((freq + 99) / 100) << 8) + | 1278 | fake_table[j] = (((freq + 99) / 100) << 8) + | |
1283 | (volt + 99) / 100; | 1279 | (volt + 99) / 100; | |
1284 | #ifdef EST_DEBUG | 1280 | #ifdef EST_DEBUG | |
1285 | printf("%s: fake entry %d: %4d mV, %4d MHz " | 1281 | printf("%s: fake entry %d: %4d mV, %4d MHz " | |
1286 | "MSR*100 mV = %4d freq = %4d\n", | 1282 | "MSR*100 mV = %4d freq = %4d\n", | |
1287 | __func__, j, MSR2MV(fake_table[j]), | 1283 | __func__, j, MSR2MV(fake_table[j]), | |
1288 | MSR2MHZ(fake_table[j], bus_clock), | 1284 | MSR2MHZ(fake_table[j], bus_clock), | |
1289 | volt, freq); | 1285 | volt, freq); | |
1290 | #endif /* EST_DEBUG */ | 1286 | #endif /* EST_DEBUG */ | |
1291 | freq -= freqinc; | 1287 | freq -= freqinc; | |
1292 | volt -= voltinc; | 1288 | volt -= voltinc; | |
1293 | } | 1289 | } | |
1294 | fake_fqlist.vendor = vendor; | 1290 | fake_fqlist.vendor = vendor; | |
1295 | fake_fqlist.table = fake_table; | 1291 | fake_fqlist.table = fake_table; | |
1296 | est_fqlist = &fake_fqlist; | 1292 | est_fqlist = &fake_fqlist; | |
1297 | } | 1293 | } | |
1298 | 1294 | |||
1299 | /* | 1295 | /* | |
1300 | * OK, tell the user the available frequencies. | 1296 | * OK, tell the user the available frequencies. | |
1301 | */ | 1297 | */ | |
1302 | freq_len = est_fqlist->n * (sizeof("9999 ")-1) + 1; | 1298 | freq_len = est_fqlist->n * (sizeof("9999 ")-1) + 1; | |
1303 | freq_names = malloc(freq_len, M_SYSCTLDATA, M_WAITOK); | 1299 | freq_names = malloc(freq_len, M_SYSCTLDATA, M_WAITOK); | |
1304 | freq_names[0] = '\0'; | 1300 | freq_names[0] = '\0'; | |
1305 | len = 0; | 1301 | len = 0; | |
1306 | for (i = 0; i < est_fqlist->n; i++) { | 1302 | for (i = 0; i < est_fqlist->n; i++) { | |
1307 | len += snprintf(freq_names + len, freq_len - len, "%d%s", | 1303 | len += snprintf(freq_names + len, freq_len - len, "%d%s", | |
1308 | MSR2MHZ(est_fqlist->table[i], bus_clock), | 1304 | MSR2MHZ(est_fqlist->table[i], bus_clock), | |
1309 | i < est_fqlist->n - 1 ? " " : ""); | 1305 | i < est_fqlist->n - 1 ? " " : ""); | |
1310 | } | 1306 | } | |
1311 | 1307 | |||
1312 | aprint_debug_dev(curcpu()->ci_dev, "%s (%d mV) ", est_desc, mv); | 1308 | aprint_debug_dev(curcpu()->ci_dev, "%s (%d mV) ", est_desc, mv); | |
1313 | aprint_debug("%d (MHz): %s\n", MSR2MHZ(msr, bus_clock), freq_names); | 1309 | aprint_debug("%d (MHz): %s\n", MSR2MHZ(msr, bus_clock), freq_names); | |
1314 | 1310 | |||
1315 | /* | 1311 | /* | |
1316 | * Setup the sysctl sub-tree machdep.est.* | 1312 | * Setup the sysctl sub-tree machdep.est.* | |
1317 | */ | 1313 | */ | |
1318 | if ((rc = sysctl_createv(NULL, 0, NULL, &node, | 1314 | if ((rc = sysctl_createv(NULL, 0, NULL, &node, | |
1319 | CTLFLAG_PERMANENT, CTLTYPE_NODE, "machdep", NULL, | 1315 | CTLFLAG_PERMANENT, CTLTYPE_NODE, "machdep", NULL, | |
1320 | NULL, 0, NULL, 0, CTL_MACHDEP, CTL_EOL)) != 0) | 1316 | NULL, 0, NULL, 0, CTL_MACHDEP, CTL_EOL)) != 0) | |
1321 | goto err; | 1317 | goto err; | |
1322 | 1318 | |||
1323 | if ((rc = sysctl_createv(NULL, 0, &node, &estnode, | 1319 | if ((rc = sysctl_createv(NULL, 0, &node, &estnode, | |
1324 | 0, CTLTYPE_NODE, "est", NULL, | 1320 | 0, CTLTYPE_NODE, "est", NULL, | |
1325 | NULL, 0, NULL, 0, CTL_CREATE, CTL_EOL)) != 0) | 1321 | NULL, 0, NULL, 0, CTL_CREATE, CTL_EOL)) != 0) | |
1326 | goto err; | 1322 | goto err; | |
1327 | 1323 | |||
1328 | if ((rc = sysctl_createv(NULL, 0, &estnode, &freqnode, | 1324 | if ((rc = sysctl_createv(NULL, 0, &estnode, &freqnode, | |
1329 | 0, CTLTYPE_NODE, "frequency", NULL, | 1325 | 0, CTLTYPE_NODE, "frequency", NULL, | |
1330 | NULL, 0, NULL, 0, CTL_CREATE, CTL_EOL)) != 0) | 1326 | NULL, 0, NULL, 0, CTL_CREATE, CTL_EOL)) != 0) | |
1331 | goto err; | 1327 | goto err; | |
1332 | 1328 | |||
1333 | if ((rc = sysctl_createv(NULL, 0, &freqnode, &node, | 1329 | if ((rc = sysctl_createv(NULL, 0, &freqnode, &node, | |
1334 | EST_TARGET_CTLFLAG, CTLTYPE_INT, "target", NULL, | 1330 | EST_TARGET_CTLFLAG, CTLTYPE_INT, "target", NULL, | |
1335 | est_sysctl_helper_set, 0, NULL, 0, CTL_CREATE, CTL_EOL)) != 0) | 1331 | est_sysctl_helper_set, 0, NULL, 0, CTL_CREATE, CTL_EOL)) != 0) | |
1336 | goto err; | 1332 | goto err; | |
1337 | 1333 | |||
1338 | est_node_target = node->sysctl_num; | 1334 | est_node_target = node->sysctl_num; | |
1339 | 1335 | |||
1340 | if ((rc = sysctl_createv(NULL, 0, &freqnode, &node, | 1336 | if ((rc = sysctl_createv(NULL, 0, &freqnode, &node, | |
1341 | 0, CTLTYPE_INT, "current", NULL, | 1337 | 0, CTLTYPE_INT, "current", NULL, | |
1342 | est_sysctl_helper_get, 0, NULL, 0, CTL_CREATE, CTL_EOL)) != 0) | 1338 | est_sysctl_helper_get, 0, NULL, 0, CTL_CREATE, CTL_EOL)) != 0) | |
1343 | goto err; | 1339 | goto err; | |
1344 | 1340 | |||
1345 | est_node_current = node->sysctl_num; | 1341 | est_node_current = node->sysctl_num; | |
1346 | 1342 | |||
1347 | if ((rc = sysctl_createv(NULL, 0, &freqnode, &node, | 1343 | if ((rc = sysctl_createv(NULL, 0, &freqnode, &node, | |
1348 | CTLFLAG_READONLY, CTLTYPE_STRING, "available", NULL, | 1344 | CTLFLAG_READONLY, CTLTYPE_STRING, "available", NULL, | |
1349 | est_sysctl_helper_all, 0, NULL, 0, CTL_CREATE, CTL_EOL)) != 0) | 1345 | est_sysctl_helper_all, 0, NULL, 0, CTL_CREATE, CTL_EOL)) != 0) | |
1350 | goto err; | 1346 | goto err; | |
1351 | 1347 | |||
1352 | return; | 1348 | return; | |
1353 | 1349 | |||
1354 | err: | 1350 | err: | |
1355 | free(freq_names, M_SYSCTLDATA); | 1351 | free(freq_names, M_SYSCTLDATA); | |
1356 | freq_names = NULL; | 1352 | freq_names = NULL; | |
1357 | 1353 | |||
1358 | aprint_error("%s: sysctl_createv failed (rc = %d)\n", __func__, rc); | 1354 | aprint_error("%s: sysctl_createv failed (rc = %d)\n", __func__, rc); | |
1359 | } | 1355 | } |