1/* $NetBSD: est.c,v 1.30 2014/04/18 15:00:37 christos 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.30 2014/04/18 15:00:37 christos 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
109struct 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) */
119enum { BUS100 = 10000, BUS133 = 13333, BUS166 = 16666, BUS200 = 20000 };
120
121/* Ultra Low Voltage Intel Pentium M processor 900 MHz */
122static 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 */
129static 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 */
137static 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 */
146static 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 */
155static 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 */
165static 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 */
176static 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 */
185static 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 */
194static 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 */
204static 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 */
214static 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 */
224static 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 */
232static 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 */
241static 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 */
250static 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 */
259static 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 */
268static 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 */
277static 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 */
286static 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 */
296static 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 */
306static 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 */
316static 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 */
326static 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 */
336static 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 */
346static 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 */
357static 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 */
368static 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 */
379static 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 */
390static 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 */
401static 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 */
412static 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 */
424static 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 */
437static 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 */
451static 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 */
460static 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 */
469static 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 */
478static 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 */
487static 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 */
496static 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 */
506static 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 */
516static 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 */
526static 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 */
536static 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 */
545static 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 */
555static 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 */
565static 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 */
575static 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 */
585static 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 */
593static 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 */
604static 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 */
615static 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 */
626static 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 */
638static 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 */
647static 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 */
659static 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 */
671static 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 */
683static 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 */
695static 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 */
704static 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 */
716static 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 */
728static 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 */
740static 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 */
752static 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 */
762static 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 */
777static 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 */
785static 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 */
793static 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 */
802static 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 */
812static 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 */
821static 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 */
831static 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 */
841static 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 */
852static 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 */
864static 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 */
874static 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 */
885static 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' */
897static 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
904static 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
986static int est_match(device_t, cfdata_t, void *);
987static void est_attach(device_t, device_t, void *);
988static int est_detach(device_t, int);
989static int est_bus_clock(struct cpu_info *);
990static bool est_tables(device_t);
991static void est_xcall(uint16_t);
992static bool est_sysctl(device_t);
993static int est_sysctl_helper(SYSCTLFN_PROTO);
994
995struct 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
1009CFATTACH_DECL_NEW(est, sizeof(struct est_softc),
1010 est_match, est_attach, est_detach, NULL);
1011
1012static int
1013est_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
1031static void
1032est_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
1057static int
1058est_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
1077static int
1078est_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
1114static bool
1115est_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
1240 if (sc->sc_fake_table == NULL)
1241 return false;
1242
1243 sc->sc_fake_fqlist.n = tablesize;
1244
1245 /* The frequency/voltage table is highest frequency first */
1246 freq = maxfreq * 100;
1247 volt = maxvolt * 100;
1248
1249 for (j = 0; j < tablesize; j++) {
1250 sc->sc_fake_table[j] = (((freq + 99) / 100) << 8) +
1251 (volt + 99) / 100;
1252#ifdef EST_DEBUG
1253 aprint_normal_dev(self, "fake entry %d: %4d mV, "
1254 "%4d MHz, MSR*100 mV = %4d freq = %4d\n",
1255 j, MSR2MV(sc->sc_fake_table[j]),
1256 MSR2MHZ(sc->sc_fake_table[j], sc->sc_bus_clock),
1257 volt, freq);
1258#endif /* EST_DEBUG */
1259 freq -= freqinc;
1260 volt -= voltinc;
1261 }
1262
1263 sc->sc_fake_fqlist.table = sc->sc_fake_table;
1264 sc->sc_fake_fqlist.vendor = cpu_vendor;
1265 sc->sc_fqlist = &sc->sc_fake_fqlist;
1266 }
1267
1268 sc->sc_freqs_len = sc->sc_fqlist->n * (sizeof("9999 ") - 1) + 1;
1269 sc->sc_freqs = kmem_zalloc(sc->sc_freqs_len, KM_SLEEP);
1270
1271 if (sc->sc_freqs == NULL)
1272 return false;
1273
1274 for (i = len = 0; i < sc->sc_fqlist->n; i++) {
1275 if (len >= sc->sc_freqs_len)
1276 break;
1277 len += snprintf(sc->sc_freqs + len, sc->sc_freqs_len - len,
1278 "%d%s", MSR2MHZ(sc->sc_fqlist->table[i], sc->sc_bus_clock),
1279 i < sc->sc_fqlist->n - 1 ? " " : "");
1280 }
1281
1282 aprint_debug_dev(self, "%d mV, %d (MHz): %s\n", mv,
1283 MSR2MHZ(msr, sc->sc_bus_clock), sc->sc_freqs);
1284
1285 return true;
1286}
1287
1288static void
1289est_xcall(uint16_t val)
1290{
1291 struct msr_rw_info msr;
1292 uint64_t xc;
1293
1294 msr.msr_read = true;
1295 msr.msr_type = MSR_PERF_CTL;
1296 msr.msr_mask = 0xffffULL;
1297 msr.msr_value = val;
1298
1299 xc = xc_broadcast(0, x86_msr_xcall, &msr, NULL);
1300 xc_wait(xc);
1301}
1302
1303static bool
1304est_sysctl(device_t self)
1305{
1306 struct est_softc *sc = device_private(self);
1307 const struct sysctlnode *node, *estnode, *freqnode;
1308 int rv;
1309
1310 /*
1311 * Setup the sysctl sub-tree machdep.est.*
1312 */
1313 rv = sysctl_createv(&sc->sc_log, 0, NULL, &node,
1314 CTLFLAG_PERMANENT, CTLTYPE_NODE, "machdep", NULL,
1315 NULL, 0, NULL, 0, CTL_MACHDEP, CTL_EOL);
1316
1317 if (rv != 0)
1318 goto fail;
1319
1320 rv = sysctl_createv(&sc->sc_log, 0, &node, &estnode,
1321 0, CTLTYPE_NODE, "est", NULL,
1322 NULL, 0, NULL, 0, CTL_CREATE, CTL_EOL);
1323
1324 if (rv != 0)
1325 goto fail;
1326
1327 rv = sysctl_createv(&sc->sc_log, 0, &estnode, &freqnode,
1328 0, CTLTYPE_NODE, "frequency", NULL,
1329 NULL, 0, NULL, 0, CTL_CREATE, CTL_EOL);
1330
1331 if (rv != 0)
1332 goto fail;
1333
1334 rv = sysctl_createv(&sc->sc_log, 0, &freqnode, &node,
1335 CTLFLAG_READWRITE, CTLTYPE_INT, "target", NULL,
1336 est_sysctl_helper, 0, (void *)sc, 0, CTL_CREATE, CTL_EOL);
1337
1338 if (rv != 0)
1339 goto fail;
1340
1341 sc->sc_node_target = node->sysctl_num;
1342
1343 rv = sysctl_createv(&sc->sc_log, 0, &freqnode, &node,
1344 0, CTLTYPE_INT, "current", NULL,
1345 est_sysctl_helper, 0, (void *)sc, 0, CTL_CREATE, CTL_EOL);
1346
1347 if (rv != 0)
1348 goto fail;
1349
1350 sc->sc_node_current = node->sysctl_num;
1351
1352 rv = sysctl_createv(&sc->sc_log, 0, &freqnode, &node,
1353 0, CTLTYPE_STRING, "available", NULL,
1354 NULL, 0, sc->sc_freqs, sc->sc_freqs_len,
1355 CTL_CREATE, CTL_EOL);
1356
1357 if (rv != 0)
1358 goto fail;
1359
1360 return true;
1361
1362fail:
1363 aprint_error_dev(self, "failed to initialize sysctl (err %d)\n", rv);
1364
1365 sysctl_teardown(&sc->sc_log);
1366 sc->sc_log = NULL;
1367
1368 return false;
1369}
1370
1371static int
1372est_sysctl_helper(SYSCTLFN_ARGS)
1373{
1374 struct sysctlnode node;
1375 struct est_softc *sc;
1376 int fq, err, i, oldfq;
1377
1378 fq = oldfq = 0;
1379
1380 node = *rnode;
1381 sc = node.sysctl_data;
1382
1383 if (sc->sc_fqlist == NULL)
1384 return EOPNOTSUPP;
1385
1386 node.sysctl_data = &fq;
1387
1388 if (rnode->sysctl_num == sc->sc_node_target) {
1389
1390 fq = oldfq = MSR2MHZ(rdmsr(MSR_PERF_CTL), sc->sc_bus_clock);
1391
1392 } else if (rnode->sysctl_num == sc->sc_node_current) {
1393
1394 fq = MSR2MHZ(rdmsr(MSR_PERF_STATUS), sc->sc_bus_clock);
1395
1396 } else
1397 return EOPNOTSUPP;
1398
1399 err = sysctl_lookup(SYSCTLFN_CALL(&node));
1400
1401 if (err != 0 || newp == NULL)
1402 return err;
1403
1404 if (fq == oldfq || rnode->sysctl_num != sc->sc_node_target)
1405 return 0;
1406
1407 for (i = sc->sc_fqlist->n - 1; i > 0; i--) {
1408
1409 if (MSR2MHZ(sc->sc_fqlist->table[i], sc->sc_bus_clock) >= fq)
1410 break;
1411 }
1412
1413 est_xcall(sc->sc_fqlist->table[i]);
1414 return 0;
1415}
1416
1417MODULE(MODULE_CLASS_DRIVER, est, NULL);
1418
1419#ifdef _MODULE
1420#include "ioconf.c"
1421#endif
1422
1423static int
1424est_modcmd(modcmd_t cmd, void *aux)
1425{
1426 int error = 0;
1427
1428 switch (cmd) {
1429 case MODULE_CMD_INIT:
1430#ifdef _MODULE
1431 error = config_init_component(cfdriver_ioconf_est,
1432 cfattach_ioconf_est, cfdata_ioconf_est);
1433#endif
1434 return error;
1435 case MODULE_CMD_FINI:
1436#ifdef _MODULE
1437 error = config_fini_component(cfdriver_ioconf_est,
1438 cfattach_ioconf_est, cfdata_ioconf_est);
1439#endif
1440 return error;
1441 default:
1442 return ENOTTY;
1443 }
1444}
1445