Sat Jul 29 11:01:15 2023 UTC ()
Pull up following revision(s) (requested by msaitoh in ticket #254):

	sys/arch/x86/x86/coretemp.c: revision 1.38-1.39 (patch)

coretemp(4): Change limits of Tjmax.
 - Change the lower limit from 70 to 60. At least, some BIOSes can change
   the value down to 62.
 - Change the upper limit from 110 to 120. At least, some BIOSes can change
   the value up to 115.
 - Print error message when rdmsr(TEMPERATURE_TARGET) failed.
 - When Tjmax exceeded the limit, print warning message and use the value
   as it is.
 - KNF.


(martin)
diff -r1.36.4.1 -r1.36.4.2 src/sys/arch/x86/x86/coretemp.c

cvs diff -r1.36.4.1 -r1.36.4.2 src/sys/arch/x86/x86/coretemp.c (switch to unified diff)

--- src/sys/arch/x86/x86/coretemp.c 2020/07/15 14:02:36 1.36.4.1
+++ src/sys/arch/x86/x86/coretemp.c 2023/07/29 11:01:14 1.36.4.2
@@ -1,392 +1,395 @@ @@ -1,392 +1,395 @@
1/* $NetBSD: coretemp.c,v 1.36.4.1 2020/07/15 14:02:36 martin Exp $ */ 1/* $NetBSD: coretemp.c,v 1.36.4.2 2023/07/29 11:01:14 martin Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2011 The NetBSD Foundation, Inc. 4 * Copyright (c) 2011 The NetBSD Foundation, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to The NetBSD Foundation 7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Jukka Ruohonen. 8 * by Jukka Ruohonen.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 13 *
14 * 1. Redistributions of source code must retain the above copyright 14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer. 15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright 16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the 17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution. 18 * documentation and/or other materials provided with the distribution.
19 * 19 *
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE. 30 * SUCH DAMAGE.
31 */ 31 */
32 32
33/*- 33/*-
34 * Copyright (c) 2007 Juan Romero Pardines. 34 * Copyright (c) 2007 Juan Romero Pardines.
35 * Copyright (c) 2007 Rui Paulo <rpaulo@FreeBSD.org> 35 * Copyright (c) 2007 Rui Paulo <rpaulo@FreeBSD.org>
36 * All rights reserved. 36 * All rights reserved.
37 * 37 *
38 * Redistribution and use in source and binary forms, with or without 38 * Redistribution and use in source and binary forms, with or without
39 * modification, are permitted provided that the following conditions 39 * modification, are permitted provided that the following conditions
40 * are met: 40 * are met:
41 * 1. Redistributions of source code must retain the above copyright 41 * 1. Redistributions of source code must retain the above copyright
42 * notice, this list of conditions and the following disclaimer. 42 * notice, this list of conditions and the following disclaimer.
43 * 2. Redistributions in binary form must reproduce the above copyright 43 * 2. Redistributions in binary form must reproduce the above copyright
44 * notice, this list of conditions and the following disclaimer in the 44 * notice, this list of conditions and the following disclaimer in the
45 * documentation and/or other materials provided with the distribution. 45 * documentation and/or other materials provided with the distribution.
46 * 46 *
47 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 47 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
48 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 48 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
49 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 49 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
50 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 50 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
51 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 51 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
52 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 52 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
53 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 53 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
54 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 54 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
55 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 55 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
56 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 56 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
57 * POSSIBILITY OF SUCH DAMAGE. 57 * POSSIBILITY OF SUCH DAMAGE.
58 * 58 *
59 * $FreeBSD: src/sys/dev/coretemp/coretemp.c,v 1.4 2007/10/15 20:00:21 netchild Exp $ 59 * $FreeBSD: src/sys/dev/coretemp/coretemp.c,v 1.4 2007/10/15 20:00:21 netchild Exp $
60 * 60 *
61 */ 61 */
62 62
63#include <sys/cdefs.h> 63#include <sys/cdefs.h>
64__KERNEL_RCSID(0, "$NetBSD: coretemp.c,v 1.36.4.1 2020/07/15 14:02:36 martin Exp $"); 64__KERNEL_RCSID(0, "$NetBSD: coretemp.c,v 1.36.4.2 2023/07/29 11:01:14 martin Exp $");
65 65
66#include <sys/param.h> 66#include <sys/param.h>
67#include <sys/device.h> 67#include <sys/device.h>
68#include <sys/cpu.h> 68#include <sys/cpu.h>
69#include <sys/module.h> 69#include <sys/module.h>
70#include <sys/xcall.h> 70#include <sys/xcall.h>
71 71
72#include <dev/sysmon/sysmonvar.h> 72#include <dev/sysmon/sysmonvar.h>
73 73
74#include <machine/cpuvar.h> 74#include <machine/cpuvar.h>
75#include <machine/cpufunc.h> 75#include <machine/cpufunc.h>
76#include <machine/cputypes.h> 76#include <machine/cputypes.h>
77#include <machine/specialreg.h> 77#include <machine/specialreg.h>
78 78
79#define MSR_THERM_STATUS_STA __BIT(0) 79#define MSR_THERM_STATUS_STA __BIT(0)
80#define MSR_THERM_STATUS_LOG __BIT(1) 80#define MSR_THERM_STATUS_LOG __BIT(1)
81#define MSR_THERM_STATUS_PROCHOT_EVT __BIT(2) 81#define MSR_THERM_STATUS_PROCHOT_EVT __BIT(2)
82#define MSR_THERM_STATUS_PROCHOT_LOG __BIT(3) 82#define MSR_THERM_STATUS_PROCHOT_LOG __BIT(3)
83#define MSR_THERM_STATUS_CRIT_STA __BIT(4) 83#define MSR_THERM_STATUS_CRIT_STA __BIT(4)
84#define MSR_THERM_STATUS_CRIT_LOG __BIT(5) 84#define MSR_THERM_STATUS_CRIT_LOG __BIT(5)
85#define MSR_THERM_STATUS_TRIP1_STA __BIT(6) 85#define MSR_THERM_STATUS_TRIP1_STA __BIT(6)
86#define MSR_THERM_STATUS_TRIP1_LOG __BIT(7) 86#define MSR_THERM_STATUS_TRIP1_LOG __BIT(7)
87#define MSR_THERM_STATUS_TRIP2_STA __BIT(8) 87#define MSR_THERM_STATUS_TRIP2_STA __BIT(8)
88#define MSR_THERM_STATUS_TRIP2_LOG __BIT(9) 88#define MSR_THERM_STATUS_TRIP2_LOG __BIT(9)
89#define MSR_THERM_STATUS_READOUT __BITS(16, 22) 89#define MSR_THERM_STATUS_READOUT __BITS(16, 22)
90#define MSR_THERM_STATUS_RESOLUTION __BITS(27, 30) 90#define MSR_THERM_STATUS_RESOLUTION __BITS(27, 30)
91#define MSR_THERM_STATUS_VALID __BIT(31) 91#define MSR_THERM_STATUS_VALID __BIT(31)
92 92
93#define MSR_THERM_INTR_HITEMP __BIT(0) 93#define MSR_THERM_INTR_HITEMP __BIT(0)
94#define MSR_THERM_INTR_LOTEMPT __BIT(1) 94#define MSR_THERM_INTR_LOTEMPT __BIT(1)
95#define MSR_THERM_INTR_PROCHOT __BIT(2) 95#define MSR_THERM_INTR_PROCHOT __BIT(2)
96#define MSR_THERM_INTR_FORCPR __BIT(3) 96#define MSR_THERM_INTR_FORCPR __BIT(3)
97#define MSR_THERM_INTR_OVERHEAT __BIT(4) 97#define MSR_THERM_INTR_OVERHEAT __BIT(4)
98#define MSR_THERM_INTR_TRIP1_VAL __BITS(8, 14) 98#define MSR_THERM_INTR_TRIP1_VAL __BITS(8, 14)
99#define MSR_THERM_INTR_TRIP1 __BIT(15) 99#define MSR_THERM_INTR_TRIP1 __BIT(15)
100#define MSR_THERM_INTR_TRIP2_VAL __BITS(16, 22) 100#define MSR_THERM_INTR_TRIP2_VAL __BITS(16, 22)
101#define MSR_THERM_INTR_TRIP2 __BIT(23) 101#define MSR_THERM_INTR_TRIP2 __BIT(23)
102 102
103#define MSR_TEMP_TARGET_READOUT __BITS(16, 23) 103#define MSR_TEMP_TARGET_READOUT __BITS(16, 23)
104 104
 105#define TJMAX_DEFAULT 100
 106#define TJMAX_LIMIT_LOW 60
 107#define TJMAX_LIMIT_HIGH 120
 108
105static int coretemp_match(device_t, cfdata_t, void *); 109static int coretemp_match(device_t, cfdata_t, void *);
106static void coretemp_attach(device_t, device_t, void *); 110static void coretemp_attach(device_t, device_t, void *);
107static int coretemp_detach(device_t, int); 111static int coretemp_detach(device_t, int);
108static int coretemp_quirks(struct cpu_info *); 112static int coretemp_quirks(struct cpu_info *);
109static void coretemp_tjmax(device_t); 113static void coretemp_tjmax(device_t);
110static void coretemp_refresh(struct sysmon_envsys *, envsys_data_t *); 114static void coretemp_refresh(struct sysmon_envsys *, envsys_data_t *);
111static void coretemp_refresh_xcall(void *, void *); 115static void coretemp_refresh_xcall(void *, void *);
112 116
113struct coretemp_softc { 117struct coretemp_softc {
114 device_t sc_dev; 118 device_t sc_dev;
115 struct cpu_info *sc_ci; 119 struct cpu_info *sc_ci;
116 struct sysmon_envsys *sc_sme; 120 struct sysmon_envsys *sc_sme;
117 envsys_data_t sc_sensor; 121 envsys_data_t sc_sensor;
118 int sc_tjmax; 122 int sc_tjmax;
119}; 123};
120 124
121CFATTACH_DECL_NEW(coretemp, sizeof(struct coretemp_softc), 125CFATTACH_DECL_NEW(coretemp, sizeof(struct coretemp_softc),
122 coretemp_match, coretemp_attach, coretemp_detach, NULL); 126 coretemp_match, coretemp_attach, coretemp_detach, NULL);
123 127
124static int 128static int
125coretemp_match(device_t parent, cfdata_t cf, void *aux) 129coretemp_match(device_t parent, cfdata_t cf, void *aux)
126{ 130{
127 struct cpufeature_attach_args *cfaa = aux; 131 struct cpufeature_attach_args *cfaa = aux;
128 struct cpu_info *ci = cfaa->ci; 132 struct cpu_info *ci = cfaa->ci;
129 uint32_t regs[4]; 133 uint32_t regs[4];
130 134
131 if (strcmp(cfaa->name, "temperature") != 0) 135 if (strcmp(cfaa->name, "temperature") != 0)
132 return 0; 136 return 0;
133 137
134 if (cpu_vendor != CPUVENDOR_INTEL || cpuid_level < 0x06) 138 if (cpu_vendor != CPUVENDOR_INTEL || cpuid_level < 0x06)
135 return 0; 139 return 0;
136 140
137 /* 141 /*
138 * Only attach on the first SMT ID. 142 * Only attach on the first SMT ID.
139 */ 143 */
140 if (ci->ci_smt_id != 0) 144 if (ci->ci_smt_id != 0)
141 return 0; 145 return 0;
142 146
143 /* 147 /*
144 * CPUID 0x06 returns 1 if the processor 148 * CPUID 0x06 returns 1 if the processor
145 * has on-die thermal sensors. EBX[0:3] 149 * has on-die thermal sensors. EBX[0:3]
146 * contains the number of sensors. 150 * contains the number of sensors.
147 */ 151 */
148 x86_cpuid(0x06, regs); 152 x86_cpuid(0x06, regs);
149 153
150 if ((regs[0] & CPUID_DSPM_DTS) == 0) 154 if ((regs[0] & CPUID_DSPM_DTS) == 0)
151 return 0; 155 return 0;
152 156
153 return coretemp_quirks(ci); 157 return coretemp_quirks(ci);
154} 158}
155 159
156static void 160static void
157coretemp_attach(device_t parent, device_t self, void *aux) 161coretemp_attach(device_t parent, device_t self, void *aux)
158{ 162{
159 struct coretemp_softc *sc = device_private(self); 163 struct coretemp_softc *sc = device_private(self);
160 struct cpufeature_attach_args *cfaa = aux; 164 struct cpufeature_attach_args *cfaa = aux;
161 struct cpu_info *ci = cfaa->ci; 165 struct cpu_info *ci = cfaa->ci;
162 uint64_t msr; 166 uint64_t msr;
163 167
164 sc->sc_ci = ci; 168 sc->sc_ci = ci;
165 sc->sc_dev = self; 169 sc->sc_dev = self;
166 170
167 msr = rdmsr(MSR_THERM_STATUS); 171 msr = rdmsr(MSR_THERM_STATUS);
168 msr = __SHIFTOUT(msr, MSR_THERM_STATUS_RESOLUTION); 172 msr = __SHIFTOUT(msr, MSR_THERM_STATUS_RESOLUTION);
169 173
170 aprint_naive("\n"); 174 aprint_naive("\n");
171 aprint_normal(": thermal sensor, %u C resolution", (uint32_t)msr); 175 aprint_normal(": thermal sensor, %u C resolution", (uint32_t)msr);
172 176
173 sc->sc_sensor.units = ENVSYS_STEMP; 177 sc->sc_sensor.units = ENVSYS_STEMP;
174 sc->sc_sensor.state = ENVSYS_SINVALID; 178 sc->sc_sensor.state = ENVSYS_SINVALID;
175 sc->sc_sensor.flags = ENVSYS_FMONCRITICAL | ENVSYS_FHAS_ENTROPY; 179 sc->sc_sensor.flags = ENVSYS_FMONCRITICAL | ENVSYS_FHAS_ENTROPY;
176 180
177 (void)pmf_device_register(self, NULL, NULL); 181 (void)pmf_device_register(self, NULL, NULL);
178 (void)snprintf(sc->sc_sensor.desc, sizeof(sc->sc_sensor.desc), 182 (void)snprintf(sc->sc_sensor.desc, sizeof(sc->sc_sensor.desc),
179 "%s temperature", device_xname(ci->ci_dev)); 183 "%s temperature", device_xname(ci->ci_dev));
180 184
181 sc->sc_sme = sysmon_envsys_create(); 185 sc->sc_sme = sysmon_envsys_create();
182 186
183 if (sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_sensor) != 0) 187 if (sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_sensor) != 0)
184 goto fail; 188 goto fail;
185 189
186 sc->sc_sme->sme_cookie = sc; 190 sc->sc_sme->sme_cookie = sc;
187 sc->sc_sme->sme_name = device_xname(self); 191 sc->sc_sme->sme_name = device_xname(self);
188 sc->sc_sme->sme_refresh = coretemp_refresh; 192 sc->sc_sme->sme_refresh = coretemp_refresh;
189 193
190 if (sysmon_envsys_register(sc->sc_sme) != 0) 194 if (sysmon_envsys_register(sc->sc_sme) != 0)
191 goto fail; 195 goto fail;
192 196
193 coretemp_tjmax(self); 197 coretemp_tjmax(self);
194 aprint_verbose(", Tjmax=%d", sc->sc_tjmax); 198 aprint_verbose(", Tjmax=%d", sc->sc_tjmax);
195 aprint_normal("\n"); 199 aprint_normal("\n");
196 return; 200 return;
197 201
198fail: 202fail:
199 sysmon_envsys_destroy(sc->sc_sme); 203 sysmon_envsys_destroy(sc->sc_sme);
200 sc->sc_sme = NULL; 204 sc->sc_sme = NULL;
201 aprint_normal("\n"); 205 aprint_normal("\n");
202} 206}
203 207
204static int 208static int
205coretemp_detach(device_t self, int flags) 209coretemp_detach(device_t self, int flags)
206{ 210{
207 struct coretemp_softc *sc = device_private(self); 211 struct coretemp_softc *sc = device_private(self);
208 212
209 if (sc->sc_sme != NULL) 213 if (sc->sc_sme != NULL)
210 sysmon_envsys_unregister(sc->sc_sme); 214 sysmon_envsys_unregister(sc->sc_sme);
211 215
212 pmf_device_deregister(self); 216 pmf_device_deregister(self);
213 217
214 return 0; 218 return 0;
215} 219}
216 220
217static int 221static int
218coretemp_quirks(struct cpu_info *ci) 222coretemp_quirks(struct cpu_info *ci)
219{ 223{
220 uint32_t model, stepping; 224 uint32_t model, stepping;
221 uint64_t msr; 225 uint64_t msr;
222 226
223 model = CPUID_TO_MODEL(ci->ci_signature); 227 model = CPUID_TO_MODEL(ci->ci_signature);
224 stepping = CPUID_TO_STEPPING(ci->ci_signature); 228 stepping = CPUID_TO_STEPPING(ci->ci_signature);
225 229
226 /* 230 /*
227 * Check if the MSR contains thermal 231 * Check if the MSR contains thermal
228 * reading valid bit, this avoid false 232 * reading valid bit, this avoid false
229 * positives on systems that fake up 233 * positives on systems that fake up
230 * a compatible CPU that doesn't have 234 * a compatible CPU that doesn't have
231 * access to these MSRs; such as VMWare. 235 * access to these MSRs; such as VMWare.
232 */ 236 */
233 msr = rdmsr(MSR_THERM_STATUS); 237 msr = rdmsr(MSR_THERM_STATUS);
234 238
235 if ((msr & MSR_THERM_STATUS_VALID) == 0) 239 if ((msr & MSR_THERM_STATUS_VALID) == 0)
236 return 0; 240 return 0;
237 241
238 /* 242 /*
239 * Check for errata AE18, "Processor Digital 243 * Check for errata AE18, "Processor Digital
240 * Thermal Sensor (DTS) Readout Stops Updating 244 * Thermal Sensor (DTS) Readout Stops Updating
241 * upon Returning from C3/C4 State". 245 * upon Returning from C3/C4 State".
242 * 246 *
243 * Adapted from the Linux coretemp driver. 247 * Adapted from the Linux coretemp driver.
244 */ 248 */
245 if (model == 0x0E && stepping < 0x0C) { 249 if (model == 0x0E && stepping < 0x0C) {
246 250
247 msr = rdmsr(MSR_BIOS_SIGN); 251 msr = rdmsr(MSR_BIOS_SIGN);
248 msr = msr >> 32; 252 msr = msr >> 32;
249 253
250 if (msr < 0x39) 254 if (msr < 0x39)
251 return 0; 255 return 0;
252 } 256 }
253 257
254 return 1; 258 return 1;
255} 259}
256 260
257void 261void
258coretemp_tjmax(device_t self) 262coretemp_tjmax(device_t self)
259{ 263{
260 struct coretemp_softc *sc = device_private(self); 264 struct coretemp_softc *sc = device_private(self);
261 struct cpu_info *ci = sc->sc_ci; 265 struct cpu_info *ci = sc->sc_ci;
262 uint32_t model, stepping; 
263 uint64_t msr; 266 uint64_t msr;
 267 uint32_t model, stepping;
 268 int tjmax;
264 269
265 model = CPUID_TO_MODEL(ci->ci_signature); 270 model = CPUID_TO_MODEL(ci->ci_signature);
266 stepping = CPUID_TO_STEPPING(ci->ci_signature); 271 stepping = CPUID_TO_STEPPING(ci->ci_signature);
267 272
268 /* 273 /* Set the initial value. */
269 * Use 100C as the initial value. 274 sc->sc_tjmax = TJMAX_DEFAULT;
270 */ 
271 sc->sc_tjmax = 100; 
272 275
273 if ((model == 0x0f && stepping >= 2) || (model == 0x0e)) { 276 if ((model == 0x0f && stepping >= 2) || (model == 0x0e)) {
274 /* 277 /*
275 * Check MSR_IA32_PLATFORM_ID(0x17) bit 28. It's not documented 278 * Check MSR_IA32_PLATFORM_ID(0x17) bit 28. It's not documented
276 * in the datasheet, but the following page describes the 279 * in the datasheet, but the following page describes the
277 * detail: 280 * detail:
278 * http://software.intel.com/en-us/articles/ 281 * http://software.intel.com/en-us/articles/
279 * mobile-intel-core2-processor-detection-table/ 282 * mobile-intel-core2-processor-detection-table/
280 * Was: http://softwarecommunity.intel.com/Wiki/Mobility/ 283 * Was: http://softwarecommunity.intel.com/Wiki/Mobility/
281 * 720.htm 284 * 720.htm
282 */ 285 */
283 if (rdmsr_safe(MSR_IA32_PLATFORM_ID, &msr) != 0) 286 if (rdmsr_safe(MSR_IA32_PLATFORM_ID, &msr) != 0)
284 goto notee; 287 goto notee;
285 if ((model < 0x17) && ((msr & __BIT(28)) == 0)) 288 if ((model < 0x17) && ((msr & __BIT(28)) == 0))
286 goto notee; 289 goto notee;
287 290
288 if (rdmsr_safe(MSR_IA32_EXT_CONFIG, &msr) == EFAULT) 291 if (rdmsr_safe(MSR_IA32_EXT_CONFIG, &msr) == EFAULT)
289 return; 292 return;
290 293
291 if ((msr & __BIT(30)) != 0) { 294 if ((msr & __BIT(30)) != 0) {
292 sc->sc_tjmax = 85; 295 sc->sc_tjmax = 85;
293 return; 296 return;
294 } 297 }
295 } else if (model == 0x17 && stepping == 0x06) { 298 } else if (model == 0x17 && stepping == 0x06) {
296 /* The mobile Penryn family. */ 299 /* The mobile Penryn family. */
297 sc->sc_tjmax = 105; 300 sc->sc_tjmax = 105;
298 return; 301 return;
299 } else if (model == 0x1c) { 302 } else if (model == 0x1c) {
300 if (stepping == 0x0a) { 303 if (stepping == 0x0a) {
301 /* 45nm Atom D400, N400 and D500 series */ 304 /* 45nm Atom D400, N400 and D500 series */
302 sc->sc_tjmax = 100; 305 sc->sc_tjmax = 100;
303 } else 306 } else
304 sc->sc_tjmax = 90; 307 sc->sc_tjmax = 90;
305 } else { 308 } else {
306notee: 309notee:
307 /* 310 /* Attempt to get Tj(max) from IA32_TEMPERATURE_TARGET. */
308 * Attempt to get Tj(max) from IA32_TEMPERATURE_TARGET, 311 if (rdmsr_safe(MSR_TEMPERATURE_TARGET, &msr) == EFAULT) {
309 * but only consider the interval [70, 110] C as valid. 312 aprint_error_dev(sc->sc_dev,
310 * It is not fully known which CPU models have the MSR. 313 "Failed to read TEMPERATURE_TARGET MSR. "
311 */ 314 "Use the default (%d)\n", sc->sc_tjmax);
312 if (rdmsr_safe(MSR_TEMPERATURE_TARGET, &msr) == EFAULT) 
313 return; 
314 
315 msr = __SHIFTOUT(msr, MSR_TEMP_TARGET_READOUT); 
316 
317 if (msr >= 70 && msr <= 110) { 
318 sc->sc_tjmax = msr; 
319 return; 315 return;
320 } 316 }
 317
 318 tjmax = __SHIFTOUT(msr, MSR_TEMP_TARGET_READOUT);
 319 if ((tjmax < TJMAX_LIMIT_LOW) || (tjmax > TJMAX_LIMIT_HIGH))
 320 aprint_error_dev(sc->sc_dev,
 321 "WARNING: Tjmax(%d) might exceeded the limit.\n",
 322 tjmax);
 323 sc->sc_tjmax = tjmax;
321 } 324 }
322} 325}
323 326
324static void 327static void
325coretemp_refresh(struct sysmon_envsys *sme, envsys_data_t *edata) 328coretemp_refresh(struct sysmon_envsys *sme, envsys_data_t *edata)
326{ 329{
327 struct coretemp_softc *sc = sme->sme_cookie; 330 struct coretemp_softc *sc = sme->sme_cookie;
328 uint64_t xc; 331 uint64_t xc;
329 332
330 xc = xc_unicast(0, coretemp_refresh_xcall, sc, edata, sc->sc_ci); 333 xc = xc_unicast(0, coretemp_refresh_xcall, sc, edata, sc->sc_ci);
331 xc_wait(xc); 334 xc_wait(xc);
332} 335}
333 336
334static void 337static void
335coretemp_refresh_xcall(void *arg0, void *arg1) 338coretemp_refresh_xcall(void *arg0, void *arg1)
336{ 339{
337 struct coretemp_softc *sc = arg0; 340 struct coretemp_softc *sc = arg0;
338 envsys_data_t *edata = arg1; 341 envsys_data_t *edata = arg1;
339 uint64_t msr; 342 uint64_t msr;
340 343
341 msr = rdmsr(MSR_THERM_STATUS); 344 msr = rdmsr(MSR_THERM_STATUS);
342 345
343 if ((msr & MSR_THERM_STATUS_VALID) == 0) 346 if ((msr & MSR_THERM_STATUS_VALID) == 0)
344 edata->state = ENVSYS_SINVALID; 347 edata->state = ENVSYS_SINVALID;
345 else { 348 else {
346 /* 349 /*
347 * The temperature is computed by 350 * The temperature is computed by
348 * subtracting the reading by Tj(max). 351 * subtracting the reading by Tj(max).
349 */ 352 */
350 edata->value_cur = sc->sc_tjmax; 353 edata->value_cur = sc->sc_tjmax;
351 edata->value_cur -= __SHIFTOUT(msr, MSR_THERM_STATUS_READOUT); 354 edata->value_cur -= __SHIFTOUT(msr, MSR_THERM_STATUS_READOUT);
352 355
353 /* 356 /*
354 * Convert to mK. 357 * Convert to mK.
355 */ 358 */
356 edata->value_cur *= 1000000; 359 edata->value_cur *= 1000000;
357 edata->value_cur += 273150000; 360 edata->value_cur += 273150000;
358 edata->state = ENVSYS_SVALID; 361 edata->state = ENVSYS_SVALID;
359 } 362 }
360 363
361 if ((msr & MSR_THERM_STATUS_CRIT_STA) != 0) 364 if ((msr & MSR_THERM_STATUS_CRIT_STA) != 0)
362 edata->state = ENVSYS_SCRITICAL; 365 edata->state = ENVSYS_SCRITICAL;
363} 366}
364 367
365MODULE(MODULE_CLASS_DRIVER, coretemp, "sysmon_envsys"); 368MODULE(MODULE_CLASS_DRIVER, coretemp, "sysmon_envsys");
366 369
367#ifdef _MODULE 370#ifdef _MODULE
368#include "ioconf.c" 371#include "ioconf.c"
369#endif 372#endif
370 373
371static int 374static int
372coretemp_modcmd(modcmd_t cmd, void *aux) 375coretemp_modcmd(modcmd_t cmd, void *aux)
373{ 376{
374 int error = 0; 377 int error = 0;
375 378
376 switch (cmd) { 379 switch (cmd) {
377 case MODULE_CMD_INIT: 380 case MODULE_CMD_INIT:
378#ifdef _MODULE 381#ifdef _MODULE
379 error = config_init_component(cfdriver_ioconf_coretemp, 382 error = config_init_component(cfdriver_ioconf_coretemp,
380 cfattach_ioconf_coretemp, cfdata_ioconf_coretemp); 383 cfattach_ioconf_coretemp, cfdata_ioconf_coretemp);
381#endif 384#endif
382 return error; 385 return error;
383 case MODULE_CMD_FINI: 386 case MODULE_CMD_FINI:
384#ifdef _MODULE 387#ifdef _MODULE
385 error = config_fini_component(cfdriver_ioconf_coretemp, 388 error = config_fini_component(cfdriver_ioconf_coretemp,
386 cfattach_ioconf_coretemp, cfdata_ioconf_coretemp); 389 cfattach_ioconf_coretemp, cfdata_ioconf_coretemp);
387#endif 390#endif
388 return error; 391 return error;
389 default: 392 default:
390 return ENOTTY; 393 return ENOTTY;
391 } 394 }
392} 395}