root/arch/x86/kernel/cpu/mce/therm_throt.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. therm_throt_process
  2. thresh_event_valid
  3. int_pln_enable_setup
  4. thermal_throttle_add_dev
  5. thermal_throttle_remove_dev
  6. thermal_throttle_online
  7. thermal_throttle_offline
  8. thermal_throttle_init_device
  9. notify_package_thresholds
  10. notify_thresholds
  11. intel_thermal_interrupt
  12. unexpected_thermal_interrupt
  13. smp_thermal_interrupt
  14. intel_thermal_supported
  15. mcheck_intel_therm_init
  16. intel_init_thermal

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * Thermal throttle event support code (such as syslog messaging and rate
   4  * limiting) that was factored out from x86_64 (mce_intel.c) and i386 (p4.c).
   5  *
   6  * This allows consistent reporting of CPU thermal throttle events.
   7  *
   8  * Maintains a counter in /sys that keeps track of the number of thermal
   9  * events, such that the user knows how bad the thermal problem might be
  10  * (since the logging to syslog is rate limited).
  11  *
  12  * Author: Dmitriy Zavin (dmitriyz@google.com)
  13  *
  14  * Credits: Adapted from Zwane Mwaikambo's original code in mce_intel.c.
  15  *          Inspired by Ross Biro's and Al Borchers' counter code.
  16  */
  17 #include <linux/interrupt.h>
  18 #include <linux/notifier.h>
  19 #include <linux/jiffies.h>
  20 #include <linux/kernel.h>
  21 #include <linux/percpu.h>
  22 #include <linux/export.h>
  23 #include <linux/types.h>
  24 #include <linux/init.h>
  25 #include <linux/smp.h>
  26 #include <linux/cpu.h>
  27 
  28 #include <asm/processor.h>
  29 #include <asm/traps.h>
  30 #include <asm/apic.h>
  31 #include <asm/mce.h>
  32 #include <asm/msr.h>
  33 #include <asm/trace/irq_vectors.h>
  34 
  35 #include "internal.h"
  36 
  37 /* How long to wait between reporting thermal events */
  38 #define CHECK_INTERVAL          (300 * HZ)
  39 
  40 #define THERMAL_THROTTLING_EVENT        0
  41 #define POWER_LIMIT_EVENT               1
  42 
  43 /*
  44  * Current thermal event state:
  45  */
  46 struct _thermal_state {
  47         bool                    new_event;
  48         int                     event;
  49         u64                     next_check;
  50         unsigned long           count;
  51         unsigned long           last_count;
  52 };
  53 
  54 struct thermal_state {
  55         struct _thermal_state core_throttle;
  56         struct _thermal_state core_power_limit;
  57         struct _thermal_state package_throttle;
  58         struct _thermal_state package_power_limit;
  59         struct _thermal_state core_thresh0;
  60         struct _thermal_state core_thresh1;
  61         struct _thermal_state pkg_thresh0;
  62         struct _thermal_state pkg_thresh1;
  63 };
  64 
  65 /* Callback to handle core threshold interrupts */
  66 int (*platform_thermal_notify)(__u64 msr_val);
  67 EXPORT_SYMBOL(platform_thermal_notify);
  68 
  69 /* Callback to handle core package threshold_interrupts */
  70 int (*platform_thermal_package_notify)(__u64 msr_val);
  71 EXPORT_SYMBOL_GPL(platform_thermal_package_notify);
  72 
  73 /* Callback support of rate control, return true, if
  74  * callback has rate control */
  75 bool (*platform_thermal_package_rate_control)(void);
  76 EXPORT_SYMBOL_GPL(platform_thermal_package_rate_control);
  77 
  78 
  79 static DEFINE_PER_CPU(struct thermal_state, thermal_state);
  80 
  81 static atomic_t therm_throt_en  = ATOMIC_INIT(0);
  82 
  83 static u32 lvtthmr_init __read_mostly;
  84 
  85 #ifdef CONFIG_SYSFS
  86 #define define_therm_throt_device_one_ro(_name)                         \
  87         static DEVICE_ATTR(_name, 0444,                                 \
  88                            therm_throt_device_show_##_name,             \
  89                                    NULL)                                \
  90 
  91 #define define_therm_throt_device_show_func(event, name)                \
  92                                                                         \
  93 static ssize_t therm_throt_device_show_##event##_##name(                \
  94                         struct device *dev,                             \
  95                         struct device_attribute *attr,                  \
  96                         char *buf)                                      \
  97 {                                                                       \
  98         unsigned int cpu = dev->id;                                     \
  99         ssize_t ret;                                                    \
 100                                                                         \
 101         preempt_disable();      /* CPU hotplug */                       \
 102         if (cpu_online(cpu)) {                                          \
 103                 ret = sprintf(buf, "%lu\n",                             \
 104                               per_cpu(thermal_state, cpu).event.name);  \
 105         } else                                                          \
 106                 ret = 0;                                                \
 107         preempt_enable();                                               \
 108                                                                         \
 109         return ret;                                                     \
 110 }
 111 
 112 define_therm_throt_device_show_func(core_throttle, count);
 113 define_therm_throt_device_one_ro(core_throttle_count);
 114 
 115 define_therm_throt_device_show_func(core_power_limit, count);
 116 define_therm_throt_device_one_ro(core_power_limit_count);
 117 
 118 define_therm_throt_device_show_func(package_throttle, count);
 119 define_therm_throt_device_one_ro(package_throttle_count);
 120 
 121 define_therm_throt_device_show_func(package_power_limit, count);
 122 define_therm_throt_device_one_ro(package_power_limit_count);
 123 
 124 static struct attribute *thermal_throttle_attrs[] = {
 125         &dev_attr_core_throttle_count.attr,
 126         NULL
 127 };
 128 
 129 static const struct attribute_group thermal_attr_group = {
 130         .attrs  = thermal_throttle_attrs,
 131         .name   = "thermal_throttle"
 132 };
 133 #endif /* CONFIG_SYSFS */
 134 
 135 #define CORE_LEVEL      0
 136 #define PACKAGE_LEVEL   1
 137 
 138 /***
 139  * therm_throt_process - Process thermal throttling event from interrupt
 140  * @curr: Whether the condition is current or not (boolean), since the
 141  *        thermal interrupt normally gets called both when the thermal
 142  *        event begins and once the event has ended.
 143  *
 144  * This function is called by the thermal interrupt after the
 145  * IRQ has been acknowledged.
 146  *
 147  * It will take care of rate limiting and printing messages to the syslog.
 148  */
 149 static void therm_throt_process(bool new_event, int event, int level)
 150 {
 151         struct _thermal_state *state;
 152         unsigned int this_cpu = smp_processor_id();
 153         bool old_event;
 154         u64 now;
 155         struct thermal_state *pstate = &per_cpu(thermal_state, this_cpu);
 156 
 157         now = get_jiffies_64();
 158         if (level == CORE_LEVEL) {
 159                 if (event == THERMAL_THROTTLING_EVENT)
 160                         state = &pstate->core_throttle;
 161                 else if (event == POWER_LIMIT_EVENT)
 162                         state = &pstate->core_power_limit;
 163                 else
 164                         return;
 165         } else if (level == PACKAGE_LEVEL) {
 166                 if (event == THERMAL_THROTTLING_EVENT)
 167                         state = &pstate->package_throttle;
 168                 else if (event == POWER_LIMIT_EVENT)
 169                         state = &pstate->package_power_limit;
 170                 else
 171                         return;
 172         } else
 173                 return;
 174 
 175         old_event = state->new_event;
 176         state->new_event = new_event;
 177 
 178         if (new_event)
 179                 state->count++;
 180 
 181         if (time_before64(now, state->next_check) &&
 182                         state->count != state->last_count)
 183                 return;
 184 
 185         state->next_check = now + CHECK_INTERVAL;
 186         state->last_count = state->count;
 187 
 188         /* if we just entered the thermal event */
 189         if (new_event) {
 190                 if (event == THERMAL_THROTTLING_EVENT)
 191                         pr_warn("CPU%d: %s temperature above threshold, cpu clock throttled (total events = %lu)\n",
 192                                 this_cpu,
 193                                 level == CORE_LEVEL ? "Core" : "Package",
 194                                 state->count);
 195                 return;
 196         }
 197         if (old_event) {
 198                 if (event == THERMAL_THROTTLING_EVENT)
 199                         pr_info("CPU%d: %s temperature/speed normal\n", this_cpu,
 200                                 level == CORE_LEVEL ? "Core" : "Package");
 201                 return;
 202         }
 203 }
 204 
 205 static int thresh_event_valid(int level, int event)
 206 {
 207         struct _thermal_state *state;
 208         unsigned int this_cpu = smp_processor_id();
 209         struct thermal_state *pstate = &per_cpu(thermal_state, this_cpu);
 210         u64 now = get_jiffies_64();
 211 
 212         if (level == PACKAGE_LEVEL)
 213                 state = (event == 0) ? &pstate->pkg_thresh0 :
 214                                                 &pstate->pkg_thresh1;
 215         else
 216                 state = (event == 0) ? &pstate->core_thresh0 :
 217                                                 &pstate->core_thresh1;
 218 
 219         if (time_before64(now, state->next_check))
 220                 return 0;
 221 
 222         state->next_check = now + CHECK_INTERVAL;
 223 
 224         return 1;
 225 }
 226 
 227 static bool int_pln_enable;
 228 static int __init int_pln_enable_setup(char *s)
 229 {
 230         int_pln_enable = true;
 231 
 232         return 1;
 233 }
 234 __setup("int_pln_enable", int_pln_enable_setup);
 235 
 236 #ifdef CONFIG_SYSFS
 237 /* Add/Remove thermal_throttle interface for CPU device: */
 238 static int thermal_throttle_add_dev(struct device *dev, unsigned int cpu)
 239 {
 240         int err;
 241         struct cpuinfo_x86 *c = &cpu_data(cpu);
 242 
 243         err = sysfs_create_group(&dev->kobj, &thermal_attr_group);
 244         if (err)
 245                 return err;
 246 
 247         if (cpu_has(c, X86_FEATURE_PLN) && int_pln_enable)
 248                 err = sysfs_add_file_to_group(&dev->kobj,
 249                                               &dev_attr_core_power_limit_count.attr,
 250                                               thermal_attr_group.name);
 251         if (cpu_has(c, X86_FEATURE_PTS)) {
 252                 err = sysfs_add_file_to_group(&dev->kobj,
 253                                               &dev_attr_package_throttle_count.attr,
 254                                               thermal_attr_group.name);
 255                 if (cpu_has(c, X86_FEATURE_PLN) && int_pln_enable)
 256                         err = sysfs_add_file_to_group(&dev->kobj,
 257                                         &dev_attr_package_power_limit_count.attr,
 258                                         thermal_attr_group.name);
 259         }
 260 
 261         return err;
 262 }
 263 
 264 static void thermal_throttle_remove_dev(struct device *dev)
 265 {
 266         sysfs_remove_group(&dev->kobj, &thermal_attr_group);
 267 }
 268 
 269 /* Get notified when a cpu comes on/off. Be hotplug friendly. */
 270 static int thermal_throttle_online(unsigned int cpu)
 271 {
 272         struct device *dev = get_cpu_device(cpu);
 273 
 274         return thermal_throttle_add_dev(dev, cpu);
 275 }
 276 
 277 static int thermal_throttle_offline(unsigned int cpu)
 278 {
 279         struct device *dev = get_cpu_device(cpu);
 280 
 281         thermal_throttle_remove_dev(dev);
 282         return 0;
 283 }
 284 
 285 static __init int thermal_throttle_init_device(void)
 286 {
 287         int ret;
 288 
 289         if (!atomic_read(&therm_throt_en))
 290                 return 0;
 291 
 292         ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "x86/therm:online",
 293                                 thermal_throttle_online,
 294                                 thermal_throttle_offline);
 295         return ret < 0 ? ret : 0;
 296 }
 297 device_initcall(thermal_throttle_init_device);
 298 
 299 #endif /* CONFIG_SYSFS */
 300 
 301 static void notify_package_thresholds(__u64 msr_val)
 302 {
 303         bool notify_thres_0 = false;
 304         bool notify_thres_1 = false;
 305 
 306         if (!platform_thermal_package_notify)
 307                 return;
 308 
 309         /* lower threshold check */
 310         if (msr_val & THERM_LOG_THRESHOLD0)
 311                 notify_thres_0 = true;
 312         /* higher threshold check */
 313         if (msr_val & THERM_LOG_THRESHOLD1)
 314                 notify_thres_1 = true;
 315 
 316         if (!notify_thres_0 && !notify_thres_1)
 317                 return;
 318 
 319         if (platform_thermal_package_rate_control &&
 320                 platform_thermal_package_rate_control()) {
 321                 /* Rate control is implemented in callback */
 322                 platform_thermal_package_notify(msr_val);
 323                 return;
 324         }
 325 
 326         /* lower threshold reached */
 327         if (notify_thres_0 && thresh_event_valid(PACKAGE_LEVEL, 0))
 328                 platform_thermal_package_notify(msr_val);
 329         /* higher threshold reached */
 330         if (notify_thres_1 && thresh_event_valid(PACKAGE_LEVEL, 1))
 331                 platform_thermal_package_notify(msr_val);
 332 }
 333 
 334 static void notify_thresholds(__u64 msr_val)
 335 {
 336         /* check whether the interrupt handler is defined;
 337          * otherwise simply return
 338          */
 339         if (!platform_thermal_notify)
 340                 return;
 341 
 342         /* lower threshold reached */
 343         if ((msr_val & THERM_LOG_THRESHOLD0) &&
 344                         thresh_event_valid(CORE_LEVEL, 0))
 345                 platform_thermal_notify(msr_val);
 346         /* higher threshold reached */
 347         if ((msr_val & THERM_LOG_THRESHOLD1) &&
 348                         thresh_event_valid(CORE_LEVEL, 1))
 349                 platform_thermal_notify(msr_val);
 350 }
 351 
 352 /* Thermal transition interrupt handler */
 353 static void intel_thermal_interrupt(void)
 354 {
 355         __u64 msr_val;
 356 
 357         if (static_cpu_has(X86_FEATURE_HWP))
 358                 wrmsrl_safe(MSR_HWP_STATUS, 0);
 359 
 360         rdmsrl(MSR_IA32_THERM_STATUS, msr_val);
 361 
 362         /* Check for violation of core thermal thresholds*/
 363         notify_thresholds(msr_val);
 364 
 365         therm_throt_process(msr_val & THERM_STATUS_PROCHOT,
 366                             THERMAL_THROTTLING_EVENT,
 367                             CORE_LEVEL);
 368 
 369         if (this_cpu_has(X86_FEATURE_PLN) && int_pln_enable)
 370                 therm_throt_process(msr_val & THERM_STATUS_POWER_LIMIT,
 371                                         POWER_LIMIT_EVENT,
 372                                         CORE_LEVEL);
 373 
 374         if (this_cpu_has(X86_FEATURE_PTS)) {
 375                 rdmsrl(MSR_IA32_PACKAGE_THERM_STATUS, msr_val);
 376                 /* check violations of package thermal thresholds */
 377                 notify_package_thresholds(msr_val);
 378                 therm_throt_process(msr_val & PACKAGE_THERM_STATUS_PROCHOT,
 379                                         THERMAL_THROTTLING_EVENT,
 380                                         PACKAGE_LEVEL);
 381                 if (this_cpu_has(X86_FEATURE_PLN) && int_pln_enable)
 382                         therm_throt_process(msr_val &
 383                                         PACKAGE_THERM_STATUS_POWER_LIMIT,
 384                                         POWER_LIMIT_EVENT,
 385                                         PACKAGE_LEVEL);
 386         }
 387 }
 388 
 389 static void unexpected_thermal_interrupt(void)
 390 {
 391         pr_err("CPU%d: Unexpected LVT thermal interrupt!\n",
 392                 smp_processor_id());
 393 }
 394 
 395 static void (*smp_thermal_vector)(void) = unexpected_thermal_interrupt;
 396 
 397 asmlinkage __visible void __irq_entry smp_thermal_interrupt(struct pt_regs *regs)
 398 {
 399         entering_irq();
 400         trace_thermal_apic_entry(THERMAL_APIC_VECTOR);
 401         inc_irq_stat(irq_thermal_count);
 402         smp_thermal_vector();
 403         trace_thermal_apic_exit(THERMAL_APIC_VECTOR);
 404         exiting_ack_irq();
 405 }
 406 
 407 /* Thermal monitoring depends on APIC, ACPI and clock modulation */
 408 static int intel_thermal_supported(struct cpuinfo_x86 *c)
 409 {
 410         if (!boot_cpu_has(X86_FEATURE_APIC))
 411                 return 0;
 412         if (!cpu_has(c, X86_FEATURE_ACPI) || !cpu_has(c, X86_FEATURE_ACC))
 413                 return 0;
 414         return 1;
 415 }
 416 
 417 void __init mcheck_intel_therm_init(void)
 418 {
 419         /*
 420          * This function is only called on boot CPU. Save the init thermal
 421          * LVT value on BSP and use that value to restore APs' thermal LVT
 422          * entry BIOS programmed later
 423          */
 424         if (intel_thermal_supported(&boot_cpu_data))
 425                 lvtthmr_init = apic_read(APIC_LVTTHMR);
 426 }
 427 
 428 void intel_init_thermal(struct cpuinfo_x86 *c)
 429 {
 430         unsigned int cpu = smp_processor_id();
 431         int tm2 = 0;
 432         u32 l, h;
 433 
 434         if (!intel_thermal_supported(c))
 435                 return;
 436 
 437         /*
 438          * First check if its enabled already, in which case there might
 439          * be some SMM goo which handles it, so we can't even put a handler
 440          * since it might be delivered via SMI already:
 441          */
 442         rdmsr(MSR_IA32_MISC_ENABLE, l, h);
 443 
 444         h = lvtthmr_init;
 445         /*
 446          * The initial value of thermal LVT entries on all APs always reads
 447          * 0x10000 because APs are woken up by BSP issuing INIT-SIPI-SIPI
 448          * sequence to them and LVT registers are reset to 0s except for
 449          * the mask bits which are set to 1s when APs receive INIT IPI.
 450          * If BIOS takes over the thermal interrupt and sets its interrupt
 451          * delivery mode to SMI (not fixed), it restores the value that the
 452          * BIOS has programmed on AP based on BSP's info we saved since BIOS
 453          * is always setting the same value for all threads/cores.
 454          */
 455         if ((h & APIC_DM_FIXED_MASK) != APIC_DM_FIXED)
 456                 apic_write(APIC_LVTTHMR, lvtthmr_init);
 457 
 458 
 459         if ((l & MSR_IA32_MISC_ENABLE_TM1) && (h & APIC_DM_SMI)) {
 460                 if (system_state == SYSTEM_BOOTING)
 461                         pr_debug("CPU%d: Thermal monitoring handled by SMI\n", cpu);
 462                 return;
 463         }
 464 
 465         /* early Pentium M models use different method for enabling TM2 */
 466         if (cpu_has(c, X86_FEATURE_TM2)) {
 467                 if (c->x86 == 6 && (c->x86_model == 9 || c->x86_model == 13)) {
 468                         rdmsr(MSR_THERM2_CTL, l, h);
 469                         if (l & MSR_THERM2_CTL_TM_SELECT)
 470                                 tm2 = 1;
 471                 } else if (l & MSR_IA32_MISC_ENABLE_TM2)
 472                         tm2 = 1;
 473         }
 474 
 475         /* We'll mask the thermal vector in the lapic till we're ready: */
 476         h = THERMAL_APIC_VECTOR | APIC_DM_FIXED | APIC_LVT_MASKED;
 477         apic_write(APIC_LVTTHMR, h);
 478 
 479         rdmsr(MSR_IA32_THERM_INTERRUPT, l, h);
 480         if (cpu_has(c, X86_FEATURE_PLN) && !int_pln_enable)
 481                 wrmsr(MSR_IA32_THERM_INTERRUPT,
 482                         (l | (THERM_INT_LOW_ENABLE
 483                         | THERM_INT_HIGH_ENABLE)) & ~THERM_INT_PLN_ENABLE, h);
 484         else if (cpu_has(c, X86_FEATURE_PLN) && int_pln_enable)
 485                 wrmsr(MSR_IA32_THERM_INTERRUPT,
 486                         l | (THERM_INT_LOW_ENABLE
 487                         | THERM_INT_HIGH_ENABLE | THERM_INT_PLN_ENABLE), h);
 488         else
 489                 wrmsr(MSR_IA32_THERM_INTERRUPT,
 490                       l | (THERM_INT_LOW_ENABLE | THERM_INT_HIGH_ENABLE), h);
 491 
 492         if (cpu_has(c, X86_FEATURE_PTS)) {
 493                 rdmsr(MSR_IA32_PACKAGE_THERM_INTERRUPT, l, h);
 494                 if (cpu_has(c, X86_FEATURE_PLN) && !int_pln_enable)
 495                         wrmsr(MSR_IA32_PACKAGE_THERM_INTERRUPT,
 496                                 (l | (PACKAGE_THERM_INT_LOW_ENABLE
 497                                 | PACKAGE_THERM_INT_HIGH_ENABLE))
 498                                 & ~PACKAGE_THERM_INT_PLN_ENABLE, h);
 499                 else if (cpu_has(c, X86_FEATURE_PLN) && int_pln_enable)
 500                         wrmsr(MSR_IA32_PACKAGE_THERM_INTERRUPT,
 501                                 l | (PACKAGE_THERM_INT_LOW_ENABLE
 502                                 | PACKAGE_THERM_INT_HIGH_ENABLE
 503                                 | PACKAGE_THERM_INT_PLN_ENABLE), h);
 504                 else
 505                         wrmsr(MSR_IA32_PACKAGE_THERM_INTERRUPT,
 506                               l | (PACKAGE_THERM_INT_LOW_ENABLE
 507                                 | PACKAGE_THERM_INT_HIGH_ENABLE), h);
 508         }
 509 
 510         smp_thermal_vector = intel_thermal_interrupt;
 511 
 512         rdmsr(MSR_IA32_MISC_ENABLE, l, h);
 513         wrmsr(MSR_IA32_MISC_ENABLE, l | MSR_IA32_MISC_ENABLE_TM1, h);
 514 
 515         /* Unmask the thermal vector: */
 516         l = apic_read(APIC_LVTTHMR);
 517         apic_write(APIC_LVTTHMR, l & ~APIC_LVT_MASKED);
 518 
 519         pr_info_once("CPU0: Thermal monitoring enabled (%s)\n",
 520                       tm2 ? "TM2" : "TM1");
 521 
 522         /* enable thermal throttle processing */
 523         atomic_set(&therm_throt_en, 1);
 524 }

/* [<][>][^][v][top][bottom][index][help] */