xref: /netbsd-src/sys/arch/x86/x86/est.c (revision 76646d9e03c9615328f50b26f06c9b57e12e065b)
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