x86/mce/therm_throt: Do not access uninitialized therm_work
It is relatively easy to trigger the following boot splat on an Ice Lake
client platform. The call stack is like:
kernel BUG at kernel/timer/timer.c:1152!
Call Trace:
__queue_delayed_work
queue_delayed_work_on
therm_throt_process
intel_thermal_interrupt
...
The reason is that a CPU's thermal interrupt is enabled prior to
executing its hotplug onlining callback which will initialize the
throttling workqueues.
Such a race can lead to therm_throt_process() accessing an uninitialized
therm_work, leading to the above BUG at a very early bootup stage.
Therefore, unmask the thermal interrupt vector only after having setup
the workqueues completely.
[ bp: Heavily massage commit message and correct comment formatting. ]
Fixes: f6656208f0
("x86/mce/therm_throt: Optimize notifications of thermal throttle")
Signed-off-by: Chuansheng Liu <chuansheng.liu@intel.com>
Signed-off-by: Borislav Petkov <bp@suse.de>
Acked-by: Tony Luck <tony.luck@intel.com>
Link: https://lkml.kernel.org/r/20200107004116.59353-1-chuansheng.liu@intel.com
This commit is contained in:
Родитель
b3a987b026
Коммит
978370956d
|
@ -467,6 +467,7 @@ static int thermal_throttle_online(unsigned int cpu)
|
|||
{
|
||||
struct thermal_state *state = &per_cpu(thermal_state, cpu);
|
||||
struct device *dev = get_cpu_device(cpu);
|
||||
u32 l;
|
||||
|
||||
state->package_throttle.level = PACKAGE_LEVEL;
|
||||
state->core_throttle.level = CORE_LEVEL;
|
||||
|
@ -474,6 +475,10 @@ static int thermal_throttle_online(unsigned int cpu)
|
|||
INIT_DELAYED_WORK(&state->package_throttle.therm_work, throttle_active_work);
|
||||
INIT_DELAYED_WORK(&state->core_throttle.therm_work, throttle_active_work);
|
||||
|
||||
/* Unmask the thermal vector after the above workqueues are initialized. */
|
||||
l = apic_read(APIC_LVTTHMR);
|
||||
apic_write(APIC_LVTTHMR, l & ~APIC_LVT_MASKED);
|
||||
|
||||
return thermal_throttle_add_dev(dev, cpu);
|
||||
}
|
||||
|
||||
|
@ -722,10 +727,6 @@ void intel_init_thermal(struct cpuinfo_x86 *c)
|
|||
rdmsr(MSR_IA32_MISC_ENABLE, l, h);
|
||||
wrmsr(MSR_IA32_MISC_ENABLE, l | MSR_IA32_MISC_ENABLE_TM1, h);
|
||||
|
||||
/* Unmask the thermal vector: */
|
||||
l = apic_read(APIC_LVTTHMR);
|
||||
apic_write(APIC_LVTTHMR, l & ~APIC_LVT_MASKED);
|
||||
|
||||
pr_info_once("CPU0: Thermal monitoring enabled (%s)\n",
|
||||
tm2 ? "TM2" : "TM1");
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче