Subject: Re: port-amd64/36633 (Enhanced Speedstep is not enabled for Intel
To: None <port-amd64-maintainer@netbsd.org, gnats-admin@netbsd.org,>
From: Pierre Pronchery <khorben@defora.org>
List: netbsd-bugs
Date: 07/21/2007 16:10:02
The following reply was made to PR port-amd64/36633; it has been noted by GNATS.
From: Pierre Pronchery <khorben@defora.org>
To: gnats-bugs@NetBSD.org
Cc:
Subject: Re: port-amd64/36633 (Enhanced Speedstep is not enabled for Intel
EM64T CPUs)
Date: Sat, 21 Jul 2007 18:09:06 +0200
This is a multi-part message in MIME format.
--------------080106030401060104070403
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: 7bit
xtraeme@netbsd.org wrote:
> Synopsis: Enhanced Speedstep is not enabled for Intel EM64T CPUs
>
> State-Changed-Why:
> The code in HEAD is able to work on amd64 for long time now:
>
> amd64: The Enhanced Speedstep driver is now able to work on EM64T
> CPUs running in 64bit mode. [xtraeme 20070603]
>
> And your patch is incorrect because you are duplicating the same
> code on amd64. Sorry I do not have plans to apply them for netbsd-4,
> someone else should create the patch and send the PR...
Here is a new one. It should be better, I actually based it on yours. I
also took the bits for the VIA CPU. I must admit though that I only
tested it on the amd64 architecture so far, please test it on i386
(xen?) before anything.
HTH,
--
khorben
--------------080106030401060104070403
Content-Type: text/plain;
name="est.diff"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="est.diff"
Index: arch/amd64/amd64/identcpu.c
===================================================================
RCS file: /cvsroot/src/sys/arch/amd64/amd64/identcpu.c,v
retrieving revision 1.7.2.2
diff -u -r1.7.2.2 identcpu.c
--- arch/amd64/amd64/identcpu.c 15 Jun 2007 10:27:36 -0000 1.7.2.2
+++ arch/amd64/amd64/identcpu.c 21 Jul 2007 15:47:30 -0000
@@ -38,6 +38,7 @@
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: identcpu.c,v 1.7.2.2 2007/06/15 10:27:36 liamjfoy Exp $");
+#include "opt_enhanced_speedstep.h"
#include "opt_powernow_k8.h"
#include <sys/types.h>
@@ -139,6 +140,17 @@
x86_print_cacheinfo(ci);
+#ifdef ENHANCED_SPEEDSTEP
+ if ((vendor == CPUVENDOR_INTEL) &&
+ (ci->ci_feature2_flags & CPUID2_EST)) {
+ if (rdmsr(MSR_MISC_ENABLE) & (1 << 16))
+ est_init(CPUVENDOR_INTEL);
+ else
+ aprint_normal("%s: Enhanced SpeedStep disabled by "
+ "BIOS\n", device_xname(ci->ci_dev));
+ }
+#endif
+
#ifdef POWERNOW_K8
if (CPUID2FAMILY(ci->ci_signature) == 15 &&
(cpu_model[0] == 'A' || cpu_model[0] == 'O') &&
Index: arch/amd64/include/cpu.h
===================================================================
RCS file: /cvsroot/src/sys/arch/amd64/include/cpu.h,v
retrieving revision 1.12.8.1
diff -u -r1.12.8.1 cpu.h
--- arch/amd64/include/cpu.h 5 Jun 2007 20:28:11 -0000 1.12.8.1
+++ arch/amd64/include/cpu.h 21 Jul 2007 15:47:30 -0000
@@ -302,6 +302,9 @@
/* powernow_k8.c */
void k8_powernow_init(void);
+/* est.c */
+void est_init(int);
+
#endif /* _KERNEL */
#include <machine/psl.h>
Index: arch/i386/conf/files.i386
===================================================================
RCS file: /cvsroot/src/sys/arch/i386/conf/files.i386,v
retrieving revision 1.296.2.1
diff -u -r1.296.2.1 files.i386
--- arch/i386/conf/files.i386 19 Jun 2007 09:26:31 -0000 1.296.2.1
+++ arch/i386/conf/files.i386 21 Jul 2007 15:47:43 -0000
@@ -54,9 +54,6 @@
defparam opt_beep.h BEEP_ONHALT_COUNT
defparam opt_beep.h BEEP_ONHALT_PITCH BEEP_ONHALT_PERIOD
-# Enhanced SpeedStep
-defflag ENHANCED_SPEEDSTEP
-
# Multiboot support
defflag opt_multiboot.h MULTIBOOT
obsolete defparam MULTIBOOT_SYMTAB_SPACE
@@ -512,10 +509,6 @@
attach vesatext at vesabios
file arch/i386/bios/vesa_text.c vesatext
-# Enhanced SpeedStep
-file arch/i386/i386/est.c enhanced_speedstep
-defflag opt_est.h EST_FREQ_USERWRITE
-
# AMD PowerNow K7
file arch/i386/i386/powernow_k7.c powernow_k7
Index: arch/i386/i386/est.c
===================================================================
RCS file: arch/i386/i386/est.c
diff -N arch/i386/i386/est.c
--- arch/i386/i386/est.c 20 Apr 2007 20:31:25 -0000 1.31.2.2
+++ /dev/null 1 Jan 1970 00:00:00 -0000
@@ -1,1065 +0,0 @@
-/* $NetBSD: est.c,v 1.31.2.2 2007/04/20 20:31:25 bouyer Exp $ */
-/*
- * Copyright (c) 2003 Michael Eriksson.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-/*-
- * Copyright (c) 2004 The NetBSD Foundation, Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the NetBSD
- * Foundation, Inc. and its contributors.
- * 4. Neither the name of The NetBSD Foundation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * This is a driver for Intel's Enhanced SpeedStep Technology (EST),
- * as implemented in Pentium M processors.
- *
- * Reference documentation:
- *
- * - IA-32 Intel Architecture Software Developer's Manual, Volume 3:
- * System Programming Guide.
- * Section 13.14, Enhanced Intel SpeedStep technology.
- * Table B-2, MSRs in Pentium M Processors.
- * http://www.intel.com/design/pentium4/manuals/253668.htm
- *
- * - Intel Pentium M Processor Datasheet.
- * Table 5, Voltage and Current Specifications.
- * http://www.intel.com/design/mobile/datashts/252612.htm
- *
- * - Intel Pentium M Processor on 90 nm Process with 2-MB L2 Cache Datasheet
- * Table 3-4, 3-5, 3-6, Voltage and Current Specifications.
- * http://www.intel.com/design/mobile/datashts/302189.htm
- *
- * - Linux cpufreq patches, speedstep-centrino.c.
- * Encoding of MSR_PERF_CTL and MSR_PERF_STATUS.
- * http://www.codemonkey.org.uk/projects/cpufreq/cpufreq-2.4.22-pre6-1.gz
- *
- * ACPI objects: _PCT is MSR location, _PSS is freq/voltage, _PPC is caps.
- */
-
-#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: est.c,v 1.31.2.2 2007/04/20 20:31:25 bouyer Exp $");
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/malloc.h>
-#include <sys/sysctl.h>
-#include <sys/once.h>
-
-#include <x86/cpu_msr.h>
-
-#include <machine/cpu.h>
-#include <machine/specialreg.h>
-
-#include "opt_est.h"
-#ifdef EST_FREQ_USERWRITE
-#define EST_TARGET_CTLFLAG (CTLFLAG_READWRITE | CTLFLAG_ANYWRITE)
-#else
-#define EST_TARGET_CTLFLAG CTLFLAG_READWRITE
-#endif
-
-/* Convert MHz and mV into IDs for passing to the MSR. */
-#define ID16(MHz, mV, bus_clk) \
- ((((MHz * 100 + 50) / bus_clk) << 8) | ((mV ? mV - 700 : 0) >> 4))
-
-/* Possible bus speeds (multiplied by 100 for rounding) */
-enum { BUS100 = 10000, BUS133 = 13333, BUS166 = 16666, BUS200 = 20000 };
-
-/* Ultra Low Voltage Intel Pentium M processor 900 MHz */
-static const uint16_t pm130_900_ulv[] = {
- ID16( 900, 1004, BUS100),
- ID16( 800, 988, BUS100),
- ID16( 600, 844, BUS100),
-};
-
-/* Ultra Low Voltage Intel Pentium M processor 1.00 GHz */
-static const uint16_t pm130_1000_ulv[] = {
- ID16(1000, 1004, BUS100),
- ID16( 900, 988, BUS100),
- ID16( 800, 972, BUS100),
- ID16( 600, 844, BUS100),
-};
-
-/* Ultra Low Voltage Intel Pentium M processor 1.10 GHz */
-static const uint16_t pm130_1100_ulv[] = {
- ID16(1100, 1004, BUS100),
- ID16(1000, 988, BUS100),
- ID16( 900, 972, BUS100),
- ID16( 800, 956, BUS100),
- ID16( 600, 844, BUS100),
-};
-
-/* Low Voltage Intel Pentium M processor 1.10 GHz */
-static const uint16_t pm130_1100_lv[] = {
- ID16(1100, 1180, BUS100),
- ID16(1000, 1164, BUS100),
- ID16( 900, 1100, BUS100),
- ID16( 800, 1020, BUS100),
- ID16( 600, 956, BUS100),
-};
-
-/* Low Voltage Intel Pentium M processor 1.20 GHz */
-static const uint16_t pm130_1200_lv[] = {
- ID16(1200, 1180, BUS100),
- ID16(1100, 1164, BUS100),
- ID16(1000, 1100, BUS100),
- ID16( 900, 1020, BUS100),
- ID16( 800, 1004, BUS100),
- ID16( 600, 956, BUS100),
-};
-
-/* Low Voltage Intel Pentium M processor 1.30 GHz */
-static const uint16_t pm130_1300_lv[] = {
- ID16(1300, 1180, BUS100),
- ID16(1200, 1164, BUS100),
- ID16(1100, 1100, BUS100),
- ID16(1000, 1020, BUS100),
- ID16( 900, 1004, BUS100),
- ID16( 800, 988, BUS100),
- ID16( 600, 956, BUS100),
-};
-
-/* Intel Pentium M processor 1.30 GHz */
-static const uint16_t pm130_1300[] = {
- ID16(1300, 1388, BUS100),
- ID16(1200, 1356, BUS100),
- ID16(1000, 1292, BUS100),
- ID16( 800, 1260, BUS100),
- ID16( 600, 956, BUS100),
-};
-
-/* Intel Pentium M processor 1.40 GHz */
-static const uint16_t pm130_1400[] = {
- ID16(1400, 1484, BUS100),
- ID16(1200, 1436, BUS100),
- ID16(1000, 1308, BUS100),
- ID16( 800, 1180, BUS100),
- ID16( 600, 956, BUS100),
-};
-
-/* Intel Pentium M processor 1.50 GHz */
-static const uint16_t pm130_1500[] = {
- ID16(1500, 1484, BUS100),
- ID16(1400, 1452, BUS100),
- ID16(1200, 1356, BUS100),
- ID16(1000, 1228, BUS100),
- ID16( 800, 1116, BUS100),
- ID16( 600, 956, BUS100),
-};
-
-/* Intel Pentium M processor 1.60 GHz */
-static const uint16_t pm130_1600[] = {
- ID16(1600, 1484, BUS100),
- ID16(1400, 1420, BUS100),
- ID16(1200, 1276, BUS100),
- ID16(1000, 1164, BUS100),
- ID16( 800, 1036, BUS100),
- ID16( 600, 956, BUS100),
-};
-
-/* Intel Pentium M processor 1.70 GHz */
-static const uint16_t pm130_1700[] = {
- ID16(1700, 1484, BUS100),
- ID16(1400, 1308, BUS100),
- ID16(1200, 1228, BUS100),
- ID16(1000, 1116, BUS100),
- ID16( 800, 1004, BUS100),
- ID16( 600, 956, BUS100),
-};
-
-/* Intel Pentium M processor 723 1.0 GHz */
-static const uint16_t pm90_n723[] = {
- ID16(1000, 940, BUS100),
- ID16( 900, 908, BUS100),
- ID16( 800, 876, BUS100),
- ID16( 600, 812, BUS100),
-};
-
-/* Intel Pentium M processor 733 1.1 GHz, VID #G */
-static const uint16_t pm90_n733g[] = {
- ID16(1100, 956, BUS100),
- ID16(1000, 940, BUS100),
- ID16( 900, 908, BUS100),
- ID16( 800, 876, BUS100),
- ID16( 600, 812, BUS100),
-};
-
-/* Intel Pentium M processor 733 1.1 GHz, VID #H */
-static const uint16_t pm90_n733h[] = {
- ID16(1100, 940, BUS100),
- ID16(1000, 924, BUS100),
- ID16( 900, 892, BUS100),
- ID16( 800, 876, BUS100),
- ID16( 600, 812, BUS100),
-};
-
-/* Intel Pentium M processor 733 1.1 GHz, VID #I */
-static const uint16_t pm90_n733i[] = {
- ID16(1100, 924, BUS100),
- ID16(1000, 908, BUS100),
- ID16( 900, 892, BUS100),
- ID16( 800, 860, BUS100),
- ID16( 600, 812, BUS100),
-};
-
-/* Intel Pentium M processor 733 1.1 GHz, VID #J */
-static const uint16_t pm90_n733j[] = {
- ID16(1100, 908, BUS100),
- ID16(1000, 892, BUS100),
- ID16( 900, 876, BUS100),
- ID16( 800, 860, BUS100),
- ID16( 600, 812, BUS100),
-};
-
-/* Intel Pentium M processor 733 1.1 GHz, VID #K */
-static const uint16_t pm90_n733k[] = {
- ID16(1100, 892, BUS100),
- ID16(1000, 876, BUS100),
- ID16( 900, 860, BUS100),
- ID16( 800, 844, BUS100),
- ID16( 600, 812, BUS100),
-};
-
-/* Intel Pentium M processor 733 1.1 GHz, VID #L */
-static const uint16_t pm90_n733l[] = {
- ID16(1100, 876, BUS100),
- ID16(1000, 876, BUS100),
- ID16( 900, 860, BUS100),
- ID16( 800, 844, BUS100),
- ID16( 600, 812, BUS100),
-};
-
-/* Intel Pentium M processor 753 1.2 GHz, VID #G */
-static const uint16_t pm90_n753g[] = {
- ID16(1200, 956, BUS100),
- ID16(1100, 940, BUS100),
- ID16(1000, 908, BUS100),
- ID16( 900, 892, BUS100),
- ID16( 800, 860, BUS100),
- ID16( 600, 812, BUS100),
-};
-
-/* Intel Pentium M processor 753 1.2 GHz, VID #H */
-static const uint16_t pm90_n753h[] = {
- ID16(1200, 940, BUS100),
- ID16(1100, 924, BUS100),
- ID16(1000, 908, BUS100),
- ID16( 900, 876, BUS100),
- ID16( 800, 860, BUS100),
- ID16( 600, 812, BUS100),
-};
-
-/* Intel Pentium M processor 753 1.2 GHz, VID #I */
-static const uint16_t pm90_n753i[] = {
- ID16(1200, 924, BUS100),
- ID16(1100, 908, BUS100),
- ID16(1000, 892, BUS100),
- ID16( 900, 876, BUS100),
- ID16( 800, 860, BUS100),
- ID16( 600, 812, BUS100),
-};
-
-/* Intel Pentium M processor 753 1.2 GHz, VID #J */
-static const uint16_t pm90_n753j[] = {
- ID16(1200, 908, BUS100),
- ID16(1100, 892, BUS100),
- ID16(1000, 876, BUS100),
- ID16( 900, 860, BUS100),
- ID16( 800, 844, BUS100),
- ID16( 600, 812, BUS100),
-};
-
-/* Intel Pentium M processor 753 1.2 GHz, VID #K */
-static const uint16_t pm90_n753k[] = {
- ID16(1200, 892, BUS100),
- ID16(1100, 892, BUS100),
- ID16(1000, 876, BUS100),
- ID16( 900, 860, BUS100),
- ID16( 800, 844, BUS100),
- ID16( 600, 812, BUS100),
-};
-
-/* Intel Pentium M processor 753 1.2 GHz, VID #L */
-static const uint16_t pm90_n753l[] = {
- ID16(1200, 876, BUS100),
- ID16(1100, 876, BUS100),
- ID16(1000, 860, BUS100),
- ID16( 900, 844, BUS100),
- ID16( 800, 844, BUS100),
- ID16( 600, 812, BUS100),
-};
-
-/* Intel Pentium M processor 773 1.3 GHz, VID #G */
-static const uint16_t pm90_n773g[] = {
- ID16(1300, 956, BUS100),
- ID16(1200, 940, BUS100),
- ID16(1100, 924, BUS100),
- ID16(1000, 908, BUS100),
- ID16( 900, 876, BUS100),
- ID16( 800, 860, BUS100),
- ID16( 600, 812, BUS100),
-};
-
-/* Intel Pentium M processor 773 1.3 GHz, VID #H */
-static const uint16_t pm90_n773h[] = {
- ID16(1300, 940, BUS100),
- ID16(1200, 924, BUS100),
- ID16(1100, 908, BUS100),
- ID16(1000, 892, BUS100),
- ID16( 900, 876, BUS100),
- ID16( 800, 860, BUS100),
- ID16( 600, 812, BUS100),
-};
-
-/* Intel Pentium M processor 773 1.3 GHz, VID #I */
-static const uint16_t pm90_n773i[] = {
- ID16(1300, 924, BUS100),
- ID16(1200, 908, BUS100),
- ID16(1100, 892, BUS100),
- ID16(1000, 876, BUS100),
- ID16( 900, 860, BUS100),
- ID16( 800, 844, BUS100),
- ID16( 600, 812, BUS100),
-};
-
-/* Intel Pentium M processor 773 1.3 GHz, VID #J */
-static const uint16_t pm90_n773j[] = {
- ID16(1300, 908, BUS100),
- ID16(1200, 908, BUS100),
- ID16(1100, 892, BUS100),
- ID16(1000, 876, BUS100),
- ID16( 900, 860, BUS100),
- ID16( 800, 844, BUS100),
- ID16( 600, 812, BUS100),
-};
-
-/* Intel Pentium M processor 773 1.3 GHz, VID #K */
-static const uint16_t pm90_n773k[] = {
- ID16(1300, 892, BUS100),
- ID16(1200, 892, BUS100),
- ID16(1100, 876, BUS100),
- ID16(1000, 860, BUS100),
- ID16( 900, 860, BUS100),
- ID16( 800, 844, BUS100),
- ID16( 600, 812, BUS100),
-};
-
-/* Intel Pentium M processor 773 1.3 GHz, VID #L */
-static const uint16_t pm90_n773l[] = {
- ID16(1300, 876, BUS100),
- ID16(1200, 876, BUS100),
- ID16(1100, 860, BUS100),
- ID16(1000, 860, BUS100),
- ID16( 900, 844, BUS100),
- ID16( 800, 844, BUS100),
- ID16( 600, 812, BUS100),
-};
-
-/* Intel Pentium M processor 738 1.4 GHz */
-static const uint16_t pm90_n738[] = {
- ID16(1400, 1116, BUS100),
- ID16(1300, 1116, BUS100),
- ID16(1200, 1100, BUS100),
- ID16(1100, 1068, BUS100),
- ID16(1000, 1052, BUS100),
- ID16( 900, 1036, BUS100),
- ID16( 800, 1020, BUS100),
- ID16( 600, 988, BUS100),
-};
-
-/* Intel Pentium M processor 758 1.5 GHz */
-static const uint16_t pm90_n758[] = {
- ID16(1500, 1116, BUS100),
- ID16(1400, 1116, BUS100),
- ID16(1300, 1100, BUS100),
- ID16(1200, 1084, BUS100),
- ID16(1100, 1068, BUS100),
- ID16(1000, 1052, BUS100),
- ID16( 900, 1036, BUS100),
- ID16( 800, 1020, BUS100),
- ID16( 600, 988, BUS100),
-};
-
-/* Intel Pentium M processor 778 1.6 GHz */
-static const uint16_t pm90_n778[] = {
- ID16(1600, 1116, BUS100),
- ID16(1500, 1116, BUS100),
- ID16(1400, 1100, BUS100),
- ID16(1300, 1184, BUS100),
- ID16(1200, 1068, BUS100),
- ID16(1100, 1052, BUS100),
- ID16(1000, 1052, BUS100),
- ID16( 900, 1036, BUS100),
- ID16( 800, 1020, BUS100),
- ID16( 600, 988, BUS100),
-};
-
-/* Intel Pentium M processor 710 1.4 GHz, 533 MHz FSB */
-static const uint16_t pm90_n710[] = {
- ID16(1400, 1340, BUS133),
- ID16(1200, 1228, BUS133),
- ID16(1000, 1148, BUS133),
- ID16( 800, 1068, BUS133),
- ID16( 600, 998, BUS133),
-};
-
-/* Intel Pentium M processor 715 1.5 GHz, VID #A */
-static const uint16_t pm90_n715a[] = {
- ID16(1500, 1340, BUS100),
- ID16(1200, 1228, BUS100),
- ID16(1000, 1148, BUS100),
- ID16( 800, 1068, BUS100),
- ID16( 600, 988, BUS100),
-};
-
-/* Intel Pentium M processor 715 1.5 GHz, VID #B */
-static const uint16_t pm90_n715b[] = {
- ID16(1500, 1324, BUS100),
- ID16(1200, 1212, BUS100),
- ID16(1000, 1148, BUS100),
- ID16( 800, 1068, BUS100),
- ID16( 600, 988, BUS100),
-};
-
-/* Intel Pentium M processor 715 1.5 GHz, VID #C */
-static const uint16_t pm90_n715c[] = {
- ID16(1500, 1308, BUS100),
- ID16(1200, 1212, BUS100),
- ID16(1000, 1132, BUS100),
- ID16( 800, 1068, BUS100),
- ID16( 600, 988, BUS100),
-};
-
-/* Intel Pentium M processor 715 1.5 GHz, VID #D */
-static const uint16_t pm90_n715d[] = {
- ID16(1500, 1276, BUS100),
- ID16(1200, 1180, BUS100),
- ID16(1000, 1116, BUS100),
- ID16( 800, 1052, BUS100),
- ID16( 600, 988, BUS100),
-};
-
-/* Intel Pentium M processor 725 1.6 GHz, VID #A */
-static const uint16_t pm90_n725a[] = {
- ID16(1600, 1340, BUS100),
- ID16(1400, 1276, BUS100),
- ID16(1200, 1212, BUS100),
- ID16(1000, 1132, BUS100),
- ID16( 800, 1068, BUS100),
- ID16( 600, 988, BUS100),
-};
-
-/* Intel Pentium M processor 725 1.6 GHz, VID #B */
-static const uint16_t pm90_n725b[] = {
- ID16(1600, 1324, BUS100),
- ID16(1400, 1260, BUS100),
- ID16(1200, 1196, BUS100),
- ID16(1000, 1132, BUS100),
- ID16( 800, 1068, BUS100),
- ID16( 600, 988, BUS100),
-};
-
-/* Intel Pentium M processor 725 1.6 GHz, VID #C */
-static const uint16_t pm90_n725c[] = {
- ID16(1600, 1308, BUS100),
- ID16(1400, 1244, BUS100),
- ID16(1200, 1180, BUS100),
- ID16(1000, 1116, BUS100),
- ID16( 800, 1052, BUS100),
- ID16( 600, 988, BUS100),
-};
-
-/* Intel Pentium M processor 725 1.6 GHz, VID #D */
-static const uint16_t pm90_n725d[] = {
- ID16(1600, 1276, BUS100),
- ID16(1400, 1228, BUS100),
- ID16(1200, 1164, BUS100),
- ID16(1000, 1116, BUS100),
- ID16( 800, 1052, BUS100),
- ID16( 600, 988, BUS100),
-};
-
-/* Intel Pentium M processor 730 1.6 GHz, 533 MHz FSB */
-static const uint16_t pm90_n730[] = {
- ID16(1600, 1308, BUS133),
- ID16(1333, 1260, BUS133),
- ID16(1200, 1212, BUS133),
- ID16(1067, 1180, BUS133),
- ID16( 800, 988, BUS133),
-};
-
-/* Intel Pentium M processor 735 1.7 GHz, VID #A */
-static const uint16_t pm90_n735a[] = {
- ID16(1700, 1340, BUS100),
- ID16(1400, 1244, BUS100),
- ID16(1200, 1180, BUS100),
- ID16(1000, 1116, BUS100),
- ID16( 800, 1052, BUS100),
- ID16( 600, 988, BUS100),
-};
-
-/* Intel Pentium M processor 735 1.7 GHz, VID #B */
-static const uint16_t pm90_n735b[] = {
- ID16(1700, 1324, BUS100),
- ID16(1400, 1244, BUS100),
- ID16(1200, 1180, BUS100),
- ID16(1000, 1116, BUS100),
- ID16( 800, 1052, BUS100),
- ID16( 600, 988, BUS100),
-};
-
-/* Intel Pentium M processor 735 1.7 GHz, VID #C */
-static const uint16_t pm90_n735c[] = {
- ID16(1700, 1308, BUS100),
- ID16(1400, 1228, BUS100),
- ID16(1200, 1164, BUS100),
- ID16(1000, 1116, BUS100),
- ID16( 800, 1052, BUS100),
- ID16( 600, 988, BUS100),
-};
-
-/* Intel Pentium M processor 735 1.7 GHz, VID #D */
-static const uint16_t pm90_n735d[] = {
- ID16(1700, 1276, BUS100),
- ID16(1400, 1212, BUS100),
- ID16(1200, 1148, BUS100),
- ID16(1000, 1100, BUS100),
- ID16( 800, 1052, BUS100),
- ID16( 600, 988, BUS100),
-};
-
-/* Intel Pentium M processor 740 1.73 GHz, 533 MHz FSB */
-static const uint16_t pm90_n740[] = {
- ID16(1733, 1356, BUS133),
- ID16(1333, 1212, BUS133),
- ID16(1067, 1100, BUS133),
- ID16( 800, 988, BUS133),
-};
-
-/* Intel Pentium M processor 745 1.8 GHz, VID #A */
-static const uint16_t pm90_n745a[] = {
- ID16(1800, 1340, BUS100),
- ID16(1600, 1292, BUS100),
- ID16(1400, 1228, BUS100),
- ID16(1200, 1164, BUS100),
- ID16(1000, 1116, BUS100),
- ID16( 800, 1052, BUS100),
- ID16( 600, 988, BUS100),
-};
-
-/* Intel Pentium M processor 745 1.8 GHz, VID #B */
-static const uint16_t pm90_n745b[] = {
- ID16(1800, 1324, BUS100),
- ID16(1600, 1276, BUS100),
- ID16(1400, 1212, BUS100),
- ID16(1200, 1164, BUS100),
- ID16(1000, 1116, BUS100),
- ID16( 800, 1052, BUS100),
- ID16( 600, 988, BUS100),
-};
-
-/* Intel Pentium M processor 745 1.8 GHz, VID #C */
-static const uint16_t pm90_n745c[] = {
- ID16(1800, 1308, BUS100),
- ID16(1600, 1260, BUS100),
- ID16(1400, 1212, BUS100),
- ID16(1200, 1148, BUS100),
- ID16(1000, 1100, BUS100),
- ID16( 800, 1052, BUS100),
- ID16( 600, 988, BUS100),
-};
-
-/* Intel Pentium M processor 745 1.8 GHz, VID #D */
-static const uint16_t pm90_n745d[] = {
- ID16(1800, 1276, BUS100),
- ID16(1600, 1228, BUS100),
- ID16(1400, 1180, BUS100),
- ID16(1200, 1132, BUS100),
- ID16(1000, 1084, BUS100),
- ID16( 800, 1036, BUS100),
- ID16( 600, 988, BUS100),
-};
-
-/* Intel Pentium M processor 750 1.86 GHz, 533 MHz FSB */
-/* values extracted from \_PR\NPSS (via _PSS) SDST ACPI table */
-static const uint16_t pm90_n750[] = {
- ID16(1867, 1308, BUS133),
- ID16(1600, 1228, BUS133),
- ID16(1333, 1148, BUS133),
- ID16(1067, 1068, BUS133),
- ID16( 800, 988, BUS133),
-};
-
-/* Intel Pentium M processor 755 2.0 GHz, VID #A */
-static const uint16_t pm90_n755a[] = {
- ID16(2000, 1340, BUS100),
- ID16(1800, 1292, BUS100),
- ID16(1600, 1244, BUS100),
- ID16(1400, 1196, BUS100),
- ID16(1200, 1148, BUS100),
- ID16(1000, 1100, BUS100),
- ID16( 800, 1052, BUS100),
- ID16( 600, 988, BUS100),
-};
-
-/* Intel Pentium M processor 755 2.0 GHz, VID #B */
-static const uint16_t pm90_n755b[] = {
- ID16(2000, 1324, BUS100),
- ID16(1800, 1276, BUS100),
- ID16(1600, 1228, BUS100),
- ID16(1400, 1180, BUS100),
- ID16(1200, 1132, BUS100),
- ID16(1000, 1084, BUS100),
- ID16( 800, 1036, BUS100),
- ID16( 600, 988, BUS100),
-};
-
-/* Intel Pentium M processor 755 2.0 GHz, VID #C */
-static const uint16_t pm90_n755c[] = {
- ID16(2000, 1308, BUS100),
- ID16(1800, 1276, BUS100),
- ID16(1600, 1228, BUS100),
- ID16(1400, 1180, BUS100),
- ID16(1200, 1132, BUS100),
- ID16(1000, 1084, BUS100),
- ID16( 800, 1036, BUS100),
- ID16( 600, 988, BUS100),
-};
-
-/* Intel Pentium M processor 755 2.0 GHz, VID #D */
-static const uint16_t pm90_n755d[] = {
- ID16(2000, 1276, BUS100),
- ID16(1800, 1244, BUS100),
- ID16(1600, 1196, BUS100),
- ID16(1400, 1164, BUS100),
- ID16(1200, 1116, BUS100),
- ID16(1000, 1084, BUS100),
- ID16( 800, 1036, BUS100),
- ID16( 600, 988, BUS100),
-};
-
-/* Intel Pentium M processor 760 2.0 GHz, 533 MHz FSB */
-static const uint16_t pm90_n760[] = {
- ID16(2000, 1356, BUS133),
- ID16(1600, 1244, BUS133),
- ID16(1333, 1164, BUS133),
- ID16(1067, 1084, BUS133),
- ID16( 800, 988, BUS133),
-};
-
-/* Intel Pentium M processor 765 2.1 GHz, VID #A */
-static const uint16_t pm90_n765a[] = {
- ID16(2100, 1340, BUS100),
- ID16(1800, 1276, BUS100),
- ID16(1600, 1228, BUS100),
- ID16(1400, 1180, BUS100),
- ID16(1200, 1132, BUS100),
- ID16(1000, 1084, BUS100),
- ID16( 800, 1036, BUS100),
- ID16( 600, 988, BUS100),
-};
-
-/* Intel Pentium M processor 765 2.1 GHz, VID #B */
-static const uint16_t pm90_n765b[] = {
- ID16(2100, 1324, BUS100),
- ID16(1800, 1260, BUS100),
- ID16(1600, 1212, BUS100),
- ID16(1400, 1180, BUS100),
- ID16(1200, 1132, BUS100),
- ID16(1000, 1084, BUS100),
- ID16( 800, 1036, BUS100),
- ID16( 600, 988, BUS100),
-};
-
-/* Intel Pentium M processor 765 2.1 GHz, VID #C */
-static const uint16_t pm90_n765c[] = {
- ID16(2100, 1308, BUS100),
- ID16(1800, 1244, BUS100),
- ID16(1600, 1212, BUS100),
- ID16(1400, 1164, BUS100),
- ID16(1200, 1116, BUS100),
- ID16(1000, 1084, BUS100),
- ID16( 800, 1036, BUS100),
- ID16( 600, 988, BUS100),
-};
-
-/* Intel Pentium M processor 765 2.1 GHz, VID #E */
-static const uint16_t pm90_n765e[] = {
- ID16(2100, 1356, BUS100),
- ID16(1800, 1292, BUS100),
- ID16(1600, 1244, BUS100),
- ID16(1400, 1196, BUS100),
- ID16(1200, 1148, BUS100),
- ID16(1000, 1100, BUS100),
- ID16( 800, 1052, BUS100),
- ID16( 600, 988, BUS100),
-};
-
-/* Intel Pentium M processor 770 2.13 GHz */
-static const uint16_t pm90_n770[] = {
- ID16(2133, 1356, BUS133),
- ID16(1867, 1292, BUS133),
- ID16(1600, 1212, BUS133),
- ID16(1333, 1148, BUS133),
- ID16(1067, 1068, BUS133),
- ID16( 800, 988, BUS133),
-};
-
-/* Intel Pentium M processor 780 2.26 GHz */
-static const uint16_t pm90_n780[] = {
- ID16(2267, 1388, BUS133),
- ID16(1867, 1292, BUS133),
- ID16(1600, 1212, BUS133),
- ID16(1333, 1148, BUS133),
- ID16(1067, 1068, BUS133),
- ID16( 800, 988, BUS133),
-};
-
-struct fqlist {
- int vendor;
- unsigned bus_clk;
- unsigned n;
- const uint16_t *table;
-};
-
-#define ENTRY(ven, bus_clk, tab) \
- { CPUVENDOR_##ven, bus_clk == BUS133 ? 1 : 0, __arraycount(tab), tab }
-
-#define BUS_CLK(fqp) ((fqp)->bus_clk ? BUS133 : BUS100)
-
-static const struct fqlist est_cpus[] = {
- ENTRY(INTEL, BUS100, pm130_900_ulv),
- ENTRY(INTEL, BUS100, pm130_1000_ulv),
- ENTRY(INTEL, BUS100, pm130_1100_ulv),
- ENTRY(INTEL, BUS100, pm130_1100_lv),
- ENTRY(INTEL, BUS100, pm130_1200_lv),
- ENTRY(INTEL, BUS100, pm130_1300_lv),
- ENTRY(INTEL, BUS100, pm130_1300),
- ENTRY(INTEL, BUS100, pm130_1400),
- ENTRY(INTEL, BUS100, pm130_1500),
- ENTRY(INTEL, BUS100, pm130_1600),
- ENTRY(INTEL, BUS100, pm130_1700),
- ENTRY(INTEL, BUS100, pm90_n723),
- ENTRY(INTEL, BUS100, pm90_n733g),
- ENTRY(INTEL, BUS100, pm90_n733h),
- ENTRY(INTEL, BUS100, pm90_n733i),
- ENTRY(INTEL, BUS100, pm90_n733j),
- ENTRY(INTEL, BUS100, pm90_n733k),
- ENTRY(INTEL, BUS100, pm90_n733l),
- ENTRY(INTEL, BUS100, pm90_n753g),
- ENTRY(INTEL, BUS100, pm90_n753h),
- ENTRY(INTEL, BUS100, pm90_n753i),
- ENTRY(INTEL, BUS100, pm90_n753j),
- ENTRY(INTEL, BUS100, pm90_n753k),
- ENTRY(INTEL, BUS100, pm90_n753l),
- ENTRY(INTEL, BUS100, pm90_n773g),
- ENTRY(INTEL, BUS100, pm90_n773h),
- ENTRY(INTEL, BUS100, pm90_n773i),
- ENTRY(INTEL, BUS100, pm90_n773j),
- ENTRY(INTEL, BUS100, pm90_n773k),
- ENTRY(INTEL, BUS100, pm90_n773l),
- ENTRY(INTEL, BUS100, pm90_n738),
- ENTRY(INTEL, BUS100, pm90_n758),
- ENTRY(INTEL, BUS100, pm90_n778),
-
- ENTRY(INTEL, BUS133, pm90_n710),
- ENTRY(INTEL, BUS100, pm90_n715a),
- ENTRY(INTEL, BUS100, pm90_n715b),
- ENTRY(INTEL, BUS100, pm90_n715c),
- ENTRY(INTEL, BUS100, pm90_n715d),
- ENTRY(INTEL, BUS100, pm90_n725a),
- ENTRY(INTEL, BUS100, pm90_n725b),
- ENTRY(INTEL, BUS100, pm90_n725c),
- ENTRY(INTEL, BUS100, pm90_n725d),
- ENTRY(INTEL, BUS133, pm90_n730),
- ENTRY(INTEL, BUS100, pm90_n735a),
- ENTRY(INTEL, BUS100, pm90_n735b),
- ENTRY(INTEL, BUS100, pm90_n735c),
- ENTRY(INTEL, BUS100, pm90_n735d),
- ENTRY(INTEL, BUS133, pm90_n740),
- ENTRY(INTEL, BUS100, pm90_n745a),
- ENTRY(INTEL, BUS100, pm90_n745b),
- ENTRY(INTEL, BUS100, pm90_n745c),
- ENTRY(INTEL, BUS100, pm90_n745d),
- ENTRY(INTEL, BUS133, pm90_n750),
- ENTRY(INTEL, BUS100, pm90_n755a),
- ENTRY(INTEL, BUS100, pm90_n755b),
- ENTRY(INTEL, BUS100, pm90_n755c),
- ENTRY(INTEL, BUS100, pm90_n755d),
- ENTRY(INTEL, BUS133, pm90_n760),
- ENTRY(INTEL, BUS100, pm90_n765a),
- ENTRY(INTEL, BUS100, pm90_n765b),
- ENTRY(INTEL, BUS100, pm90_n765c),
- ENTRY(INTEL, BUS100, pm90_n765e),
- ENTRY(INTEL, BUS133, pm90_n770),
- ENTRY(INTEL, BUS133, pm90_n780)
-};
-
-#define MSR2FREQINC(msr) (((int) (msr) >> 8) & 0xff)
-#define MSR2VOLTINC(msr) ((int) (msr) & 0xff)
-
-#define MSR2MHZ(msr, bus) ((MSR2FREQINC((msr)) * (bus) + 50) / 100)
-#define MSR2MV(msr) (MSR2VOLTINC(msr) * 16 + 700)
-
-static const struct fqlist *est_fqlist; /* not NULL if functional */
-static uint16_t fake_table[3]; /* guessed est_cpu table */
-static struct fqlist fake_fqlist;
-static int est_node_target, est_node_current;
-static const char est_desc[] = "Enhanced SpeedStep";
-static int lvendor;
-/* bus_clock is assigned in identcpu.c */
-int bus_clock;
-
-static int est_sysctl_helper(SYSCTLFN_PROTO);
-static int est_init_once(void);
-static void est_init_main(int);
-
-static int
-est_sysctl_helper(SYSCTLFN_ARGS)
-{
- struct msr_cpu_broadcast mcb;
- struct sysctlnode node;
- int fq, oldfq, error;
-
- if (est_fqlist == NULL)
- return EOPNOTSUPP;
-
- node = *rnode;
- node.sysctl_data = &fq;
-
- oldfq = 0;
- if (rnode->sysctl_num == est_node_target)
- fq = oldfq = MSR2MHZ(rdmsr(MSR_PERF_CTL), bus_clock);
- else if (rnode->sysctl_num == est_node_current)
- fq = MSR2MHZ(rdmsr(MSR_PERF_STATUS), bus_clock);
- else
- return EOPNOTSUPP;
-
- error = sysctl_lookup(SYSCTLFN_CALL(&node));
- if (error || newp == NULL)
- return error;
-
- /* support writing to ...frequency.target */
- if (rnode->sysctl_num == est_node_target && fq != oldfq) {
- int i;
-
- for (i = est_fqlist->n - 1; i > 0; i--)
- if (MSR2MHZ(est_fqlist->table[i], bus_clock) >= fq)
- break;
- fq = MSR2MHZ(est_fqlist->table[i], bus_clock);
- mcb.msr_read = true;
- mcb.msr_type = MSR_PERF_CTL;
- mcb.msr_mask = 0xffffULL;
- mcb.msr_value = est_fqlist->table[i];
- msr_cpu_broadcast(&mcb);
- }
-
- return 0;
-}
-
-static int
-est_init_once(void)
-{
- est_init_main(lvendor);
- return 0;
-}
-
-void
-est_init(int vendor)
-{
- int error;
- static ONCE_DECL(est_initialized);
-
- error = RUN_ONCE(&est_initialized, est_init_once);
- if (__predict_false(error != 0)) {
- return;
- }
-}
-
-static void
-est_init_main(int vendor)
-{
- const struct fqlist *fql;
- const struct sysctlnode *node, *estnode, *freqnode;
- uint64_t msr;
- uint16_t cur, idhi, idlo;
- int i, rc;
- int mv;
- size_t len, freq_len;
- char *freq_names, *cpuname;
-
- cpuname = curcpu()->ci_dev->dv_xname;
-
- if (bus_clock == 0) {
- aprint_debug("%s: unknown system bus clock\n", __func__);
- return;
- }
-
- lvendor = vendor;
-
- msr = rdmsr(MSR_PERF_STATUS);
- idhi = (msr >> 32) & 0xffff;
- idlo = (msr >> 48) & 0xffff;
- cur = msr & 0xffff;
- if (idhi == 0 || idlo == 0 || cur == 0 ||
- ((cur >> 8) & 0xff) < ((idlo >> 8) & 0xff) ||
- ((cur >> 8) & 0xff) > ((idhi >> 8) & 0xff)) {
- aprint_debug("%s: strange msr value 0x%016llx\n", __func__, msr);
- return;
- }
-
- msr = rdmsr(MSR_PERF_STATUS);
- mv = MSR2MV(msr);
- aprint_normal("%s: %s (%d mV) ", cpuname, est_desc, mv);
- aprint_normal("%d MHz\n", MSR2MHZ(msr, bus_clock));
-
- /*
- * Find an entry which matches (vendor, bus_clock, idhi, idlo)
- */
- est_fqlist = NULL;
- for (i = 0; i < __arraycount(est_cpus); i++) {
- fql = &est_cpus[i];
- if (vendor == fql->vendor && bus_clock == BUS_CLK(fql) &&
- idhi == fql->table[0] && idlo == fql->table[fql->n - 1]) {
- est_fqlist = fql;
- break;
- }
- }
-
- if (est_fqlist == NULL) {
- aprint_normal("%s: unknown Enhanced SpeedStep CPU.\n",
- cpuname);
-
- /*
- * Some CPUs report the same frequency in idhi and idlo,
- * so do not run est on them.
- */
- if (idhi == idlo)
- return;
- /*
- * Generate a fake table with the power states we know.
- */
- fake_table[0] = idhi;
- if (cur == idhi || cur == idlo) {
- aprint_normal("%s: using only highest and lowest "
- "power states.\n", cpuname);
-
- fake_table[1] = idlo;
- fake_fqlist.n = 2;
- } else {
- aprint_normal("%s: using only highest, current "
- "and lowest power states.\n", cpuname);
-
- fake_table[1] = cur;
- fake_table[2] = idlo;
- fake_fqlist.n = 3;
- }
- fake_fqlist.vendor = vendor;
- fake_fqlist.table = fake_table;
- est_fqlist = &fake_fqlist;
- }
-
- /*
- * OK, tell the user the available frequencies.
- */
- freq_len = est_fqlist->n * (sizeof("9999 ")-1) + 1;
- freq_names = malloc(freq_len, M_SYSCTLDATA, M_WAITOK);
- freq_names[0] = '\0';
- len = 0;
- for (i = 0; i < est_fqlist->n; i++) {
- len += snprintf(freq_names + len, freq_len - len, "%d%s",
- MSR2MHZ(est_fqlist->table[i], bus_clock),
- i < est_fqlist->n - 1 ? " " : "");
- }
- aprint_normal("%s: %s frequencies available (MHz): %s\n",
- cpuname, est_desc, freq_names);
-
- /*
- * Setup the sysctl sub-tree machdep.est.*
- */
- if ((rc = sysctl_createv(NULL, 0, NULL, &node,
- CTLFLAG_PERMANENT, CTLTYPE_NODE, "machdep", NULL,
- NULL, 0, NULL, 0, CTL_MACHDEP, CTL_EOL)) != 0)
- goto err;
-
- if ((rc = sysctl_createv(NULL, 0, &node, &estnode,
- 0, CTLTYPE_NODE, "est", NULL,
- NULL, 0, NULL, 0, CTL_CREATE, CTL_EOL)) != 0)
- goto err;
-
- if ((rc = sysctl_createv(NULL, 0, &estnode, &freqnode,
- 0, CTLTYPE_NODE, "frequency", NULL,
- NULL, 0, NULL, 0, CTL_CREATE, CTL_EOL)) != 0)
- goto err;
-
- if ((rc = sysctl_createv(NULL, 0, &freqnode, &node,
- EST_TARGET_CTLFLAG, CTLTYPE_INT, "target", NULL,
- est_sysctl_helper, 0, NULL, 0, CTL_CREATE, CTL_EOL)) != 0)
- goto err;
- est_node_target = node->sysctl_num;
-
- if ((rc = sysctl_createv(NULL, 0, &freqnode, &node,
- 0, CTLTYPE_INT, "current", NULL,
- est_sysctl_helper, 0, NULL, 0, CTL_CREATE, CTL_EOL)) != 0)
- goto err;
- est_node_current = node->sysctl_num;
-
- if ((rc = sysctl_createv(NULL, 0, &freqnode, &node,
- 0, CTLTYPE_STRING, "available", NULL,
- NULL, 0, freq_names, freq_len, CTL_CREATE, CTL_EOL)) != 0)
- goto err;
-
- return;
-
- err:
- free(freq_names, M_SYSCTLDATA);
- aprint_normal("%s: sysctl_createv failed (rc = %d)\n", __func__, rc);
-}
Index: arch/x86/conf/files.x86
===================================================================
RCS file: /cvsroot/src/sys/arch/x86/conf/files.x86,v
retrieving revision 1.20.2.1
diff -u -r1.20.2.1 files.x86
--- arch/x86/conf/files.x86 20 Apr 2007 20:31:26 -0000 1.20.2.1
+++ arch/x86/conf/files.x86 21 Jul 2007 15:48:00 -0000
@@ -10,6 +10,10 @@
defflag opt_pcifixup.h PCI_ADDR_FIXUP PCI_BUS_FIXUP
PCI_INTR_FIXUP PCI_INTR_FIXUP_FORCE
+# Intel Enhanced Speedstep
+defflag ENHANCED_SPEEDSTEP
+defflag opt_est.h EST_FREQ_USERWRITE
+
# AMD Powernow/Cool`n'Quiet Technology
defflag opt_powernow_k8.h POWERNOW_K8
@@ -57,6 +61,10 @@
file arch/x86/x86/powernow_k8.c powernow_k8
file arch/x86/x86/powernow_common.c powernow_k8 | powernow_k7
+# Intel Enhanced Speedstep
+file arch/x86/x86/est.c enhanced_speedstep
+file arch/x86/x86/intel_busclock.c enhanced_speedstep
+
#IPMI device
device ipmi : sysmon_envsys, sysmon_wdog
attach ipmi at ipmibus
Index: arch/x86/include/cpuvar.h
===================================================================
RCS file: /cvsroot/src/sys/arch/x86/include/cpuvar.h,v
retrieving revision 1.5
diff -u -r1.5 cpuvar.h
--- arch/x86/include/cpuvar.h 8 Aug 2006 16:34:34 -0000 1.5
+++ arch/x86/include/cpuvar.h 21 Jul 2007 15:48:01 -0000
@@ -70,6 +70,9 @@
* SUCH DAMAGE.
*/
+#ifndef _X86_CPUVAR_H_
+#define _X86_CPUVAR_H_
+
struct cpu_functions {
int (*start)(struct cpu_info *);
int (*stop)(struct cpu_info *);
@@ -94,6 +97,9 @@
#ifdef _KERNEL
#include "opt_multiprocessor.h"
+#ifndef XEN
+#include "opt_enhanced_speedstep.h"
+#endif
#ifdef MULTIPROCESSOR
extern u_int32_t cpus_running;
@@ -107,4 +113,13 @@
void cpu_init(struct cpu_info *);
void cpu_init_first(void);
+#ifdef ENHANCED_SPEEDSTEP
+void est_init(int);
+int via_get_bus_clock(struct cpu_info *);
+int p3_get_bus_clock(struct cpu_info *);
+int p4_get_bus_clock(struct cpu_info *);
#endif
+
+#endif
+
+#endif /* !_X86_CPUVAR_H_ */
Index: arch/x86/x86/est.c
===================================================================
RCS file: arch/x86/x86/est.c
diff -N arch/x86/x86/est.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ arch/x86/x86/est.c 21 Jul 2007 15:48:02 -0000
@@ -0,0 +1,1249 @@
+/* $NetBSD: est.c,v 1.2 2007/07/01 20:12:35 xtraeme Exp $ */
+/*
+ * Copyright (c) 2003 Michael Eriksson.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*-
+ * Copyright (c) 2004 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * This is a driver for Intel's Enhanced SpeedStep Technology (EST),
+ * as implemented in Pentium M processors.
+ *
+ * Reference documentation:
+ *
+ * - IA-32 Intel Architecture Software Developer's Manual, Volume 3:
+ * System Programming Guide.
+ * Section 13.14, Enhanced Intel SpeedStep technology.
+ * Table B-2, MSRs in Pentium M Processors.
+ * http://www.intel.com/design/pentium4/manuals/253668.htm
+ *
+ * - Intel Pentium M Processor Datasheet.
+ * Table 5, Voltage and Current Specifications.
+ * http://www.intel.com/design/mobile/datashts/252612.htm
+ *
+ * - Intel Pentium M Processor on 90 nm Process with 2-MB L2 Cache Datasheet
+ * Table 3-4, 3-5, 3-6, Voltage and Current Specifications.
+ * http://www.intel.com/design/mobile/datashts/302189.htm
+ *
+ * - Linux cpufreq patches, speedstep-centrino.c.
+ * Encoding of MSR_PERF_CTL and MSR_PERF_STATUS.
+ * http://www.codemonkey.org.uk/projects/cpufreq/cpufreq-2.4.22-pre6-1.gz
+ *
+ * ACPI objects: _PCT is MSR location, _PSS is freq/voltage, _PPC is caps.
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: est.c,v 1.2 2007/07/01 20:12:35 xtraeme Exp $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+#include <sys/sysctl.h>
+#include <sys/once.h>
+
+#include <x86/cpuvar.h>
+#include <x86/cputypes.h>
+#include <x86/cpu_msr.h>
+
+#include <machine/cpu.h>
+#include <machine/specialreg.h>
+
+#include "opt_est.h"
+#ifdef EST_FREQ_USERWRITE
+#define EST_TARGET_CTLFLAG (CTLFLAG_READWRITE | CTLFLAG_ANYWRITE)
+#else
+#define EST_TARGET_CTLFLAG CTLFLAG_READWRITE
+#endif
+
+/* Convert MHz and mV into IDs for passing to the MSR. */
+#define ID16(MHz, mV, bus_clk) \
+ ((((MHz * 100 + 50) / bus_clk) << 8) | ((mV ? mV - 700 : 0) >> 4))
+
+/* Possible bus speeds (multiplied by 100 for rounding) */
+enum { BUS100 = 10000, BUS133 = 13333, BUS166 = 16666, BUS200 = 20000 };
+
+/* Ultra Low Voltage Intel Pentium M processor 900 MHz */
+static const uint16_t pm130_900_ulv[] = {
+ ID16( 900, 1004, BUS100),
+ ID16( 800, 988, BUS100),
+ ID16( 600, 844, BUS100),
+};
+
+/* Ultra Low Voltage Intel Pentium M processor 1.00 GHz */
+static const uint16_t pm130_1000_ulv[] = {
+ ID16(1000, 1004, BUS100),
+ ID16( 900, 988, BUS100),
+ ID16( 800, 972, BUS100),
+ ID16( 600, 844, BUS100),
+};
+
+/* Ultra Low Voltage Intel Pentium M processor 1.10 GHz */
+static const uint16_t pm130_1100_ulv[] = {
+ ID16(1100, 1004, BUS100),
+ ID16(1000, 988, BUS100),
+ ID16( 900, 972, BUS100),
+ ID16( 800, 956, BUS100),
+ ID16( 600, 844, BUS100),
+};
+
+/* Low Voltage Intel Pentium M processor 1.10 GHz */
+static const uint16_t pm130_1100_lv[] = {
+ ID16(1100, 1180, BUS100),
+ ID16(1000, 1164, BUS100),
+ ID16( 900, 1100, BUS100),
+ ID16( 800, 1020, BUS100),
+ ID16( 600, 956, BUS100),
+};
+
+/* Low Voltage Intel Pentium M processor 1.20 GHz */
+static const uint16_t pm130_1200_lv[] = {
+ ID16(1200, 1180, BUS100),
+ ID16(1100, 1164, BUS100),
+ ID16(1000, 1100, BUS100),
+ ID16( 900, 1020, BUS100),
+ ID16( 800, 1004, BUS100),
+ ID16( 600, 956, BUS100),
+};
+
+/* Low Voltage Intel Pentium M processor 1.30 GHz */
+static const uint16_t pm130_1300_lv[] = {
+ ID16(1300, 1180, BUS100),
+ ID16(1200, 1164, BUS100),
+ ID16(1100, 1100, BUS100),
+ ID16(1000, 1020, BUS100),
+ ID16( 900, 1004, BUS100),
+ ID16( 800, 988, BUS100),
+ ID16( 600, 956, BUS100),
+};
+
+/* Intel Pentium M processor 1.30 GHz */
+static const uint16_t pm130_1300[] = {
+ ID16(1300, 1388, BUS100),
+ ID16(1200, 1356, BUS100),
+ ID16(1000, 1292, BUS100),
+ ID16( 800, 1260, BUS100),
+ ID16( 600, 956, BUS100),
+};
+
+/* Intel Pentium M processor 1.40 GHz */
+static const uint16_t pm130_1400[] = {
+ ID16(1400, 1484, BUS100),
+ ID16(1200, 1436, BUS100),
+ ID16(1000, 1308, BUS100),
+ ID16( 800, 1180, BUS100),
+ ID16( 600, 956, BUS100),
+};
+
+/* Intel Pentium M processor 1.50 GHz */
+static const uint16_t pm130_1500[] = {
+ ID16(1500, 1484, BUS100),
+ ID16(1400, 1452, BUS100),
+ ID16(1200, 1356, BUS100),
+ ID16(1000, 1228, BUS100),
+ ID16( 800, 1116, BUS100),
+ ID16( 600, 956, BUS100),
+};
+
+/* Intel Pentium M processor 1.60 GHz */
+static const uint16_t pm130_1600[] = {
+ ID16(1600, 1484, BUS100),
+ ID16(1400, 1420, BUS100),
+ ID16(1200, 1276, BUS100),
+ ID16(1000, 1164, BUS100),
+ ID16( 800, 1036, BUS100),
+ ID16( 600, 956, BUS100),
+};
+
+/* Intel Pentium M processor 1.70 GHz */
+static const uint16_t pm130_1700[] = {
+ ID16(1700, 1484, BUS100),
+ ID16(1400, 1308, BUS100),
+ ID16(1200, 1228, BUS100),
+ ID16(1000, 1116, BUS100),
+ ID16( 800, 1004, BUS100),
+ ID16( 600, 956, BUS100),
+};
+
+/* Intel Pentium M processor 723 1.0 GHz */
+static const uint16_t pm90_n723[] = {
+ ID16(1000, 940, BUS100),
+ ID16( 900, 908, BUS100),
+ ID16( 800, 876, BUS100),
+ ID16( 600, 812, BUS100),
+};
+
+/* Intel Pentium M processor 733 1.1 GHz, VID #G */
+static const uint16_t pm90_n733g[] = {
+ ID16(1100, 956, BUS100),
+ ID16(1000, 940, BUS100),
+ ID16( 900, 908, BUS100),
+ ID16( 800, 876, BUS100),
+ ID16( 600, 812, BUS100),
+};
+
+/* Intel Pentium M processor 733 1.1 GHz, VID #H */
+static const uint16_t pm90_n733h[] = {
+ ID16(1100, 940, BUS100),
+ ID16(1000, 924, BUS100),
+ ID16( 900, 892, BUS100),
+ ID16( 800, 876, BUS100),
+ ID16( 600, 812, BUS100),
+};
+
+/* Intel Pentium M processor 733 1.1 GHz, VID #I */
+static const uint16_t pm90_n733i[] = {
+ ID16(1100, 924, BUS100),
+ ID16(1000, 908, BUS100),
+ ID16( 900, 892, BUS100),
+ ID16( 800, 860, BUS100),
+ ID16( 600, 812, BUS100),
+};
+
+/* Intel Pentium M processor 733 1.1 GHz, VID #J */
+static const uint16_t pm90_n733j[] = {
+ ID16(1100, 908, BUS100),
+ ID16(1000, 892, BUS100),
+ ID16( 900, 876, BUS100),
+ ID16( 800, 860, BUS100),
+ ID16( 600, 812, BUS100),
+};
+
+/* Intel Pentium M processor 733 1.1 GHz, VID #K */
+static const uint16_t pm90_n733k[] = {
+ ID16(1100, 892, BUS100),
+ ID16(1000, 876, BUS100),
+ ID16( 900, 860, BUS100),
+ ID16( 800, 844, BUS100),
+ ID16( 600, 812, BUS100),
+};
+
+/* Intel Pentium M processor 733 1.1 GHz, VID #L */
+static const uint16_t pm90_n733l[] = {
+ ID16(1100, 876, BUS100),
+ ID16(1000, 876, BUS100),
+ ID16( 900, 860, BUS100),
+ ID16( 800, 844, BUS100),
+ ID16( 600, 812, BUS100),
+};
+
+/* Intel Pentium M processor 753 1.2 GHz, VID #G */
+static const uint16_t pm90_n753g[] = {
+ ID16(1200, 956, BUS100),
+ ID16(1100, 940, BUS100),
+ ID16(1000, 908, BUS100),
+ ID16( 900, 892, BUS100),
+ ID16( 800, 860, BUS100),
+ ID16( 600, 812, BUS100),
+};
+
+/* Intel Pentium M processor 753 1.2 GHz, VID #H */
+static const uint16_t pm90_n753h[] = {
+ ID16(1200, 940, BUS100),
+ ID16(1100, 924, BUS100),
+ ID16(1000, 908, BUS100),
+ ID16( 900, 876, BUS100),
+ ID16( 800, 860, BUS100),
+ ID16( 600, 812, BUS100),
+};
+
+/* Intel Pentium M processor 753 1.2 GHz, VID #I */
+static const uint16_t pm90_n753i[] = {
+ ID16(1200, 924, BUS100),
+ ID16(1100, 908, BUS100),
+ ID16(1000, 892, BUS100),
+ ID16( 900, 876, BUS100),
+ ID16( 800, 860, BUS100),
+ ID16( 600, 812, BUS100),
+};
+
+/* Intel Pentium M processor 753 1.2 GHz, VID #J */
+static const uint16_t pm90_n753j[] = {
+ ID16(1200, 908, BUS100),
+ ID16(1100, 892, BUS100),
+ ID16(1000, 876, BUS100),
+ ID16( 900, 860, BUS100),
+ ID16( 800, 844, BUS100),
+ ID16( 600, 812, BUS100),
+};
+
+/* Intel Pentium M processor 753 1.2 GHz, VID #K */
+static const uint16_t pm90_n753k[] = {
+ ID16(1200, 892, BUS100),
+ ID16(1100, 892, BUS100),
+ ID16(1000, 876, BUS100),
+ ID16( 900, 860, BUS100),
+ ID16( 800, 844, BUS100),
+ ID16( 600, 812, BUS100),
+};
+
+/* Intel Pentium M processor 753 1.2 GHz, VID #L */
+static const uint16_t pm90_n753l[] = {
+ ID16(1200, 876, BUS100),
+ ID16(1100, 876, BUS100),
+ ID16(1000, 860, BUS100),
+ ID16( 900, 844, BUS100),
+ ID16( 800, 844, BUS100),
+ ID16( 600, 812, BUS100),
+};
+
+/* Intel Pentium M processor 773 1.3 GHz, VID #G */
+static const uint16_t pm90_n773g[] = {
+ ID16(1300, 956, BUS100),
+ ID16(1200, 940, BUS100),
+ ID16(1100, 924, BUS100),
+ ID16(1000, 908, BUS100),
+ ID16( 900, 876, BUS100),
+ ID16( 800, 860, BUS100),
+ ID16( 600, 812, BUS100),
+};
+
+/* Intel Pentium M processor 773 1.3 GHz, VID #H */
+static const uint16_t pm90_n773h[] = {
+ ID16(1300, 940, BUS100),
+ ID16(1200, 924, BUS100),
+ ID16(1100, 908, BUS100),
+ ID16(1000, 892, BUS100),
+ ID16( 900, 876, BUS100),
+ ID16( 800, 860, BUS100),
+ ID16( 600, 812, BUS100),
+};
+
+/* Intel Pentium M processor 773 1.3 GHz, VID #I */
+static const uint16_t pm90_n773i[] = {
+ ID16(1300, 924, BUS100),
+ ID16(1200, 908, BUS100),
+ ID16(1100, 892, BUS100),
+ ID16(1000, 876, BUS100),
+ ID16( 900, 860, BUS100),
+ ID16( 800, 844, BUS100),
+ ID16( 600, 812, BUS100),
+};
+
+/* Intel Pentium M processor 773 1.3 GHz, VID #J */
+static const uint16_t pm90_n773j[] = {
+ ID16(1300, 908, BUS100),
+ ID16(1200, 908, BUS100),
+ ID16(1100, 892, BUS100),
+ ID16(1000, 876, BUS100),
+ ID16( 900, 860, BUS100),
+ ID16( 800, 844, BUS100),
+ ID16( 600, 812, BUS100),
+};
+
+/* Intel Pentium M processor 773 1.3 GHz, VID #K */
+static const uint16_t pm90_n773k[] = {
+ ID16(1300, 892, BUS100),
+ ID16(1200, 892, BUS100),
+ ID16(1100, 876, BUS100),
+ ID16(1000, 860, BUS100),
+ ID16( 900, 860, BUS100),
+ ID16( 800, 844, BUS100),
+ ID16( 600, 812, BUS100),
+};
+
+/* Intel Pentium M processor 773 1.3 GHz, VID #L */
+static const uint16_t pm90_n773l[] = {
+ ID16(1300, 876, BUS100),
+ ID16(1200, 876, BUS100),
+ ID16(1100, 860, BUS100),
+ ID16(1000, 860, BUS100),
+ ID16( 900, 844, BUS100),
+ ID16( 800, 844, BUS100),
+ ID16( 600, 812, BUS100),
+};
+
+/* Intel Pentium M processor 738 1.4 GHz */
+static const uint16_t pm90_n738[] = {
+ ID16(1400, 1116, BUS100),
+ ID16(1300, 1116, BUS100),
+ ID16(1200, 1100, BUS100),
+ ID16(1100, 1068, BUS100),
+ ID16(1000, 1052, BUS100),
+ ID16( 900, 1036, BUS100),
+ ID16( 800, 1020, BUS100),
+ ID16( 600, 988, BUS100),
+};
+
+/* Intel Pentium M processor 758 1.5 GHz */
+static const uint16_t pm90_n758[] = {
+ ID16(1500, 1116, BUS100),
+ ID16(1400, 1116, BUS100),
+ ID16(1300, 1100, BUS100),
+ ID16(1200, 1084, BUS100),
+ ID16(1100, 1068, BUS100),
+ ID16(1000, 1052, BUS100),
+ ID16( 900, 1036, BUS100),
+ ID16( 800, 1020, BUS100),
+ ID16( 600, 988, BUS100),
+};
+
+/* Intel Pentium M processor 778 1.6 GHz */
+static const uint16_t pm90_n778[] = {
+ ID16(1600, 1116, BUS100),
+ ID16(1500, 1116, BUS100),
+ ID16(1400, 1100, BUS100),
+ ID16(1300, 1184, BUS100),
+ ID16(1200, 1068, BUS100),
+ ID16(1100, 1052, BUS100),
+ ID16(1000, 1052, BUS100),
+ ID16( 900, 1036, BUS100),
+ ID16( 800, 1020, BUS100),
+ ID16( 600, 988, BUS100),
+};
+
+/* Intel Pentium M processor 710 1.4 GHz, 533 MHz FSB */
+static const uint16_t pm90_n710[] = {
+ ID16(1400, 1340, BUS133),
+ ID16(1200, 1228, BUS133),
+ ID16(1000, 1148, BUS133),
+ ID16( 800, 1068, BUS133),
+ ID16( 600, 998, BUS133),
+};
+
+/* Intel Pentium M processor 715 1.5 GHz, VID #A */
+static const uint16_t pm90_n715a[] = {
+ ID16(1500, 1340, BUS100),
+ ID16(1200, 1228, BUS100),
+ ID16(1000, 1148, BUS100),
+ ID16( 800, 1068, BUS100),
+ ID16( 600, 988, BUS100),
+};
+
+/* Intel Pentium M processor 715 1.5 GHz, VID #B */
+static const uint16_t pm90_n715b[] = {
+ ID16(1500, 1324, BUS100),
+ ID16(1200, 1212, BUS100),
+ ID16(1000, 1148, BUS100),
+ ID16( 800, 1068, BUS100),
+ ID16( 600, 988, BUS100),
+};
+
+/* Intel Pentium M processor 715 1.5 GHz, VID #C */
+static const uint16_t pm90_n715c[] = {
+ ID16(1500, 1308, BUS100),
+ ID16(1200, 1212, BUS100),
+ ID16(1000, 1132, BUS100),
+ ID16( 800, 1068, BUS100),
+ ID16( 600, 988, BUS100),
+};
+
+/* Intel Pentium M processor 715 1.5 GHz, VID #D */
+static const uint16_t pm90_n715d[] = {
+ ID16(1500, 1276, BUS100),
+ ID16(1200, 1180, BUS100),
+ ID16(1000, 1116, BUS100),
+ ID16( 800, 1052, BUS100),
+ ID16( 600, 988, BUS100),
+};
+
+/* Intel Pentium M processor 725 1.6 GHz, VID #A */
+static const uint16_t pm90_n725a[] = {
+ ID16(1600, 1340, BUS100),
+ ID16(1400, 1276, BUS100),
+ ID16(1200, 1212, BUS100),
+ ID16(1000, 1132, BUS100),
+ ID16( 800, 1068, BUS100),
+ ID16( 600, 988, BUS100),
+};
+
+/* Intel Pentium M processor 725 1.6 GHz, VID #B */
+static const uint16_t pm90_n725b[] = {
+ ID16(1600, 1324, BUS100),
+ ID16(1400, 1260, BUS100),
+ ID16(1200, 1196, BUS100),
+ ID16(1000, 1132, BUS100),
+ ID16( 800, 1068, BUS100),
+ ID16( 600, 988, BUS100),
+};
+
+/* Intel Pentium M processor 725 1.6 GHz, VID #C */
+static const uint16_t pm90_n725c[] = {
+ ID16(1600, 1308, BUS100),
+ ID16(1400, 1244, BUS100),
+ ID16(1200, 1180, BUS100),
+ ID16(1000, 1116, BUS100),
+ ID16( 800, 1052, BUS100),
+ ID16( 600, 988, BUS100),
+};
+
+/* Intel Pentium M processor 725 1.6 GHz, VID #D */
+static const uint16_t pm90_n725d[] = {
+ ID16(1600, 1276, BUS100),
+ ID16(1400, 1228, BUS100),
+ ID16(1200, 1164, BUS100),
+ ID16(1000, 1116, BUS100),
+ ID16( 800, 1052, BUS100),
+ ID16( 600, 988, BUS100),
+};
+
+/* Intel Pentium M processor 730 1.6 GHz, 533 MHz FSB */
+static const uint16_t pm90_n730[] = {
+ ID16(1600, 1308, BUS133),
+ ID16(1333, 1260, BUS133),
+ ID16(1200, 1212, BUS133),
+ ID16(1067, 1180, BUS133),
+ ID16( 800, 988, BUS133),
+};
+
+/* Intel Pentium M processor 735 1.7 GHz, VID #A */
+static const uint16_t pm90_n735a[] = {
+ ID16(1700, 1340, BUS100),
+ ID16(1400, 1244, BUS100),
+ ID16(1200, 1180, BUS100),
+ ID16(1000, 1116, BUS100),
+ ID16( 800, 1052, BUS100),
+ ID16( 600, 988, BUS100),
+};
+
+/* Intel Pentium M processor 735 1.7 GHz, VID #B */
+static const uint16_t pm90_n735b[] = {
+ ID16(1700, 1324, BUS100),
+ ID16(1400, 1244, BUS100),
+ ID16(1200, 1180, BUS100),
+ ID16(1000, 1116, BUS100),
+ ID16( 800, 1052, BUS100),
+ ID16( 600, 988, BUS100),
+};
+
+/* Intel Pentium M processor 735 1.7 GHz, VID #C */
+static const uint16_t pm90_n735c[] = {
+ ID16(1700, 1308, BUS100),
+ ID16(1400, 1228, BUS100),
+ ID16(1200, 1164, BUS100),
+ ID16(1000, 1116, BUS100),
+ ID16( 800, 1052, BUS100),
+ ID16( 600, 988, BUS100),
+};
+
+/* Intel Pentium M processor 735 1.7 GHz, VID #D */
+static const uint16_t pm90_n735d[] = {
+ ID16(1700, 1276, BUS100),
+ ID16(1400, 1212, BUS100),
+ ID16(1200, 1148, BUS100),
+ ID16(1000, 1100, BUS100),
+ ID16( 800, 1052, BUS100),
+ ID16( 600, 988, BUS100),
+};
+
+/* Intel Pentium M processor 740 1.73 GHz, 533 MHz FSB */
+static const uint16_t pm90_n740[] = {
+ ID16(1733, 1356, BUS133),
+ ID16(1333, 1212, BUS133),
+ ID16(1067, 1100, BUS133),
+ ID16( 800, 988, BUS133),
+};
+
+/* Intel Pentium M processor 745 1.8 GHz, VID #A */
+static const uint16_t pm90_n745a[] = {
+ ID16(1800, 1340, BUS100),
+ ID16(1600, 1292, BUS100),
+ ID16(1400, 1228, BUS100),
+ ID16(1200, 1164, BUS100),
+ ID16(1000, 1116, BUS100),
+ ID16( 800, 1052, BUS100),
+ ID16( 600, 988, BUS100),
+};
+
+/* Intel Pentium M processor 745 1.8 GHz, VID #B */
+static const uint16_t pm90_n745b[] = {
+ ID16(1800, 1324, BUS100),
+ ID16(1600, 1276, BUS100),
+ ID16(1400, 1212, BUS100),
+ ID16(1200, 1164, BUS100),
+ ID16(1000, 1116, BUS100),
+ ID16( 800, 1052, BUS100),
+ ID16( 600, 988, BUS100),
+};
+
+/* Intel Pentium M processor 745 1.8 GHz, VID #C */
+static const uint16_t pm90_n745c[] = {
+ ID16(1800, 1308, BUS100),
+ ID16(1600, 1260, BUS100),
+ ID16(1400, 1212, BUS100),
+ ID16(1200, 1148, BUS100),
+ ID16(1000, 1100, BUS100),
+ ID16( 800, 1052, BUS100),
+ ID16( 600, 988, BUS100),
+};
+
+/* Intel Pentium M processor 745 1.8 GHz, VID #D */
+static const uint16_t pm90_n745d[] = {
+ ID16(1800, 1276, BUS100),
+ ID16(1600, 1228, BUS100),
+ ID16(1400, 1180, BUS100),
+ ID16(1200, 1132, BUS100),
+ ID16(1000, 1084, BUS100),
+ ID16( 800, 1036, BUS100),
+ ID16( 600, 988, BUS100),
+};
+
+/* Intel Pentium M processor 750 1.86 GHz, 533 MHz FSB */
+/* values extracted from \_PR\NPSS (via _PSS) SDST ACPI table */
+static const uint16_t pm90_n750[] = {
+ ID16(1867, 1308, BUS133),
+ ID16(1600, 1228, BUS133),
+ ID16(1333, 1148, BUS133),
+ ID16(1067, 1068, BUS133),
+ ID16( 800, 988, BUS133),
+};
+
+/* Intel Pentium M processor 755 2.0 GHz, VID #A */
+static const uint16_t pm90_n755a[] = {
+ ID16(2000, 1340, BUS100),
+ ID16(1800, 1292, BUS100),
+ ID16(1600, 1244, BUS100),
+ ID16(1400, 1196, BUS100),
+ ID16(1200, 1148, BUS100),
+ ID16(1000, 1100, BUS100),
+ ID16( 800, 1052, BUS100),
+ ID16( 600, 988, BUS100),
+};
+
+/* Intel Pentium M processor 755 2.0 GHz, VID #B */
+static const uint16_t pm90_n755b[] = {
+ ID16(2000, 1324, BUS100),
+ ID16(1800, 1276, BUS100),
+ ID16(1600, 1228, BUS100),
+ ID16(1400, 1180, BUS100),
+ ID16(1200, 1132, BUS100),
+ ID16(1000, 1084, BUS100),
+ ID16( 800, 1036, BUS100),
+ ID16( 600, 988, BUS100),
+};
+
+/* Intel Pentium M processor 755 2.0 GHz, VID #C */
+static const uint16_t pm90_n755c[] = {
+ ID16(2000, 1308, BUS100),
+ ID16(1800, 1276, BUS100),
+ ID16(1600, 1228, BUS100),
+ ID16(1400, 1180, BUS100),
+ ID16(1200, 1132, BUS100),
+ ID16(1000, 1084, BUS100),
+ ID16( 800, 1036, BUS100),
+ ID16( 600, 988, BUS100),
+};
+
+/* Intel Pentium M processor 755 2.0 GHz, VID #D */
+static const uint16_t pm90_n755d[] = {
+ ID16(2000, 1276, BUS100),
+ ID16(1800, 1244, BUS100),
+ ID16(1600, 1196, BUS100),
+ ID16(1400, 1164, BUS100),
+ ID16(1200, 1116, BUS100),
+ ID16(1000, 1084, BUS100),
+ ID16( 800, 1036, BUS100),
+ ID16( 600, 988, BUS100),
+};
+
+/* Intel Pentium M processor 760 2.0 GHz, 533 MHz FSB */
+static const uint16_t pm90_n760[] = {
+ ID16(2000, 1356, BUS133),
+ ID16(1600, 1244, BUS133),
+ ID16(1333, 1164, BUS133),
+ ID16(1067, 1084, BUS133),
+ ID16( 800, 988, BUS133),
+};
+
+/* Intel Pentium M processor 765 2.1 GHz, VID #A */
+static const uint16_t pm90_n765a[] = {
+ ID16(2100, 1340, BUS100),
+ ID16(1800, 1276, BUS100),
+ ID16(1600, 1228, BUS100),
+ ID16(1400, 1180, BUS100),
+ ID16(1200, 1132, BUS100),
+ ID16(1000, 1084, BUS100),
+ ID16( 800, 1036, BUS100),
+ ID16( 600, 988, BUS100),
+};
+
+/* Intel Pentium M processor 765 2.1 GHz, VID #B */
+static const uint16_t pm90_n765b[] = {
+ ID16(2100, 1324, BUS100),
+ ID16(1800, 1260, BUS100),
+ ID16(1600, 1212, BUS100),
+ ID16(1400, 1180, BUS100),
+ ID16(1200, 1132, BUS100),
+ ID16(1000, 1084, BUS100),
+ ID16( 800, 1036, BUS100),
+ ID16( 600, 988, BUS100),
+};
+
+/* Intel Pentium M processor 765 2.1 GHz, VID #C */
+static const uint16_t pm90_n765c[] = {
+ ID16(2100, 1308, BUS100),
+ ID16(1800, 1244, BUS100),
+ ID16(1600, 1212, BUS100),
+ ID16(1400, 1164, BUS100),
+ ID16(1200, 1116, BUS100),
+ ID16(1000, 1084, BUS100),
+ ID16( 800, 1036, BUS100),
+ ID16( 600, 988, BUS100),
+};
+
+/* Intel Pentium M processor 765 2.1 GHz, VID #E */
+static const uint16_t pm90_n765e[] = {
+ ID16(2100, 1356, BUS100),
+ ID16(1800, 1292, BUS100),
+ ID16(1600, 1244, BUS100),
+ ID16(1400, 1196, BUS100),
+ ID16(1200, 1148, BUS100),
+ ID16(1000, 1100, BUS100),
+ ID16( 800, 1052, BUS100),
+ ID16( 600, 988, BUS100),
+};
+
+/* Intel Pentium M processor 770 2.13 GHz */
+static const uint16_t pm90_n770[] = {
+ ID16(2133, 1356, BUS133),
+ ID16(1867, 1292, BUS133),
+ ID16(1600, 1212, BUS133),
+ ID16(1333, 1148, BUS133),
+ ID16(1067, 1068, BUS133),
+ ID16( 800, 988, BUS133),
+};
+
+/* Intel Pentium M processor 780 2.26 GHz */
+static const uint16_t pm90_n780[] = {
+ ID16(2267, 1388, BUS133),
+ ID16(1867, 1292, BUS133),
+ ID16(1600, 1212, BUS133),
+ ID16(1333, 1148, BUS133),
+ ID16(1067, 1068, BUS133),
+ ID16( 800, 988, BUS133),
+};
+
+/*
+ * VIA C7-M 500 MHz FSB, 400 MHz FSB, and ULV variants.
+ * Data from the "VIA C7-M Processor BIOS Writer's Guide (v2.17)" datasheet.
+ */
+
+/* 1.00GHz Centaur C7-M ULV */
+static const uint16_t C7M_770_ULV[] = {
+ ID16(1000, 844, BUS100),
+ ID16( 800, 796, BUS100),
+ ID16( 600, 796, BUS100),
+ ID16( 400, 796, BUS100),
+};
+
+/* 1.00GHz Centaur C7-M ULV */
+static const uint16_t C7M_779_ULV[] = {
+ ID16(1000, 796, BUS100),
+ ID16( 800, 796, BUS100),
+ ID16( 600, 796, BUS100),
+ ID16( 400, 796, BUS100),
+};
+
+/* 1.20GHz Centaur C7-M ULV */
+static const uint16_t C7M_772_ULV[] = {
+ ID16(1200, 844, BUS100),
+ ID16(1000, 844, BUS100),
+ ID16( 800, 828, BUS100),
+ ID16( 600, 796, BUS100),
+ ID16( 400, 796, BUS100),
+};
+
+/* 1.50GHz Centaur C7-M ULV */
+static const uint16_t C7M_775_ULV[] = {
+ ID16(1500, 956, BUS100),
+ ID16(1400, 940, BUS100),
+ ID16(1000, 860, BUS100),
+ ID16( 800, 828, BUS100),
+ ID16( 600, 796, BUS100),
+ ID16( 400, 796, BUS100),
+};
+
+/* 1.20GHz Centaur C7-M 400 MHz FSB */
+static const uint16_t C7M_771[] = {
+ ID16(1200, 860, BUS100),
+ ID16(1000, 860, BUS100),
+ ID16( 800, 844, BUS100),
+ ID16( 600, 844, BUS100),
+ ID16( 400, 844, BUS100),
+};
+
+/* 1.50GHz Centaur C7-M 400 MHz FSB */
+static const u_int16_t C7M_754[] = {
+ ID16(1500, 1004, BUS100),
+ ID16(1400, 988, BUS100),
+ ID16(1000, 940, BUS100),
+ ID16( 800, 844, BUS100),
+ ID16( 600, 844, BUS100),
+ ID16( 400, 844, BUS100),
+};
+
+/* 1.60GHz Centaur C7-M 400 MHz FSB */
+static const uint16_t C7M_764[] = {
+ ID16(1600, 1084, BUS100),
+ ID16(1400, 1052, BUS100),
+ ID16(1000, 1004, BUS100),
+ ID16( 800, 844, BUS100),
+ ID16( 600, 844, BUS100),
+ ID16( 400, 844, BUS100),
+};
+
+/* 1.80GHz Centaur C7-M 400 MHz FSB */
+static const uint16_t C7M_784[] = {
+ ID16(1800, 1148, BUS100),
+ ID16(1600, 1100, BUS100),
+ ID16(1400, 1052, BUS100),
+ ID16(1000, 1004, BUS100),
+ ID16( 800, 844, BUS100),
+ ID16( 600, 844, BUS100),
+ ID16( 400, 844, BUS100),
+};
+
+/* 2.00GHz Centaur C7-M 400 MHz FSB */
+static const uint16_t C7M_794[] = {
+ ID16(2000, 1148, BUS100),
+ ID16(1800, 1132, BUS100),
+ ID16(1600, 1100, BUS100),
+ ID16(1400, 1052, BUS100),
+ ID16(1000, 1004, BUS100),
+ ID16( 800, 844, BUS100),
+ ID16( 600, 844, BUS100),
+ ID16( 400, 844, BUS100),
+};
+
+/* 1.60GHz Centaur C7-M 533 MHz FSB */
+static const uint16_t C7M_765[] = {
+ ID16(1600, 1084, BUS133),
+ ID16(1467, 1052, BUS133),
+ ID16(1200, 1004, BUS133),
+ ID16( 800, 844, BUS133),
+ ID16( 667, 844, BUS133),
+ ID16( 533, 844, BUS133),
+};
+
+/* 2.00GHz Centaur C7-M 533 MHz FSB */
+static const uint16_t C7M_785[] = {
+ ID16(1867, 1148, BUS133),
+ ID16(1600, 1100, BUS133),
+ ID16(1467, 1052, BUS133),
+ ID16(1200, 1004, BUS133),
+ ID16( 800, 844, BUS133),
+ ID16( 667, 844, BUS133),
+ ID16( 533, 844, BUS133),
+};
+
+/* 2.00GHz Centaur C7-M 533 MHz FSB */
+static const uint16_t C7M_795[] = {
+ ID16(2000, 1148, BUS133),
+ ID16(1867, 1132, BUS133),
+ ID16(1600, 1100, BUS133),
+ ID16(1467, 1052, BUS133),
+ ID16(1200, 1004, BUS133),
+ ID16( 800, 844, BUS133),
+ ID16( 667, 844, BUS133),
+ ID16( 533, 844, BUS133),
+};
+
+/* 1.00GHz VIA Eden 90nm 'Esther' */
+static const uint16_t eden90_1000[] = {
+ ID16(1000, 844, BUS100),
+ ID16( 800, 844, BUS100),
+ ID16( 600, 844, BUS100),
+ ID16( 400, 844, BUS100),
+};
+
+struct fqlist {
+ int vendor;
+ unsigned bus_clk;
+ unsigned n;
+ const uint16_t *table;
+};
+
+#define ENTRY(ven, bus_clk, tab) \
+ { CPUVENDOR_##ven, bus_clk == BUS133 ? 1 : 0, __arraycount(tab), tab }
+
+#define BUS_CLK(fqp) ((fqp)->bus_clk ? BUS133 : BUS100)
+
+static const struct fqlist est_cpus[] = {
+ ENTRY(INTEL, BUS100, pm130_900_ulv),
+ ENTRY(INTEL, BUS100, pm130_1000_ulv),
+ ENTRY(INTEL, BUS100, pm130_1100_ulv),
+ ENTRY(INTEL, BUS100, pm130_1100_lv),
+ ENTRY(INTEL, BUS100, pm130_1200_lv),
+ ENTRY(INTEL, BUS100, pm130_1300_lv),
+ ENTRY(INTEL, BUS100, pm130_1300),
+ ENTRY(INTEL, BUS100, pm130_1400),
+ ENTRY(INTEL, BUS100, pm130_1500),
+ ENTRY(INTEL, BUS100, pm130_1600),
+ ENTRY(INTEL, BUS100, pm130_1700),
+ ENTRY(INTEL, BUS100, pm90_n723),
+ ENTRY(INTEL, BUS100, pm90_n733g),
+ ENTRY(INTEL, BUS100, pm90_n733h),
+ ENTRY(INTEL, BUS100, pm90_n733i),
+ ENTRY(INTEL, BUS100, pm90_n733j),
+ ENTRY(INTEL, BUS100, pm90_n733k),
+ ENTRY(INTEL, BUS100, pm90_n733l),
+ ENTRY(INTEL, BUS100, pm90_n753g),
+ ENTRY(INTEL, BUS100, pm90_n753h),
+ ENTRY(INTEL, BUS100, pm90_n753i),
+ ENTRY(INTEL, BUS100, pm90_n753j),
+ ENTRY(INTEL, BUS100, pm90_n753k),
+ ENTRY(INTEL, BUS100, pm90_n753l),
+ ENTRY(INTEL, BUS100, pm90_n773g),
+ ENTRY(INTEL, BUS100, pm90_n773h),
+ ENTRY(INTEL, BUS100, pm90_n773i),
+ ENTRY(INTEL, BUS100, pm90_n773j),
+ ENTRY(INTEL, BUS100, pm90_n773k),
+ ENTRY(INTEL, BUS100, pm90_n773l),
+ ENTRY(INTEL, BUS100, pm90_n738),
+ ENTRY(INTEL, BUS100, pm90_n758),
+ ENTRY(INTEL, BUS100, pm90_n778),
+
+ ENTRY(INTEL, BUS133, pm90_n710),
+ ENTRY(INTEL, BUS100, pm90_n715a),
+ ENTRY(INTEL, BUS100, pm90_n715b),
+ ENTRY(INTEL, BUS100, pm90_n715c),
+ ENTRY(INTEL, BUS100, pm90_n715d),
+ ENTRY(INTEL, BUS100, pm90_n725a),
+ ENTRY(INTEL, BUS100, pm90_n725b),
+ ENTRY(INTEL, BUS100, pm90_n725c),
+ ENTRY(INTEL, BUS100, pm90_n725d),
+ ENTRY(INTEL, BUS133, pm90_n730),
+ ENTRY(INTEL, BUS100, pm90_n735a),
+ ENTRY(INTEL, BUS100, pm90_n735b),
+ ENTRY(INTEL, BUS100, pm90_n735c),
+ ENTRY(INTEL, BUS100, pm90_n735d),
+ ENTRY(INTEL, BUS133, pm90_n740),
+ ENTRY(INTEL, BUS100, pm90_n745a),
+ ENTRY(INTEL, BUS100, pm90_n745b),
+ ENTRY(INTEL, BUS100, pm90_n745c),
+ ENTRY(INTEL, BUS100, pm90_n745d),
+ ENTRY(INTEL, BUS133, pm90_n750),
+ ENTRY(INTEL, BUS100, pm90_n755a),
+ ENTRY(INTEL, BUS100, pm90_n755b),
+ ENTRY(INTEL, BUS100, pm90_n755c),
+ ENTRY(INTEL, BUS100, pm90_n755d),
+ ENTRY(INTEL, BUS133, pm90_n760),
+ ENTRY(INTEL, BUS100, pm90_n765a),
+ ENTRY(INTEL, BUS100, pm90_n765b),
+ ENTRY(INTEL, BUS100, pm90_n765c),
+ ENTRY(INTEL, BUS100, pm90_n765e),
+ ENTRY(INTEL, BUS133, pm90_n770),
+ ENTRY(INTEL, BUS133, pm90_n780),
+
+ ENTRY(IDT, BUS100, C7M_770_ULV),
+ ENTRY(IDT, BUS100, C7M_779_ULV),
+ ENTRY(IDT, BUS100, C7M_772_ULV),
+ ENTRY(IDT, BUS100, C7M_771),
+ ENTRY(IDT, BUS100, C7M_775_ULV),
+ ENTRY(IDT, BUS100, C7M_754),
+ ENTRY(IDT, BUS100, C7M_764),
+ ENTRY(IDT, BUS133, C7M_765),
+ ENTRY(IDT, BUS100, C7M_784),
+ ENTRY(IDT, BUS133, C7M_785),
+ ENTRY(IDT, BUS100, C7M_794),
+ ENTRY(IDT, BUS133, C7M_795),
+
+ ENTRY(IDT, BUS100, eden90_1000)
+};
+
+#define MSR2FREQINC(msr) (((int) (msr) >> 8) & 0xff)
+#define MSR2VOLTINC(msr) ((int) (msr) & 0xff)
+
+#define MSR2MHZ(msr, bus) ((MSR2FREQINC((msr)) * (bus) + 50) / 100)
+#define MSR2MV(msr) (MSR2VOLTINC(msr) * 16 + 700)
+
+static const struct fqlist *est_fqlist; /* not NULL if functional */
+static uint16_t fake_table[3]; /* guessed est_cpu table */
+static struct fqlist fake_fqlist;
+static int est_node_target, est_node_current;
+static const char est_desc[] = "Enhanced SpeedStep";
+static int lvendor, bus_clock;
+
+static int est_sysctl_helper(SYSCTLFN_PROTO);
+static int est_init_once(void);
+static void est_init_main(int);
+
+static int
+est_sysctl_helper(SYSCTLFN_ARGS)
+{
+ struct msr_cpu_broadcast mcb;
+ struct sysctlnode node;
+ int fq, oldfq, error;
+
+ if (est_fqlist == NULL)
+ return EOPNOTSUPP;
+
+ node = *rnode;
+ node.sysctl_data = &fq;
+
+ oldfq = 0;
+ if (rnode->sysctl_num == est_node_target)
+ fq = oldfq = MSR2MHZ(rdmsr(MSR_PERF_CTL), bus_clock);
+ else if (rnode->sysctl_num == est_node_current)
+ fq = MSR2MHZ(rdmsr(MSR_PERF_STATUS), bus_clock);
+ else
+ return EOPNOTSUPP;
+
+ error = sysctl_lookup(SYSCTLFN_CALL(&node));
+ if (error || newp == NULL)
+ return error;
+
+ /* support writing to ...frequency.target */
+ if (rnode->sysctl_num == est_node_target && fq != oldfq) {
+ int i;
+
+ for (i = est_fqlist->n - 1; i > 0; i--)
+ if (MSR2MHZ(est_fqlist->table[i], bus_clock) >= fq)
+ break;
+ fq = MSR2MHZ(est_fqlist->table[i], bus_clock);
+ mcb.msr_read = true;
+ mcb.msr_type = MSR_PERF_CTL;
+ mcb.msr_mask = 0xffffULL;
+ mcb.msr_value = est_fqlist->table[i];
+ msr_cpu_broadcast(&mcb);
+ }
+
+ return 0;
+}
+
+static int
+est_init_once(void)
+{
+ est_init_main(lvendor);
+ return 0;
+}
+
+void
+est_init(int vendor)
+{
+ int error;
+ static ONCE_DECL(est_initialized);
+
+ lvendor = vendor;
+
+ error = RUN_ONCE(&est_initialized, est_init_once);
+ if (__predict_false(error != 0))
+ return;
+}
+
+static void
+est_init_main(int vendor)
+{
+#ifdef __i386__
+ const struct fqlist *fql;
+#endif
+ const struct sysctlnode *node, *estnode, *freqnode;
+ uint64_t msr;
+ uint16_t cur, idhi, idlo;
+ uint8_t crhi, crlo, crcur;
+ int i, mv, rc;
+ size_t len, freq_len;
+ char *freq_names, *cpuname;
+
+ cpuname = curcpu()->ci_dev->dv_xname;
+
+ if (CPUID2FAMILY(curcpu()->ci_signature) == 15)
+ bus_clock = p4_get_bus_clock(curcpu());
+ else if (CPUID2FAMILY(curcpu()->ci_signature) == 6) {
+ if (vendor == CPUVENDOR_IDT)
+ bus_clock = via_get_bus_clock(curcpu());
+ else
+ bus_clock = p3_get_bus_clock(curcpu());
+ }
+
+ if (bus_clock == 0) {
+ aprint_normal("%s: unknown system bus clock\n", __func__);
+ return;
+ }
+
+ msr = rdmsr(MSR_PERF_STATUS);
+ idhi = (msr >> 32) & 0xffff;
+ idlo = (msr >> 48) & 0xffff;
+ cur = msr & 0xffff;
+ crhi = (idhi >> 8) & 0xff;
+ crlo = (idlo >> 8) & 0xff;
+ crcur = (cur >> 8) & 0xff;
+
+#ifdef __i386__
+ if (idhi == 0 || idlo == 0 || cur == 0 ||
+ ((cur >> 8) & 0xff) < ((idlo >> 8) & 0xff) ||
+ ((cur >> 8) & 0xff) > ((idhi >> 8) & 0xff)) {
+ aprint_debug("%s: strange msr value 0x%016llx\n", __func__, msr);
+ return;
+ }
+#endif
+
+#ifdef __amd64__
+ if (crlo == 0 || crhi == crlo) {
+ aprint_debug("%s: crlo == 0 || crhi == crlo\n", __func__);
+ return;
+ }
+
+ if (crhi == 0 || crcur == 0 || crlo > crhi ||
+ crcur < crlo || crcur > crhi) {
+ /*
+ * Do complain about other weirdness, because we first want to
+ * know about it, before we decide what to do with it
+ */
+ aprint_normal("%s: EST: strange msr value 0x%" PRIu64 "\n",
+ cpuname, msr);
+ return;
+ }
+#endif
+
+ msr = rdmsr(MSR_PERF_STATUS);
+ mv = MSR2MV(msr);
+ aprint_normal("%s: %s (%d mV) ", cpuname, est_desc, mv);
+ aprint_normal("%d MHz\n", MSR2MHZ(msr, bus_clock));
+
+#ifdef __i386__
+ /*
+ * Find an entry which matches (vendor, bus_clock, idhi, idlo)
+ */
+ est_fqlist = NULL;
+ for (i = 0; i < __arraycount(est_cpus); i++) {
+ fql = &est_cpus[i];
+ if (vendor == fql->vendor && bus_clock == BUS_CLK(fql) &&
+ idhi == fql->table[0] && idlo == fql->table[fql->n - 1]) {
+ est_fqlist = fql;
+ break;
+ }
+ }
+#endif
+
+ if (est_fqlist == NULL) {
+ aprint_normal("%s: unknown Enhanced SpeedStep CPU.\n",
+ cpuname);
+
+ /*
+ * Some CPUs report the same frequency in idhi and idlo,
+ * so do not run est on them.
+ */
+ if (idhi == idlo)
+ return;
+ /*
+ * Generate a fake table with the power states we know.
+ */
+ fake_table[0] = idhi;
+ if (cur == idhi || cur == idlo) {
+ aprint_normal("%s: using only highest and lowest "
+ "power states.\n", cpuname);
+
+ fake_table[1] = idlo;
+ fake_fqlist.n = 2;
+ } else {
+ aprint_normal("%s: using only highest, current "
+ "and lowest power states.\n", cpuname);
+
+ fake_table[1] = cur;
+ fake_table[2] = idlo;
+ fake_fqlist.n = 3;
+ }
+ fake_fqlist.vendor = vendor;
+ fake_fqlist.table = fake_table;
+ est_fqlist = &fake_fqlist;
+ }
+
+ /*
+ * OK, tell the user the available frequencies.
+ */
+ freq_len = est_fqlist->n * (sizeof("9999 ")-1) + 1;
+ freq_names = malloc(freq_len, M_SYSCTLDATA, M_WAITOK);
+ freq_names[0] = '\0';
+ len = 0;
+ for (i = 0; i < est_fqlist->n; i++) {
+ len += snprintf(freq_names + len, freq_len - len, "%d%s",
+ MSR2MHZ(est_fqlist->table[i], bus_clock),
+ i < est_fqlist->n - 1 ? " " : "");
+ }
+ aprint_normal("%s: %s frequencies available (MHz): %s\n",
+ cpuname, est_desc, freq_names);
+
+ /*
+ * Setup the sysctl sub-tree machdep.est.*
+ */
+ if ((rc = sysctl_createv(NULL, 0, NULL, &node,
+ CTLFLAG_PERMANENT, CTLTYPE_NODE, "machdep", NULL,
+ NULL, 0, NULL, 0, CTL_MACHDEP, CTL_EOL)) != 0)
+ goto err;
+
+ if ((rc = sysctl_createv(NULL, 0, &node, &estnode,
+ 0, CTLTYPE_NODE, "est", NULL,
+ NULL, 0, NULL, 0, CTL_CREATE, CTL_EOL)) != 0)
+ goto err;
+
+ if ((rc = sysctl_createv(NULL, 0, &estnode, &freqnode,
+ 0, CTLTYPE_NODE, "frequency", NULL,
+ NULL, 0, NULL, 0, CTL_CREATE, CTL_EOL)) != 0)
+ goto err;
+
+ if ((rc = sysctl_createv(NULL, 0, &freqnode, &node,
+ EST_TARGET_CTLFLAG, CTLTYPE_INT, "target", NULL,
+ est_sysctl_helper, 0, NULL, 0, CTL_CREATE, CTL_EOL)) != 0)
+ goto err;
+ est_node_target = node->sysctl_num;
+
+ if ((rc = sysctl_createv(NULL, 0, &freqnode, &node,
+ 0, CTLTYPE_INT, "current", NULL,
+ est_sysctl_helper, 0, NULL, 0, CTL_CREATE, CTL_EOL)) != 0)
+ goto err;
+ est_node_current = node->sysctl_num;
+
+ if ((rc = sysctl_createv(NULL, 0, &freqnode, &node,
+ 0, CTLTYPE_STRING, "available", NULL,
+ NULL, 0, freq_names, freq_len, CTL_CREATE, CTL_EOL)) != 0)
+ goto err;
+
+ return;
+
+ err:
+ free(freq_names, M_SYSCTLDATA);
+ aprint_normal("%s: sysctl_createv failed (rc = %d)\n", __func__, rc);
+}
Index: arch/x86/x86/intel_busclock.c
===================================================================
RCS file: arch/x86/x86/intel_busclock.c
diff -N arch/x86/x86/intel_busclock.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ arch/x86/x86/intel_busclock.c 21 Jul 2007 15:48:02 -0000
@@ -0,0 +1,225 @@
+/* $NetBSD: intel_busclock.c,v 1.2 2007/07/01 20:12:36 xtraeme Exp $ */
+
+/*-
+ * Copyright (c) 1999, 2000, 2001 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Frank van der Linden, and by Jason R. Thorpe.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: intel_busclock.c,v 1.2 2007/07/01 20:12:36 xtraeme Exp $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+
+#include <machine/specialreg.h>
+#include <machine/pio.h>
+#include <machine/cpu.h>
+
+#include <x86/cpuvar.h>
+
+int
+via_get_bus_clock(struct cpu_info *ci)
+{
+ uint64_t msr;
+ int bus, bus_clock = 0;
+
+ msr = rdmsr(MSR_EBL_CR_POWERON);
+ bus = (msr >> 18) & 0x3;
+ switch (bus) {
+ case 0:
+ bus_clock = 10000;
+ break;
+ case 1:
+ bus_clock = 13333;
+ break;
+ case 2:
+ bus_clock = 20000;
+ break;
+ case 3:
+ bus_clock = 16667;
+ break;
+ default:
+ break;
+ }
+
+ return bus_clock;
+}
+
+int
+p3_get_bus_clock(struct cpu_info *ci)
+{
+ uint64_t msr;
+ int bus, bus_clock = 0;
+
+ switch (CPUID2MODEL(ci->ci_signature)) {
+ case 0x9: /* Pentium M (130 nm, Banias) */
+ bus_clock = 10000;
+ break;
+ case 0xd: /* Pentium M (90 nm, Dothan) */
+ msr = rdmsr(MSR_FSB_FREQ);
+ bus = (msr >> 0) & 0x7;
+ switch (bus) {
+ case 0:
+ bus_clock = 10000;
+ break;
+ case 1:
+ bus_clock = 13333;
+ break;
+ default:
+ aprint_debug("%s: unknown Pentium M FSB_FREQ "
+ "value %d", device_xname(ci->ci_dev), bus);
+ goto print_msr;
+ }
+ break;
+ case 0xe: /* Core Duo/Solo */
+ case 0xf: /* Core Xeon */
+ msr = rdmsr(MSR_FSB_FREQ);
+ bus = (msr >> 0) & 0x7;
+ switch (bus) {
+ case 5:
+ bus_clock = 10000;
+ break;
+ case 1:
+ bus_clock = 13333;
+ break;
+ case 3:
+ bus_clock = 16667;
+ break;
+ case 2:
+ bus_clock = 20000;
+ break;
+ case 0:
+ bus_clock = 26667;
+ break;
+ case 4:
+ bus_clock = 33333;
+ break;
+ default:
+ aprint_debug("%s: unknown Core FSB_FREQ value %d",
+ device_xname(ci->ci_dev), bus);
+ goto print_msr;
+ }
+ break;
+ case 0x1: /* Pentium Pro, model 1 */
+ case 0x3: /* Pentium II, model 3 */
+ case 0x5: /* Pentium II, II Xeon, Celeron, model 5 */
+ case 0x6: /* Celeron, model 6 */
+ case 0x7: /* Pentium III, III Xeon, model 7 */
+ case 0x8: /* Pentium III, III Xeon, Celeron, model 8 */
+ case 0xa: /* Pentium III Xeon, model A */
+ case 0xb: /* Pentium III, model B */
+ msr = rdmsr(MSR_EBL_CR_POWERON);
+ bus = (msr >> 18) & 0x3;
+ switch (bus) {
+ case 0:
+ bus_clock = 6666;
+ break;
+ case 1:
+ bus_clock = 13333;
+ break;
+ case 2:
+ bus_clock = 10000;
+ break;
+ default:
+ aprint_debug("%s: unknown i686 EBL_CR_POWERON "
+ "value %d ", device_xname(ci->ci_dev), bus);
+ goto print_msr;
+ }
+ break;
+ default:
+ aprint_debug("%s: unknown i686 model %d, can't get bus clock",
+ device_xname(ci->ci_dev),
+ CPUID2MODEL(ci->ci_signature));
+print_msr:
+ /*
+ * Show the EBL_CR_POWERON MSR, so we'll at least have
+ * some extra information, such as clock ratio, etc.
+ */
+ aprint_debug(" (0x%" PRIu64 ")\n", rdmsr(MSR_EBL_CR_POWERON));
+ break;
+ }
+
+ return bus_clock;
+}
+
+int
+p4_get_bus_clock(struct cpu_info *ci)
+{
+ uint64_t msr;
+ int bus, bus_clock = 0;
+
+ msr = rdmsr(MSR_EBC_FREQUENCY_ID);
+ if (CPUID2MODEL(ci->ci_signature) < 2) {
+ bus = (msr >> 21) & 0x7;
+ switch (bus) {
+ case 0:
+ bus_clock = 10000;
+ break;
+ case 1:
+ bus_clock = 13333;
+ break;
+ default:
+ aprint_debug("%s: unknown Pentium 4 (model %d) "
+ "EBC_FREQUENCY_ID value %d\n",
+ device_xname(ci->ci_dev),
+ CPUID2MODEL(ci->ci_signature), bus);
+ break;
+ }
+ } else {
+ bus = (msr >> 16) & 0x7;
+ switch (bus) {
+ case 0:
+ bus_clock = (CPUID2MODEL(ci->ci_signature) == 2) ?
+ 10000 : 26666;
+ break;
+ case 1:
+ bus_clock = 13333;
+ break;
+ case 2:
+ bus_clock = 20000;
+ break;
+ case 3:
+ bus_clock = 16666;
+ break;
+ default:
+ aprint_debug("%s: unknown Pentium 4 (model %d) "
+ "EBC_FREQUENCY_ID value %d\n",
+ device_xname(ci->ci_dev),
+ CPUID2MODEL(ci->ci_signature), bus);
+ break;
+ }
+ }
+
+ return bus_clock;
+}
--------------080106030401060104070403--