xref: /dragonfly/sys/dev/powermng/coretemp/coretemp.c (revision dae65060)
13a514b87SHasso Tepper /*
2575aab54SSascha Wildner  * Copyright (c) 2007, 2008 Rui Paulo <rpaulo@FreeBSD.org>
33a514b87SHasso Tepper  * All rights reserved.
43a514b87SHasso Tepper  *
53a514b87SHasso Tepper  * Redistribution and use in source and binary forms, with or without
63a514b87SHasso Tepper  * modification, are permitted provided that the following conditions
73a514b87SHasso Tepper  * are met:
83a514b87SHasso Tepper  * 1. Redistributions of source code must retain the above copyright
93a514b87SHasso Tepper  *    notice, this list of conditions and the following disclaimer.
103a514b87SHasso Tepper  * 2. Redistributions in binary form must reproduce the above copyright
113a514b87SHasso Tepper  *    notice, this list of conditions and the following disclaimer in the
123a514b87SHasso Tepper  *    documentation and/or other materials provided with the distribution.
133a514b87SHasso Tepper  *
143a514b87SHasso Tepper  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
153a514b87SHasso Tepper  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
163a514b87SHasso Tepper  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
173a514b87SHasso Tepper  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
183a514b87SHasso Tepper  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
193a514b87SHasso Tepper  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
203a514b87SHasso Tepper  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
213a514b87SHasso Tepper  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
223a514b87SHasso Tepper  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
233a514b87SHasso Tepper  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
243a514b87SHasso Tepper  * POSSIBILITY OF SUCH DAMAGE.
253a514b87SHasso Tepper  *
26575aab54SSascha Wildner  * $FreeBSD: src/sys/dev/coretemp/coretemp.c,v 1.14 2011/05/05 19:15:15 delphij Exp $
273a514b87SHasso Tepper  */
283a514b87SHasso Tepper 
293a514b87SHasso Tepper /*
303a514b87SHasso Tepper  * Device driver for Intel's On Die thermal sensor via MSR.
313a514b87SHasso Tepper  * First introduced in Intel's Core line of processors.
323a514b87SHasso Tepper  */
333a514b87SHasso Tepper 
343a514b87SHasso Tepper #include <sys/param.h>
353a514b87SHasso Tepper #include <sys/bus.h>
363a514b87SHasso Tepper #include <sys/systm.h>
373a514b87SHasso Tepper #include <sys/module.h>
383a514b87SHasso Tepper #include <sys/conf.h>
39056f320bSSepherosa Ziehau #include <sys/cpu_topology.h>
403a514b87SHasso Tepper #include <sys/kernel.h>
41*dae65060Szrj #include <sys/malloc.h>
423a514b87SHasso Tepper #include <sys/sensors.h>
433a514b87SHasso Tepper #include <sys/proc.h>	/* for curthread */
443a514b87SHasso Tepper #include <sys/sched.h>
45ce72fc09SSepherosa Ziehau #include <sys/thread2.h>
46680d36f5SSepherosa Ziehau #include <sys/bitops.h>
473a514b87SHasso Tepper 
483a514b87SHasso Tepper #include <machine/specialreg.h>
493a514b87SHasso Tepper #include <machine/cpufunc.h>
5086b7a03aSSascha Wildner #include <machine/cputypes.h>
513a514b87SHasso Tepper #include <machine/md_var.h>
523a514b87SHasso Tepper 
53c000328cSSepherosa Ziehau #include "cpu_if.h"
54c000328cSSepherosa Ziehau 
55680d36f5SSepherosa Ziehau #define MSR_THERM_STATUS_TM_STATUS	__BIT64(0)
56680d36f5SSepherosa Ziehau #define MSR_THERM_STATUS_TM_STATUS_LOG	__BIT64(1)
57680d36f5SSepherosa Ziehau #define MSR_THERM_STATUS_PROCHOT	__BIT64(2)
58680d36f5SSepherosa Ziehau #define MSR_THERM_STATUS_PROCHOT_LOG	__BIT64(3)
59680d36f5SSepherosa Ziehau #define MSR_THERM_STATUS_CRIT		__BIT64(4)
60680d36f5SSepherosa Ziehau #define MSR_THERM_STATUS_CRIT_LOG	__BIT64(5)
61680d36f5SSepherosa Ziehau #define MSR_THERM_STATUS_THRESH1	__BIT64(6)
62680d36f5SSepherosa Ziehau #define MSR_THERM_STATUS_THRESH1_LOG	__BIT64(7)
63680d36f5SSepherosa Ziehau #define MSR_THERM_STATUS_THRESH2	__BIT64(8)
64680d36f5SSepherosa Ziehau #define MSR_THERM_STATUS_THRESH2_LOG	__BIT64(9)
65680d36f5SSepherosa Ziehau #define MSR_THERM_STATUS_PWRLIM		__BIT64(10)
66680d36f5SSepherosa Ziehau #define MSR_THERM_STATUS_PWRLIM_LOG	__BIT64(11)
67680d36f5SSepherosa Ziehau #define MSR_THERM_STATUS_READ		__BITS64(16, 22)
68680d36f5SSepherosa Ziehau #define MSR_THERM_STATUS_RES		__BITS64(27, 30)
69680d36f5SSepherosa Ziehau #define MSR_THERM_STATUS_READ_VALID	__BIT64(31)
70680d36f5SSepherosa Ziehau 
71680d36f5SSepherosa Ziehau #define MSR_THERM_STATUS_HAS_STATUS(msr) \
72680d36f5SSepherosa Ziehau     (((msr) & (MSR_THERM_STATUS_TM_STATUS | MSR_THERM_STATUS_TM_STATUS_LOG)) ==\
73680d36f5SSepherosa Ziehau      (MSR_THERM_STATUS_TM_STATUS | MSR_THERM_STATUS_TM_STATUS_LOG))
74680d36f5SSepherosa Ziehau 
75680d36f5SSepherosa Ziehau #define MSR_THERM_STATUS_IS_CRITICAL(msr) \
76680d36f5SSepherosa Ziehau     (((msr) & (MSR_THERM_STATUS_CRIT | MSR_THERM_STATUS_CRIT_LOG)) == \
77680d36f5SSepherosa Ziehau      (MSR_THERM_STATUS_CRIT | MSR_THERM_STATUS_CRIT_LOG))
78680d36f5SSepherosa Ziehau 
7985843744SSepherosa Ziehau #define MSR_PKGTM_STATUS_TM_STATUS	__BIT64(0)
8085843744SSepherosa Ziehau #define MSR_PKGTM_STATUS_TM_STATUS_LOG	__BIT64(1)
8185843744SSepherosa Ziehau #define MSR_PKGTM_STATUS_PROCHOT	__BIT64(2)
8285843744SSepherosa Ziehau #define MSR_PKGTM_STATUS_PROCHOT_LOG	__BIT64(3)
8385843744SSepherosa Ziehau #define MSR_PKGTM_STATUS_CRIT		__BIT64(4)
8485843744SSepherosa Ziehau #define MSR_PKGTM_STATUS_CRIT_LOG	__BIT64(5)
8585843744SSepherosa Ziehau #define MSR_PKGTM_STATUS_THRESH1	__BIT64(6)
8685843744SSepherosa Ziehau #define MSR_PKGTM_STATUS_THRESH1_LOG	__BIT64(7)
8785843744SSepherosa Ziehau #define MSR_PKGTM_STATUS_THRESH2	__BIT64(8)
8885843744SSepherosa Ziehau #define MSR_PKGTM_STATUS_THRESH2_LOG	__BIT64(9)
8985843744SSepherosa Ziehau #define MSR_PKGTM_STATUS_PWRLIM		__BIT64(10)
9085843744SSepherosa Ziehau #define MSR_PKGTM_STATUS_PWRLIM_LOG	__BIT64(11)
9185843744SSepherosa Ziehau #define MSR_PKGTM_STATUS_READ		__BITS64(16, 22)
9285843744SSepherosa Ziehau 
9385843744SSepherosa Ziehau #define MSR_PKGTM_STATUS_HAS_STATUS(msr) \
9485843744SSepherosa Ziehau     (((msr) & (MSR_PKGTM_STATUS_TM_STATUS | MSR_PKGTM_STATUS_TM_STATUS_LOG)) ==\
9585843744SSepherosa Ziehau      (MSR_PKGTM_STATUS_TM_STATUS | MSR_PKGTM_STATUS_TM_STATUS_LOG))
9685843744SSepherosa Ziehau 
9785843744SSepherosa Ziehau #define MSR_PKGTM_STATUS_IS_CRITICAL(msr) \
9885843744SSepherosa Ziehau     (((msr) & (MSR_PKGTM_STATUS_CRIT | MSR_PKGTM_STATUS_CRIT_LOG)) == \
9985843744SSepherosa Ziehau      (MSR_PKGTM_STATUS_CRIT | MSR_PKGTM_STATUS_CRIT_LOG))
10085843744SSepherosa Ziehau 
10185843744SSepherosa Ziehau #define CORETEMP_TEMP_INVALID	-1
10285843744SSepherosa Ziehau 
103056f320bSSepherosa Ziehau struct coretemp_sensor {
104c000328cSSepherosa Ziehau 	struct ksensordev	*c_sensdev;
105056f320bSSepherosa Ziehau 	struct ksensor		c_sens;
106056f320bSSepherosa Ziehau };
107056f320bSSepherosa Ziehau 
1083a514b87SHasso Tepper struct coretemp_softc {
1093a514b87SHasso Tepper 	device_t		sc_dev;
1103a514b87SHasso Tepper 	int			sc_tjmax;
111ce72fc09SSepherosa Ziehau 
112056f320bSSepherosa Ziehau 	int			sc_nsens;
113056f320bSSepherosa Ziehau 	struct coretemp_sensor	*sc_sens;
11485843744SSepherosa Ziehau 	struct coretemp_sensor	*sc_pkg_sens;
115056f320bSSepherosa Ziehau 
1164c79bfdaSSepherosa Ziehau 	struct sensor_task	*sc_senstask;
117ce72fc09SSepherosa Ziehau 	int			sc_cpu;
118ce72fc09SSepherosa Ziehau 	volatile uint32_t	sc_flags;	/* CORETEMP_FLAG_ */
119ce72fc09SSepherosa Ziehau 	volatile uint64_t	sc_msr;
12085843744SSepherosa Ziehau 	volatile uint64_t	sc_pkg_msr;
1213a514b87SHasso Tepper };
1223a514b87SHasso Tepper 
12318df9562SSepherosa Ziehau #define CORETEMP_FLAG_CRIT	0x4
12485843744SSepherosa Ziehau #define CORETEMP_FLAG_PKGCRIT	0x8
12585843744SSepherosa Ziehau 
12685843744SSepherosa Ziehau #define CORETEMP_HAS_PKGSENSOR(sc)	((sc)->sc_pkg_sens != NULL)
127ce72fc09SSepherosa Ziehau 
1283a514b87SHasso Tepper /*
1293a514b87SHasso Tepper  * Device methods.
1303a514b87SHasso Tepper  */
1313a514b87SHasso Tepper static void	coretemp_identify(driver_t *driver, device_t parent);
1323a514b87SHasso Tepper static int	coretemp_probe(device_t dev);
1333a514b87SHasso Tepper static int	coretemp_attach(device_t dev);
1343a514b87SHasso Tepper static int	coretemp_detach(device_t dev);
1353a514b87SHasso Tepper 
1364c79bfdaSSepherosa Ziehau static void	coretemp_msr_fetch(struct coretemp_softc *sc, uint64_t *msr,
13785843744SSepherosa Ziehau 		    uint64_t *pkg_msr);
13885843744SSepherosa Ziehau static int	coretemp_msr_temp(struct coretemp_softc *sc, uint64_t msr);
13985843744SSepherosa Ziehau static void	coretemp_sensor_update(struct coretemp_softc *sc, int temp);
14085843744SSepherosa Ziehau static void	coretemp_sensor_task(void *arg);
14185843744SSepherosa Ziehau 
14285843744SSepherosa Ziehau static void	coretemp_pkg_sensor_task(void *arg);
14385843744SSepherosa Ziehau static void	coretemp_pkg_sensor_update(struct coretemp_softc *sc, int temp);
14485843744SSepherosa Ziehau static int	coretemp_pkg_msr_temp(struct coretemp_softc *sc, uint64_t msr);
1453a514b87SHasso Tepper 
1463a514b87SHasso Tepper static device_method_t coretemp_methods[] = {
1473a514b87SHasso Tepper 	/* Device interface */
1483a514b87SHasso Tepper 	DEVMETHOD(device_identify,	coretemp_identify),
1493a514b87SHasso Tepper 	DEVMETHOD(device_probe,		coretemp_probe),
1503a514b87SHasso Tepper 	DEVMETHOD(device_attach,	coretemp_attach),
1513a514b87SHasso Tepper 	DEVMETHOD(device_detach,	coretemp_detach),
1523a514b87SHasso Tepper 
153d3c9c58eSSascha Wildner 	DEVMETHOD_END
1543a514b87SHasso Tepper };
1553a514b87SHasso Tepper 
1563a514b87SHasso Tepper static driver_t coretemp_driver = {
1573a514b87SHasso Tepper 	"coretemp",
1583a514b87SHasso Tepper 	coretemp_methods,
1593a514b87SHasso Tepper 	sizeof(struct coretemp_softc),
1603a514b87SHasso Tepper };
1613a514b87SHasso Tepper 
1623a514b87SHasso Tepper static devclass_t coretemp_devclass;
1633a514b87SHasso Tepper DRIVER_MODULE(coretemp, cpu, coretemp_driver, coretemp_devclass, NULL, NULL);
16400961cb1SSascha Wildner MODULE_VERSION(coretemp, 1);
1653a514b87SHasso Tepper 
16685843744SSepherosa Ziehau static __inline void
coretemp_sensor_set(struct ksensor * sens,const struct coretemp_softc * sc,uint32_t crit_flag,int temp)16785843744SSepherosa Ziehau coretemp_sensor_set(struct ksensor *sens, const struct coretemp_softc *sc,
16885843744SSepherosa Ziehau     uint32_t crit_flag, int temp)
16985843744SSepherosa Ziehau {
1707273d7b8SSepherosa Ziehau 	enum sensor_status status;
1717273d7b8SSepherosa Ziehau 
17285843744SSepherosa Ziehau 	if (sc->sc_flags & crit_flag)
1737273d7b8SSepherosa Ziehau 		status = SENSOR_S_CRIT;
17485843744SSepherosa Ziehau 	else
1757273d7b8SSepherosa Ziehau 		status = SENSOR_S_OK;
1767273d7b8SSepherosa Ziehau 	sensor_set_temp_degc(sens, temp, status);
17785843744SSepherosa Ziehau }
17885843744SSepherosa Ziehau 
1793a514b87SHasso Tepper static void
coretemp_identify(driver_t * driver,device_t parent)1803a514b87SHasso Tepper coretemp_identify(driver_t *driver, device_t parent)
1813a514b87SHasso Tepper {
1823a514b87SHasso Tepper 	device_t child;
1833a514b87SHasso Tepper 
1843a514b87SHasso Tepper 	/* Make sure we're not being doubly invoked. */
1853a514b87SHasso Tepper 	if (device_find_child(parent, "coretemp", -1) != NULL)
1863a514b87SHasso Tepper 		return;
1873a514b87SHasso Tepper 
188e99c31a3SSepherosa Ziehau 	/* Check that the vendor is Intel. */
189e99c31a3SSepherosa Ziehau 	if (cpu_vendor_id != CPU_VENDOR_INTEL)
1903a514b87SHasso Tepper 		return;
191e99c31a3SSepherosa Ziehau 
1923a514b87SHasso Tepper 	/*
193e99c31a3SSepherosa Ziehau 	 * Some Intel CPUs, namely the PIII, don't have thermal sensors,
194e99c31a3SSepherosa Ziehau 	 * but report them in cpu_thermal_feature.  This leads to a later
195e99c31a3SSepherosa Ziehau 	 * GPF when the sensor is queried via a MSR, so we stop here.
1963a514b87SHasso Tepper 	 */
197e99c31a3SSepherosa Ziehau 	if (CPUID_TO_MODEL(cpu_id) < 0xe)
198e99c31a3SSepherosa Ziehau 		return;
199e99c31a3SSepherosa Ziehau 
200e99c31a3SSepherosa Ziehau 	if ((cpu_thermal_feature & CPUID_THERMAL_SENSOR) == 0)
2013a514b87SHasso Tepper 		return;
2023a514b87SHasso Tepper 
2033a514b87SHasso Tepper 	/*
2043a514b87SHasso Tepper 	 * We add a child for each CPU since settings must be performed
2053a514b87SHasso Tepper 	 * on each CPU in the SMP case.
2063a514b87SHasso Tepper 	 */
2073a514b87SHasso Tepper 	child = device_add_child(parent, "coretemp", -1);
2083a514b87SHasso Tepper 	if (child == NULL)
2093a514b87SHasso Tepper 		device_printf(parent, "add coretemp child failed\n");
2103a514b87SHasso Tepper }
2113a514b87SHasso Tepper 
2123a514b87SHasso Tepper static int
coretemp_probe(device_t dev)2133a514b87SHasso Tepper coretemp_probe(device_t dev)
2143a514b87SHasso Tepper {
2153a514b87SHasso Tepper 	if (resource_disabled("coretemp", 0))
2163a514b87SHasso Tepper 		return (ENXIO);
2173a514b87SHasso Tepper 
2183a514b87SHasso Tepper 	device_set_desc(dev, "CPU On-Die Thermal Sensors");
2193a514b87SHasso Tepper 
2203a514b87SHasso Tepper 	return (BUS_PROBE_GENERIC);
2213a514b87SHasso Tepper }
2223a514b87SHasso Tepper 
2233a514b87SHasso Tepper static int
coretemp_attach(device_t dev)2243a514b87SHasso Tepper coretemp_attach(device_t dev)
2253a514b87SHasso Tepper {
2263a514b87SHasso Tepper 	struct coretemp_softc *sc = device_get_softc(dev);
227056f320bSSepherosa Ziehau 	const struct cpu_node *node, *start_node;
228056f320bSSepherosa Ziehau 	cpumask_t cpu_mask;
2293a514b87SHasso Tepper 	device_t pdev;
2303a514b87SHasso Tepper 	uint64_t msr;
231575aab54SSascha Wildner 	int cpu_model, cpu_stepping;
232056f320bSSepherosa Ziehau 	int ret, tjtarget, cpu, sens_idx;
23385843744SSepherosa Ziehau 	int master_cpu;
23485843744SSepherosa Ziehau 	struct coretemp_sensor *csens;
235c000328cSSepherosa Ziehau 	boolean_t sens_task = FALSE;
2363a514b87SHasso Tepper 
2373a514b87SHasso Tepper 	sc->sc_dev = dev;
2383a514b87SHasso Tepper 	pdev = device_get_parent(dev);
239575aab54SSascha Wildner 	cpu_model = CPUID_TO_MODEL(cpu_id);
240575aab54SSascha Wildner 	cpu_stepping = cpu_id & CPUID_STEPPING;
241575aab54SSascha Wildner 
242013ec85cSSepherosa Ziehau #if 0
243013ec85cSSepherosa Ziehau 	/*
244575aab54SSascha Wildner 	 * XXXrpaulo: I have this CPU model and when it returns from C3
245575aab54SSascha Wildner 	 * coretemp continues to function properly.
246575aab54SSascha Wildner 	 */
2473a514b87SHasso Tepper 
2483a514b87SHasso Tepper 	/*
2493a514b87SHasso Tepper 	 * Check for errata AE18.
2503a514b87SHasso Tepper 	 * "Processor Digital Thermal Sensor (DTS) Readout stops
2513a514b87SHasso Tepper 	 *  updating upon returning from C3/C4 state."
2523a514b87SHasso Tepper 	 *
2533a514b87SHasso Tepper 	 * Adapted from the Linux coretemp driver.
2543a514b87SHasso Tepper 	 */
255575aab54SSascha Wildner 	if (cpu_model == 0xe && cpu_stepping < 0xc) {
2563a514b87SHasso Tepper 		msr = rdmsr(MSR_BIOS_SIGN);
2573a514b87SHasso Tepper 		msr = msr >> 32;
2583a514b87SHasso Tepper 		if (msr < 0x39) {
2593a514b87SHasso Tepper 			device_printf(dev, "not supported (Intel errata "
2603a514b87SHasso Tepper 			    "AE18), try updating your BIOS\n");
2613a514b87SHasso Tepper 			return (ENXIO);
2623a514b87SHasso Tepper 		}
2633a514b87SHasso Tepper 	}
264575aab54SSascha Wildner #endif
265575aab54SSascha Wildner 
266575aab54SSascha Wildner 	/*
267575aab54SSascha Wildner 	 * Use 100C as the initial value.
268575aab54SSascha Wildner 	 */
269575aab54SSascha Wildner 	sc->sc_tjmax = 100;
270575aab54SSascha Wildner 
271575aab54SSascha Wildner 	if ((cpu_model == 0xf && cpu_stepping >= 2) || cpu_model == 0xe) {
2723a514b87SHasso Tepper 		/*
2733a514b87SHasso Tepper 		 * On some Core 2 CPUs, there's an undocumented MSR that
2743a514b87SHasso Tepper 		 * can tell us if Tj(max) is 100 or 85.
2753a514b87SHasso Tepper 		 *
276056f320bSSepherosa Ziehau 		 * The if-clause for CPUs having the MSR_IA32_EXT_CONFIG
277056f320bSSepherosa Ziehau 		 * was adapted from the Linux coretemp driver.
2783a514b87SHasso Tepper 		 */
2793a514b87SHasso Tepper 		msr = rdmsr(MSR_IA32_EXT_CONFIG);
2803a514b87SHasso Tepper 		if (msr & (1 << 30))
2813a514b87SHasso Tepper 			sc->sc_tjmax = 85;
282575aab54SSascha Wildner 	} else if (cpu_model == 0x17) {
283575aab54SSascha Wildner 		switch (cpu_stepping) {
284575aab54SSascha Wildner 		case 0x6:	/* Mobile Core 2 Duo */
285575aab54SSascha Wildner 			sc->sc_tjmax = 105;
286575aab54SSascha Wildner 			break;
287575aab54SSascha Wildner 		default:	/* Unknown stepping */
288575aab54SSascha Wildner 			break;
2893a514b87SHasso Tepper 		}
290575aab54SSascha Wildner 	} else if (cpu_model == 0x1c) {
291575aab54SSascha Wildner 		switch (cpu_stepping) {
292575aab54SSascha Wildner 		case 0xa:	/* 45nm Atom D400, N400 and D500 series */
293575aab54SSascha Wildner 			sc->sc_tjmax = 100;
294575aab54SSascha Wildner 			break;
295575aab54SSascha Wildner 		default:
296575aab54SSascha Wildner 			sc->sc_tjmax = 90;
297575aab54SSascha Wildner 			break;
298575aab54SSascha Wildner 		}
299575aab54SSascha Wildner 	} else {
300575aab54SSascha Wildner 		/*
301575aab54SSascha Wildner 		 * Attempt to get Tj(max) from MSR IA32_TEMPERATURE_TARGET.
302575aab54SSascha Wildner 		 *
303575aab54SSascha Wildner 		 * This method is described in Intel white paper "CPU
304575aab54SSascha Wildner 		 * Monitoring With DTS/PECI". (#322683)
305575aab54SSascha Wildner 		 */
306575aab54SSascha Wildner 		ret = rdmsr_safe(MSR_IA32_TEMPERATURE_TARGET, &msr);
307575aab54SSascha Wildner 		if (ret == 0) {
308575aab54SSascha Wildner 			tjtarget = (msr >> 16) & 0xff;
309575aab54SSascha Wildner 
310575aab54SSascha Wildner 			/*
311575aab54SSascha Wildner 			 * On earlier generation of processors, the value
312575aab54SSascha Wildner 			 * obtained from IA32_TEMPERATURE_TARGET register is
313575aab54SSascha Wildner 			 * an offset that needs to be summed with a model
314575aab54SSascha Wildner 			 * specific base.  It is however not clear what
315575aab54SSascha Wildner 			 * these numbers are, with the publicly available
316575aab54SSascha Wildner 			 * documents from Intel.
317575aab54SSascha Wildner 			 *
31882844f50SSepherosa Ziehau 			 * For now, we consider [70, 110]C range, as
319575aab54SSascha Wildner 			 * described in #322683, as "reasonable" and accept
320575aab54SSascha Wildner 			 * these values whenever the MSR is available for
321575aab54SSascha Wildner 			 * read, regardless the CPU model.
322575aab54SSascha Wildner 			 */
32382844f50SSepherosa Ziehau 			if (tjtarget >= 70 && tjtarget <= 110)
324575aab54SSascha Wildner 				sc->sc_tjmax = tjtarget;
325575aab54SSascha Wildner 			else
326575aab54SSascha Wildner 				device_printf(dev, "Tj(target) value %d "
327575aab54SSascha Wildner 				    "does not seem right.\n", tjtarget);
328575aab54SSascha Wildner 		} else
329575aab54SSascha Wildner 			device_printf(dev, "Can not get Tj(target) "
330575aab54SSascha Wildner 			    "from your CPU, using 100C.\n");
331575aab54SSascha Wildner 	}
332575aab54SSascha Wildner 
333575aab54SSascha Wildner 	if (bootverbose)
334575aab54SSascha Wildner 		device_printf(dev, "Setting TjMax=%d\n", sc->sc_tjmax);
3353a514b87SHasso Tepper 
336ce72fc09SSepherosa Ziehau 	sc->sc_cpu = device_get_unit(device_get_parent(dev));
337ce72fc09SSepherosa Ziehau 
338056f320bSSepherosa Ziehau 	start_node = get_cpu_node_by_cpuid(sc->sc_cpu);
339056f320bSSepherosa Ziehau 
340056f320bSSepherosa Ziehau 	node = start_node;
341056f320bSSepherosa Ziehau 	while (node != NULL) {
34261e47a39SSepherosa Ziehau 		if (node->type == CORE_LEVEL) {
34361e47a39SSepherosa Ziehau 			if (node->child_no == 0)
34461e47a39SSepherosa Ziehau 				node = NULL;
345056f320bSSepherosa Ziehau 			break;
34661e47a39SSepherosa Ziehau 		}
347056f320bSSepherosa Ziehau 		node = node->parent_node;
348056f320bSSepherosa Ziehau 	}
349056f320bSSepherosa Ziehau 	if (node != NULL) {
35085843744SSepherosa Ziehau 		master_cpu = BSRCPUMASK(node->members);
351056f320bSSepherosa Ziehau 		if (bootverbose) {
352056f320bSSepherosa Ziehau 			device_printf(dev, "master cpu%d, count %u\n",
353056f320bSSepherosa Ziehau 			    master_cpu, node->child_no);
354056f320bSSepherosa Ziehau 		}
355056f320bSSepherosa Ziehau 		if (sc->sc_cpu != master_cpu)
356056f320bSSepherosa Ziehau 			return (0);
357056f320bSSepherosa Ziehau 
358056f320bSSepherosa Ziehau 		KKASSERT(node->child_no > 0);
359056f320bSSepherosa Ziehau 		sc->sc_nsens = node->child_no;
360056f320bSSepherosa Ziehau 		cpu_mask = node->members;
361056f320bSSepherosa Ziehau 	} else {
362056f320bSSepherosa Ziehau 		sc->sc_nsens = 1;
363056f320bSSepherosa Ziehau 		CPUMASK_ASSBIT(cpu_mask, sc->sc_cpu);
364056f320bSSepherosa Ziehau 	}
365056f320bSSepherosa Ziehau 	sc->sc_sens = kmalloc(sizeof(struct coretemp_sensor) * sc->sc_nsens,
366056f320bSSepherosa Ziehau 	    M_DEVBUF, M_WAITOK | M_ZERO);
367056f320bSSepherosa Ziehau 
368056f320bSSepherosa Ziehau 	sens_idx = 0;
369056f320bSSepherosa Ziehau 	CPUSET_FOREACH(cpu, cpu_mask) {
370c000328cSSepherosa Ziehau 		device_t cpu_dev;
371c000328cSSepherosa Ziehau 
372c000328cSSepherosa Ziehau 		cpu_dev = devclass_find_unit("cpu", cpu);
373c000328cSSepherosa Ziehau 		if (cpu_dev == NULL)
374c000328cSSepherosa Ziehau 			continue;
375c000328cSSepherosa Ziehau 
376056f320bSSepherosa Ziehau 		KKASSERT(sens_idx < sc->sc_nsens);
377056f320bSSepherosa Ziehau 		csens = &sc->sc_sens[sens_idx];
378056f320bSSepherosa Ziehau 
379c000328cSSepherosa Ziehau 		csens->c_sensdev = CPU_GET_SENSDEV(cpu_dev);
380c000328cSSepherosa Ziehau 		if (csens->c_sensdev == NULL)
381c000328cSSepherosa Ziehau 			continue;
382c000328cSSepherosa Ziehau 
3833a514b87SHasso Tepper 		/*
3843a514b87SHasso Tepper 		 * Add hw.sensors.cpuN.temp0 MIB.
3853a514b87SHasso Tepper 		 */
386056f320bSSepherosa Ziehau 		ksnprintf(csens->c_sens.desc, sizeof(csens->c_sens.desc),
387949251baSSepherosa Ziehau 		    "node%d core%d temp", get_chip_ID(cpu),
388056f320bSSepherosa Ziehau 		    get_core_number_within_chip(cpu));
389056f320bSSepherosa Ziehau 		csens->c_sens.type = SENSOR_TEMP;
3907273d7b8SSepherosa Ziehau 		sensor_set_unknown(&csens->c_sens);
391c000328cSSepherosa Ziehau 		sensor_attach(csens->c_sensdev, &csens->c_sens);
392056f320bSSepherosa Ziehau 
393056f320bSSepherosa Ziehau 		++sens_idx;
394056f320bSSepherosa Ziehau 	}
39585843744SSepherosa Ziehau 
396c000328cSSepherosa Ziehau 	if (sens_idx == 0) {
397c000328cSSepherosa Ziehau 		kfree(sc->sc_sens, M_DEVBUF);
398c000328cSSepherosa Ziehau 		sc->sc_sens = NULL;
399c000328cSSepherosa Ziehau 		sc->sc_nsens = 0;
400c000328cSSepherosa Ziehau 	} else {
401c000328cSSepherosa Ziehau 		sens_task = TRUE;
402c000328cSSepherosa Ziehau 	}
403c000328cSSepherosa Ziehau 
40485843744SSepherosa Ziehau 	if (cpu_thermal_feature & CPUID_THERMAL_PTM) {
40585843744SSepherosa Ziehau 		boolean_t pkg_sens = TRUE;
40685843744SSepherosa Ziehau 
40785843744SSepherosa Ziehau 		/*
40885843744SSepherosa Ziehau 		 * Package thermal sensor
40985843744SSepherosa Ziehau 		 */
41085843744SSepherosa Ziehau 
41185843744SSepherosa Ziehau 		node = start_node;
41285843744SSepherosa Ziehau 		while (node != NULL) {
41385843744SSepherosa Ziehau 			if (node->type == CHIP_LEVEL) {
41485843744SSepherosa Ziehau 				if (node->child_no == 0)
41585843744SSepherosa Ziehau 					node = NULL;
41685843744SSepherosa Ziehau 				break;
41785843744SSepherosa Ziehau 			}
41885843744SSepherosa Ziehau 			node = node->parent_node;
41985843744SSepherosa Ziehau 		}
42085843744SSepherosa Ziehau 		if (node != NULL) {
42185843744SSepherosa Ziehau 			master_cpu = BSRCPUMASK(node->members);
42285843744SSepherosa Ziehau 			if (bootverbose) {
42385843744SSepherosa Ziehau 				device_printf(dev, "pkg master cpu%d\n",
42485843744SSepherosa Ziehau 				    master_cpu);
42585843744SSepherosa Ziehau 			}
42685843744SSepherosa Ziehau 			if (sc->sc_cpu != master_cpu)
42785843744SSepherosa Ziehau 				pkg_sens = FALSE;
42885843744SSepherosa Ziehau 		}
42985843744SSepherosa Ziehau 
43085843744SSepherosa Ziehau 		if (pkg_sens) {
43185843744SSepherosa Ziehau 			csens = sc->sc_pkg_sens =
43285843744SSepherosa Ziehau 			    kmalloc(sizeof(struct coretemp_sensor), M_DEVBUF,
43385843744SSepherosa Ziehau 			    M_WAITOK | M_ZERO);
434c000328cSSepherosa Ziehau 			csens->c_sensdev = kmalloc(sizeof(struct ksensordev),
435c000328cSSepherosa Ziehau 			    M_DEVBUF, M_WAITOK | M_ZERO);
43685843744SSepherosa Ziehau 
43785843744SSepherosa Ziehau 			/*
43885843744SSepherosa Ziehau 			 * Add hw.sensors.cpu_nodeN.temp0 MIB.
43985843744SSepherosa Ziehau 			 */
440c000328cSSepherosa Ziehau 			ksnprintf(csens->c_sensdev->xname,
441c000328cSSepherosa Ziehau 			    sizeof(csens->c_sensdev->xname), "cpu_node%d",
44285843744SSepherosa Ziehau 			    get_chip_ID(sc->sc_cpu));
44385843744SSepherosa Ziehau 			ksnprintf(csens->c_sens.desc,
444949251baSSepherosa Ziehau 			    sizeof(csens->c_sens.desc), "node%d temp",
44585843744SSepherosa Ziehau 			    get_chip_ID(sc->sc_cpu));
44685843744SSepherosa Ziehau 			csens->c_sens.type = SENSOR_TEMP;
4477273d7b8SSepherosa Ziehau 			sensor_set_unknown(&csens->c_sens);
448c000328cSSepherosa Ziehau 			sensor_attach(csens->c_sensdev, &csens->c_sens);
449c000328cSSepherosa Ziehau 			sensordev_install(csens->c_sensdev);
450c000328cSSepherosa Ziehau 
451c000328cSSepherosa Ziehau 			sens_task = TRUE;
45285843744SSepherosa Ziehau 		}
45385843744SSepherosa Ziehau 	}
45485843744SSepherosa Ziehau 
455c000328cSSepherosa Ziehau 	if (sens_task) {
4564c79bfdaSSepherosa Ziehau 		if (CORETEMP_HAS_PKGSENSOR(sc)) {
4574c79bfdaSSepherosa Ziehau 			sc->sc_senstask = sensor_task_register2(sc,
4584c79bfdaSSepherosa Ziehau 			    coretemp_pkg_sensor_task, 2, sc->sc_cpu);
4594c79bfdaSSepherosa Ziehau 		} else {
460c000328cSSepherosa Ziehau 			KASSERT(sc->sc_sens != NULL, ("no sensors"));
4614c79bfdaSSepherosa Ziehau 			sc->sc_senstask = sensor_task_register2(sc,
4624c79bfdaSSepherosa Ziehau 			    coretemp_sensor_task, 2, sc->sc_cpu);
4634c79bfdaSSepherosa Ziehau 		}
464c000328cSSepherosa Ziehau 	}
4653a514b87SHasso Tepper 
4663a514b87SHasso Tepper 	return (0);
4673a514b87SHasso Tepper }
4683a514b87SHasso Tepper 
4693a514b87SHasso Tepper static int
coretemp_detach(device_t dev)4703a514b87SHasso Tepper coretemp_detach(device_t dev)
4713a514b87SHasso Tepper {
4723a514b87SHasso Tepper 	struct coretemp_softc *sc = device_get_softc(dev);
473c000328cSSepherosa Ziehau 	struct coretemp_sensor *csens;
474c000328cSSepherosa Ziehau 
475c000328cSSepherosa Ziehau 	if (sc->sc_senstask != NULL)
476c000328cSSepherosa Ziehau 		sensor_task_unregister2(sc->sc_senstask);
4773a514b87SHasso Tepper 
478056f320bSSepherosa Ziehau 	if (sc->sc_nsens > 0) {
479056f320bSSepherosa Ziehau 		int i;
4803a514b87SHasso Tepper 
481c000328cSSepherosa Ziehau 		for (i = 0; i < sc->sc_nsens; ++i) {
482c000328cSSepherosa Ziehau 			csens = &sc->sc_sens[i];
483c000328cSSepherosa Ziehau 			if (csens->c_sensdev == NULL)
484c000328cSSepherosa Ziehau 				continue;
485c000328cSSepherosa Ziehau 			sensor_detach(csens->c_sensdev, &csens->c_sens);
486c000328cSSepherosa Ziehau 		}
487056f320bSSepherosa Ziehau 		kfree(sc->sc_sens, M_DEVBUF);
488c000328cSSepherosa Ziehau 	}
48985843744SSepherosa Ziehau 
49085843744SSepherosa Ziehau 	if (sc->sc_pkg_sens != NULL) {
491c000328cSSepherosa Ziehau 		csens = sc->sc_pkg_sens;
492c000328cSSepherosa Ziehau 		sensordev_deinstall(csens->c_sensdev);
493c000328cSSepherosa Ziehau 		kfree(csens->c_sensdev, M_DEVBUF);
494c000328cSSepherosa Ziehau 		kfree(csens, M_DEVBUF);
495056f320bSSepherosa Ziehau 	}
4963a514b87SHasso Tepper 	return (0);
4973a514b87SHasso Tepper }
4983a514b87SHasso Tepper 
49985843744SSepherosa Ziehau static int
coretemp_msr_temp(struct coretemp_softc * sc,uint64_t msr)50085843744SSepherosa Ziehau coretemp_msr_temp(struct coretemp_softc *sc, uint64_t msr)
50185843744SSepherosa Ziehau {
50285843744SSepherosa Ziehau 	int temp;
5033a514b87SHasso Tepper 
5043a514b87SHasso Tepper 	/*
5053a514b87SHasso Tepper 	 * Check for Thermal Status and Thermal Status Log.
5063a514b87SHasso Tepper 	 */
507680d36f5SSepherosa Ziehau 	if (MSR_THERM_STATUS_HAS_STATUS(msr))
50885843744SSepherosa Ziehau 		device_printf(sc->sc_dev, "PROCHOT asserted\n");
5093a514b87SHasso Tepper 
510680d36f5SSepherosa Ziehau 	if (msr & MSR_THERM_STATUS_READ_VALID)
511680d36f5SSepherosa Ziehau 		temp = sc->sc_tjmax - __SHIFTOUT(msr, MSR_THERM_STATUS_READ);
512680d36f5SSepherosa Ziehau 	else
51385843744SSepherosa Ziehau 		temp = CORETEMP_TEMP_INVALID;
5143a514b87SHasso Tepper 
5153a514b87SHasso Tepper 	/*
5163a514b87SHasso Tepper 	 * Check for Critical Temperature Status and Critical
5173a514b87SHasso Tepper 	 * Temperature Log.
5183a514b87SHasso Tepper 	 * It doesn't really matter if the current temperature is
5193a514b87SHasso Tepper 	 * invalid because the "Critical Temperature Log" bit will
5203a514b87SHasso Tepper 	 * tell us if the Critical Temperature has been reached in
5213a514b87SHasso Tepper 	 * past. It's not directly related to the current temperature.
5223a514b87SHasso Tepper 	 *
5233a514b87SHasso Tepper 	 * If we reach a critical level, allow devctl(4) to catch this
5243a514b87SHasso Tepper 	 * and shutdown the system.
5253a514b87SHasso Tepper 	 */
526680d36f5SSepherosa Ziehau 	if (MSR_THERM_STATUS_IS_CRITICAL(msr)) {
52718df9562SSepherosa Ziehau 		if ((sc->sc_flags & CORETEMP_FLAG_CRIT) == 0) {
5283f8829e8SSepherosa Ziehau 			char stemp[16], data[64];
52918df9562SSepherosa Ziehau 
53085843744SSepherosa Ziehau 			device_printf(sc->sc_dev,
53185843744SSepherosa Ziehau 			    "critical temperature detected, "
5323a514b87SHasso Tepper 			    "suggest system shutdown\n");
5333a514b87SHasso Tepper 			ksnprintf(stemp, sizeof(stemp), "%d", temp);
5343f8829e8SSepherosa Ziehau 			ksnprintf(data, sizeof(data),
5353f8829e8SSepherosa Ziehau 			    "notify=0xcc node=%d core=%d",
5363f8829e8SSepherosa Ziehau 			    get_chip_ID(sc->sc_cpu),
5373f8829e8SSepherosa Ziehau 			    get_core_number_within_chip(sc->sc_cpu));
5383f8829e8SSepherosa Ziehau 			devctl_notify("coretemp", "Thermal", stemp, data);
5394c79bfdaSSepherosa Ziehau 			sc->sc_flags |= CORETEMP_FLAG_CRIT;
54018df9562SSepherosa Ziehau 		}
54118df9562SSepherosa Ziehau 	} else if (sc->sc_flags & CORETEMP_FLAG_CRIT) {
5424c79bfdaSSepherosa Ziehau 		sc->sc_flags &= ~CORETEMP_FLAG_CRIT;
5433a514b87SHasso Tepper 	}
5443a514b87SHasso Tepper 
54585843744SSepherosa Ziehau 	return temp;
546ce72fc09SSepherosa Ziehau }
547ce72fc09SSepherosa Ziehau 
54885843744SSepherosa Ziehau static int
coretemp_pkg_msr_temp(struct coretemp_softc * sc,uint64_t msr)54985843744SSepherosa Ziehau coretemp_pkg_msr_temp(struct coretemp_softc *sc, uint64_t msr)
55085843744SSepherosa Ziehau {
55185843744SSepherosa Ziehau 	int temp;
55285843744SSepherosa Ziehau 
55385843744SSepherosa Ziehau 	/*
55485843744SSepherosa Ziehau 	 * Check for Thermal Status and Thermal Status Log.
55585843744SSepherosa Ziehau 	 */
55685843744SSepherosa Ziehau 	if (MSR_PKGTM_STATUS_HAS_STATUS(msr))
55785843744SSepherosa Ziehau 		device_printf(sc->sc_dev, "package PROCHOT asserted\n");
55885843744SSepherosa Ziehau 
55985843744SSepherosa Ziehau 	temp = sc->sc_tjmax - __SHIFTOUT(msr, MSR_PKGTM_STATUS_READ);
56085843744SSepherosa Ziehau 
56185843744SSepherosa Ziehau 	/*
56285843744SSepherosa Ziehau 	 * Check for Critical Temperature Status and Critical
56385843744SSepherosa Ziehau 	 * Temperature Log.
56485843744SSepherosa Ziehau 	 * It doesn't really matter if the current temperature is
56585843744SSepherosa Ziehau 	 * invalid because the "Critical Temperature Log" bit will
56685843744SSepherosa Ziehau 	 * tell us if the Critical Temperature has been reached in
56785843744SSepherosa Ziehau 	 * past. It's not directly related to the current temperature.
56885843744SSepherosa Ziehau 	 *
56985843744SSepherosa Ziehau 	 * If we reach a critical level, allow devctl(4) to catch this
57085843744SSepherosa Ziehau 	 * and shutdown the system.
57185843744SSepherosa Ziehau 	 */
57285843744SSepherosa Ziehau 	if (MSR_PKGTM_STATUS_IS_CRITICAL(msr)) {
57385843744SSepherosa Ziehau 		if ((sc->sc_flags & CORETEMP_FLAG_PKGCRIT) == 0) {
5743f8829e8SSepherosa Ziehau 			char stemp[16], data[64];
57585843744SSepherosa Ziehau 
57685843744SSepherosa Ziehau 			device_printf(sc->sc_dev,
57785843744SSepherosa Ziehau 			    "critical temperature detected, "
57885843744SSepherosa Ziehau 			    "suggest system shutdown\n");
57985843744SSepherosa Ziehau 			ksnprintf(stemp, sizeof(stemp), "%d", temp);
5803f8829e8SSepherosa Ziehau 			ksnprintf(data, sizeof(data), "notify=0xcc node=%d",
5813f8829e8SSepherosa Ziehau 			    get_chip_ID(sc->sc_cpu));
5823f8829e8SSepherosa Ziehau 			devctl_notify("coretemp", "Thermal", stemp, data);
5834c79bfdaSSepherosa Ziehau 			sc->sc_flags |= CORETEMP_FLAG_PKGCRIT;
58485843744SSepherosa Ziehau 		}
58585843744SSepherosa Ziehau 	} else if (sc->sc_flags & CORETEMP_FLAG_PKGCRIT) {
5864c79bfdaSSepherosa Ziehau 		sc->sc_flags &= ~CORETEMP_FLAG_PKGCRIT;
58785843744SSepherosa Ziehau 	}
58885843744SSepherosa Ziehau 
58985843744SSepherosa Ziehau 	return temp;
59085843744SSepherosa Ziehau }
59185843744SSepherosa Ziehau 
5924c79bfdaSSepherosa Ziehau static void
coretemp_msr_fetch(struct coretemp_softc * sc,uint64_t * msr,uint64_t * pkg_msr)59385843744SSepherosa Ziehau coretemp_msr_fetch(struct coretemp_softc *sc, uint64_t *msr, uint64_t *pkg_msr)
59485843744SSepherosa Ziehau {
5954c79bfdaSSepherosa Ziehau 	KASSERT(sc->sc_cpu == mycpuid,
5964c79bfdaSSepherosa Ziehau 	    ("%s not on the target cpu%d, but on %d",
5974c79bfdaSSepherosa Ziehau 	     device_get_name(sc->sc_dev), sc->sc_cpu, mycpuid));
5984c79bfdaSSepherosa Ziehau 
59985843744SSepherosa Ziehau 	*msr = rdmsr(MSR_THERM_STATUS);
60085843744SSepherosa Ziehau 	if (pkg_msr != NULL)
60185843744SSepherosa Ziehau 		*pkg_msr = rdmsr(MSR_PKG_THERM_STATUS);
60285843744SSepherosa Ziehau }
6033a514b87SHasso Tepper 
6043a514b87SHasso Tepper static void
coretemp_sensor_update(struct coretemp_softc * sc,int temp)60585843744SSepherosa Ziehau coretemp_sensor_update(struct coretemp_softc *sc, int temp)
6063a514b87SHasso Tepper {
607c000328cSSepherosa Ziehau 	struct coretemp_sensor *csens;
60885843744SSepherosa Ziehau 	int i;
6093a514b87SHasso Tepper 
610c000328cSSepherosa Ziehau 	if (sc->sc_sens == NULL)
611c000328cSSepherosa Ziehau 		return;
612c000328cSSepherosa Ziehau 
6134c79bfdaSSepherosa Ziehau 	if (temp == CORETEMP_TEMP_INVALID) {
614c000328cSSepherosa Ziehau 		for (i = 0; i < sc->sc_nsens; ++i) {
615c000328cSSepherosa Ziehau 			csens = &sc->sc_sens[i];
616c000328cSSepherosa Ziehau 			if (csens->c_sensdev == NULL)
617c000328cSSepherosa Ziehau 				continue;
618c000328cSSepherosa Ziehau 			sensor_set_invalid(&csens->c_sens);
619c000328cSSepherosa Ziehau 		}
6203a514b87SHasso Tepper 	} else {
621056f320bSSepherosa Ziehau 		for (i = 0; i < sc->sc_nsens; ++i) {
622c000328cSSepherosa Ziehau 			csens = &sc->sc_sens[i];
623c000328cSSepherosa Ziehau 			if (csens->c_sensdev == NULL)
624c000328cSSepherosa Ziehau 				continue;
625c000328cSSepherosa Ziehau 			coretemp_sensor_set(&csens->c_sens, sc,
62685843744SSepherosa Ziehau 			    CORETEMP_FLAG_CRIT, temp);
62785843744SSepherosa Ziehau 		}
62885843744SSepherosa Ziehau 	}
62985843744SSepherosa Ziehau }
63085843744SSepherosa Ziehau 
63185843744SSepherosa Ziehau static void
coretemp_pkg_sensor_update(struct coretemp_softc * sc,int temp)63285843744SSepherosa Ziehau coretemp_pkg_sensor_update(struct coretemp_softc *sc, int temp)
63385843744SSepherosa Ziehau {
63485843744SSepherosa Ziehau 	KKASSERT(sc->sc_pkg_sens != NULL);
6354c79bfdaSSepherosa Ziehau 	if (temp == CORETEMP_TEMP_INVALID) {
6367273d7b8SSepherosa Ziehau 		sensor_set_invalid(&sc->sc_pkg_sens->c_sens);
63785843744SSepherosa Ziehau 	} else {
63885843744SSepherosa Ziehau 		coretemp_sensor_set(&sc->sc_pkg_sens->c_sens, sc,
63985843744SSepherosa Ziehau 		    CORETEMP_FLAG_PKGCRIT, temp);
64085843744SSepherosa Ziehau 	}
64185843744SSepherosa Ziehau }
64285843744SSepherosa Ziehau 
64385843744SSepherosa Ziehau static void
coretemp_sensor_task(void * arg)64485843744SSepherosa Ziehau coretemp_sensor_task(void *arg)
64585843744SSepherosa Ziehau {
64685843744SSepherosa Ziehau 	struct coretemp_softc *sc = arg;
64785843744SSepherosa Ziehau 	uint64_t msr;
64885843744SSepherosa Ziehau 	int temp;
64985843744SSepherosa Ziehau 
6504c79bfdaSSepherosa Ziehau 	coretemp_msr_fetch(sc, &msr, NULL);
65185843744SSepherosa Ziehau 	temp = coretemp_msr_temp(sc, msr);
65285843744SSepherosa Ziehau 
65385843744SSepherosa Ziehau 	coretemp_sensor_update(sc, temp);
654056f320bSSepherosa Ziehau }
65585843744SSepherosa Ziehau 
65685843744SSepherosa Ziehau static void
coretemp_pkg_sensor_task(void * arg)65785843744SSepherosa Ziehau coretemp_pkg_sensor_task(void *arg)
65885843744SSepherosa Ziehau {
65985843744SSepherosa Ziehau 	struct coretemp_softc *sc = arg;
66085843744SSepherosa Ziehau 	uint64_t msr, pkg_msr;
66185843744SSepherosa Ziehau 	int temp, pkg_temp;
66285843744SSepherosa Ziehau 
6634c79bfdaSSepherosa Ziehau 	coretemp_msr_fetch(sc, &msr, &pkg_msr);
66485843744SSepherosa Ziehau 	temp = coretemp_msr_temp(sc, msr);
66585843744SSepherosa Ziehau 	pkg_temp = coretemp_pkg_msr_temp(sc, pkg_msr);
66685843744SSepherosa Ziehau 
66785843744SSepherosa Ziehau 	coretemp_sensor_update(sc, temp);
66885843744SSepherosa Ziehau 	coretemp_pkg_sensor_update(sc, pkg_temp);
6693a514b87SHasso Tepper }
670