xref: /linux/drivers/thermal/intel/therm_throt.c (revision 1ac731c529cd4d6adbce134754b51ff7d822b145)
19223d0dcSBorislav Petkov // SPDX-License-Identifier: GPL-2.0-only
29223d0dcSBorislav Petkov /*
39223d0dcSBorislav Petkov  * Thermal throttle event support code (such as syslog messaging and rate
49223d0dcSBorislav Petkov  * limiting) that was factored out from x86_64 (mce_intel.c) and i386 (p4.c).
59223d0dcSBorislav Petkov  *
69223d0dcSBorislav Petkov  * This allows consistent reporting of CPU thermal throttle events.
79223d0dcSBorislav Petkov  *
89223d0dcSBorislav Petkov  * Maintains a counter in /sys that keeps track of the number of thermal
99223d0dcSBorislav Petkov  * events, such that the user knows how bad the thermal problem might be
109223d0dcSBorislav Petkov  * (since the logging to syslog is rate limited).
119223d0dcSBorislav Petkov  *
129223d0dcSBorislav Petkov  * Author: Dmitriy Zavin (dmitriyz@google.com)
139223d0dcSBorislav Petkov  *
149223d0dcSBorislav Petkov  * Credits: Adapted from Zwane Mwaikambo's original code in mce_intel.c.
159223d0dcSBorislav Petkov  *          Inspired by Ross Biro's and Al Borchers' counter code.
169223d0dcSBorislav Petkov  */
179223d0dcSBorislav Petkov #include <linux/interrupt.h>
189223d0dcSBorislav Petkov #include <linux/notifier.h>
199223d0dcSBorislav Petkov #include <linux/jiffies.h>
209223d0dcSBorislav Petkov #include <linux/kernel.h>
219223d0dcSBorislav Petkov #include <linux/percpu.h>
229223d0dcSBorislav Petkov #include <linux/export.h>
239223d0dcSBorislav Petkov #include <linux/types.h>
249223d0dcSBorislav Petkov #include <linux/init.h>
259223d0dcSBorislav Petkov #include <linux/smp.h>
269223d0dcSBorislav Petkov #include <linux/cpu.h>
279223d0dcSBorislav Petkov 
289223d0dcSBorislav Petkov #include <asm/processor.h>
299223d0dcSBorislav Petkov #include <asm/thermal.h>
309223d0dcSBorislav Petkov #include <asm/traps.h>
319223d0dcSBorislav Petkov #include <asm/apic.h>
329223d0dcSBorislav Petkov #include <asm/irq.h>
339223d0dcSBorislav Petkov #include <asm/msr.h>
349223d0dcSBorislav Petkov 
351cb19cabSRicardo Neri #include "intel_hfi.h"
369223d0dcSBorislav Petkov #include "thermal_interrupt.h"
379223d0dcSBorislav Petkov 
389223d0dcSBorislav Petkov /* How long to wait between reporting thermal events */
399223d0dcSBorislav Petkov #define CHECK_INTERVAL		(300 * HZ)
409223d0dcSBorislav Petkov 
419223d0dcSBorislav Petkov #define THERMAL_THROTTLING_EVENT	0
429223d0dcSBorislav Petkov #define POWER_LIMIT_EVENT		1
439223d0dcSBorislav Petkov 
449223d0dcSBorislav Petkov /**
459223d0dcSBorislav Petkov  * struct _thermal_state - Represent the current thermal event state
469223d0dcSBorislav Petkov  * @next_check:			Stores the next timestamp, when it is allowed
479223d0dcSBorislav Petkov  *				to log the next warning message.
489223d0dcSBorislav Petkov  * @last_interrupt_time:	Stores the timestamp for the last threshold
499223d0dcSBorislav Petkov  *				high event.
509223d0dcSBorislav Petkov  * @therm_work:			Delayed workqueue structure
519223d0dcSBorislav Petkov  * @count:			Stores the current running count for thermal
529223d0dcSBorislav Petkov  *				or power threshold interrupts.
539223d0dcSBorislav Petkov  * @last_count:			Stores the previous running count for thermal
549223d0dcSBorislav Petkov  *				or power threshold interrupts.
559223d0dcSBorislav Petkov  * @max_time_ms:		This shows the maximum amount of time CPU was
569223d0dcSBorislav Petkov  *				in throttled state for a single thermal
579223d0dcSBorislav Petkov  *				threshold high to low state.
589223d0dcSBorislav Petkov  * @total_time_ms:		This is a cumulative time during which CPU was
599223d0dcSBorislav Petkov  *				in the throttled state.
609223d0dcSBorislav Petkov  * @rate_control_active:	Set when a throttling message is logged.
619223d0dcSBorislav Petkov  *				This is used for the purpose of rate-control.
629223d0dcSBorislav Petkov  * @new_event:			Stores the last high/low status of the
639223d0dcSBorislav Petkov  *				THERM_STATUS_PROCHOT or
649223d0dcSBorislav Petkov  *				THERM_STATUS_POWER_LIMIT.
659223d0dcSBorislav Petkov  * @level:			Stores whether this _thermal_state instance is
669223d0dcSBorislav Petkov  *				for a CORE level or for PACKAGE level.
679223d0dcSBorislav Petkov  * @sample_index:		Index for storing the next sample in the buffer
689223d0dcSBorislav Petkov  *				temp_samples[].
699223d0dcSBorislav Petkov  * @sample_count:		Total number of samples collected in the buffer
709223d0dcSBorislav Petkov  *				temp_samples[].
719223d0dcSBorislav Petkov  * @average:			The last moving average of temperature samples
729223d0dcSBorislav Petkov  * @baseline_temp:		Temperature at which thermal threshold high
739223d0dcSBorislav Petkov  *				interrupt was generated.
749223d0dcSBorislav Petkov  * @temp_samples:		Storage for temperature samples to calculate
759223d0dcSBorislav Petkov  *				moving average.
769223d0dcSBorislav Petkov  *
779223d0dcSBorislav Petkov  * This structure is used to represent data related to thermal state for a CPU.
789223d0dcSBorislav Petkov  * There is a separate storage for core and package level for each CPU.
799223d0dcSBorislav Petkov  */
809223d0dcSBorislav Petkov struct _thermal_state {
819223d0dcSBorislav Petkov 	u64			next_check;
829223d0dcSBorislav Petkov 	u64			last_interrupt_time;
839223d0dcSBorislav Petkov 	struct delayed_work	therm_work;
849223d0dcSBorislav Petkov 	unsigned long		count;
859223d0dcSBorislav Petkov 	unsigned long		last_count;
869223d0dcSBorislav Petkov 	unsigned long		max_time_ms;
879223d0dcSBorislav Petkov 	unsigned long		total_time_ms;
889223d0dcSBorislav Petkov 	bool			rate_control_active;
899223d0dcSBorislav Petkov 	bool			new_event;
909223d0dcSBorislav Petkov 	u8			level;
919223d0dcSBorislav Petkov 	u8			sample_index;
929223d0dcSBorislav Petkov 	u8			sample_count;
939223d0dcSBorislav Petkov 	u8			average;
949223d0dcSBorislav Petkov 	u8			baseline_temp;
959223d0dcSBorislav Petkov 	u8			temp_samples[3];
969223d0dcSBorislav Petkov };
979223d0dcSBorislav Petkov 
989223d0dcSBorislav Petkov struct thermal_state {
999223d0dcSBorislav Petkov 	struct _thermal_state core_throttle;
1009223d0dcSBorislav Petkov 	struct _thermal_state core_power_limit;
1019223d0dcSBorislav Petkov 	struct _thermal_state package_throttle;
1029223d0dcSBorislav Petkov 	struct _thermal_state package_power_limit;
1039223d0dcSBorislav Petkov 	struct _thermal_state core_thresh0;
1049223d0dcSBorislav Petkov 	struct _thermal_state core_thresh1;
1059223d0dcSBorislav Petkov 	struct _thermal_state pkg_thresh0;
1069223d0dcSBorislav Petkov 	struct _thermal_state pkg_thresh1;
1079223d0dcSBorislav Petkov };
1089223d0dcSBorislav Petkov 
1099223d0dcSBorislav Petkov /* Callback to handle core threshold interrupts */
1109223d0dcSBorislav Petkov int (*platform_thermal_notify)(__u64 msr_val);
1119223d0dcSBorislav Petkov EXPORT_SYMBOL(platform_thermal_notify);
1129223d0dcSBorislav Petkov 
1139223d0dcSBorislav Petkov /* Callback to handle core package threshold_interrupts */
1149223d0dcSBorislav Petkov int (*platform_thermal_package_notify)(__u64 msr_val);
1159223d0dcSBorislav Petkov EXPORT_SYMBOL_GPL(platform_thermal_package_notify);
1169223d0dcSBorislav Petkov 
1179223d0dcSBorislav Petkov /* Callback support of rate control, return true, if
1189223d0dcSBorislav Petkov  * callback has rate control */
1199223d0dcSBorislav Petkov bool (*platform_thermal_package_rate_control)(void);
1209223d0dcSBorislav Petkov EXPORT_SYMBOL_GPL(platform_thermal_package_rate_control);
1219223d0dcSBorislav Petkov 
1229223d0dcSBorislav Petkov 
1239223d0dcSBorislav Petkov static DEFINE_PER_CPU(struct thermal_state, thermal_state);
1249223d0dcSBorislav Petkov 
1259223d0dcSBorislav Petkov static atomic_t therm_throt_en	= ATOMIC_INIT(0);
1269223d0dcSBorislav Petkov 
1279223d0dcSBorislav Petkov static u32 lvtthmr_init __read_mostly;
1289223d0dcSBorislav Petkov 
1299223d0dcSBorislav Petkov #ifdef CONFIG_SYSFS
1309223d0dcSBorislav Petkov #define define_therm_throt_device_one_ro(_name)				\
1319223d0dcSBorislav Petkov 	static DEVICE_ATTR(_name, 0444,					\
1329223d0dcSBorislav Petkov 			   therm_throt_device_show_##_name,		\
1339223d0dcSBorislav Petkov 				   NULL)				\
1349223d0dcSBorislav Petkov 
1359223d0dcSBorislav Petkov #define define_therm_throt_device_show_func(event, name)		\
1369223d0dcSBorislav Petkov 									\
1379223d0dcSBorislav Petkov static ssize_t therm_throt_device_show_##event##_##name(		\
1389223d0dcSBorislav Petkov 			struct device *dev,				\
1399223d0dcSBorislav Petkov 			struct device_attribute *attr,			\
1409223d0dcSBorislav Petkov 			char *buf)					\
1419223d0dcSBorislav Petkov {									\
1429223d0dcSBorislav Petkov 	unsigned int cpu = dev->id;					\
1439223d0dcSBorislav Petkov 	ssize_t ret;							\
1449223d0dcSBorislav Petkov 									\
1459223d0dcSBorislav Petkov 	preempt_disable();	/* CPU hotplug */			\
1469223d0dcSBorislav Petkov 	if (cpu_online(cpu)) {						\
1479223d0dcSBorislav Petkov 		ret = sprintf(buf, "%lu\n",				\
1489223d0dcSBorislav Petkov 			      per_cpu(thermal_state, cpu).event.name);	\
1499223d0dcSBorislav Petkov 	} else								\
1509223d0dcSBorislav Petkov 		ret = 0;						\
1519223d0dcSBorislav Petkov 	preempt_enable();						\
1529223d0dcSBorislav Petkov 									\
1539223d0dcSBorislav Petkov 	return ret;							\
1549223d0dcSBorislav Petkov }
1559223d0dcSBorislav Petkov 
1569223d0dcSBorislav Petkov define_therm_throt_device_show_func(core_throttle, count);
1579223d0dcSBorislav Petkov define_therm_throt_device_one_ro(core_throttle_count);
1589223d0dcSBorislav Petkov 
1599223d0dcSBorislav Petkov define_therm_throt_device_show_func(core_power_limit, count);
1609223d0dcSBorislav Petkov define_therm_throt_device_one_ro(core_power_limit_count);
1619223d0dcSBorislav Petkov 
1629223d0dcSBorislav Petkov define_therm_throt_device_show_func(package_throttle, count);
1639223d0dcSBorislav Petkov define_therm_throt_device_one_ro(package_throttle_count);
1649223d0dcSBorislav Petkov 
1659223d0dcSBorislav Petkov define_therm_throt_device_show_func(package_power_limit, count);
1669223d0dcSBorislav Petkov define_therm_throt_device_one_ro(package_power_limit_count);
1679223d0dcSBorislav Petkov 
1689223d0dcSBorislav Petkov define_therm_throt_device_show_func(core_throttle, max_time_ms);
1699223d0dcSBorislav Petkov define_therm_throt_device_one_ro(core_throttle_max_time_ms);
1709223d0dcSBorislav Petkov 
1719223d0dcSBorislav Petkov define_therm_throt_device_show_func(package_throttle, max_time_ms);
1729223d0dcSBorislav Petkov define_therm_throt_device_one_ro(package_throttle_max_time_ms);
1739223d0dcSBorislav Petkov 
1749223d0dcSBorislav Petkov define_therm_throt_device_show_func(core_throttle, total_time_ms);
1759223d0dcSBorislav Petkov define_therm_throt_device_one_ro(core_throttle_total_time_ms);
1769223d0dcSBorislav Petkov 
1779223d0dcSBorislav Petkov define_therm_throt_device_show_func(package_throttle, total_time_ms);
1789223d0dcSBorislav Petkov define_therm_throt_device_one_ro(package_throttle_total_time_ms);
1799223d0dcSBorislav Petkov 
1809223d0dcSBorislav Petkov static struct attribute *thermal_throttle_attrs[] = {
1819223d0dcSBorislav Petkov 	&dev_attr_core_throttle_count.attr,
1829223d0dcSBorislav Petkov 	&dev_attr_core_throttle_max_time_ms.attr,
1839223d0dcSBorislav Petkov 	&dev_attr_core_throttle_total_time_ms.attr,
1849223d0dcSBorislav Petkov 	NULL
1859223d0dcSBorislav Petkov };
1869223d0dcSBorislav Petkov 
1879223d0dcSBorislav Petkov static const struct attribute_group thermal_attr_group = {
1889223d0dcSBorislav Petkov 	.attrs	= thermal_throttle_attrs,
1899223d0dcSBorislav Petkov 	.name	= "thermal_throttle"
1909223d0dcSBorislav Petkov };
1919223d0dcSBorislav Petkov #endif /* CONFIG_SYSFS */
1929223d0dcSBorislav Petkov 
1939223d0dcSBorislav Petkov #define THERM_THROT_POLL_INTERVAL	HZ
1949223d0dcSBorislav Petkov #define THERM_STATUS_PROCHOT_LOG	BIT(1)
1959223d0dcSBorislav Petkov 
196*117e4e5bSSrinivas Pandruvada static u64 therm_intr_core_clear_mask;
197*117e4e5bSSrinivas Pandruvada static u64 therm_intr_pkg_clear_mask;
198*117e4e5bSSrinivas Pandruvada 
thermal_intr_init_core_clear_mask(void)199*117e4e5bSSrinivas Pandruvada static void thermal_intr_init_core_clear_mask(void)
200*117e4e5bSSrinivas Pandruvada {
201*117e4e5bSSrinivas Pandruvada 	if (therm_intr_core_clear_mask)
202*117e4e5bSSrinivas Pandruvada 		return;
203*117e4e5bSSrinivas Pandruvada 
204*117e4e5bSSrinivas Pandruvada 	/*
205*117e4e5bSSrinivas Pandruvada 	 * Reference: Intel SDM  Volume 4
206*117e4e5bSSrinivas Pandruvada 	 * "Table 2-2. IA-32 Architectural MSRs", MSR 0x19C
207*117e4e5bSSrinivas Pandruvada 	 * IA32_THERM_STATUS.
208*117e4e5bSSrinivas Pandruvada 	 */
209*117e4e5bSSrinivas Pandruvada 
210*117e4e5bSSrinivas Pandruvada 	/*
211*117e4e5bSSrinivas Pandruvada 	 * Bit 1, 3, 5: CPUID.01H:EDX[22] = 1. This driver will not
212*117e4e5bSSrinivas Pandruvada 	 * enable interrupts, when 0 as it checks for X86_FEATURE_ACPI.
213*117e4e5bSSrinivas Pandruvada 	 */
214*117e4e5bSSrinivas Pandruvada 	therm_intr_core_clear_mask = (BIT(1) | BIT(3) | BIT(5));
215*117e4e5bSSrinivas Pandruvada 
216*117e4e5bSSrinivas Pandruvada 	/*
217*117e4e5bSSrinivas Pandruvada 	 * Bit 7 and 9: Thermal Threshold #1 and #2 log
218*117e4e5bSSrinivas Pandruvada 	 * If CPUID.01H:ECX[8] = 1
219*117e4e5bSSrinivas Pandruvada 	 */
220*117e4e5bSSrinivas Pandruvada 	if (boot_cpu_has(X86_FEATURE_TM2))
221*117e4e5bSSrinivas Pandruvada 		therm_intr_core_clear_mask |= (BIT(7) | BIT(9));
222*117e4e5bSSrinivas Pandruvada 
223*117e4e5bSSrinivas Pandruvada 	/* Bit 11: Power Limitation log (R/WC0) If CPUID.06H:EAX[4] = 1 */
224*117e4e5bSSrinivas Pandruvada 	if (boot_cpu_has(X86_FEATURE_PLN))
225*117e4e5bSSrinivas Pandruvada 		therm_intr_core_clear_mask |= BIT(11);
226*117e4e5bSSrinivas Pandruvada 
227*117e4e5bSSrinivas Pandruvada 	/*
228*117e4e5bSSrinivas Pandruvada 	 * Bit 13: Current Limit log (R/WC0) If CPUID.06H:EAX[7] = 1
229*117e4e5bSSrinivas Pandruvada 	 * Bit 15: Cross Domain Limit log (R/WC0) If CPUID.06H:EAX[7] = 1
230*117e4e5bSSrinivas Pandruvada 	 */
231*117e4e5bSSrinivas Pandruvada 	if (boot_cpu_has(X86_FEATURE_HWP))
232*117e4e5bSSrinivas Pandruvada 		therm_intr_core_clear_mask |= (BIT(13) | BIT(15));
233*117e4e5bSSrinivas Pandruvada }
234*117e4e5bSSrinivas Pandruvada 
thermal_intr_init_pkg_clear_mask(void)235*117e4e5bSSrinivas Pandruvada static void thermal_intr_init_pkg_clear_mask(void)
236*117e4e5bSSrinivas Pandruvada {
237*117e4e5bSSrinivas Pandruvada 	if (therm_intr_pkg_clear_mask)
238*117e4e5bSSrinivas Pandruvada 		return;
239*117e4e5bSSrinivas Pandruvada 
240*117e4e5bSSrinivas Pandruvada 	/*
241*117e4e5bSSrinivas Pandruvada 	 * Reference: Intel SDM  Volume 4
242*117e4e5bSSrinivas Pandruvada 	 * "Table 2-2. IA-32 Architectural MSRs", MSR 0x1B1
243*117e4e5bSSrinivas Pandruvada 	 * IA32_PACKAGE_THERM_STATUS.
244*117e4e5bSSrinivas Pandruvada 	 */
245*117e4e5bSSrinivas Pandruvada 
246*117e4e5bSSrinivas Pandruvada 	/* All bits except BIT 26 depend on CPUID.06H: EAX[6] = 1 */
247*117e4e5bSSrinivas Pandruvada 	if (boot_cpu_has(X86_FEATURE_PTS))
248*117e4e5bSSrinivas Pandruvada 		therm_intr_pkg_clear_mask = (BIT(1) | BIT(3) | BIT(5) | BIT(7) | BIT(9) | BIT(11));
249*117e4e5bSSrinivas Pandruvada 
250*117e4e5bSSrinivas Pandruvada 	/*
251*117e4e5bSSrinivas Pandruvada 	 * Intel SDM Volume 2A: Thermal and Power Management Leaf
252*117e4e5bSSrinivas Pandruvada 	 * Bit 26: CPUID.06H: EAX[19] = 1
253*117e4e5bSSrinivas Pandruvada 	 */
254*117e4e5bSSrinivas Pandruvada 	if (boot_cpu_has(X86_FEATURE_HFI))
255*117e4e5bSSrinivas Pandruvada 		therm_intr_pkg_clear_mask |= BIT(26);
256*117e4e5bSSrinivas Pandruvada }
2579223d0dcSBorislav Petkov 
258930d06bfSSrinivas Pandruvada /*
259930d06bfSSrinivas Pandruvada  * Clear the bits in package thermal status register for bit = 1
260930d06bfSSrinivas Pandruvada  * in bitmask
261930d06bfSSrinivas Pandruvada  */
thermal_clear_package_intr_status(int level,u64 bit_mask)262930d06bfSSrinivas Pandruvada void thermal_clear_package_intr_status(int level, u64 bit_mask)
2639223d0dcSBorislav Petkov {
264930d06bfSSrinivas Pandruvada 	u64 msr_val;
2659223d0dcSBorislav Petkov 	int msr;
2669223d0dcSBorislav Petkov 
2679223d0dcSBorislav Petkov 	if (level == CORE_LEVEL) {
2689223d0dcSBorislav Petkov 		msr  = MSR_IA32_THERM_STATUS;
269*117e4e5bSSrinivas Pandruvada 		msr_val = therm_intr_core_clear_mask;
2709223d0dcSBorislav Petkov 	} else {
2719223d0dcSBorislav Petkov 		msr  = MSR_IA32_PACKAGE_THERM_STATUS;
272*117e4e5bSSrinivas Pandruvada 		msr_val = therm_intr_pkg_clear_mask;
2739223d0dcSBorislav Petkov 	}
2749223d0dcSBorislav Petkov 
275930d06bfSSrinivas Pandruvada 	msr_val &= ~bit_mask;
276930d06bfSSrinivas Pandruvada 	wrmsrl(msr, msr_val);
2779223d0dcSBorislav Petkov }
278930d06bfSSrinivas Pandruvada EXPORT_SYMBOL_GPL(thermal_clear_package_intr_status);
2799223d0dcSBorislav Petkov 
get_therm_status(int level,bool * proc_hot,u8 * temp)2809223d0dcSBorislav Petkov static void get_therm_status(int level, bool *proc_hot, u8 *temp)
2819223d0dcSBorislav Petkov {
2829223d0dcSBorislav Petkov 	int msr;
2839223d0dcSBorislav Petkov 	u64 msr_val;
2849223d0dcSBorislav Petkov 
2859223d0dcSBorislav Petkov 	if (level == CORE_LEVEL)
2869223d0dcSBorislav Petkov 		msr = MSR_IA32_THERM_STATUS;
2879223d0dcSBorislav Petkov 	else
2889223d0dcSBorislav Petkov 		msr = MSR_IA32_PACKAGE_THERM_STATUS;
2899223d0dcSBorislav Petkov 
2909223d0dcSBorislav Petkov 	rdmsrl(msr, msr_val);
2919223d0dcSBorislav Petkov 	if (msr_val & THERM_STATUS_PROCHOT_LOG)
2929223d0dcSBorislav Petkov 		*proc_hot = true;
2939223d0dcSBorislav Petkov 	else
2949223d0dcSBorislav Petkov 		*proc_hot = false;
2959223d0dcSBorislav Petkov 
2969223d0dcSBorislav Petkov 	*temp = (msr_val >> 16) & 0x7F;
2979223d0dcSBorislav Petkov }
2989223d0dcSBorislav Petkov 
throttle_active_work(struct work_struct * work)2999223d0dcSBorislav Petkov static void __maybe_unused throttle_active_work(struct work_struct *work)
3009223d0dcSBorislav Petkov {
3019223d0dcSBorislav Petkov 	struct _thermal_state *state = container_of(to_delayed_work(work),
3029223d0dcSBorislav Petkov 						struct _thermal_state, therm_work);
3039223d0dcSBorislav Petkov 	unsigned int i, avg, this_cpu = smp_processor_id();
3049223d0dcSBorislav Petkov 	u64 now = get_jiffies_64();
3059223d0dcSBorislav Petkov 	bool hot;
3069223d0dcSBorislav Petkov 	u8 temp;
3079223d0dcSBorislav Petkov 
3089223d0dcSBorislav Petkov 	get_therm_status(state->level, &hot, &temp);
3099223d0dcSBorislav Petkov 	/* temperature value is offset from the max so lesser means hotter */
3109223d0dcSBorislav Petkov 	if (!hot && temp > state->baseline_temp) {
3119223d0dcSBorislav Petkov 		if (state->rate_control_active)
3129223d0dcSBorislav Petkov 			pr_info("CPU%d: %s temperature/speed normal (total events = %lu)\n",
3139223d0dcSBorislav Petkov 				this_cpu,
3149223d0dcSBorislav Petkov 				state->level == CORE_LEVEL ? "Core" : "Package",
3159223d0dcSBorislav Petkov 				state->count);
3169223d0dcSBorislav Petkov 
3179223d0dcSBorislav Petkov 		state->rate_control_active = false;
3189223d0dcSBorislav Petkov 		return;
3199223d0dcSBorislav Petkov 	}
3209223d0dcSBorislav Petkov 
3219223d0dcSBorislav Petkov 	if (time_before64(now, state->next_check) &&
3229223d0dcSBorislav Petkov 			  state->rate_control_active)
3239223d0dcSBorislav Petkov 		goto re_arm;
3249223d0dcSBorislav Petkov 
3259223d0dcSBorislav Petkov 	state->next_check = now + CHECK_INTERVAL;
3269223d0dcSBorislav Petkov 
3279223d0dcSBorislav Petkov 	if (state->count != state->last_count) {
3289223d0dcSBorislav Petkov 		/* There was one new thermal interrupt */
3299223d0dcSBorislav Petkov 		state->last_count = state->count;
3309223d0dcSBorislav Petkov 		state->average = 0;
3319223d0dcSBorislav Petkov 		state->sample_count = 0;
3329223d0dcSBorislav Petkov 		state->sample_index = 0;
3339223d0dcSBorislav Petkov 	}
3349223d0dcSBorislav Petkov 
3359223d0dcSBorislav Petkov 	state->temp_samples[state->sample_index] = temp;
3369223d0dcSBorislav Petkov 	state->sample_count++;
3379223d0dcSBorislav Petkov 	state->sample_index = (state->sample_index + 1) % ARRAY_SIZE(state->temp_samples);
3389223d0dcSBorislav Petkov 	if (state->sample_count < ARRAY_SIZE(state->temp_samples))
3399223d0dcSBorislav Petkov 		goto re_arm;
3409223d0dcSBorislav Petkov 
3419223d0dcSBorislav Petkov 	avg = 0;
3429223d0dcSBorislav Petkov 	for (i = 0; i < ARRAY_SIZE(state->temp_samples); ++i)
3439223d0dcSBorislav Petkov 		avg += state->temp_samples[i];
3449223d0dcSBorislav Petkov 
3459223d0dcSBorislav Petkov 	avg /= ARRAY_SIZE(state->temp_samples);
3469223d0dcSBorislav Petkov 
3479223d0dcSBorislav Petkov 	if (state->average > avg) {
3489223d0dcSBorislav Petkov 		pr_warn("CPU%d: %s temperature is above threshold, cpu clock is throttled (total events = %lu)\n",
3499223d0dcSBorislav Petkov 			this_cpu,
3509223d0dcSBorislav Petkov 			state->level == CORE_LEVEL ? "Core" : "Package",
3519223d0dcSBorislav Petkov 			state->count);
3529223d0dcSBorislav Petkov 		state->rate_control_active = true;
3539223d0dcSBorislav Petkov 	}
3549223d0dcSBorislav Petkov 
3559223d0dcSBorislav Petkov 	state->average = avg;
3569223d0dcSBorislav Petkov 
3579223d0dcSBorislav Petkov re_arm:
358930d06bfSSrinivas Pandruvada 	thermal_clear_package_intr_status(state->level, THERM_STATUS_PROCHOT_LOG);
3599223d0dcSBorislav Petkov 	schedule_delayed_work_on(this_cpu, &state->therm_work, THERM_THROT_POLL_INTERVAL);
3609223d0dcSBorislav Petkov }
3619223d0dcSBorislav Petkov 
3629223d0dcSBorislav Petkov /***
3639223d0dcSBorislav Petkov  * therm_throt_process - Process thermal throttling event from interrupt
3649223d0dcSBorislav Petkov  * @curr: Whether the condition is current or not (boolean), since the
3659223d0dcSBorislav Petkov  *        thermal interrupt normally gets called both when the thermal
3669223d0dcSBorislav Petkov  *        event begins and once the event has ended.
3679223d0dcSBorislav Petkov  *
3689223d0dcSBorislav Petkov  * This function is called by the thermal interrupt after the
3699223d0dcSBorislav Petkov  * IRQ has been acknowledged.
3709223d0dcSBorislav Petkov  *
3719223d0dcSBorislav Petkov  * It will take care of rate limiting and printing messages to the syslog.
3729223d0dcSBorislav Petkov  */
therm_throt_process(bool new_event,int event,int level)3739223d0dcSBorislav Petkov static void therm_throt_process(bool new_event, int event, int level)
3749223d0dcSBorislav Petkov {
3759223d0dcSBorislav Petkov 	struct _thermal_state *state;
3769223d0dcSBorislav Petkov 	unsigned int this_cpu = smp_processor_id();
3779223d0dcSBorislav Petkov 	bool old_event;
3789223d0dcSBorislav Petkov 	u64 now;
3799223d0dcSBorislav Petkov 	struct thermal_state *pstate = &per_cpu(thermal_state, this_cpu);
3809223d0dcSBorislav Petkov 
3819223d0dcSBorislav Petkov 	now = get_jiffies_64();
3829223d0dcSBorislav Petkov 	if (level == CORE_LEVEL) {
3839223d0dcSBorislav Petkov 		if (event == THERMAL_THROTTLING_EVENT)
3849223d0dcSBorislav Petkov 			state = &pstate->core_throttle;
3859223d0dcSBorislav Petkov 		else if (event == POWER_LIMIT_EVENT)
3869223d0dcSBorislav Petkov 			state = &pstate->core_power_limit;
3879223d0dcSBorislav Petkov 		else
3889223d0dcSBorislav Petkov 			return;
3899223d0dcSBorislav Petkov 	} else if (level == PACKAGE_LEVEL) {
3909223d0dcSBorislav Petkov 		if (event == THERMAL_THROTTLING_EVENT)
3919223d0dcSBorislav Petkov 			state = &pstate->package_throttle;
3929223d0dcSBorislav Petkov 		else if (event == POWER_LIMIT_EVENT)
3939223d0dcSBorislav Petkov 			state = &pstate->package_power_limit;
3949223d0dcSBorislav Petkov 		else
3959223d0dcSBorislav Petkov 			return;
3969223d0dcSBorislav Petkov 	} else
3979223d0dcSBorislav Petkov 		return;
3989223d0dcSBorislav Petkov 
3999223d0dcSBorislav Petkov 	old_event = state->new_event;
4009223d0dcSBorislav Petkov 	state->new_event = new_event;
4019223d0dcSBorislav Petkov 
4029223d0dcSBorislav Petkov 	if (new_event)
4039223d0dcSBorislav Petkov 		state->count++;
4049223d0dcSBorislav Petkov 
4059223d0dcSBorislav Petkov 	if (event != THERMAL_THROTTLING_EVENT)
4069223d0dcSBorislav Petkov 		return;
4079223d0dcSBorislav Petkov 
4089223d0dcSBorislav Petkov 	if (new_event && !state->last_interrupt_time) {
4099223d0dcSBorislav Petkov 		bool hot;
4109223d0dcSBorislav Petkov 		u8 temp;
4119223d0dcSBorislav Petkov 
4129223d0dcSBorislav Petkov 		get_therm_status(state->level, &hot, &temp);
4139223d0dcSBorislav Petkov 		/*
4149223d0dcSBorislav Petkov 		 * Ignore short temperature spike as the system is not close
4159223d0dcSBorislav Petkov 		 * to PROCHOT. 10C offset is large enough to ignore. It is
4169223d0dcSBorislav Petkov 		 * already dropped from the high threshold temperature.
4179223d0dcSBorislav Petkov 		 */
4189223d0dcSBorislav Petkov 		if (temp > 10)
4199223d0dcSBorislav Petkov 			return;
4209223d0dcSBorislav Petkov 
4219223d0dcSBorislav Petkov 		state->baseline_temp = temp;
4229223d0dcSBorislav Petkov 		state->last_interrupt_time = now;
4239223d0dcSBorislav Petkov 		schedule_delayed_work_on(this_cpu, &state->therm_work, THERM_THROT_POLL_INTERVAL);
4249223d0dcSBorislav Petkov 	} else if (old_event && state->last_interrupt_time) {
4259223d0dcSBorislav Petkov 		unsigned long throttle_time;
4269223d0dcSBorislav Petkov 
4279223d0dcSBorislav Petkov 		throttle_time = jiffies_delta_to_msecs(now - state->last_interrupt_time);
4289223d0dcSBorislav Petkov 		if (throttle_time > state->max_time_ms)
4299223d0dcSBorislav Petkov 			state->max_time_ms = throttle_time;
4309223d0dcSBorislav Petkov 		state->total_time_ms += throttle_time;
4319223d0dcSBorislav Petkov 		state->last_interrupt_time = 0;
4329223d0dcSBorislav Petkov 	}
4339223d0dcSBorislav Petkov }
4349223d0dcSBorislav Petkov 
thresh_event_valid(int level,int event)4359223d0dcSBorislav Petkov static int thresh_event_valid(int level, int event)
4369223d0dcSBorislav Petkov {
4379223d0dcSBorislav Petkov 	struct _thermal_state *state;
4389223d0dcSBorislav Petkov 	unsigned int this_cpu = smp_processor_id();
4399223d0dcSBorislav Petkov 	struct thermal_state *pstate = &per_cpu(thermal_state, this_cpu);
4409223d0dcSBorislav Petkov 	u64 now = get_jiffies_64();
4419223d0dcSBorislav Petkov 
4429223d0dcSBorislav Petkov 	if (level == PACKAGE_LEVEL)
4439223d0dcSBorislav Petkov 		state = (event == 0) ? &pstate->pkg_thresh0 :
4449223d0dcSBorislav Petkov 						&pstate->pkg_thresh1;
4459223d0dcSBorislav Petkov 	else
4469223d0dcSBorislav Petkov 		state = (event == 0) ? &pstate->core_thresh0 :
4479223d0dcSBorislav Petkov 						&pstate->core_thresh1;
4489223d0dcSBorislav Petkov 
4499223d0dcSBorislav Petkov 	if (time_before64(now, state->next_check))
4509223d0dcSBorislav Petkov 		return 0;
4519223d0dcSBorislav Petkov 
4529223d0dcSBorislav Petkov 	state->next_check = now + CHECK_INTERVAL;
4539223d0dcSBorislav Petkov 
4549223d0dcSBorislav Petkov 	return 1;
4559223d0dcSBorislav Petkov }
4569223d0dcSBorislav Petkov 
4579223d0dcSBorislav Petkov static bool int_pln_enable;
int_pln_enable_setup(char * s)4589223d0dcSBorislav Petkov static int __init int_pln_enable_setup(char *s)
4599223d0dcSBorislav Petkov {
4609223d0dcSBorislav Petkov 	int_pln_enable = true;
4619223d0dcSBorislav Petkov 
4629223d0dcSBorislav Petkov 	return 1;
4639223d0dcSBorislav Petkov }
4649223d0dcSBorislav Petkov __setup("int_pln_enable", int_pln_enable_setup);
4659223d0dcSBorislav Petkov 
4669223d0dcSBorislav Petkov #ifdef CONFIG_SYSFS
4679223d0dcSBorislav Petkov /* Add/Remove thermal_throttle interface for CPU device: */
thermal_throttle_add_dev(struct device * dev,unsigned int cpu)4689223d0dcSBorislav Petkov static int thermal_throttle_add_dev(struct device *dev, unsigned int cpu)
4699223d0dcSBorislav Petkov {
4709223d0dcSBorislav Petkov 	int err;
4719223d0dcSBorislav Petkov 	struct cpuinfo_x86 *c = &cpu_data(cpu);
4729223d0dcSBorislav Petkov 
4739223d0dcSBorislav Petkov 	err = sysfs_create_group(&dev->kobj, &thermal_attr_group);
4749223d0dcSBorislav Petkov 	if (err)
4759223d0dcSBorislav Petkov 		return err;
4769223d0dcSBorislav Petkov 
4779223d0dcSBorislav Petkov 	if (cpu_has(c, X86_FEATURE_PLN) && int_pln_enable) {
4789223d0dcSBorislav Petkov 		err = sysfs_add_file_to_group(&dev->kobj,
4799223d0dcSBorislav Petkov 					      &dev_attr_core_power_limit_count.attr,
4809223d0dcSBorislav Petkov 					      thermal_attr_group.name);
4819223d0dcSBorislav Petkov 		if (err)
4829223d0dcSBorislav Petkov 			goto del_group;
4839223d0dcSBorislav Petkov 	}
4849223d0dcSBorislav Petkov 
4859223d0dcSBorislav Petkov 	if (cpu_has(c, X86_FEATURE_PTS)) {
4869223d0dcSBorislav Petkov 		err = sysfs_add_file_to_group(&dev->kobj,
4879223d0dcSBorislav Petkov 					      &dev_attr_package_throttle_count.attr,
4889223d0dcSBorislav Petkov 					      thermal_attr_group.name);
4899223d0dcSBorislav Petkov 		if (err)
4909223d0dcSBorislav Petkov 			goto del_group;
4919223d0dcSBorislav Petkov 
4929223d0dcSBorislav Petkov 		err = sysfs_add_file_to_group(&dev->kobj,
4939223d0dcSBorislav Petkov 					      &dev_attr_package_throttle_max_time_ms.attr,
4949223d0dcSBorislav Petkov 					      thermal_attr_group.name);
4959223d0dcSBorislav Petkov 		if (err)
4969223d0dcSBorislav Petkov 			goto del_group;
4979223d0dcSBorislav Petkov 
4989223d0dcSBorislav Petkov 		err = sysfs_add_file_to_group(&dev->kobj,
4999223d0dcSBorislav Petkov 					      &dev_attr_package_throttle_total_time_ms.attr,
5009223d0dcSBorislav Petkov 					      thermal_attr_group.name);
5019223d0dcSBorislav Petkov 		if (err)
5029223d0dcSBorislav Petkov 			goto del_group;
5039223d0dcSBorislav Petkov 
5049223d0dcSBorislav Petkov 		if (cpu_has(c, X86_FEATURE_PLN) && int_pln_enable) {
5059223d0dcSBorislav Petkov 			err = sysfs_add_file_to_group(&dev->kobj,
5069223d0dcSBorislav Petkov 					&dev_attr_package_power_limit_count.attr,
5079223d0dcSBorislav Petkov 					thermal_attr_group.name);
5089223d0dcSBorislav Petkov 			if (err)
5099223d0dcSBorislav Petkov 				goto del_group;
5109223d0dcSBorislav Petkov 		}
5119223d0dcSBorislav Petkov 	}
5129223d0dcSBorislav Petkov 
5139223d0dcSBorislav Petkov 	return 0;
5149223d0dcSBorislav Petkov 
5159223d0dcSBorislav Petkov del_group:
5169223d0dcSBorislav Petkov 	sysfs_remove_group(&dev->kobj, &thermal_attr_group);
5179223d0dcSBorislav Petkov 
5189223d0dcSBorislav Petkov 	return err;
5199223d0dcSBorislav Petkov }
5209223d0dcSBorislav Petkov 
thermal_throttle_remove_dev(struct device * dev)5219223d0dcSBorislav Petkov static void thermal_throttle_remove_dev(struct device *dev)
5229223d0dcSBorislav Petkov {
5239223d0dcSBorislav Petkov 	sysfs_remove_group(&dev->kobj, &thermal_attr_group);
5249223d0dcSBorislav Petkov }
5259223d0dcSBorislav Petkov 
5269223d0dcSBorislav Petkov /* Get notified when a cpu comes on/off. Be hotplug friendly. */
thermal_throttle_online(unsigned int cpu)5279223d0dcSBorislav Petkov static int thermal_throttle_online(unsigned int cpu)
5289223d0dcSBorislav Petkov {
5299223d0dcSBorislav Petkov 	struct thermal_state *state = &per_cpu(thermal_state, cpu);
5309223d0dcSBorislav Petkov 	struct device *dev = get_cpu_device(cpu);
5319223d0dcSBorislav Petkov 	u32 l;
5329223d0dcSBorislav Petkov 
5339223d0dcSBorislav Petkov 	state->package_throttle.level = PACKAGE_LEVEL;
5349223d0dcSBorislav Petkov 	state->core_throttle.level = CORE_LEVEL;
5359223d0dcSBorislav Petkov 
5369223d0dcSBorislav Petkov 	INIT_DELAYED_WORK(&state->package_throttle.therm_work, throttle_active_work);
5379223d0dcSBorislav Petkov 	INIT_DELAYED_WORK(&state->core_throttle.therm_work, throttle_active_work);
5389223d0dcSBorislav Petkov 
5392d74e631SRicardo Neri 	/*
5402d74e631SRicardo Neri 	 * The first CPU coming online will enable the HFI. Usually this causes
5412d74e631SRicardo Neri 	 * hardware to issue an HFI thermal interrupt. Such interrupt will reach
5422d74e631SRicardo Neri 	 * the CPU once we enable the thermal vector in the local APIC.
5432d74e631SRicardo Neri 	 */
5442d74e631SRicardo Neri 	intel_hfi_online(cpu);
5452d74e631SRicardo Neri 
5469223d0dcSBorislav Petkov 	/* Unmask the thermal vector after the above workqueues are initialized. */
5479223d0dcSBorislav Petkov 	l = apic_read(APIC_LVTTHMR);
5489223d0dcSBorislav Petkov 	apic_write(APIC_LVTTHMR, l & ~APIC_LVT_MASKED);
5499223d0dcSBorislav Petkov 
5509223d0dcSBorislav Petkov 	return thermal_throttle_add_dev(dev, cpu);
5519223d0dcSBorislav Petkov }
5529223d0dcSBorislav Petkov 
thermal_throttle_offline(unsigned int cpu)5539223d0dcSBorislav Petkov static int thermal_throttle_offline(unsigned int cpu)
5549223d0dcSBorislav Petkov {
5559223d0dcSBorislav Petkov 	struct thermal_state *state = &per_cpu(thermal_state, cpu);
5569223d0dcSBorislav Petkov 	struct device *dev = get_cpu_device(cpu);
5579223d0dcSBorislav Petkov 	u32 l;
5589223d0dcSBorislav Petkov 
5599223d0dcSBorislav Petkov 	/* Mask the thermal vector before draining evtl. pending work */
5609223d0dcSBorislav Petkov 	l = apic_read(APIC_LVTTHMR);
5619223d0dcSBorislav Petkov 	apic_write(APIC_LVTTHMR, l | APIC_LVT_MASKED);
5629223d0dcSBorislav Petkov 
5632d74e631SRicardo Neri 	intel_hfi_offline(cpu);
5642d74e631SRicardo Neri 
5659223d0dcSBorislav Petkov 	cancel_delayed_work_sync(&state->package_throttle.therm_work);
5669223d0dcSBorislav Petkov 	cancel_delayed_work_sync(&state->core_throttle.therm_work);
5679223d0dcSBorislav Petkov 
5689223d0dcSBorislav Petkov 	state->package_throttle.rate_control_active = false;
5699223d0dcSBorislav Petkov 	state->core_throttle.rate_control_active = false;
5709223d0dcSBorislav Petkov 
5719223d0dcSBorislav Petkov 	thermal_throttle_remove_dev(dev);
5729223d0dcSBorislav Petkov 	return 0;
5739223d0dcSBorislav Petkov }
5749223d0dcSBorislav Petkov 
thermal_throttle_init_device(void)5759223d0dcSBorislav Petkov static __init int thermal_throttle_init_device(void)
5769223d0dcSBorislav Petkov {
5779223d0dcSBorislav Petkov 	int ret;
5789223d0dcSBorislav Petkov 
5799223d0dcSBorislav Petkov 	if (!atomic_read(&therm_throt_en))
5809223d0dcSBorislav Petkov 		return 0;
5819223d0dcSBorislav Petkov 
5821cb19cabSRicardo Neri 	intel_hfi_init();
5831cb19cabSRicardo Neri 
5849223d0dcSBorislav Petkov 	ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "x86/therm:online",
5859223d0dcSBorislav Petkov 				thermal_throttle_online,
5869223d0dcSBorislav Petkov 				thermal_throttle_offline);
5879223d0dcSBorislav Petkov 	return ret < 0 ? ret : 0;
5889223d0dcSBorislav Petkov }
5899223d0dcSBorislav Petkov device_initcall(thermal_throttle_init_device);
5909223d0dcSBorislav Petkov 
5919223d0dcSBorislav Petkov #endif /* CONFIG_SYSFS */
5929223d0dcSBorislav Petkov 
notify_package_thresholds(__u64 msr_val)5939223d0dcSBorislav Petkov static void notify_package_thresholds(__u64 msr_val)
5949223d0dcSBorislav Petkov {
5959223d0dcSBorislav Petkov 	bool notify_thres_0 = false;
5969223d0dcSBorislav Petkov 	bool notify_thres_1 = false;
5979223d0dcSBorislav Petkov 
5989223d0dcSBorislav Petkov 	if (!platform_thermal_package_notify)
5999223d0dcSBorislav Petkov 		return;
6009223d0dcSBorislav Petkov 
6019223d0dcSBorislav Petkov 	/* lower threshold check */
6029223d0dcSBorislav Petkov 	if (msr_val & THERM_LOG_THRESHOLD0)
6039223d0dcSBorislav Petkov 		notify_thres_0 = true;
6049223d0dcSBorislav Petkov 	/* higher threshold check */
6059223d0dcSBorislav Petkov 	if (msr_val & THERM_LOG_THRESHOLD1)
6069223d0dcSBorislav Petkov 		notify_thres_1 = true;
6079223d0dcSBorislav Petkov 
6089223d0dcSBorislav Petkov 	if (!notify_thres_0 && !notify_thres_1)
6099223d0dcSBorislav Petkov 		return;
6109223d0dcSBorislav Petkov 
6119223d0dcSBorislav Petkov 	if (platform_thermal_package_rate_control &&
6129223d0dcSBorislav Petkov 		platform_thermal_package_rate_control()) {
6139223d0dcSBorislav Petkov 		/* Rate control is implemented in callback */
6149223d0dcSBorislav Petkov 		platform_thermal_package_notify(msr_val);
6159223d0dcSBorislav Petkov 		return;
6169223d0dcSBorislav Petkov 	}
6179223d0dcSBorislav Petkov 
6189223d0dcSBorislav Petkov 	/* lower threshold reached */
6199223d0dcSBorislav Petkov 	if (notify_thres_0 && thresh_event_valid(PACKAGE_LEVEL, 0))
6209223d0dcSBorislav Petkov 		platform_thermal_package_notify(msr_val);
6219223d0dcSBorislav Petkov 	/* higher threshold reached */
6229223d0dcSBorislav Petkov 	if (notify_thres_1 && thresh_event_valid(PACKAGE_LEVEL, 1))
6239223d0dcSBorislav Petkov 		platform_thermal_package_notify(msr_val);
6249223d0dcSBorislav Petkov }
6259223d0dcSBorislav Petkov 
notify_thresholds(__u64 msr_val)6269223d0dcSBorislav Petkov static void notify_thresholds(__u64 msr_val)
6279223d0dcSBorislav Petkov {
6289223d0dcSBorislav Petkov 	/* check whether the interrupt handler is defined;
6299223d0dcSBorislav Petkov 	 * otherwise simply return
6309223d0dcSBorislav Petkov 	 */
6319223d0dcSBorislav Petkov 	if (!platform_thermal_notify)
6329223d0dcSBorislav Petkov 		return;
6339223d0dcSBorislav Petkov 
6349223d0dcSBorislav Petkov 	/* lower threshold reached */
6359223d0dcSBorislav Petkov 	if ((msr_val & THERM_LOG_THRESHOLD0) &&
6369223d0dcSBorislav Petkov 			thresh_event_valid(CORE_LEVEL, 0))
6379223d0dcSBorislav Petkov 		platform_thermal_notify(msr_val);
6389223d0dcSBorislav Petkov 	/* higher threshold reached */
6399223d0dcSBorislav Petkov 	if ((msr_val & THERM_LOG_THRESHOLD1) &&
6409223d0dcSBorislav Petkov 			thresh_event_valid(CORE_LEVEL, 1))
6419223d0dcSBorislav Petkov 		platform_thermal_notify(msr_val);
6429223d0dcSBorislav Petkov }
6439223d0dcSBorislav Petkov 
notify_hwp_interrupt(void)644950809cdSSrinivas Pandruvada void __weak notify_hwp_interrupt(void)
645950809cdSSrinivas Pandruvada {
646950809cdSSrinivas Pandruvada 	wrmsrl_safe(MSR_HWP_STATUS, 0);
647950809cdSSrinivas Pandruvada }
648950809cdSSrinivas Pandruvada 
6499223d0dcSBorislav Petkov /* Thermal transition interrupt handler */
intel_thermal_interrupt(void)6509223d0dcSBorislav Petkov void intel_thermal_interrupt(void)
6519223d0dcSBorislav Petkov {
6529223d0dcSBorislav Petkov 	__u64 msr_val;
6539223d0dcSBorislav Petkov 
6549223d0dcSBorislav Petkov 	if (static_cpu_has(X86_FEATURE_HWP))
655950809cdSSrinivas Pandruvada 		notify_hwp_interrupt();
6569223d0dcSBorislav Petkov 
6579223d0dcSBorislav Petkov 	rdmsrl(MSR_IA32_THERM_STATUS, msr_val);
6589223d0dcSBorislav Petkov 
6599223d0dcSBorislav Petkov 	/* Check for violation of core thermal thresholds*/
6609223d0dcSBorislav Petkov 	notify_thresholds(msr_val);
6619223d0dcSBorislav Petkov 
6629223d0dcSBorislav Petkov 	therm_throt_process(msr_val & THERM_STATUS_PROCHOT,
6639223d0dcSBorislav Petkov 			    THERMAL_THROTTLING_EVENT,
6649223d0dcSBorislav Petkov 			    CORE_LEVEL);
6659223d0dcSBorislav Petkov 
6669223d0dcSBorislav Petkov 	if (this_cpu_has(X86_FEATURE_PLN) && int_pln_enable)
6679223d0dcSBorislav Petkov 		therm_throt_process(msr_val & THERM_STATUS_POWER_LIMIT,
6689223d0dcSBorislav Petkov 					POWER_LIMIT_EVENT,
6699223d0dcSBorislav Petkov 					CORE_LEVEL);
6709223d0dcSBorislav Petkov 
6719223d0dcSBorislav Petkov 	if (this_cpu_has(X86_FEATURE_PTS)) {
6729223d0dcSBorislav Petkov 		rdmsrl(MSR_IA32_PACKAGE_THERM_STATUS, msr_val);
6739223d0dcSBorislav Petkov 		/* check violations of package thermal thresholds */
6749223d0dcSBorislav Petkov 		notify_package_thresholds(msr_val);
6759223d0dcSBorislav Petkov 		therm_throt_process(msr_val & PACKAGE_THERM_STATUS_PROCHOT,
6769223d0dcSBorislav Petkov 					THERMAL_THROTTLING_EVENT,
6779223d0dcSBorislav Petkov 					PACKAGE_LEVEL);
6789223d0dcSBorislav Petkov 		if (this_cpu_has(X86_FEATURE_PLN) && int_pln_enable)
6799223d0dcSBorislav Petkov 			therm_throt_process(msr_val &
6809223d0dcSBorislav Petkov 					PACKAGE_THERM_STATUS_POWER_LIMIT,
6819223d0dcSBorislav Petkov 					POWER_LIMIT_EVENT,
6829223d0dcSBorislav Petkov 					PACKAGE_LEVEL);
683ab09b074SRicardo Neri 
684ab09b074SRicardo Neri 		if (this_cpu_has(X86_FEATURE_HFI))
685ab09b074SRicardo Neri 			intel_hfi_process_event(msr_val &
686ab09b074SRicardo Neri 						PACKAGE_THERM_STATUS_HFI_UPDATED);
6879223d0dcSBorislav Petkov 	}
6889223d0dcSBorislav Petkov }
6899223d0dcSBorislav Petkov 
6909223d0dcSBorislav Petkov /* Thermal monitoring depends on APIC, ACPI and clock modulation */
intel_thermal_supported(struct cpuinfo_x86 * c)6919223d0dcSBorislav Petkov static int intel_thermal_supported(struct cpuinfo_x86 *c)
6929223d0dcSBorislav Petkov {
6939223d0dcSBorislav Petkov 	if (!boot_cpu_has(X86_FEATURE_APIC))
6949223d0dcSBorislav Petkov 		return 0;
6959223d0dcSBorislav Petkov 	if (!cpu_has(c, X86_FEATURE_ACPI) || !cpu_has(c, X86_FEATURE_ACC))
6969223d0dcSBorislav Petkov 		return 0;
6979223d0dcSBorislav Petkov 	return 1;
6989223d0dcSBorislav Petkov }
6999223d0dcSBorislav Petkov 
x86_thermal_enabled(void)7009223d0dcSBorislav Petkov bool x86_thermal_enabled(void)
7019223d0dcSBorislav Petkov {
7029223d0dcSBorislav Petkov 	return atomic_read(&therm_throt_en);
7039223d0dcSBorislav Petkov }
7049223d0dcSBorislav Petkov 
therm_lvt_init(void)7059a90ed06SBorislav Petkov void __init therm_lvt_init(void)
7069a90ed06SBorislav Petkov {
7079a90ed06SBorislav Petkov 	/*
7089a90ed06SBorislav Petkov 	 * This function is only called on boot CPU. Save the init thermal
7099a90ed06SBorislav Petkov 	 * LVT value on BSP and use that value to restore APs' thermal LVT
7109a90ed06SBorislav Petkov 	 * entry BIOS programmed later
7119a90ed06SBorislav Petkov 	 */
7129a90ed06SBorislav Petkov 	if (intel_thermal_supported(&boot_cpu_data))
7139a90ed06SBorislav Petkov 		lvtthmr_init = apic_read(APIC_LVTTHMR);
7149a90ed06SBorislav Petkov }
7159a90ed06SBorislav Petkov 
intel_init_thermal(struct cpuinfo_x86 * c)7169223d0dcSBorislav Petkov void intel_init_thermal(struct cpuinfo_x86 *c)
7179223d0dcSBorislav Petkov {
7189223d0dcSBorislav Petkov 	unsigned int cpu = smp_processor_id();
7199223d0dcSBorislav Petkov 	int tm2 = 0;
7209223d0dcSBorislav Petkov 	u32 l, h;
7219223d0dcSBorislav Petkov 
7229223d0dcSBorislav Petkov 	if (!intel_thermal_supported(c))
7239223d0dcSBorislav Petkov 		return;
7249223d0dcSBorislav Petkov 
7259223d0dcSBorislav Petkov 	/*
7269223d0dcSBorislav Petkov 	 * First check if its enabled already, in which case there might
7279223d0dcSBorislav Petkov 	 * be some SMM goo which handles it, so we can't even put a handler
7289223d0dcSBorislav Petkov 	 * since it might be delivered via SMI already:
7299223d0dcSBorislav Petkov 	 */
7309223d0dcSBorislav Petkov 	rdmsr(MSR_IA32_MISC_ENABLE, l, h);
7319223d0dcSBorislav Petkov 
7329223d0dcSBorislav Petkov 	h = lvtthmr_init;
7339223d0dcSBorislav Petkov 	/*
7349223d0dcSBorislav Petkov 	 * The initial value of thermal LVT entries on all APs always reads
7359223d0dcSBorislav Petkov 	 * 0x10000 because APs are woken up by BSP issuing INIT-SIPI-SIPI
7369223d0dcSBorislav Petkov 	 * sequence to them and LVT registers are reset to 0s except for
7379223d0dcSBorislav Petkov 	 * the mask bits which are set to 1s when APs receive INIT IPI.
7389223d0dcSBorislav Petkov 	 * If BIOS takes over the thermal interrupt and sets its interrupt
7399223d0dcSBorislav Petkov 	 * delivery mode to SMI (not fixed), it restores the value that the
7409223d0dcSBorislav Petkov 	 * BIOS has programmed on AP based on BSP's info we saved since BIOS
7419223d0dcSBorislav Petkov 	 * is always setting the same value for all threads/cores.
7429223d0dcSBorislav Petkov 	 */
7439223d0dcSBorislav Petkov 	if ((h & APIC_DM_FIXED_MASK) != APIC_DM_FIXED)
7449223d0dcSBorislav Petkov 		apic_write(APIC_LVTTHMR, lvtthmr_init);
7459223d0dcSBorislav Petkov 
7469223d0dcSBorislav Petkov 
7479223d0dcSBorislav Petkov 	if ((l & MSR_IA32_MISC_ENABLE_TM1) && (h & APIC_DM_SMI)) {
7489223d0dcSBorislav Petkov 		if (system_state == SYSTEM_BOOTING)
7499223d0dcSBorislav Petkov 			pr_debug("CPU%d: Thermal monitoring handled by SMI\n", cpu);
7509223d0dcSBorislav Petkov 		return;
7519223d0dcSBorislav Petkov 	}
7529223d0dcSBorislav Petkov 
7539223d0dcSBorislav Petkov 	/* early Pentium M models use different method for enabling TM2 */
7549223d0dcSBorislav Petkov 	if (cpu_has(c, X86_FEATURE_TM2)) {
7559223d0dcSBorislav Petkov 		if (c->x86 == 6 && (c->x86_model == 9 || c->x86_model == 13)) {
7569223d0dcSBorislav Petkov 			rdmsr(MSR_THERM2_CTL, l, h);
7579223d0dcSBorislav Petkov 			if (l & MSR_THERM2_CTL_TM_SELECT)
7589223d0dcSBorislav Petkov 				tm2 = 1;
7599223d0dcSBorislav Petkov 		} else if (l & MSR_IA32_MISC_ENABLE_TM2)
7609223d0dcSBorislav Petkov 			tm2 = 1;
7619223d0dcSBorislav Petkov 	}
7629223d0dcSBorislav Petkov 
7639223d0dcSBorislav Petkov 	/* We'll mask the thermal vector in the lapic till we're ready: */
7649223d0dcSBorislav Petkov 	h = THERMAL_APIC_VECTOR | APIC_DM_FIXED | APIC_LVT_MASKED;
7659223d0dcSBorislav Petkov 	apic_write(APIC_LVTTHMR, h);
7669223d0dcSBorislav Petkov 
767*117e4e5bSSrinivas Pandruvada 	thermal_intr_init_core_clear_mask();
768*117e4e5bSSrinivas Pandruvada 	thermal_intr_init_pkg_clear_mask();
769*117e4e5bSSrinivas Pandruvada 
7709223d0dcSBorislav Petkov 	rdmsr(MSR_IA32_THERM_INTERRUPT, l, h);
7719223d0dcSBorislav Petkov 	if (cpu_has(c, X86_FEATURE_PLN) && !int_pln_enable)
7729223d0dcSBorislav Petkov 		wrmsr(MSR_IA32_THERM_INTERRUPT,
7739223d0dcSBorislav Petkov 			(l | (THERM_INT_LOW_ENABLE
7749223d0dcSBorislav Petkov 			| THERM_INT_HIGH_ENABLE)) & ~THERM_INT_PLN_ENABLE, h);
7759223d0dcSBorislav Petkov 	else if (cpu_has(c, X86_FEATURE_PLN) && int_pln_enable)
7769223d0dcSBorislav Petkov 		wrmsr(MSR_IA32_THERM_INTERRUPT,
7779223d0dcSBorislav Petkov 			l | (THERM_INT_LOW_ENABLE
7789223d0dcSBorislav Petkov 			| THERM_INT_HIGH_ENABLE | THERM_INT_PLN_ENABLE), h);
7799223d0dcSBorislav Petkov 	else
7809223d0dcSBorislav Petkov 		wrmsr(MSR_IA32_THERM_INTERRUPT,
7819223d0dcSBorislav Petkov 		      l | (THERM_INT_LOW_ENABLE | THERM_INT_HIGH_ENABLE), h);
7829223d0dcSBorislav Petkov 
7839223d0dcSBorislav Petkov 	if (cpu_has(c, X86_FEATURE_PTS)) {
7849223d0dcSBorislav Petkov 		rdmsr(MSR_IA32_PACKAGE_THERM_INTERRUPT, l, h);
7859223d0dcSBorislav Petkov 		if (cpu_has(c, X86_FEATURE_PLN) && !int_pln_enable)
7869223d0dcSBorislav Petkov 			wrmsr(MSR_IA32_PACKAGE_THERM_INTERRUPT,
7879223d0dcSBorislav Petkov 				(l | (PACKAGE_THERM_INT_LOW_ENABLE
7889223d0dcSBorislav Petkov 				| PACKAGE_THERM_INT_HIGH_ENABLE))
7899223d0dcSBorislav Petkov 				& ~PACKAGE_THERM_INT_PLN_ENABLE, h);
7909223d0dcSBorislav Petkov 		else if (cpu_has(c, X86_FEATURE_PLN) && int_pln_enable)
7919223d0dcSBorislav Petkov 			wrmsr(MSR_IA32_PACKAGE_THERM_INTERRUPT,
7929223d0dcSBorislav Petkov 				l | (PACKAGE_THERM_INT_LOW_ENABLE
7939223d0dcSBorislav Petkov 				| PACKAGE_THERM_INT_HIGH_ENABLE
7949223d0dcSBorislav Petkov 				| PACKAGE_THERM_INT_PLN_ENABLE), h);
7959223d0dcSBorislav Petkov 		else
7969223d0dcSBorislav Petkov 			wrmsr(MSR_IA32_PACKAGE_THERM_INTERRUPT,
7979223d0dcSBorislav Petkov 			      l | (PACKAGE_THERM_INT_LOW_ENABLE
7989223d0dcSBorislav Petkov 				| PACKAGE_THERM_INT_HIGH_ENABLE), h);
799ab09b074SRicardo Neri 
800ab09b074SRicardo Neri 		if (cpu_has(c, X86_FEATURE_HFI)) {
801ab09b074SRicardo Neri 			rdmsr(MSR_IA32_PACKAGE_THERM_INTERRUPT, l, h);
802ab09b074SRicardo Neri 			wrmsr(MSR_IA32_PACKAGE_THERM_INTERRUPT,
803ab09b074SRicardo Neri 			      l | PACKAGE_THERM_INT_HFI_ENABLE, h);
804ab09b074SRicardo Neri 		}
8059223d0dcSBorislav Petkov 	}
8069223d0dcSBorislav Petkov 
8079223d0dcSBorislav Petkov 	rdmsr(MSR_IA32_MISC_ENABLE, l, h);
8089223d0dcSBorislav Petkov 	wrmsr(MSR_IA32_MISC_ENABLE, l | MSR_IA32_MISC_ENABLE_TM1, h);
8099223d0dcSBorislav Petkov 
8109223d0dcSBorislav Petkov 	pr_info_once("CPU0: Thermal monitoring enabled (%s)\n",
8119223d0dcSBorislav Petkov 		      tm2 ? "TM2" : "TM1");
8129223d0dcSBorislav Petkov 
8139223d0dcSBorislav Petkov 	/* enable thermal throttle processing */
8149223d0dcSBorislav Petkov 	atomic_set(&therm_throt_en, 1);
8159223d0dcSBorislav Petkov }
816