1 /* $OpenBSD: est.c,v 1.55 2023/01/30 10:49:05 jsg Exp $ */
2 /*
3 * Copyright (c) 2003 Michael Eriksson.
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
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
15 * derived from this software without specific prior written permission.
16 *
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
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
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
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
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29
30 /*
31 * This is a driver for Intel's Enhanced SpeedStep, as implemented in
32 * Pentium M processors.
33 *
34 * Reference documentation:
35 *
36 * - IA-32 Intel Architecture Software Developer's Manual, Volume 3:
37 * System Programming Guide.
38 * Section 13.14, Enhanced Intel SpeedStep technology.
39 * Table B-2, MSRs in Pentium M Processors.
40 * http://www.intel.com/design/pentium4/manuals/245472.htm
41 *
42 * - Intel Pentium M Processor Datasheet.
43 * Table 5, Voltage and Current Specifications.
44 * http://www.intel.com/design/mobile/datashts/252612.htm
45 *
46 * - Intel Pentium M Processor on 90 nm Process with 2-MB L2 Cache Datasheet
47 * Table 3-4, Voltage and Current Specifications.
48 * http://www.intel.com/design/mobile/datashts/302189.htm
49 *
50 * - Linux cpufreq patches, speedstep-centrino.c.
51 * Encoding of MSR_PERF_CTL and MSR_PERF_STATUS.
52 * http://www.codemonkey.org.uk/projects/cpufreq/cpufreq-2.4.22-pre6-1.gz
53 */
54
55
56 #include <sys/param.h>
57 #include <sys/systm.h>
58 #include <sys/sysctl.h>
59 #include <sys/malloc.h>
60
61 #include <machine/cpu.h>
62 #include <machine/cpufunc.h>
63 #include <machine/specialreg.h>
64 #include <machine/bus.h>
65
66 #include "acpicpu.h"
67
68 #if NACPICPU > 0
69 #include <dev/acpi/acpidev.h>
70 #endif
71
72 /* Convert MHz and mV into IDs for passing to the MSR. */
73 #define ID16(MHz, mV, bus_clk) \
74 { ((((MHz * 100 + 50) / bus_clk) << 8) | ((mV ? mV - 700 : 0) >> 4)), \
75 MHz }
76
77 struct est_op {
78 uint16_t ctrl;
79 uint16_t mhz;
80 uint16_t pct;
81 };
82
83 /* Ultra Low Voltage Intel Pentium M processor 900 MHz */
84 static struct est_op pm130_900_ulv[] = {
85 ID16( 900, 1004, BUS100),
86 ID16( 800, 988, BUS100),
87 ID16( 600, 844, BUS100),
88 };
89
90 /* Ultra Low Voltage Intel Pentium M processor 1.00 GHz */
91 static struct est_op pm130_1000_ulv[] = {
92 ID16(1000, 1004, BUS100),
93 ID16( 900, 988, BUS100),
94 ID16( 800, 972, BUS100),
95 ID16( 600, 844, BUS100),
96 };
97
98 /* Ultra Low Voltage Intel Pentium M processor 1.10 GHz */
99 static struct est_op pm130_1100_ulv[] = {
100 ID16(1100, 1004, BUS100),
101 ID16(1000, 988, BUS100),
102 ID16( 900, 972, BUS100),
103 ID16( 800, 956, BUS100),
104 ID16( 600, 844, BUS100),
105 };
106
107 /* Low Voltage Intel Pentium M processor 1.10 GHz */
108 static struct est_op pm130_1100_lv[] = {
109 ID16(1100, 1180, BUS100),
110 ID16(1000, 1164, BUS100),
111 ID16( 900, 1100, BUS100),
112 ID16( 800, 1020, BUS100),
113 ID16( 600, 956, BUS100),
114 };
115
116 /* Low Voltage Intel Pentium M processor 1.20 GHz */
117 static struct est_op pm130_1200_lv[] = {
118 ID16(1200, 1180, BUS100),
119 ID16(1100, 1164, BUS100),
120 ID16(1000, 1100, BUS100),
121 ID16( 900, 1020, BUS100),
122 ID16( 800, 1004, BUS100),
123 ID16( 600, 956, BUS100),
124 };
125
126 /* Low Voltage Intel Pentium M processor 1.30 GHz */
127 static struct est_op pm130_1300_lv[] = {
128 ID16(1300, 1180, BUS100),
129 ID16(1200, 1164, BUS100),
130 ID16(1100, 1100, BUS100),
131 ID16(1000, 1020, BUS100),
132 ID16( 900, 1004, BUS100),
133 ID16( 800, 988, BUS100),
134 ID16( 600, 956, BUS100),
135 };
136
137 /* Intel Pentium M processor 1.30 GHz */
138 static struct est_op pm130_1300[] = {
139 ID16(1300, 1388, BUS100),
140 ID16(1200, 1356, BUS100),
141 ID16(1000, 1292, BUS100),
142 ID16( 800, 1260, BUS100),
143 ID16( 600, 956, BUS100),
144 };
145
146 /* Intel Pentium M processor 1.40 GHz */
147 static struct est_op pm130_1400[] = {
148 ID16(1400, 1484, BUS100),
149 ID16(1200, 1436, BUS100),
150 ID16(1000, 1308, BUS100),
151 ID16( 800, 1180, BUS100),
152 ID16( 600, 956, BUS100),
153 };
154
155 /* Intel Pentium M processor 1.50 GHz */
156 static struct est_op pm130_1500[] = {
157 ID16(1500, 1484, BUS100),
158 ID16(1400, 1452, BUS100),
159 ID16(1200, 1356, BUS100),
160 ID16(1000, 1228, BUS100),
161 ID16( 800, 1116, BUS100),
162 ID16( 600, 956, BUS100),
163 };
164
165 /* Intel Pentium M processor 1.60 GHz */
166 static struct est_op pm130_1600[] = {
167 ID16(1600, 1484, BUS100),
168 ID16(1400, 1420, BUS100),
169 ID16(1200, 1276, BUS100),
170 ID16(1000, 1164, BUS100),
171 ID16( 800, 1036, BUS100),
172 ID16( 600, 956, BUS100),
173 };
174
175 /* Intel Pentium M processor 1.70 GHz */
176 static struct est_op pm130_1700[] = {
177 ID16(1700, 1484, BUS100),
178 ID16(1400, 1308, BUS100),
179 ID16(1200, 1228, BUS100),
180 ID16(1000, 1116, BUS100),
181 ID16( 800, 1004, BUS100),
182 ID16( 600, 956, BUS100),
183 };
184
185 /* Intel Pentium M processor 723 1.0 GHz */
186 static struct est_op pm90_n723[] = {
187 ID16(1000, 940, BUS100),
188 ID16( 900, 908, BUS100),
189 ID16( 800, 876, BUS100),
190 ID16( 600, 812, BUS100),
191 };
192
193 /* Intel Pentium M processor 733 1.1 GHz, VID #G */
194 static struct est_op pm90_n733g[] = {
195 ID16(1100, 956, BUS100),
196 ID16(1000, 940, BUS100),
197 ID16( 900, 908, BUS100),
198 ID16( 800, 876, BUS100),
199 ID16( 600, 812, BUS100),
200 };
201
202 /* Intel Pentium M processor 733 1.1 GHz, VID #H */
203 static struct est_op pm90_n733h[] = {
204 ID16(1100, 940, BUS100),
205 ID16(1000, 924, BUS100),
206 ID16( 900, 892, BUS100),
207 ID16( 800, 876, BUS100),
208 ID16( 600, 812, BUS100),
209 };
210
211 /* Intel Pentium M processor 733 1.1 GHz, VID #I */
212 static struct est_op pm90_n733i[] = {
213 ID16(1100, 924, BUS100),
214 ID16(1000, 908, BUS100),
215 ID16( 900, 892, BUS100),
216 ID16( 800, 860, BUS100),
217 ID16( 600, 812, BUS100),
218 };
219
220 /* Intel Pentium M processor 733 1.1 GHz, VID #J */
221 static struct est_op pm90_n733j[] = {
222 ID16(1100, 908, BUS100),
223 ID16(1000, 892, BUS100),
224 ID16( 900, 876, BUS100),
225 ID16( 800, 860, BUS100),
226 ID16( 600, 812, BUS100),
227 };
228
229 /* Intel Pentium M processor 733 1.1 GHz, VID #K */
230 static struct est_op pm90_n733k[] = {
231 ID16(1100, 892, BUS100),
232 ID16(1000, 876, BUS100),
233 ID16( 900, 860, BUS100),
234 ID16( 800, 844, BUS100),
235 ID16( 600, 812, BUS100),
236 };
237
238 /* Intel Pentium M processor 733 1.1 GHz, VID #L */
239 static struct est_op pm90_n733l[] = {
240 ID16(1100, 876, BUS100),
241 ID16(1000, 876, BUS100),
242 ID16( 900, 860, BUS100),
243 ID16( 800, 844, BUS100),
244 ID16( 600, 812, BUS100),
245 };
246
247 /* Intel Pentium M processor 753 1.2 GHz, VID #G */
248 static struct est_op pm90_n753g[] = {
249 ID16(1200, 956, BUS100),
250 ID16(1100, 940, BUS100),
251 ID16(1000, 908, BUS100),
252 ID16( 900, 892, BUS100),
253 ID16( 800, 860, BUS100),
254 ID16( 600, 812, BUS100),
255 };
256
257 /* Intel Pentium M processor 753 1.2 GHz, VID #H */
258 static struct est_op pm90_n753h[] = {
259 ID16(1200, 940, BUS100),
260 ID16(1100, 924, BUS100),
261 ID16(1000, 908, BUS100),
262 ID16( 900, 876, BUS100),
263 ID16( 800, 860, BUS100),
264 ID16( 600, 812, BUS100),
265 };
266
267 /* Intel Pentium M processor 753 1.2 GHz, VID #I */
268 static struct est_op pm90_n753i[] = {
269 ID16(1200, 924, BUS100),
270 ID16(1100, 908, BUS100),
271 ID16(1000, 892, BUS100),
272 ID16( 900, 876, BUS100),
273 ID16( 800, 860, BUS100),
274 ID16( 600, 812, BUS100),
275 };
276
277 /* Intel Pentium M processor 753 1.2 GHz, VID #J */
278 static struct est_op pm90_n753j[] = {
279 ID16(1200, 908, BUS100),
280 ID16(1100, 892, BUS100),
281 ID16(1000, 876, BUS100),
282 ID16( 900, 860, BUS100),
283 ID16( 800, 844, BUS100),
284 ID16( 600, 812, BUS100),
285 };
286
287 /* Intel Pentium M processor 753 1.2 GHz, VID #K */
288 static struct est_op pm90_n753k[] = {
289 ID16(1200, 892, BUS100),
290 ID16(1100, 892, BUS100),
291 ID16(1000, 876, BUS100),
292 ID16( 900, 860, BUS100),
293 ID16( 800, 844, BUS100),
294 ID16( 600, 812, BUS100),
295 };
296
297 /* Intel Pentium M processor 753 1.2 GHz, VID #L */
298 static struct est_op pm90_n753l[] = {
299 ID16(1200, 876, BUS100),
300 ID16(1100, 876, BUS100),
301 ID16(1000, 860, BUS100),
302 ID16( 900, 844, BUS100),
303 ID16( 800, 844, BUS100),
304 ID16( 600, 812, BUS100),
305 };
306
307 /* Intel Pentium M processor 773 1.3 GHz, VID #G */
308 static struct est_op pm90_n773g[] = {
309 ID16(1300, 956, BUS100),
310 ID16(1200, 940, BUS100),
311 ID16(1100, 924, BUS100),
312 ID16(1000, 908, BUS100),
313 ID16( 900, 876, BUS100),
314 ID16( 800, 860, BUS100),
315 ID16( 600, 812, BUS100),
316 };
317
318 /* Intel Pentium M processor 773 1.3 GHz, VID #H */
319 static struct est_op pm90_n773h[] = {
320 ID16(1300, 940, BUS100),
321 ID16(1200, 924, BUS100),
322 ID16(1100, 908, BUS100),
323 ID16(1000, 892, BUS100),
324 ID16( 900, 876, BUS100),
325 ID16( 800, 860, BUS100),
326 ID16( 600, 812, BUS100),
327 };
328
329 /* Intel Pentium M processor 773 1.3 GHz, VID #I */
330 static struct est_op pm90_n773i[] = {
331 ID16(1300, 924, BUS100),
332 ID16(1200, 908, BUS100),
333 ID16(1100, 892, BUS100),
334 ID16(1000, 876, BUS100),
335 ID16( 900, 860, BUS100),
336 ID16( 800, 844, BUS100),
337 ID16( 600, 812, BUS100),
338 };
339
340 /* Intel Pentium M processor 773 1.3 GHz, VID #J */
341 static struct est_op pm90_n773j[] = {
342 ID16(1300, 908, BUS100),
343 ID16(1200, 908, BUS100),
344 ID16(1100, 892, BUS100),
345 ID16(1000, 876, BUS100),
346 ID16( 900, 860, BUS100),
347 ID16( 800, 844, BUS100),
348 ID16( 600, 812, BUS100),
349 };
350
351 /* Intel Pentium M processor 773 1.3 GHz, VID #K */
352 static struct est_op pm90_n773k[] = {
353 ID16(1300, 892, BUS100),
354 ID16(1200, 892, BUS100),
355 ID16(1100, 876, BUS100),
356 ID16(1000, 860, BUS100),
357 ID16( 900, 860, BUS100),
358 ID16( 800, 844, BUS100),
359 ID16( 600, 812, BUS100),
360 };
361
362 /* Intel Pentium M processor 773 1.3 GHz, VID #L */
363 static struct est_op pm90_n773l[] = {
364 ID16(1300, 876, BUS100),
365 ID16(1200, 876, BUS100),
366 ID16(1100, 860, BUS100),
367 ID16(1000, 860, BUS100),
368 ID16( 900, 844, BUS100),
369 ID16( 800, 844, BUS100),
370 ID16( 600, 812, BUS100),
371 };
372
373 /* Intel Pentium M processor 738 1.4 GHz */
374 static struct est_op pm90_n738[] = {
375 ID16(1400, 1116, BUS100),
376 ID16(1300, 1116, BUS100),
377 ID16(1200, 1100, BUS100),
378 ID16(1100, 1068, BUS100),
379 ID16(1000, 1052, BUS100),
380 ID16( 900, 1036, BUS100),
381 ID16( 800, 1020, BUS100),
382 ID16( 600, 988, BUS100),
383 };
384
385 /* Intel Pentium M processor 758 1.5 GHz */
386 static struct est_op pm90_n758[] = {
387 ID16(1500, 1116, BUS100),
388 ID16(1400, 1116, BUS100),
389 ID16(1300, 1100, BUS100),
390 ID16(1200, 1084, BUS100),
391 ID16(1100, 1068, BUS100),
392 ID16(1000, 1052, BUS100),
393 ID16( 900, 1036, BUS100),
394 ID16( 800, 1020, BUS100),
395 ID16( 600, 988, BUS100),
396 };
397
398 /* Intel Pentium M processor 778 1.6 GHz */
399 static struct est_op pm90_n778[] = {
400 ID16(1600, 1116, BUS100),
401 ID16(1500, 1116, BUS100),
402 ID16(1400, 1100, BUS100),
403 ID16(1300, 1184, BUS100),
404 ID16(1200, 1068, BUS100),
405 ID16(1100, 1052, BUS100),
406 ID16(1000, 1052, BUS100),
407 ID16( 900, 1036, BUS100),
408 ID16( 800, 1020, BUS100),
409 ID16( 600, 988, BUS100),
410 };
411
412 /* Intel Pentium M processor 710 1.4 GHz, 533 MHz FSB */
413 static struct est_op pm90_n710[] = {
414 ID16(1400, 1340, BUS133),
415 ID16(1200, 1228, BUS133),
416 ID16(1000, 1148, BUS133),
417 ID16( 800, 1068, BUS133),
418 ID16( 600, 998, BUS133),
419 };
420
421 /* Intel Pentium M processor 715 1.5 GHz, VID #A */
422 static struct est_op pm90_n715a[] = {
423 ID16(1500, 1340, BUS100),
424 ID16(1200, 1228, BUS100),
425 ID16(1000, 1148, BUS100),
426 ID16( 800, 1068, BUS100),
427 ID16( 600, 988, BUS100),
428 };
429
430 /* Intel Pentium M processor 715 1.5 GHz, VID #B */
431 static struct est_op pm90_n715b[] = {
432 ID16(1500, 1324, BUS100),
433 ID16(1200, 1212, BUS100),
434 ID16(1000, 1148, BUS100),
435 ID16( 800, 1068, BUS100),
436 ID16( 600, 988, BUS100),
437 };
438
439 /* Intel Pentium M processor 715 1.5 GHz, VID #C */
440 static struct est_op pm90_n715c[] = {
441 ID16(1500, 1308, BUS100),
442 ID16(1200, 1212, BUS100),
443 ID16(1000, 1132, BUS100),
444 ID16( 800, 1068, BUS100),
445 ID16( 600, 988, BUS100),
446 };
447
448 /* Intel Pentium M processor 715 1.5 GHz, VID #D */
449 static struct est_op pm90_n715d[] = {
450 ID16(1500, 1276, BUS100),
451 ID16(1200, 1180, BUS100),
452 ID16(1000, 1116, BUS100),
453 ID16( 800, 1052, BUS100),
454 ID16( 600, 988, BUS100),
455 };
456
457 /* Intel Pentium M processor 725 1.6 GHz, VID #A */
458 static struct est_op pm90_n725a[] = {
459 ID16(1600, 1340, BUS100),
460 ID16(1400, 1276, BUS100),
461 ID16(1200, 1212, BUS100),
462 ID16(1000, 1132, BUS100),
463 ID16( 800, 1068, BUS100),
464 ID16( 600, 988, BUS100),
465 };
466
467 /* Intel Pentium M processor 725 1.6 GHz, VID #B */
468 static struct est_op pm90_n725b[] = {
469 ID16(1600, 1324, BUS100),
470 ID16(1400, 1260, BUS100),
471 ID16(1200, 1196, BUS100),
472 ID16(1000, 1132, BUS100),
473 ID16( 800, 1068, BUS100),
474 ID16( 600, 988, BUS100),
475 };
476
477 /* Intel Pentium M processor 725 1.6 GHz, VID #C */
478 static struct est_op pm90_n725c[] = {
479 ID16(1600, 1308, BUS100),
480 ID16(1400, 1244, BUS100),
481 ID16(1200, 1180, BUS100),
482 ID16(1000, 1116, BUS100),
483 ID16( 800, 1052, BUS100),
484 ID16( 600, 988, BUS100),
485 };
486
487 /* Intel Pentium M processor 725 1.6 GHz, VID #D */
488 static struct est_op pm90_n725d[] = {
489 ID16(1600, 1276, BUS100),
490 ID16(1400, 1228, BUS100),
491 ID16(1200, 1164, BUS100),
492 ID16(1000, 1116, BUS100),
493 ID16( 800, 1052, BUS100),
494 ID16( 600, 988, BUS100),
495 };
496
497 /* Intel Pentium M processor 730 1.6 GHz, 533 MHz FSB */
498 static struct est_op pm90_n730[] = {
499 ID16(1600, 1308, BUS133),
500 ID16(1333, 1260, BUS133),
501 ID16(1200, 1212, BUS133),
502 ID16(1067, 1180, BUS133),
503 ID16( 800, 988, BUS133),
504 };
505
506 /* Intel Pentium M processor 735 1.7 GHz, VID #A */
507 static struct est_op pm90_n735a[] = {
508 ID16(1700, 1340, BUS100),
509 ID16(1400, 1244, BUS100),
510 ID16(1200, 1180, BUS100),
511 ID16(1000, 1116, BUS100),
512 ID16( 800, 1052, BUS100),
513 ID16( 600, 988, BUS100),
514 };
515
516 /* Intel Pentium M processor 735 1.7 GHz, VID #B */
517 static struct est_op pm90_n735b[] = {
518 ID16(1700, 1324, BUS100),
519 ID16(1400, 1244, BUS100),
520 ID16(1200, 1180, BUS100),
521 ID16(1000, 1116, BUS100),
522 ID16( 800, 1052, BUS100),
523 ID16( 600, 988, BUS100),
524 };
525
526 /* Intel Pentium M processor 735 1.7 GHz, VID #C */
527 static struct est_op pm90_n735c[] = {
528 ID16(1700, 1308, BUS100),
529 ID16(1400, 1228, BUS100),
530 ID16(1200, 1164, BUS100),
531 ID16(1000, 1116, BUS100),
532 ID16( 800, 1052, BUS100),
533 ID16( 600, 988, BUS100),
534 };
535
536 /* Intel Pentium M processor 735 1.7 GHz, VID #D */
537 static struct est_op pm90_n735d[] = {
538 ID16(1700, 1276, BUS100),
539 ID16(1400, 1212, BUS100),
540 ID16(1200, 1148, BUS100),
541 ID16(1000, 1100, BUS100),
542 ID16( 800, 1052, BUS100),
543 ID16( 600, 988, BUS100),
544 };
545
546 /* Intel Pentium M processor 740 1.73 GHz, 533 MHz FSB */
547 static struct est_op pm90_n740[] = {
548 ID16(1733, 1356, BUS133),
549 ID16(1333, 1212, BUS133),
550 ID16(1067, 1100, BUS133),
551 ID16( 800, 988, BUS133),
552 };
553
554 /* Intel Pentium M processor 745 1.8 GHz, VID #A */
555 static struct est_op pm90_n745a[] = {
556 ID16(1800, 1340, BUS100),
557 ID16(1600, 1292, BUS100),
558 ID16(1400, 1228, BUS100),
559 ID16(1200, 1164, BUS100),
560 ID16(1000, 1116, BUS100),
561 ID16( 800, 1052, BUS100),
562 ID16( 600, 988, BUS100),
563 };
564
565 /* Intel Pentium M processor 745 1.8 GHz, VID #B */
566 static struct est_op pm90_n745b[] = {
567 ID16(1800, 1324, BUS100),
568 ID16(1600, 1276, BUS100),
569 ID16(1400, 1212, BUS100),
570 ID16(1200, 1164, BUS100),
571 ID16(1000, 1116, BUS100),
572 ID16( 800, 1052, BUS100),
573 ID16( 600, 988, BUS100),
574 };
575
576 /* Intel Pentium M processor 745 1.8 GHz, VID #C */
577 static struct est_op pm90_n745c[] = {
578 ID16(1800, 1308, BUS100),
579 ID16(1600, 1260, BUS100),
580 ID16(1400, 1212, BUS100),
581 ID16(1200, 1148, BUS100),
582 ID16(1000, 1100, BUS100),
583 ID16( 800, 1052, BUS100),
584 ID16( 600, 988, BUS100),
585 };
586
587 /* Intel Pentium M processor 745 1.8 GHz, VID #D */
588 static struct est_op pm90_n745d[] = {
589 ID16(1800, 1276, BUS100),
590 ID16(1600, 1228, BUS100),
591 ID16(1400, 1180, BUS100),
592 ID16(1200, 1132, BUS100),
593 ID16(1000, 1084, BUS100),
594 ID16( 800, 1036, BUS100),
595 ID16( 600, 988, BUS100),
596 };
597
598 /* Intel Pentium M processor 750 1.86 GHz, 533 MHz FSB */
599 /* values extracted from \_PR\NPSS (via _PSS) SDST ACPI table */
600 static struct est_op pm90_n750[] = {
601 ID16(1867, 1308, BUS133),
602 ID16(1600, 1228, BUS133),
603 ID16(1333, 1148, BUS133),
604 ID16(1067, 1068, BUS133),
605 ID16( 800, 988, BUS133),
606 };
607
608 /* Intel Pentium M processor 755 2.0 GHz, VID #A */
609 static struct est_op pm90_n755a[] = {
610 ID16(2000, 1340, BUS100),
611 ID16(1800, 1292, BUS100),
612 ID16(1600, 1244, BUS100),
613 ID16(1400, 1196, BUS100),
614 ID16(1200, 1148, BUS100),
615 ID16(1000, 1100, BUS100),
616 ID16( 800, 1052, BUS100),
617 ID16( 600, 988, BUS100),
618 };
619
620 /* Intel Pentium M processor 755 2.0 GHz, VID #B */
621 static struct est_op pm90_n755b[] = {
622 ID16(2000, 1324, BUS100),
623 ID16(1800, 1276, BUS100),
624 ID16(1600, 1228, BUS100),
625 ID16(1400, 1180, BUS100),
626 ID16(1200, 1132, BUS100),
627 ID16(1000, 1084, BUS100),
628 ID16( 800, 1036, BUS100),
629 ID16( 600, 988, BUS100),
630 };
631
632 /* Intel Pentium M processor 755 2.0 GHz, VID #C */
633 static struct est_op pm90_n755c[] = {
634 ID16(2000, 1308, BUS100),
635 ID16(1800, 1276, BUS100),
636 ID16(1600, 1228, BUS100),
637 ID16(1400, 1180, BUS100),
638 ID16(1200, 1132, BUS100),
639 ID16(1000, 1084, BUS100),
640 ID16( 800, 1036, BUS100),
641 ID16( 600, 988, BUS100),
642 };
643
644 /* Intel Pentium M processor 755 2.0 GHz, VID #D */
645 static struct est_op pm90_n755d[] = {
646 ID16(2000, 1276, BUS100),
647 ID16(1800, 1244, BUS100),
648 ID16(1600, 1196, BUS100),
649 ID16(1400, 1164, BUS100),
650 ID16(1200, 1116, BUS100),
651 ID16(1000, 1084, BUS100),
652 ID16( 800, 1036, BUS100),
653 ID16( 600, 988, BUS100),
654 };
655
656 /* Intel Pentium M processor 760 2.0 GHz, 533 MHz FSB */
657 static struct est_op pm90_n760[] = {
658 ID16(2000, 1356, BUS133),
659 ID16(1600, 1244, BUS133),
660 ID16(1333, 1164, BUS133),
661 ID16(1067, 1084, BUS133),
662 ID16( 800, 988, BUS133),
663 };
664
665 /* Intel Pentium M processor 765 2.1 GHz, VID #A */
666 static struct est_op pm90_n765a[] = {
667 ID16(2100, 1340, BUS100),
668 ID16(1800, 1276, BUS100),
669 ID16(1600, 1228, BUS100),
670 ID16(1400, 1180, BUS100),
671 ID16(1200, 1132, BUS100),
672 ID16(1000, 1084, BUS100),
673 ID16( 800, 1036, BUS100),
674 ID16( 600, 988, BUS100),
675 };
676
677 /* Intel Pentium M processor 765 2.1 GHz, VID #B */
678 static struct est_op pm90_n765b[] = {
679 ID16(2100, 1324, BUS100),
680 ID16(1800, 1260, BUS100),
681 ID16(1600, 1212, BUS100),
682 ID16(1400, 1180, BUS100),
683 ID16(1200, 1132, BUS100),
684 ID16(1000, 1084, BUS100),
685 ID16( 800, 1036, BUS100),
686 ID16( 600, 988, BUS100),
687 };
688
689 /* Intel Pentium M processor 765 2.1 GHz, VID #C */
690 static struct est_op pm90_n765c[] = {
691 ID16(2100, 1308, BUS100),
692 ID16(1800, 1244, BUS100),
693 ID16(1600, 1212, BUS100),
694 ID16(1400, 1164, BUS100),
695 ID16(1200, 1116, BUS100),
696 ID16(1000, 1084, BUS100),
697 ID16( 800, 1036, BUS100),
698 ID16( 600, 988, BUS100),
699 };
700
701 /* Intel Pentium M processor 765 2.1 GHz, VID #E */
702 static struct est_op pm90_n765e[] = {
703 ID16(2100, 1356, BUS100),
704 ID16(1800, 1292, BUS100),
705 ID16(1600, 1244, BUS100),
706 ID16(1400, 1196, BUS100),
707 ID16(1200, 1148, BUS100),
708 ID16(1000, 1100, BUS100),
709 ID16( 800, 1052, BUS100),
710 ID16( 600, 988, BUS100),
711 };
712
713 /* Intel Pentium M processor 770 2.13 GHz */
714 static struct est_op pm90_n770[] = {
715 ID16(2133, 1356, BUS133),
716 ID16(1867, 1292, BUS133),
717 ID16(1600, 1212, BUS133),
718 ID16(1333, 1148, BUS133),
719 ID16(1067, 1068, BUS133),
720 ID16( 800, 988, BUS133),
721 };
722
723 /*
724 * VIA C7-M 500 MHz FSB, 400 MHz FSB, and ULV variants.
725 * Data from the "VIA C7-M Processor BIOS Writer's Guide (v2.17)" datasheet.
726 */
727
728 /* 1.00GHz Centaur C7-M ULV */
729 static struct est_op C7M_770_ULV[] = {
730 ID16(1000, 844, BUS100),
731 ID16( 800, 796, BUS100),
732 ID16( 600, 796, BUS100),
733 ID16( 400, 796, BUS100),
734 };
735
736 /* 1.00GHz Centaur C7-M ULV */
737 static struct est_op C7M_779_ULV[] = {
738 ID16(1000, 796, BUS100),
739 ID16( 800, 796, BUS100),
740 ID16( 600, 796, BUS100),
741 ID16( 400, 796, BUS100),
742 };
743
744 /* 1.20GHz Centaur C7-M ULV */
745 static struct est_op C7M_772_ULV[] = {
746 ID16(1200, 844, BUS100),
747 ID16(1000, 844, BUS100),
748 ID16( 800, 828, BUS100),
749 ID16( 600, 796, BUS100),
750 ID16( 400, 796, BUS100),
751 };
752
753 /* 1.50GHz Centaur C7-M ULV */
754 static struct est_op C7M_775_ULV[] = {
755 ID16(1500, 956, BUS100),
756 ID16(1400, 940, BUS100),
757 ID16(1000, 860, BUS100),
758 ID16( 800, 828, BUS100),
759 ID16( 600, 796, BUS100),
760 ID16( 400, 796, BUS100),
761 };
762
763 /* 1.20GHz Centaur C7-M 400 MHz FSB */
764 static struct est_op C7M_771[] = {
765 ID16(1200, 860, BUS100),
766 ID16(1000, 860, BUS100),
767 ID16( 800, 844, BUS100),
768 ID16( 600, 844, BUS100),
769 ID16( 400, 844, BUS100),
770 };
771
772 /* 1.50GHz Centaur C7-M 400 MHz FSB */
773 static struct est_op C7M_754[] = {
774 ID16(1500, 1004, BUS100),
775 ID16(1400, 988, BUS100),
776 ID16(1000, 940, BUS100),
777 ID16( 800, 844, BUS100),
778 ID16( 600, 844, BUS100),
779 ID16( 400, 844, BUS100),
780 };
781
782 /* 1.60GHz Centaur C7-M 400 MHz FSB */
783 static struct est_op C7M_764[] = {
784 ID16(1600, 1084, BUS100),
785 ID16(1400, 1052, BUS100),
786 ID16(1000, 1004, BUS100),
787 ID16( 800, 844, BUS100),
788 ID16( 600, 844, BUS100),
789 ID16( 400, 844, BUS100),
790 };
791
792 /* 1.80GHz Centaur C7-M 400 MHz FSB */
793 static struct est_op C7M_784[] = {
794 ID16(1800, 1148, BUS100),
795 ID16(1600, 1100, BUS100),
796 ID16(1400, 1052, BUS100),
797 ID16(1000, 1004, BUS100),
798 ID16( 800, 844, BUS100),
799 ID16( 600, 844, BUS100),
800 ID16( 400, 844, BUS100),
801 };
802
803 /* 2.00GHz Centaur C7-M 400 MHz FSB */
804 static struct est_op C7M_794[] = {
805 ID16(2000, 1148, BUS100),
806 ID16(1800, 1132, BUS100),
807 ID16(1600, 1100, BUS100),
808 ID16(1400, 1052, BUS100),
809 ID16(1000, 1004, BUS100),
810 ID16( 800, 844, BUS100),
811 ID16( 600, 844, BUS100),
812 ID16( 400, 844, BUS100),
813 };
814
815 /* 1.60GHz Centaur C7-M 533 MHz FSB */
816 static struct est_op C7M_765[] = {
817 ID16(1600, 1084, BUS133),
818 ID16(1467, 1052, BUS133),
819 ID16(1200, 1004, BUS133),
820 ID16( 800, 844, BUS133),
821 ID16( 667, 844, BUS133),
822 ID16( 533, 844, BUS133),
823 };
824
825 /* 2.00GHz Centaur C7-M 533 MHz FSB */
826 static struct est_op C7M_785[] = {
827 ID16(1867, 1148, BUS133),
828 ID16(1600, 1100, BUS133),
829 ID16(1467, 1052, BUS133),
830 ID16(1200, 1004, BUS133),
831 ID16( 800, 844, BUS133),
832 ID16( 667, 844, BUS133),
833 ID16( 533, 844, BUS133),
834 };
835
836 /* 2.00GHz Centaur C7-M 533 MHz FSB */
837 static struct est_op C7M_795[] = {
838 ID16(2000, 1148, BUS133),
839 ID16(1867, 1132, BUS133),
840 ID16(1600, 1100, BUS133),
841 ID16(1467, 1052, BUS133),
842 ID16(1200, 1004, BUS133),
843 ID16( 800, 844, BUS133),
844 ID16( 667, 844, BUS133),
845 ID16( 533, 844, BUS133),
846 };
847
848 /* 1.00GHz VIA Eden 90nm 'Esther' */
849 static struct est_op eden90_1000[] = {
850 ID16(1000, 844, BUS100),
851 ID16( 800, 844, BUS100),
852 ID16( 600, 844, BUS100),
853 ID16( 400, 844, BUS100),
854 };
855
856
857 struct fqlist {
858 int vendor: 5;
859 unsigned bus_clk : 1;
860 unsigned n : 5;
861 struct est_op *table;
862 };
863
864 #define ENTRY(ven, bus_clk, tab) \
865 { CPUVENDOR_##ven, bus_clk == BUS133 ? 1 : 0, nitems(tab), tab }
866
867 #define BUS_CLK(fqp) ((fqp)->bus_clk ? BUS133 : BUS100)
868
869 static struct fqlist est_cpus[] = {
870 ENTRY(INTEL, BUS100, pm130_900_ulv),
871 ENTRY(INTEL, BUS100, pm130_1000_ulv),
872 ENTRY(INTEL, BUS100, pm130_1100_ulv),
873 ENTRY(INTEL, BUS100, pm130_1100_lv),
874 ENTRY(INTEL, BUS100, pm130_1200_lv),
875 ENTRY(INTEL, BUS100, pm130_1300_lv),
876 ENTRY(INTEL, BUS100, pm130_1300),
877 ENTRY(INTEL, BUS100, pm130_1400),
878 ENTRY(INTEL, BUS100, pm130_1500),
879 ENTRY(INTEL, BUS100, pm130_1600),
880 ENTRY(INTEL, BUS100, pm130_1700),
881
882 ENTRY(INTEL, BUS100, pm90_n723),
883 ENTRY(INTEL, BUS100, pm90_n733g),
884 ENTRY(INTEL, BUS100, pm90_n733h),
885 ENTRY(INTEL, BUS100, pm90_n733i),
886 ENTRY(INTEL, BUS100, pm90_n733j),
887 ENTRY(INTEL, BUS100, pm90_n733k),
888 ENTRY(INTEL, BUS100, pm90_n733l),
889 ENTRY(INTEL, BUS100, pm90_n753g),
890 ENTRY(INTEL, BUS100, pm90_n753h),
891 ENTRY(INTEL, BUS100, pm90_n753i),
892 ENTRY(INTEL, BUS100, pm90_n753j),
893 ENTRY(INTEL, BUS100, pm90_n753k),
894 ENTRY(INTEL, BUS100, pm90_n753l),
895 ENTRY(INTEL, BUS100, pm90_n773g),
896 ENTRY(INTEL, BUS100, pm90_n773h),
897 ENTRY(INTEL, BUS100, pm90_n773i),
898 ENTRY(INTEL, BUS100, pm90_n773j),
899 ENTRY(INTEL, BUS100, pm90_n773k),
900 ENTRY(INTEL, BUS100, pm90_n773l),
901 ENTRY(INTEL, BUS100, pm90_n738),
902 ENTRY(INTEL, BUS100, pm90_n758),
903 ENTRY(INTEL, BUS100, pm90_n778),
904
905 ENTRY(INTEL, BUS133, pm90_n710),
906 ENTRY(INTEL, BUS100, pm90_n715a),
907 ENTRY(INTEL, BUS100, pm90_n715b),
908 ENTRY(INTEL, BUS100, pm90_n715c),
909 ENTRY(INTEL, BUS100, pm90_n715d),
910 ENTRY(INTEL, BUS100, pm90_n725a),
911 ENTRY(INTEL, BUS100, pm90_n725b),
912 ENTRY(INTEL, BUS100, pm90_n725c),
913 ENTRY(INTEL, BUS100, pm90_n725d),
914 ENTRY(INTEL, BUS133, pm90_n730),
915 ENTRY(INTEL, BUS100, pm90_n735a),
916 ENTRY(INTEL, BUS100, pm90_n735b),
917 ENTRY(INTEL, BUS100, pm90_n735c),
918 ENTRY(INTEL, BUS100, pm90_n735d),
919 ENTRY(INTEL, BUS133, pm90_n740),
920 ENTRY(INTEL, BUS100, pm90_n745a),
921 ENTRY(INTEL, BUS100, pm90_n745b),
922 ENTRY(INTEL, BUS100, pm90_n745c),
923 ENTRY(INTEL, BUS100, pm90_n745d),
924 ENTRY(INTEL, BUS133, pm90_n750),
925 ENTRY(INTEL, BUS100, pm90_n755a),
926 ENTRY(INTEL, BUS100, pm90_n755b),
927 ENTRY(INTEL, BUS100, pm90_n755c),
928 ENTRY(INTEL, BUS100, pm90_n755d),
929 ENTRY(INTEL, BUS133, pm90_n760),
930 ENTRY(INTEL, BUS100, pm90_n765a),
931 ENTRY(INTEL, BUS100, pm90_n765b),
932 ENTRY(INTEL, BUS100, pm90_n765c),
933 ENTRY(INTEL, BUS100, pm90_n765e),
934 ENTRY(INTEL, BUS133, pm90_n770),
935
936 ENTRY(VIA, BUS100, C7M_770_ULV),
937 ENTRY(VIA, BUS100, C7M_779_ULV),
938 ENTRY(VIA, BUS100, C7M_772_ULV),
939 ENTRY(VIA, BUS100, C7M_771),
940 ENTRY(VIA, BUS100, C7M_775_ULV),
941 ENTRY(VIA, BUS100, C7M_754),
942 ENTRY(VIA, BUS100, C7M_764),
943 ENTRY(VIA, BUS133, C7M_765),
944 ENTRY(VIA, BUS100, C7M_784),
945 ENTRY(VIA, BUS133, C7M_785),
946 ENTRY(VIA, BUS100, C7M_794),
947 ENTRY(VIA, BUS133, C7M_795),
948
949 ENTRY(VIA, BUS100, eden90_1000),
950 };
951
952 #define MSR2MHZ(msr, bus) \
953 (((((int) (msr) >> 8) & 0xff) * (bus) + 50) / 100)
954 #define MSR2MV(msr) \
955 (((int) (msr) & 0xff) * 16 + 700)
956
957 static struct fqlist *est_fqlist;
958
959 extern int setperf_prio;
960 extern int perflevel;
961
962 void p4_get_bus_clock(struct cpu_info *);
963 void p3_get_bus_clock(struct cpu_info *);
964 void cyrix3_get_bus_clock(struct cpu_info *);
965
966 #if NACPICPU > 0
967 struct fqlist * est_acpi_init(void);
968 void est_acpi_pss_changed(struct acpicpu_pss *, int);
969
970 struct fqlist *
est_acpi_init(void)971 est_acpi_init(void)
972 {
973 struct acpicpu_pss *pss;
974 struct fqlist *acpilist;
975 int nstates, i;
976 int high, low;
977
978 if ((nstates = acpicpu_fetch_pss(&pss)) == 0)
979 goto nolist;
980
981 high = pss[0].pss_core_freq;
982 low = pss[nstates - 1].pss_core_freq;
983 if (high - low <= 0)
984 goto nolist;
985
986 if ((acpilist = malloc(sizeof(struct fqlist), M_DEVBUF, M_NOWAIT))
987 == NULL)
988 goto nolist;
989
990 if ((acpilist->table = mallocarray(nstates, sizeof(struct est_op),
991 M_DEVBUF, M_NOWAIT)) == NULL)
992 goto notable;
993
994 acpilist->n = nstates;
995
996 for (i = 0; i < nstates; i++) {
997 acpilist->table[i].mhz = pss[i].pss_core_freq;
998 acpilist->table[i].ctrl = pss[i].pss_ctrl;
999 acpilist->table[i].pct =
1000 (pss[i].pss_core_freq - low) * 100 / (high - low);
1001 }
1002
1003 acpicpu_set_notify(est_acpi_pss_changed);
1004
1005 return acpilist;
1006
1007 notable:
1008 free(acpilist, M_DEVBUF, sizeof(*acpilist));
1009 acpilist = NULL;
1010 nolist:
1011 return NULL;
1012 }
1013
1014 void
est_acpi_pss_changed(struct acpicpu_pss * pss,int npss)1015 est_acpi_pss_changed(struct acpicpu_pss *pss, int npss)
1016 {
1017 struct fqlist *acpilist;
1018 int needtran = 1, i;
1019 int high, low;
1020 u_int64_t msr;
1021 u_int16_t cur;
1022
1023 msr = rdmsr(MSR_PERF_STATUS);
1024 cur = msr & 0xffff;
1025
1026 high = pss[0].pss_core_freq;
1027 low = pss[npss - 1].pss_core_freq;
1028 if (high - low <= 0) {
1029 printf("est_acpi_pss_changed: new est state has no "
1030 "speed step\n");
1031 return;
1032 }
1033
1034 if ((acpilist = malloc(sizeof(struct fqlist), M_DEVBUF, M_NOWAIT))
1035 == NULL) {
1036 printf("est_acpi_pss_changed: cannot allocate memory for new "
1037 "est state\n");
1038 return;
1039 }
1040
1041 if ((acpilist->table = mallocarray(npss, sizeof(struct est_op),
1042 M_DEVBUF, M_NOWAIT)) == NULL) {
1043 printf("est_acpi_pss_changed: cannot allocate memory for new "
1044 "operating points\n");
1045 free(acpilist, M_DEVBUF, sizeof(*acpilist));
1046 return;
1047 }
1048
1049 for (i = 0; i < npss; i++) {
1050 acpilist->table[i].mhz = pss[i].pss_core_freq;
1051 acpilist->table[i].ctrl = pss[i].pss_ctrl;
1052 acpilist->table[i].pct =
1053 (pss[i].pss_core_freq - low) * 100 / (high - low);
1054 if (pss[i].pss_ctrl == cur)
1055 needtran = 0;
1056 }
1057
1058 free(est_fqlist->table, M_DEVBUF, npss * sizeof(struct est_op));
1059 free(est_fqlist, M_DEVBUF, sizeof *est_fqlist);
1060 est_fqlist = acpilist;
1061
1062 if (needtran) {
1063 est_setperf(perflevel);
1064 }
1065 }
1066 #endif
1067
1068 void
est_init(struct cpu_info * ci,int vendor)1069 est_init(struct cpu_info *ci, int vendor)
1070 {
1071 const char *cpu_device = ci->ci_dev->dv_xname;
1072 int i, low, high;
1073 u_int64_t msr;
1074 u_int16_t idhi, idlo, cur;
1075 u_int8_t crhi, crlo, crcur;
1076 struct fqlist *fql;
1077 struct fqlist *fake_fqlist;
1078 struct est_op *fake_table;
1079
1080 if (setperf_prio > 3)
1081 return;
1082
1083 #if NACPICPU > 0
1084 est_fqlist = est_acpi_init();
1085 #endif
1086
1087 /* bus_clock is only used if we can't get values from ACPI */
1088 if (est_fqlist == NULL) {
1089 if (vendor == CPUVENDOR_VIA)
1090 cyrix3_get_bus_clock(ci);
1091 else if (ci->ci_family == 0xf)
1092 p4_get_bus_clock(ci);
1093 else if (ci->ci_family == 6)
1094 p3_get_bus_clock(ci);
1095 }
1096
1097 /*
1098 * Interpreting the values of PERF_STATUS is not valid
1099 * on recent processors so don't do it on anything unknown
1100 */
1101 if (est_fqlist == NULL && bus_clock != 0) {
1102 msr = rdmsr(MSR_PERF_STATUS);
1103 idhi = (msr >> 32) & 0xffff;
1104 idlo = (msr >> 48) & 0xffff;
1105 cur = msr & 0xffff;
1106 crhi = (idhi >> 8) & 0xff;
1107 crlo = (idlo >> 8) & 0xff;
1108 crcur = (cur >> 8) & 0xff;
1109 /*
1110 * Find an entry which matches (vendor, bus_clock, idhi, idlo)
1111 */
1112 for (i = 0; i < nitems(est_cpus); i++) {
1113 fql = &est_cpus[i];
1114 if (vendor == fql->vendor && bus_clock == BUS_CLK(fql)
1115 && idhi == fql->table[0].ctrl
1116 && idlo == fql->table[fql->n - 1].ctrl) {
1117 est_fqlist = fql;
1118 break;
1119 }
1120 }
1121 }
1122
1123 if (est_fqlist == NULL && bus_clock != 0) {
1124 if (crhi == 0 || crcur == 0 || crlo > crhi ||
1125 crcur < crlo || crcur > crhi) {
1126 /*
1127 * Do complain about other weirdness, because we first
1128 * want to know about it, before we decide what to do
1129 * with it.
1130 */
1131 printf("%s: EST: strange msr value 0x%016llx\n",
1132 cpu_device, msr);
1133 return;
1134 }
1135 if (crlo == 0 || crhi == crlo) {
1136 /*
1137 * Don't complain about these cases, and silently
1138 * disable EST: - A lowest clock ratio of 0, which
1139 * seems to happen on all Pentium 4's that report EST.
1140 * - An equal highest and lowest clock ratio, which
1141 * happens on at least the Core 2 Duo X6800, maybe on
1142 * newer models too.
1143 */
1144 return;
1145 }
1146
1147 printf("%s: unknown Enhanced SpeedStep CPU, msr 0x%016llx\n",
1148 cpu_device, msr);
1149 /*
1150 * Generate a fake table with the power states we know.
1151 */
1152
1153 if ((fake_fqlist = malloc(sizeof(struct fqlist), M_DEVBUF,
1154 M_NOWAIT)) == NULL) {
1155 printf("%s: EST: cannot allocate memory for fake "
1156 "list\n", cpu_device);
1157 return;
1158 }
1159
1160
1161 if ((fake_table = mallocarray(3, sizeof(struct est_op),
1162 M_DEVBUF, M_NOWAIT)) == NULL) {
1163 free(fake_fqlist, M_DEVBUF, sizeof(struct fqlist));
1164 printf("%s: EST: cannot allocate memory for fake "
1165 "table\n", cpu_device);
1166 return;
1167 }
1168 fake_table[0].ctrl = idhi;
1169 fake_table[0].mhz = MSR2MHZ(idhi, bus_clock);
1170 if (cur == idhi || cur == idlo) {
1171 printf("%s: using only highest and lowest power "
1172 "states\n", cpu_device);
1173
1174 fake_table[0].pct = 51;
1175
1176 fake_table[1].ctrl = idlo;
1177 fake_table[1].mhz = MSR2MHZ(idlo, bus_clock);
1178 fake_table[1].pct = 0;
1179 fake_fqlist->n = 2;
1180 } else {
1181 printf("%s: using only highest, current and lowest "
1182 "power states\n", cpu_device);
1183
1184 fake_table[0].pct = 67;
1185
1186 fake_table[1].ctrl = cur;
1187 fake_table[1].mhz = MSR2MHZ(cur, bus_clock);
1188 fake_table[1].pct = 34;
1189
1190 fake_table[2].ctrl = idlo;
1191 fake_table[2].mhz = MSR2MHZ(idlo, bus_clock);
1192 fake_table[2].pct = 0;
1193 fake_fqlist->n = 3;
1194 }
1195
1196 fake_fqlist->vendor = vendor;
1197 fake_fqlist->table = fake_table;
1198 est_fqlist = fake_fqlist;
1199 }
1200
1201 if (est_fqlist == NULL)
1202 return;
1203
1204 if (est_fqlist->n < 2)
1205 goto nospeedstep;
1206
1207 low = est_fqlist->table[est_fqlist->n - 1].mhz;
1208 high = est_fqlist->table[0].mhz;
1209 if (low == high)
1210 goto nospeedstep;
1211
1212 perflevel = (cpuspeed - low) * 100 / (high - low);
1213
1214 printf("%s: Enhanced SpeedStep %d MHz", cpu_device, cpuspeed);
1215
1216 /*
1217 * OK, tell the user the available frequencies.
1218 */
1219 printf(": speeds: ");
1220 for (i = 0; i < est_fqlist->n; i++)
1221 printf("%d%s", est_fqlist->table[i].mhz, i < est_fqlist->n - 1
1222 ? ", " : " MHz\n");
1223
1224 cpu_setperf = est_setperf;
1225 setperf_prio = 3;
1226
1227 return;
1228
1229 nospeedstep:
1230 /*
1231 * While est_fqlist can point into the static est_cpus[],
1232 * it can't fail in that case and therefore can't reach here.
1233 */
1234 free(est_fqlist->table, M_DEVBUF, 0);
1235 free(est_fqlist, M_DEVBUF, sizeof(*est_fqlist));
1236 }
1237
1238 void
est_setperf(int level)1239 est_setperf(int level)
1240 {
1241 int i;
1242 uint64_t msr;
1243
1244 if (est_fqlist == NULL)
1245 return;
1246
1247 for (i = 0; i < est_fqlist->n; i++) {
1248 if (level >= est_fqlist->table[i].pct)
1249 break;
1250 }
1251
1252 msr = rdmsr(MSR_PERF_CTL);
1253 msr &= ~0xffffULL;
1254 msr |= est_fqlist->table[i].ctrl;
1255
1256 wrmsr(MSR_PERF_CTL, msr);
1257 cpuspeed = est_fqlist->table[i].mhz;
1258 }
1259