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