1 /* $NetBSD: est.c,v 1.33 2021/10/07 12:52:27 msaitoh 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 * Copyright (c) 2004 The NetBSD Foundation, Inc.
30 * All rights reserved.
31 *
32 * Redistribution and use in source and binary forms, with or without
33 * modification, are permitted provided that the following conditions
34 * are met:
35 * 1. Redistributions of source code must retain the above copyright
36 * notice, this list of conditions and the following disclaimer.
37 * 2. Redistributions in binary form must reproduce the above copyright
38 * notice, this list of conditions and the following disclaimer in the
39 * documentation and/or other materials provided with the distribution.
40 *
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
43 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
44 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
45 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
46 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
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
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
51 * POSSIBILITY OF SUCH DAMAGE.
52 */
53
54 /*
55 * This is a driver for Intel's Enhanced SpeedStep Technology (EST),
56 * as implemented in Pentium M processors.
57 *
58 * Reference documentation:
59 *
60 * - IA-32 Intel Architecture Software Developer's Manual, Volume 3:
61 * System Programming Guide.
62 * Section 13.14, Enhanced Intel SpeedStep technology.
63 * Table B-2, MSRs in Pentium M Processors.
64 * http://www.intel.com/design/pentium4/manuals/253668.htm
65 *
66 * - Intel Pentium M Processor Datasheet.
67 * Table 5, Voltage and Current Specifications.
68 * http://www.intel.com/design/mobile/datashts/252612.htm
69 *
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.
72 * http://www.intel.com/design/mobile/datashts/302189.htm
73 *
74 * - Linux cpufreq patches, speedstep-centrino.c.
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
77 */
78 #include <sys/cdefs.h>
79 __KERNEL_RCSID(0, "$NetBSD: est.c,v 1.33 2021/10/07 12:52:27 msaitoh Exp $");
80
81 #include <sys/param.h>
82 #include <sys/device.h>
83 #include <sys/kmem.h>
84 #include <sys/module.h>
85 #include <sys/sysctl.h>
86 #include <sys/xcall.h>
87
88 #include <x86/cpuvar.h>
89 #include <x86/cputypes.h>
90 #include <x86/cpu_msr.h>
91 #include <x86/est.h>
92 #include <x86/specialreg.h>
93
94 #define MSR2FREQINC(msr) (((int) (msr) >> 8) & 0xff)
95 #define MSR2VOLTINC(msr) ((int) (msr) & 0xff)
96
97 #define MSR2MHZ(msr, bus) ((MSR2FREQINC((msr)) * (bus) + 50) / 100)
98 #define MSR2MV(msr) (MSR2VOLTINC(msr) * 16 + 700)
99
100 /* Convert MHz and mV into IDs for passing to the MSR. */
101 #define ID16(MHz, mV, bus_clk) \
102 ((((MHz * 100 + 50) / bus_clk) << 8) | ((mV ? mV - 700 : 0) >> 4))
103
104 #define ENTRY(ven, bus_clk, tab) \
105 { CPUVENDOR_##ven, bus_clk == BUS133 ? 1 : 0, __arraycount(tab), tab }
106
107 #define BUS_CLK(fqp) ((fqp)->bus_clk ? BUS133 : BUS100)
108
109 struct fqlist {
110 int vendor;
111 unsigned bus_clk;
112 unsigned n;
113 const uint16_t *table;
114 };
115
116 #ifdef __i386__
117
118 /* Possible bus speeds (multiplied by 100 for rounding) */
119 enum { BUS100 = 10000, BUS133 = 13333, BUS166 = 16666, BUS200 = 20000 };
120
121 /* Ultra Low Voltage Intel Pentium M processor 900 MHz */
122 static const uint16_t pm130_900_ulv[] = {
123 ID16( 900, 1004, BUS100),
124 ID16( 800, 988, BUS100),
125 ID16( 600, 844, BUS100),
126 };
127
128 /* Ultra Low Voltage Intel Pentium M processor 1.00 GHz */
129 static const uint16_t pm130_1000_ulv[] = {
130 ID16(1000, 1004, BUS100),
131 ID16( 900, 988, BUS100),
132 ID16( 800, 972, BUS100),
133 ID16( 600, 844, BUS100),
134 };
135
136 /* Ultra Low Voltage Intel Pentium M processor 1.10 GHz */
137 static const uint16_t pm130_1100_ulv[] = {
138 ID16(1100, 1004, BUS100),
139 ID16(1000, 988, BUS100),
140 ID16( 900, 972, BUS100),
141 ID16( 800, 956, BUS100),
142 ID16( 600, 844, BUS100),
143 };
144
145 /* Low Voltage Intel Pentium M processor 1.10 GHz */
146 static const uint16_t pm130_1100_lv[] = {
147 ID16(1100, 1180, BUS100),
148 ID16(1000, 1164, BUS100),
149 ID16( 900, 1100, BUS100),
150 ID16( 800, 1020, BUS100),
151 ID16( 600, 956, BUS100),
152 };
153
154 /* Low Voltage Intel Pentium M processor 1.20 GHz */
155 static const uint16_t pm130_1200_lv[] = {
156 ID16(1200, 1180, BUS100),
157 ID16(1100, 1164, BUS100),
158 ID16(1000, 1100, BUS100),
159 ID16( 900, 1020, BUS100),
160 ID16( 800, 1004, BUS100),
161 ID16( 600, 956, BUS100),
162 };
163
164 /* Low Voltage Intel Pentium M processor 1.30 GHz */
165 static const uint16_t pm130_1300_lv[] = {
166 ID16(1300, 1180, BUS100),
167 ID16(1200, 1164, BUS100),
168 ID16(1100, 1100, BUS100),
169 ID16(1000, 1020, BUS100),
170 ID16( 900, 1004, BUS100),
171 ID16( 800, 988, BUS100),
172 ID16( 600, 956, BUS100),
173 };
174
175 /* Intel Pentium M processor 1.30 GHz */
176 static const uint16_t pm130_1300[] = {
177 ID16(1300, 1388, BUS100),
178 ID16(1200, 1356, BUS100),
179 ID16(1000, 1292, BUS100),
180 ID16( 800, 1260, BUS100),
181 ID16( 600, 956, BUS100),
182 };
183
184 /* Intel Pentium M processor 1.40 GHz */
185 static const uint16_t pm130_1400[] = {
186 ID16(1400, 1484, BUS100),
187 ID16(1200, 1436, BUS100),
188 ID16(1000, 1308, BUS100),
189 ID16( 800, 1180, BUS100),
190 ID16( 600, 956, BUS100),
191 };
192
193 /* Intel Pentium M processor 1.50 GHz */
194 static const uint16_t pm130_1500[] = {
195 ID16(1500, 1484, BUS100),
196 ID16(1400, 1452, BUS100),
197 ID16(1200, 1356, BUS100),
198 ID16(1000, 1228, BUS100),
199 ID16( 800, 1116, BUS100),
200 ID16( 600, 956, BUS100),
201 };
202
203 /* Intel Pentium M processor 1.60 GHz */
204 static const uint16_t pm130_1600[] = {
205 ID16(1600, 1484, BUS100),
206 ID16(1400, 1420, BUS100),
207 ID16(1200, 1276, BUS100),
208 ID16(1000, 1164, BUS100),
209 ID16( 800, 1036, BUS100),
210 ID16( 600, 956, BUS100),
211 };
212
213 /* Intel Pentium M processor 1.70 GHz */
214 static const uint16_t pm130_1700[] = {
215 ID16(1700, 1484, BUS100),
216 ID16(1400, 1308, BUS100),
217 ID16(1200, 1228, BUS100),
218 ID16(1000, 1116, BUS100),
219 ID16( 800, 1004, BUS100),
220 ID16( 600, 956, BUS100),
221 };
222
223 /* Intel Pentium M processor 723 1.0 GHz */
224 static const uint16_t pm90_n723[] = {
225 ID16(1000, 940, BUS100),
226 ID16( 900, 908, BUS100),
227 ID16( 800, 876, BUS100),
228 ID16( 600, 812, BUS100),
229 };
230
231 /* Intel Pentium M processor 733 1.1 GHz, VID #G */
232 static const uint16_t pm90_n733g[] = {
233 ID16(1100, 956, BUS100),
234 ID16(1000, 940, BUS100),
235 ID16( 900, 908, BUS100),
236 ID16( 800, 876, BUS100),
237 ID16( 600, 812, BUS100),
238 };
239
240 /* Intel Pentium M processor 733 1.1 GHz, VID #H */
241 static const uint16_t pm90_n733h[] = {
242 ID16(1100, 940, BUS100),
243 ID16(1000, 924, BUS100),
244 ID16( 900, 892, BUS100),
245 ID16( 800, 876, BUS100),
246 ID16( 600, 812, BUS100),
247 };
248
249 /* Intel Pentium M processor 733 1.1 GHz, VID #I */
250 static const uint16_t pm90_n733i[] = {
251 ID16(1100, 924, BUS100),
252 ID16(1000, 908, BUS100),
253 ID16( 900, 892, BUS100),
254 ID16( 800, 860, BUS100),
255 ID16( 600, 812, BUS100),
256 };
257
258 /* Intel Pentium M processor 733 1.1 GHz, VID #J */
259 static const uint16_t pm90_n733j[] = {
260 ID16(1100, 908, BUS100),
261 ID16(1000, 892, BUS100),
262 ID16( 900, 876, BUS100),
263 ID16( 800, 860, BUS100),
264 ID16( 600, 812, BUS100),
265 };
266
267 /* Intel Pentium M processor 733 1.1 GHz, VID #K */
268 static const uint16_t pm90_n733k[] = {
269 ID16(1100, 892, BUS100),
270 ID16(1000, 876, BUS100),
271 ID16( 900, 860, BUS100),
272 ID16( 800, 844, BUS100),
273 ID16( 600, 812, BUS100),
274 };
275
276 /* Intel Pentium M processor 733 1.1 GHz, VID #L */
277 static const uint16_t pm90_n733l[] = {
278 ID16(1100, 876, BUS100),
279 ID16(1000, 876, BUS100),
280 ID16( 900, 860, BUS100),
281 ID16( 800, 844, BUS100),
282 ID16( 600, 812, BUS100),
283 };
284
285 /* Intel Pentium M processor 753 1.2 GHz, VID #G */
286 static const uint16_t pm90_n753g[] = {
287 ID16(1200, 956, BUS100),
288 ID16(1100, 940, BUS100),
289 ID16(1000, 908, BUS100),
290 ID16( 900, 892, BUS100),
291 ID16( 800, 860, BUS100),
292 ID16( 600, 812, BUS100),
293 };
294
295 /* Intel Pentium M processor 753 1.2 GHz, VID #H */
296 static const uint16_t pm90_n753h[] = {
297 ID16(1200, 940, BUS100),
298 ID16(1100, 924, BUS100),
299 ID16(1000, 908, BUS100),
300 ID16( 900, 876, BUS100),
301 ID16( 800, 860, BUS100),
302 ID16( 600, 812, BUS100),
303 };
304
305 /* Intel Pentium M processor 753 1.2 GHz, VID #I */
306 static const uint16_t pm90_n753i[] = {
307 ID16(1200, 924, BUS100),
308 ID16(1100, 908, BUS100),
309 ID16(1000, 892, BUS100),
310 ID16( 900, 876, BUS100),
311 ID16( 800, 860, BUS100),
312 ID16( 600, 812, BUS100),
313 };
314
315 /* Intel Pentium M processor 753 1.2 GHz, VID #J */
316 static const uint16_t pm90_n753j[] = {
317 ID16(1200, 908, BUS100),
318 ID16(1100, 892, BUS100),
319 ID16(1000, 876, BUS100),
320 ID16( 900, 860, BUS100),
321 ID16( 800, 844, BUS100),
322 ID16( 600, 812, BUS100),
323 };
324
325 /* Intel Pentium M processor 753 1.2 GHz, VID #K */
326 static const uint16_t pm90_n753k[] = {
327 ID16(1200, 892, BUS100),
328 ID16(1100, 892, BUS100),
329 ID16(1000, 876, BUS100),
330 ID16( 900, 860, BUS100),
331 ID16( 800, 844, BUS100),
332 ID16( 600, 812, BUS100),
333 };
334
335 /* Intel Pentium M processor 753 1.2 GHz, VID #L */
336 static const uint16_t pm90_n753l[] = {
337 ID16(1200, 876, BUS100),
338 ID16(1100, 876, BUS100),
339 ID16(1000, 860, BUS100),
340 ID16( 900, 844, BUS100),
341 ID16( 800, 844, BUS100),
342 ID16( 600, 812, BUS100),
343 };
344
345 /* Intel Pentium M processor 773 1.3 GHz, VID #G */
346 static const uint16_t pm90_n773g[] = {
347 ID16(1300, 956, BUS100),
348 ID16(1200, 940, BUS100),
349 ID16(1100, 924, BUS100),
350 ID16(1000, 908, BUS100),
351 ID16( 900, 876, BUS100),
352 ID16( 800, 860, BUS100),
353 ID16( 600, 812, BUS100),
354 };
355
356 /* Intel Pentium M processor 773 1.3 GHz, VID #H */
357 static const uint16_t pm90_n773h[] = {
358 ID16(1300, 940, BUS100),
359 ID16(1200, 924, BUS100),
360 ID16(1100, 908, BUS100),
361 ID16(1000, 892, BUS100),
362 ID16( 900, 876, BUS100),
363 ID16( 800, 860, BUS100),
364 ID16( 600, 812, BUS100),
365 };
366
367 /* Intel Pentium M processor 773 1.3 GHz, VID #I */
368 static const uint16_t pm90_n773i[] = {
369 ID16(1300, 924, BUS100),
370 ID16(1200, 908, BUS100),
371 ID16(1100, 892, BUS100),
372 ID16(1000, 876, BUS100),
373 ID16( 900, 860, BUS100),
374 ID16( 800, 844, BUS100),
375 ID16( 600, 812, BUS100),
376 };
377
378 /* Intel Pentium M processor 773 1.3 GHz, VID #J */
379 static const uint16_t pm90_n773j[] = {
380 ID16(1300, 908, BUS100),
381 ID16(1200, 908, BUS100),
382 ID16(1100, 892, BUS100),
383 ID16(1000, 876, BUS100),
384 ID16( 900, 860, BUS100),
385 ID16( 800, 844, BUS100),
386 ID16( 600, 812, BUS100),
387 };
388
389 /* Intel Pentium M processor 773 1.3 GHz, VID #K */
390 static const uint16_t pm90_n773k[] = {
391 ID16(1300, 892, BUS100),
392 ID16(1200, 892, BUS100),
393 ID16(1100, 876, BUS100),
394 ID16(1000, 860, BUS100),
395 ID16( 900, 860, BUS100),
396 ID16( 800, 844, BUS100),
397 ID16( 600, 812, BUS100),
398 };
399
400 /* Intel Pentium M processor 773 1.3 GHz, VID #L */
401 static const uint16_t pm90_n773l[] = {
402 ID16(1300, 876, BUS100),
403 ID16(1200, 876, BUS100),
404 ID16(1100, 860, BUS100),
405 ID16(1000, 860, BUS100),
406 ID16( 900, 844, BUS100),
407 ID16( 800, 844, BUS100),
408 ID16( 600, 812, BUS100),
409 };
410
411 /* Intel Pentium M processor 738 1.4 GHz */
412 static const uint16_t pm90_n738[] = {
413 ID16(1400, 1116, BUS100),
414 ID16(1300, 1116, BUS100),
415 ID16(1200, 1100, BUS100),
416 ID16(1100, 1068, BUS100),
417 ID16(1000, 1052, BUS100),
418 ID16( 900, 1036, BUS100),
419 ID16( 800, 1020, BUS100),
420 ID16( 600, 988, BUS100),
421 };
422
423 /* Intel Pentium M processor 758 1.5 GHz */
424 static const uint16_t pm90_n758[] = {
425 ID16(1500, 1116, BUS100),
426 ID16(1400, 1116, BUS100),
427 ID16(1300, 1100, BUS100),
428 ID16(1200, 1084, BUS100),
429 ID16(1100, 1068, BUS100),
430 ID16(1000, 1052, BUS100),
431 ID16( 900, 1036, BUS100),
432 ID16( 800, 1020, BUS100),
433 ID16( 600, 988, BUS100),
434 };
435
436 /* Intel Pentium M processor 778 1.6 GHz */
437 static const uint16_t pm90_n778[] = {
438 ID16(1600, 1116, BUS100),
439 ID16(1500, 1116, BUS100),
440 ID16(1400, 1100, BUS100),
441 ID16(1300, 1184, BUS100),
442 ID16(1200, 1068, BUS100),
443 ID16(1100, 1052, BUS100),
444 ID16(1000, 1052, BUS100),
445 ID16( 900, 1036, BUS100),
446 ID16( 800, 1020, BUS100),
447 ID16( 600, 988, BUS100),
448 };
449
450 /* Intel Pentium M processor 710 1.4 GHz, 533 MHz FSB */
451 static const uint16_t pm90_n710[] = {
452 ID16(1400, 1340, BUS133),
453 ID16(1200, 1228, BUS133),
454 ID16(1000, 1148, BUS133),
455 ID16( 800, 1068, BUS133),
456 ID16( 600, 998, BUS133),
457 };
458
459 /* Intel Pentium M processor 715 1.5 GHz, VID #A */
460 static const uint16_t pm90_n715a[] = {
461 ID16(1500, 1340, BUS100),
462 ID16(1200, 1228, BUS100),
463 ID16(1000, 1148, BUS100),
464 ID16( 800, 1068, BUS100),
465 ID16( 600, 988, BUS100),
466 };
467
468 /* Intel Pentium M processor 715 1.5 GHz, VID #B */
469 static const uint16_t pm90_n715b[] = {
470 ID16(1500, 1324, BUS100),
471 ID16(1200, 1212, BUS100),
472 ID16(1000, 1148, BUS100),
473 ID16( 800, 1068, BUS100),
474 ID16( 600, 988, BUS100),
475 };
476
477 /* Intel Pentium M processor 715 1.5 GHz, VID #C */
478 static const uint16_t pm90_n715c[] = {
479 ID16(1500, 1308, BUS100),
480 ID16(1200, 1212, BUS100),
481 ID16(1000, 1132, BUS100),
482 ID16( 800, 1068, BUS100),
483 ID16( 600, 988, BUS100),
484 };
485
486 /* Intel Pentium M processor 715 1.5 GHz, VID #D */
487 static const uint16_t pm90_n715d[] = {
488 ID16(1500, 1276, BUS100),
489 ID16(1200, 1180, BUS100),
490 ID16(1000, 1116, BUS100),
491 ID16( 800, 1052, BUS100),
492 ID16( 600, 988, BUS100),
493 };
494
495 /* Intel Pentium M processor 725 1.6 GHz, VID #A */
496 static const uint16_t pm90_n725a[] = {
497 ID16(1600, 1340, BUS100),
498 ID16(1400, 1276, BUS100),
499 ID16(1200, 1212, BUS100),
500 ID16(1000, 1132, BUS100),
501 ID16( 800, 1068, BUS100),
502 ID16( 600, 988, BUS100),
503 };
504
505 /* Intel Pentium M processor 725 1.6 GHz, VID #B */
506 static const uint16_t pm90_n725b[] = {
507 ID16(1600, 1324, BUS100),
508 ID16(1400, 1260, BUS100),
509 ID16(1200, 1196, BUS100),
510 ID16(1000, 1132, BUS100),
511 ID16( 800, 1068, BUS100),
512 ID16( 600, 988, BUS100),
513 };
514
515 /* Intel Pentium M processor 725 1.6 GHz, VID #C */
516 static const uint16_t pm90_n725c[] = {
517 ID16(1600, 1308, BUS100),
518 ID16(1400, 1244, BUS100),
519 ID16(1200, 1180, BUS100),
520 ID16(1000, 1116, BUS100),
521 ID16( 800, 1052, BUS100),
522 ID16( 600, 988, BUS100),
523 };
524
525 /* Intel Pentium M processor 725 1.6 GHz, VID #D */
526 static const uint16_t pm90_n725d[] = {
527 ID16(1600, 1276, BUS100),
528 ID16(1400, 1228, BUS100),
529 ID16(1200, 1164, BUS100),
530 ID16(1000, 1116, BUS100),
531 ID16( 800, 1052, BUS100),
532 ID16( 600, 988, BUS100),
533 };
534
535 /* Intel Pentium M processor 730 1.6 GHz, 533 MHz FSB */
536 static const uint16_t pm90_n730[] = {
537 ID16(1600, 1308, BUS133),
538 ID16(1333, 1260, BUS133),
539 ID16(1200, 1212, BUS133),
540 ID16(1067, 1180, BUS133),
541 ID16( 800, 988, BUS133),
542 };
543
544 /* Intel Pentium M processor 735 1.7 GHz, VID #A */
545 static const uint16_t pm90_n735a[] = {
546 ID16(1700, 1340, BUS100),
547 ID16(1400, 1244, BUS100),
548 ID16(1200, 1180, BUS100),
549 ID16(1000, 1116, BUS100),
550 ID16( 800, 1052, BUS100),
551 ID16( 600, 988, BUS100),
552 };
553
554 /* Intel Pentium M processor 735 1.7 GHz, VID #B */
555 static const uint16_t pm90_n735b[] = {
556 ID16(1700, 1324, BUS100),
557 ID16(1400, 1244, BUS100),
558 ID16(1200, 1180, BUS100),
559 ID16(1000, 1116, BUS100),
560 ID16( 800, 1052, BUS100),
561 ID16( 600, 988, BUS100),
562 };
563
564 /* Intel Pentium M processor 735 1.7 GHz, VID #C */
565 static const uint16_t pm90_n735c[] = {
566 ID16(1700, 1308, BUS100),
567 ID16(1400, 1228, BUS100),
568 ID16(1200, 1164, BUS100),
569 ID16(1000, 1116, BUS100),
570 ID16( 800, 1052, BUS100),
571 ID16( 600, 988, BUS100),
572 };
573
574 /* Intel Pentium M processor 735 1.7 GHz, VID #D */
575 static const uint16_t pm90_n735d[] = {
576 ID16(1700, 1276, BUS100),
577 ID16(1400, 1212, BUS100),
578 ID16(1200, 1148, BUS100),
579 ID16(1000, 1100, BUS100),
580 ID16( 800, 1052, BUS100),
581 ID16( 600, 988, BUS100),
582 };
583
584 /* Intel Pentium M processor 740 1.73 GHz, 533 MHz FSB */
585 static const uint16_t pm90_n740[] = {
586 ID16(1733, 1356, BUS133),
587 ID16(1333, 1212, BUS133),
588 ID16(1067, 1100, BUS133),
589 ID16( 800, 988, BUS133),
590 };
591
592 /* Intel Pentium M processor 745 1.8 GHz, VID #A */
593 static const uint16_t pm90_n745a[] = {
594 ID16(1800, 1340, BUS100),
595 ID16(1600, 1292, BUS100),
596 ID16(1400, 1228, BUS100),
597 ID16(1200, 1164, BUS100),
598 ID16(1000, 1116, BUS100),
599 ID16( 800, 1052, BUS100),
600 ID16( 600, 988, BUS100),
601 };
602
603 /* Intel Pentium M processor 745 1.8 GHz, VID #B */
604 static const uint16_t pm90_n745b[] = {
605 ID16(1800, 1324, BUS100),
606 ID16(1600, 1276, BUS100),
607 ID16(1400, 1212, BUS100),
608 ID16(1200, 1164, BUS100),
609 ID16(1000, 1116, BUS100),
610 ID16( 800, 1052, BUS100),
611 ID16( 600, 988, BUS100),
612 };
613
614 /* Intel Pentium M processor 745 1.8 GHz, VID #C */
615 static const uint16_t pm90_n745c[] = {
616 ID16(1800, 1308, BUS100),
617 ID16(1600, 1260, BUS100),
618 ID16(1400, 1212, BUS100),
619 ID16(1200, 1148, BUS100),
620 ID16(1000, 1100, BUS100),
621 ID16( 800, 1052, BUS100),
622 ID16( 600, 988, BUS100),
623 };
624
625 /* Intel Pentium M processor 745 1.8 GHz, VID #D */
626 static const uint16_t pm90_n745d[] = {
627 ID16(1800, 1276, BUS100),
628 ID16(1600, 1228, BUS100),
629 ID16(1400, 1180, BUS100),
630 ID16(1200, 1132, BUS100),
631 ID16(1000, 1084, BUS100),
632 ID16( 800, 1036, BUS100),
633 ID16( 600, 988, BUS100),
634 };
635
636 /* Intel Pentium M processor 750 1.86 GHz, 533 MHz FSB */
637 /* values extracted from \_PR\NPSS (via _PSS) SDST ACPI table */
638 static const uint16_t pm90_n750[] = {
639 ID16(1867, 1308, BUS133),
640 ID16(1600, 1228, BUS133),
641 ID16(1333, 1148, BUS133),
642 ID16(1067, 1068, BUS133),
643 ID16( 800, 988, BUS133),
644 };
645
646 /* Intel Pentium M processor 755 2.0 GHz, VID #A */
647 static const uint16_t pm90_n755a[] = {
648 ID16(2000, 1340, BUS100),
649 ID16(1800, 1292, BUS100),
650 ID16(1600, 1244, BUS100),
651 ID16(1400, 1196, BUS100),
652 ID16(1200, 1148, BUS100),
653 ID16(1000, 1100, BUS100),
654 ID16( 800, 1052, BUS100),
655 ID16( 600, 988, BUS100),
656 };
657
658 /* Intel Pentium M processor 755 2.0 GHz, VID #B */
659 static const uint16_t pm90_n755b[] = {
660 ID16(2000, 1324, BUS100),
661 ID16(1800, 1276, BUS100),
662 ID16(1600, 1228, BUS100),
663 ID16(1400, 1180, BUS100),
664 ID16(1200, 1132, BUS100),
665 ID16(1000, 1084, BUS100),
666 ID16( 800, 1036, BUS100),
667 ID16( 600, 988, BUS100),
668 };
669
670 /* Intel Pentium M processor 755 2.0 GHz, VID #C */
671 static const uint16_t pm90_n755c[] = {
672 ID16(2000, 1308, BUS100),
673 ID16(1800, 1276, BUS100),
674 ID16(1600, 1228, BUS100),
675 ID16(1400, 1180, BUS100),
676 ID16(1200, 1132, BUS100),
677 ID16(1000, 1084, BUS100),
678 ID16( 800, 1036, BUS100),
679 ID16( 600, 988, BUS100),
680 };
681
682 /* Intel Pentium M processor 755 2.0 GHz, VID #D */
683 static const uint16_t pm90_n755d[] = {
684 ID16(2000, 1276, BUS100),
685 ID16(1800, 1244, BUS100),
686 ID16(1600, 1196, BUS100),
687 ID16(1400, 1164, BUS100),
688 ID16(1200, 1116, BUS100),
689 ID16(1000, 1084, BUS100),
690 ID16( 800, 1036, BUS100),
691 ID16( 600, 988, BUS100),
692 };
693
694 /* Intel Pentium M processor 760 2.0 GHz, 533 MHz FSB */
695 static const uint16_t pm90_n760[] = {
696 ID16(2000, 1356, BUS133),
697 ID16(1600, 1244, BUS133),
698 ID16(1333, 1164, BUS133),
699 ID16(1067, 1084, BUS133),
700 ID16( 800, 988, BUS133),
701 };
702
703 /* Intel Pentium M processor 765 2.1 GHz, VID #A */
704 static const uint16_t pm90_n765a[] = {
705 ID16(2100, 1340, BUS100),
706 ID16(1800, 1276, BUS100),
707 ID16(1600, 1228, BUS100),
708 ID16(1400, 1180, BUS100),
709 ID16(1200, 1132, BUS100),
710 ID16(1000, 1084, BUS100),
711 ID16( 800, 1036, BUS100),
712 ID16( 600, 988, BUS100),
713 };
714
715 /* Intel Pentium M processor 765 2.1 GHz, VID #B */
716 static const uint16_t pm90_n765b[] = {
717 ID16(2100, 1324, BUS100),
718 ID16(1800, 1260, BUS100),
719 ID16(1600, 1212, BUS100),
720 ID16(1400, 1180, BUS100),
721 ID16(1200, 1132, BUS100),
722 ID16(1000, 1084, BUS100),
723 ID16( 800, 1036, BUS100),
724 ID16( 600, 988, BUS100),
725 };
726
727 /* Intel Pentium M processor 765 2.1 GHz, VID #C */
728 static const uint16_t pm90_n765c[] = {
729 ID16(2100, 1308, BUS100),
730 ID16(1800, 1244, BUS100),
731 ID16(1600, 1212, BUS100),
732 ID16(1400, 1164, BUS100),
733 ID16(1200, 1116, BUS100),
734 ID16(1000, 1084, BUS100),
735 ID16( 800, 1036, BUS100),
736 ID16( 600, 988, BUS100),
737 };
738
739 /* Intel Pentium M processor 765 2.1 GHz, VID #E */
740 static const uint16_t pm90_n765e[] = {
741 ID16(2100, 1356, BUS100),
742 ID16(1800, 1292, BUS100),
743 ID16(1600, 1244, BUS100),
744 ID16(1400, 1196, BUS100),
745 ID16(1200, 1148, BUS100),
746 ID16(1000, 1100, BUS100),
747 ID16( 800, 1052, BUS100),
748 ID16( 600, 988, BUS100),
749 };
750
751 /* Intel Pentium M processor 770 2.13 GHz */
752 static const uint16_t pm90_n770[] = {
753 ID16(2133, 1356, BUS133),
754 ID16(1867, 1292, BUS133),
755 ID16(1600, 1212, BUS133),
756 ID16(1333, 1148, BUS133),
757 ID16(1067, 1068, BUS133),
758 ID16( 800, 988, BUS133),
759 };
760
761 /* Intel Pentium M processor 780 2.26 GHz */
762 static const uint16_t pm90_n780[] = {
763 ID16(2267, 1388, BUS133),
764 ID16(1867, 1292, BUS133),
765 ID16(1600, 1212, BUS133),
766 ID16(1333, 1148, BUS133),
767 ID16(1067, 1068, BUS133),
768 ID16( 800, 988, BUS133),
769 };
770
771 /*
772 * VIA C7-M 500 MHz FSB, 400 MHz FSB, and ULV variants.
773 * Data from the "VIA C7-M Processor BIOS Writer's Guide (v2.17)" datasheet.
774 */
775
776 /* 1.00GHz Centaur C7-M ULV */
777 static const uint16_t C7M_770_ULV[] = {
778 ID16(1000, 844, BUS100),
779 ID16( 800, 796, BUS100),
780 ID16( 600, 796, BUS100),
781 ID16( 400, 796, BUS100),
782 };
783
784 /* 1.00GHz Centaur C7-M ULV */
785 static const uint16_t C7M_779_ULV[] = {
786 ID16(1000, 796, BUS100),
787 ID16( 800, 796, BUS100),
788 ID16( 600, 796, BUS100),
789 ID16( 400, 796, BUS100),
790 };
791
792 /* 1.20GHz Centaur C7-M ULV */
793 static const uint16_t C7M_772_ULV[] = {
794 ID16(1200, 844, BUS100),
795 ID16(1000, 844, BUS100),
796 ID16( 800, 828, BUS100),
797 ID16( 600, 796, BUS100),
798 ID16( 400, 796, BUS100),
799 };
800
801 /* 1.50GHz Centaur C7-M ULV */
802 static const uint16_t C7M_775_ULV[] = {
803 ID16(1500, 956, BUS100),
804 ID16(1400, 940, BUS100),
805 ID16(1000, 860, BUS100),
806 ID16( 800, 828, BUS100),
807 ID16( 600, 796, BUS100),
808 ID16( 400, 796, BUS100),
809 };
810
811 /* 1.20GHz Centaur C7-M 400 MHz FSB */
812 static const uint16_t C7M_771[] = {
813 ID16(1200, 860, BUS100),
814 ID16(1000, 860, BUS100),
815 ID16( 800, 844, BUS100),
816 ID16( 600, 844, BUS100),
817 ID16( 400, 844, BUS100),
818 };
819
820 /* 1.50GHz Centaur C7-M 400 MHz FSB */
821 static const uint16_t C7M_754[] = {
822 ID16(1500, 1004, BUS100),
823 ID16(1400, 988, BUS100),
824 ID16(1000, 940, BUS100),
825 ID16( 800, 844, BUS100),
826 ID16( 600, 844, BUS100),
827 ID16( 400, 844, BUS100),
828 };
829
830 /* 1.60GHz Centaur C7-M 400 MHz FSB */
831 static const uint16_t C7M_764[] = {
832 ID16(1600, 1084, BUS100),
833 ID16(1400, 1052, BUS100),
834 ID16(1000, 1004, BUS100),
835 ID16( 800, 844, BUS100),
836 ID16( 600, 844, BUS100),
837 ID16( 400, 844, BUS100),
838 };
839
840 /* 1.80GHz Centaur C7-M 400 MHz FSB */
841 static const uint16_t C7M_784[] = {
842 ID16(1800, 1148, BUS100),
843 ID16(1600, 1100, BUS100),
844 ID16(1400, 1052, BUS100),
845 ID16(1000, 1004, BUS100),
846 ID16( 800, 844, BUS100),
847 ID16( 600, 844, BUS100),
848 ID16( 400, 844, BUS100),
849 };
850
851 /* 2.00GHz Centaur C7-M 400 MHz FSB */
852 static const uint16_t C7M_794[] = {
853 ID16(2000, 1148, BUS100),
854 ID16(1800, 1132, BUS100),
855 ID16(1600, 1100, BUS100),
856 ID16(1400, 1052, BUS100),
857 ID16(1000, 1004, BUS100),
858 ID16( 800, 844, BUS100),
859 ID16( 600, 844, BUS100),
860 ID16( 400, 844, BUS100),
861 };
862
863 /* 1.60GHz Centaur C7-M 533 MHz FSB */
864 static const uint16_t C7M_765[] = {
865 ID16(1600, 1084, BUS133),
866 ID16(1467, 1052, BUS133),
867 ID16(1200, 1004, BUS133),
868 ID16( 800, 844, BUS133),
869 ID16( 667, 844, BUS133),
870 ID16( 533, 844, BUS133),
871 };
872
873 /* 2.00GHz Centaur C7-M 533 MHz FSB */
874 static const uint16_t C7M_785[] = {
875 ID16(1867, 1148, BUS133),
876 ID16(1600, 1100, BUS133),
877 ID16(1467, 1052, BUS133),
878 ID16(1200, 1004, BUS133),
879 ID16( 800, 844, BUS133),
880 ID16( 667, 844, BUS133),
881 ID16( 533, 844, BUS133),
882 };
883
884 /* 2.00GHz Centaur C7-M 533 MHz FSB */
885 static const uint16_t C7M_795[] = {
886 ID16(2000, 1148, BUS133),
887 ID16(1867, 1132, BUS133),
888 ID16(1600, 1100, BUS133),
889 ID16(1467, 1052, BUS133),
890 ID16(1200, 1004, BUS133),
891 ID16( 800, 844, BUS133),
892 ID16( 667, 844, BUS133),
893 ID16( 533, 844, BUS133),
894 };
895
896 /* 1.00GHz VIA Eden 90nm 'Esther' */
897 static const uint16_t eden90_1000[] = {
898 ID16(1000, 844, BUS100),
899 ID16( 800, 844, BUS100),
900 ID16( 600, 844, BUS100),
901 ID16( 400, 844, BUS100),
902 };
903
904 static const struct fqlist est_cpus[] = {
905 ENTRY(INTEL, BUS100, pm130_900_ulv),
906 ENTRY(INTEL, BUS100, pm130_1000_ulv),
907 ENTRY(INTEL, BUS100, pm130_1100_ulv),
908 ENTRY(INTEL, BUS100, pm130_1100_lv),
909 ENTRY(INTEL, BUS100, pm130_1200_lv),
910 ENTRY(INTEL, BUS100, pm130_1300_lv),
911 ENTRY(INTEL, BUS100, pm130_1300),
912 ENTRY(INTEL, BUS100, pm130_1400),
913 ENTRY(INTEL, BUS100, pm130_1500),
914 ENTRY(INTEL, BUS100, pm130_1600),
915 ENTRY(INTEL, BUS100, pm130_1700),
916 ENTRY(INTEL, BUS100, pm90_n723),
917 ENTRY(INTEL, BUS100, pm90_n733g),
918 ENTRY(INTEL, BUS100, pm90_n733h),
919 ENTRY(INTEL, BUS100, pm90_n733i),
920 ENTRY(INTEL, BUS100, pm90_n733j),
921 ENTRY(INTEL, BUS100, pm90_n733k),
922 ENTRY(INTEL, BUS100, pm90_n733l),
923 ENTRY(INTEL, BUS100, pm90_n753g),
924 ENTRY(INTEL, BUS100, pm90_n753h),
925 ENTRY(INTEL, BUS100, pm90_n753i),
926 ENTRY(INTEL, BUS100, pm90_n753j),
927 ENTRY(INTEL, BUS100, pm90_n753k),
928 ENTRY(INTEL, BUS100, pm90_n753l),
929 ENTRY(INTEL, BUS100, pm90_n773g),
930 ENTRY(INTEL, BUS100, pm90_n773h),
931 ENTRY(INTEL, BUS100, pm90_n773i),
932 ENTRY(INTEL, BUS100, pm90_n773j),
933 ENTRY(INTEL, BUS100, pm90_n773k),
934 ENTRY(INTEL, BUS100, pm90_n773l),
935 ENTRY(INTEL, BUS100, pm90_n738),
936 ENTRY(INTEL, BUS100, pm90_n758),
937 ENTRY(INTEL, BUS100, pm90_n778),
938 ENTRY(INTEL, BUS133, pm90_n710),
939 ENTRY(INTEL, BUS100, pm90_n715a),
940 ENTRY(INTEL, BUS100, pm90_n715b),
941 ENTRY(INTEL, BUS100, pm90_n715c),
942 ENTRY(INTEL, BUS100, pm90_n715d),
943 ENTRY(INTEL, BUS100, pm90_n725a),
944 ENTRY(INTEL, BUS100, pm90_n725b),
945 ENTRY(INTEL, BUS100, pm90_n725c),
946 ENTRY(INTEL, BUS100, pm90_n725d),
947 ENTRY(INTEL, BUS133, pm90_n730),
948 ENTRY(INTEL, BUS100, pm90_n735a),
949 ENTRY(INTEL, BUS100, pm90_n735b),
950 ENTRY(INTEL, BUS100, pm90_n735c),
951 ENTRY(INTEL, BUS100, pm90_n735d),
952 ENTRY(INTEL, BUS133, pm90_n740),
953 ENTRY(INTEL, BUS100, pm90_n745a),
954 ENTRY(INTEL, BUS100, pm90_n745b),
955 ENTRY(INTEL, BUS100, pm90_n745c),
956 ENTRY(INTEL, BUS100, pm90_n745d),
957 ENTRY(INTEL, BUS133, pm90_n750),
958 ENTRY(INTEL, BUS100, pm90_n755a),
959 ENTRY(INTEL, BUS100, pm90_n755b),
960 ENTRY(INTEL, BUS100, pm90_n755c),
961 ENTRY(INTEL, BUS100, pm90_n755d),
962 ENTRY(INTEL, BUS133, pm90_n760),
963 ENTRY(INTEL, BUS100, pm90_n765a),
964 ENTRY(INTEL, BUS100, pm90_n765b),
965 ENTRY(INTEL, BUS100, pm90_n765c),
966 ENTRY(INTEL, BUS100, pm90_n765e),
967 ENTRY(INTEL, BUS133, pm90_n770),
968 ENTRY(INTEL, BUS133, pm90_n780),
969 ENTRY(IDT, BUS100, C7M_770_ULV),
970 ENTRY(IDT, BUS100, C7M_779_ULV),
971 ENTRY(IDT, BUS100, C7M_772_ULV),
972 ENTRY(IDT, BUS100, C7M_771),
973 ENTRY(IDT, BUS100, C7M_775_ULV),
974 ENTRY(IDT, BUS100, C7M_754),
975 ENTRY(IDT, BUS100, C7M_764),
976 ENTRY(IDT, BUS133, C7M_765),
977 ENTRY(IDT, BUS100, C7M_784),
978 ENTRY(IDT, BUS133, C7M_785),
979 ENTRY(IDT, BUS100, C7M_794),
980 ENTRY(IDT, BUS133, C7M_795),
981 ENTRY(IDT, BUS100, eden90_1000)
982 };
983
984 #endif /* __i386__ */
985
986 static int est_match(device_t, cfdata_t, void *);
987 static void est_attach(device_t, device_t, void *);
988 static int est_detach(device_t, int);
989 static int est_bus_clock(struct cpu_info *);
990 static bool est_tables(device_t);
991 static void est_xcall(uint16_t);
992 static bool est_sysctl(device_t);
993 static int est_sysctl_helper(SYSCTLFN_PROTO);
994
995 struct est_softc {
996 device_t sc_dev;
997 struct cpu_info *sc_ci;
998 struct sysctllog *sc_log;
999 struct fqlist *sc_fqlist;
1000 struct fqlist sc_fake_fqlist;
1001 uint16_t *sc_fake_table;
1002 char *sc_freqs;
1003 size_t sc_freqs_len;
1004 int sc_bus_clock;
1005 int sc_node_target;
1006 int sc_node_current;
1007 };
1008
1009 CFATTACH_DECL_NEW(est, sizeof(struct est_softc),
1010 est_match, est_attach, est_detach, NULL);
1011
1012 static int
est_match(device_t parent,cfdata_t cf,void * aux)1013 est_match(device_t parent, cfdata_t cf, void *aux)
1014 {
1015 struct cpufeature_attach_args *cfaa = aux;
1016 struct cpu_info *ci = cfaa->ci;
1017
1018 if (strcmp(cfaa->name, "frequency") != 0)
1019 return 0;
1020
1021 if (cpu_vendor != CPUVENDOR_IDT &&
1022 cpu_vendor != CPUVENDOR_INTEL)
1023 return 0;
1024
1025 if ((ci->ci_feat_val[1] & CPUID2_EST) == 0)
1026 return 0;
1027
1028 return (est_bus_clock(ci) != 0) ? 5 : 0;
1029 }
1030
1031 static void
est_attach(device_t parent,device_t self,void * aux)1032 est_attach(device_t parent, device_t self, void *aux)
1033 {
1034 struct est_softc *sc = device_private(self);
1035 struct cpufeature_attach_args *cfaa = aux;
1036 struct cpu_info *ci = cfaa->ci;
1037
1038 sc->sc_ci = ci;
1039 sc->sc_dev = self;
1040 sc->sc_log = NULL;
1041 sc->sc_freqs = NULL;
1042 sc->sc_fqlist = NULL;
1043 sc->sc_fake_table = NULL;
1044 sc->sc_bus_clock = est_bus_clock(ci);
1045
1046 KASSERT(sc->sc_bus_clock != 0);
1047
1048 aprint_naive("\n");
1049 aprint_normal(": Enhanced SpeedStep\n");
1050
1051 (void)pmf_device_register(self, NULL, NULL);
1052
1053 if (est_tables(self) != false)
1054 est_sysctl(self);
1055 }
1056
1057 static int
est_detach(device_t self,int flags)1058 est_detach(device_t self, int flags)
1059 {
1060 struct est_softc *sc = device_private(self);
1061 uint16_t n = sc->sc_fake_fqlist.n;
1062
1063 if (sc->sc_log != NULL)
1064 sysctl_teardown(&sc->sc_log);
1065
1066 if (sc->sc_freqs != NULL)
1067 kmem_free(sc->sc_freqs, sc->sc_freqs_len);
1068
1069 if (sc->sc_fake_table != NULL)
1070 kmem_free(sc->sc_fake_table, n * sizeof(*sc->sc_fake_table));
1071
1072 pmf_device_deregister(self);
1073
1074 return 0;
1075 }
1076
1077 static int
est_bus_clock(struct cpu_info * ci)1078 est_bus_clock(struct cpu_info *ci)
1079 {
1080 uint32_t family, model;
1081 int bus_clock = 0;
1082
1083 family = CPUID_TO_BASEFAMILY(ci->ci_signature);
1084 model = CPUID_TO_MODEL(ci->ci_signature);
1085
1086 switch (family) {
1087
1088 case 0x0f:
1089 bus_clock = p4_get_bus_clock(ci);
1090 break;
1091
1092 case 0x06:
1093
1094 if (cpu_vendor != CPUVENDOR_IDT)
1095 bus_clock = p3_get_bus_clock(ci);
1096 else {
1097 switch (model) {
1098
1099 case 0x0a: /* C7 Esther */
1100 case 0x0d: /* C7 Esther */
1101 bus_clock = viac7_get_bus_clock(ci);
1102 break;
1103
1104 default:
1105 bus_clock = via_get_bus_clock(ci);
1106 break;
1107 }
1108 }
1109 }
1110
1111 return bus_clock;
1112 }
1113
1114 static bool
est_tables(device_t self)1115 est_tables(device_t self)
1116 {
1117 struct est_softc *sc = device_private(self);
1118
1119 #ifdef __i386__
1120 const struct fqlist *fql;
1121 #endif
1122 uint64_t msr;
1123 uint16_t cur, idhi, idlo;
1124 size_t len;
1125 int i, mv;
1126
1127 msr = rdmsr(MSR_PERF_STATUS);
1128
1129 idhi = (msr >> 32) & 0xffff;
1130 idlo = (msr >> 48) & 0xffff;
1131 cur = msr & 0xffff;
1132
1133 #ifdef __i386__
1134 if (idhi == 0 || idlo == 0 || cur == 0 ||
1135 ((cur >> 8) & 0xff) < ((idlo >> 8) & 0xff) ||
1136 ((cur >> 8) & 0xff) > ((idhi >> 8) & 0xff)) {
1137 aprint_debug_dev(self, "strange msr value 0x%"PRIx64"\n", msr);
1138 return false;
1139 }
1140 #endif
1141
1142 #ifdef __amd64__
1143 uint8_t crhi = (idhi >> 8) & 0xff;
1144 uint8_t crlo = (idlo >> 8) & 0xff;
1145 uint8_t crcur = (cur >> 8) & 0xff;
1146 if (crlo == 0 || crhi == 0 || crcur == 0 || crhi == crlo ||
1147 crlo > crhi || crcur < crlo || crcur > crhi) {
1148 /*
1149 * Do complain about other weirdness, because we first want to
1150 * know about it, before we decide what to do with it
1151 */
1152 aprint_debug_dev(self, "strange msr value 0x%"PRIu64"\n", msr);
1153 aprint_debug_dev(self, " crhi=%u, crlo=%u, crcur=%u\n",
1154 crhi, crlo, crcur);
1155 return false;
1156 }
1157 #endif
1158
1159 msr = rdmsr(MSR_PERF_STATUS);
1160 mv = MSR2MV(msr);
1161
1162 #ifdef __i386__
1163 /*
1164 * Find an entry which matches (vendor, bus_clock, idhi, idlo).
1165 */
1166 sc->sc_fqlist = NULL;
1167
1168 for (i = 0; i < __arraycount(est_cpus); i++) {
1169
1170 fql = &est_cpus[i];
1171
1172 if (cpu_vendor == fql->vendor &&
1173 sc->sc_bus_clock == BUS_CLK(fql) &&
1174 idhi == fql->table[0] && idlo == fql->table[fql->n - 1]) {
1175 sc->sc_fqlist = __UNCONST(fql);
1176 break;
1177 }
1178 }
1179 #endif
1180
1181 if (sc->sc_fqlist == NULL) {
1182 int j, tablesize, freq, volt;
1183 int minfreq, minvolt, maxfreq, maxvolt, freqinc, voltinc;
1184
1185 /*
1186 * Some CPUs report the same frequency in idhi and idlo,
1187 * so do not run est on them.
1188 */
1189 if (idhi == idlo) {
1190 aprint_debug_dev(self, "idhi == idlo\n");
1191 return false;
1192 }
1193
1194 #ifdef EST_DEBUG
1195 aprint_normal_dev(self, "bus_clock = %d\n", sc->sc_bus_clock);
1196 aprint_normal_dev(self, "idlo = 0x%x\n", idlo);
1197 aprint_normal_dev(self, "lo %4d mV, %4d MHz\n",
1198 MSR2MV(idlo), MSR2MHZ(idlo, sc->sc_bus_clock));
1199 aprint_normal_dev(self, "raw %4d , %4d \n",
1200 (idlo & 0xff), ((idlo >> 8) & 0xff));
1201 aprint_normal_dev(self, "idhi = 0x%x\n", idhi);
1202 aprint_normal_dev(self, "hi %4d mV, %4d MHz\n",
1203 MSR2MV(idhi), MSR2MHZ(idhi, sc->sc_bus_clock));
1204 aprint_normal_dev(self, "raw %4d , %4d \n",
1205 (idhi & 0xff), ((idhi >> 8) & 0xff));
1206 aprint_normal_dev(self, "cur = 0x%x\n", cur);
1207 #endif
1208
1209 /*
1210 * Generate a fake table with the power states we know,
1211 * interpolating the voltages and frequencies between the
1212 * high and low values. The (milli)voltages are always
1213 * rounded up when computing the table.
1214 */
1215 minfreq = MSR2FREQINC(idlo);
1216 maxfreq = MSR2FREQINC(idhi);
1217 minvolt = MSR2VOLTINC(idlo);
1218 maxvolt = MSR2VOLTINC(idhi);
1219 freqinc = maxfreq - minfreq;
1220 voltinc = maxvolt - minvolt;
1221
1222 /* Avoid diving by zero. */
1223 if (freqinc == 0)
1224 return false;
1225
1226 if (freqinc < voltinc || voltinc == 0) {
1227 tablesize = maxfreq - minfreq + 1;
1228 if (voltinc != 0)
1229 voltinc = voltinc * 100 / freqinc - 1;
1230 freqinc = 100;
1231 } else {
1232 tablesize = maxvolt - minvolt + 1;
1233 freqinc = freqinc * 100 / voltinc - 1;
1234 voltinc = 100;
1235 }
1236
1237 sc->sc_fake_table = kmem_alloc(tablesize *
1238 sizeof(uint16_t), KM_SLEEP);
1239 sc->sc_fake_fqlist.n = tablesize;
1240
1241 /* The frequency/voltage table is highest frequency first */
1242 freq = maxfreq * 100;
1243 volt = maxvolt * 100;
1244
1245 for (j = 0; j < tablesize; j++) {
1246 sc->sc_fake_table[j] = (((freq + 99) / 100) << 8) +
1247 (volt + 99) / 100;
1248 #ifdef EST_DEBUG
1249 aprint_normal_dev(self, "fake entry %d: %4d mV, "
1250 "%4d MHz, MSR*100 mV = %4d freq = %4d\n",
1251 j, MSR2MV(sc->sc_fake_table[j]),
1252 MSR2MHZ(sc->sc_fake_table[j], sc->sc_bus_clock),
1253 volt, freq);
1254 #endif /* EST_DEBUG */
1255 freq -= freqinc;
1256 volt -= voltinc;
1257 }
1258
1259 sc->sc_fake_fqlist.table = sc->sc_fake_table;
1260 sc->sc_fake_fqlist.vendor = cpu_vendor;
1261 sc->sc_fqlist = &sc->sc_fake_fqlist;
1262 }
1263
1264 sc->sc_freqs_len = sc->sc_fqlist->n * (sizeof("9999 ") - 1) + 1;
1265 sc->sc_freqs = kmem_zalloc(sc->sc_freqs_len, KM_SLEEP);
1266 for (i = len = 0; i < sc->sc_fqlist->n; i++) {
1267 if (len >= sc->sc_freqs_len)
1268 break;
1269 len += snprintf(sc->sc_freqs + len, sc->sc_freqs_len - len,
1270 "%d%s", MSR2MHZ(sc->sc_fqlist->table[i], sc->sc_bus_clock),
1271 i < sc->sc_fqlist->n - 1 ? " " : "");
1272 }
1273
1274 aprint_debug_dev(self, "%d mV, %d (MHz): %s\n", mv,
1275 MSR2MHZ(msr, sc->sc_bus_clock), sc->sc_freqs);
1276
1277 return true;
1278 }
1279
1280 static void
est_xcall(uint16_t val)1281 est_xcall(uint16_t val)
1282 {
1283 struct msr_rw_info msr;
1284 uint64_t xc;
1285
1286 msr.msr_read = true;
1287 msr.msr_type = MSR_PERF_CTL;
1288 msr.msr_mask = 0xffffULL;
1289 msr.msr_value = val;
1290
1291 xc = xc_broadcast(0, x86_msr_xcall, &msr, NULL);
1292 xc_wait(xc);
1293 }
1294
1295 static bool
est_sysctl(device_t self)1296 est_sysctl(device_t self)
1297 {
1298 struct est_softc *sc = device_private(self);
1299 const struct sysctlnode *node, *cpunode, *freqnode;
1300 int rv;
1301
1302 /*
1303 * Setup the sysctl sub-tree machdep.cpu.*
1304 */
1305 rv = sysctl_createv(&sc->sc_log, 0, NULL, &node,
1306 CTLFLAG_PERMANENT, CTLTYPE_NODE, "machdep", NULL,
1307 NULL, 0, NULL, 0, CTL_MACHDEP, CTL_EOL);
1308
1309 if (rv != 0)
1310 goto fail;
1311
1312 rv = sysctl_createv(&sc->sc_log, 0, &node, &cpunode,
1313 0, CTLTYPE_NODE, "cpu", NULL,
1314 NULL, 0, NULL, 0, CTL_CREATE, CTL_EOL);
1315
1316 if (rv != 0)
1317 goto fail;
1318
1319 rv = sysctl_createv(&sc->sc_log, 0, &cpunode, &freqnode,
1320 0, CTLTYPE_NODE, "frequency", NULL,
1321 NULL, 0, NULL, 0, CTL_CREATE, CTL_EOL);
1322
1323 if (rv != 0)
1324 goto fail;
1325
1326 rv = sysctl_createv(&sc->sc_log, 0, &freqnode, &node,
1327 CTLFLAG_READWRITE, CTLTYPE_INT, "target", NULL,
1328 est_sysctl_helper, 0, (void *)sc, 0, CTL_CREATE, CTL_EOL);
1329
1330 if (rv != 0)
1331 goto fail;
1332
1333 sc->sc_node_target = node->sysctl_num;
1334
1335 rv = sysctl_createv(&sc->sc_log, 0, &freqnode, &node,
1336 0, CTLTYPE_INT, "current", NULL,
1337 est_sysctl_helper, 0, (void *)sc, 0, CTL_CREATE, CTL_EOL);
1338
1339 if (rv != 0)
1340 goto fail;
1341
1342 sc->sc_node_current = node->sysctl_num;
1343
1344 rv = sysctl_createv(&sc->sc_log, 0, &freqnode, &node,
1345 0, CTLTYPE_STRING, "available", NULL,
1346 NULL, 0, sc->sc_freqs, sc->sc_freqs_len,
1347 CTL_CREATE, CTL_EOL);
1348
1349 if (rv != 0)
1350 goto fail;
1351
1352 return true;
1353
1354 fail:
1355 aprint_error_dev(self, "failed to initialize sysctl (err %d)\n", rv);
1356
1357 sysctl_teardown(&sc->sc_log);
1358 sc->sc_log = NULL;
1359
1360 return false;
1361 }
1362
1363 static int
est_sysctl_helper(SYSCTLFN_ARGS)1364 est_sysctl_helper(SYSCTLFN_ARGS)
1365 {
1366 struct sysctlnode node;
1367 struct est_softc *sc;
1368 int fq, err, i, oldfq;
1369
1370 fq = oldfq = 0;
1371
1372 node = *rnode;
1373 sc = node.sysctl_data;
1374
1375 if (sc->sc_fqlist == NULL)
1376 return EOPNOTSUPP;
1377
1378 node.sysctl_data = &fq;
1379
1380 if (rnode->sysctl_num == sc->sc_node_target) {
1381
1382 fq = oldfq = MSR2MHZ(rdmsr(MSR_PERF_CTL), sc->sc_bus_clock);
1383
1384 } else if (rnode->sysctl_num == sc->sc_node_current) {
1385
1386 fq = MSR2MHZ(rdmsr(MSR_PERF_STATUS), sc->sc_bus_clock);
1387
1388 } else
1389 return EOPNOTSUPP;
1390
1391 err = sysctl_lookup(SYSCTLFN_CALL(&node));
1392
1393 if (err != 0 || newp == NULL)
1394 return err;
1395
1396 if (fq == oldfq || rnode->sysctl_num != sc->sc_node_target)
1397 return 0;
1398
1399 for (i = sc->sc_fqlist->n - 1; i > 0; i--) {
1400
1401 if (MSR2MHZ(sc->sc_fqlist->table[i], sc->sc_bus_clock) >= fq)
1402 break;
1403 }
1404
1405 est_xcall(sc->sc_fqlist->table[i]);
1406 return 0;
1407 }
1408
1409 MODULE(MODULE_CLASS_DRIVER, est, NULL);
1410
1411 #ifdef _MODULE
1412 #include "ioconf.c"
1413 #endif
1414
1415 static int
est_modcmd(modcmd_t cmd,void * aux)1416 est_modcmd(modcmd_t cmd, void *aux)
1417 {
1418 int error = 0;
1419
1420 switch (cmd) {
1421 case MODULE_CMD_INIT:
1422 #ifdef _MODULE
1423 error = config_init_component(cfdriver_ioconf_est,
1424 cfattach_ioconf_est, cfdata_ioconf_est);
1425 #endif
1426 return error;
1427 case MODULE_CMD_FINI:
1428 #ifdef _MODULE
1429 error = config_fini_component(cfdriver_ioconf_est,
1430 cfattach_ioconf_est, cfdata_ioconf_est);
1431 #endif
1432 return error;
1433 default:
1434 return ENOTTY;
1435 }
1436 }
1437