hwmon: (coretemp) Fix handling of isolated SMT siblings

Commit 0f8b916bc5 ("hwmon: (coretemp) avoid RDMSR interrupts to
isolated CPUs") prevents create_core_data() from creating temperature
data for an isolated CPU. coretemp_cpu_online(), however, still adds
that CPU to pdata->cpumask.

When an isolated SMT thread is processed before a housekeeping sibling,
the mask makes coretemp_cpu_online() believe that the core is already
represented. The housekeeping sibling then gets no temperature
attributes. Package attributes are similarly not retried when the first
CPU processed in a die is isolated.

The mask is also used to select a replacement CPU when a sensor target
goes offline. Including isolated CPUs permits the driver to retarget a
sensor to one, causing subsequent sysfs reads to send an RDMSR IPI to an
isolated CPU.

Keep isolated CPUs out of pdata->cpumask by moving the housekeeping check
to coretemp_cpu_online(). Sensor creation is then deferred to an eligible
CPU, and hotplug replacement targets remain on housekeeping CPUs.

Tested on an Intel Core i7-10510U running 6.18.50-3-cachyos-lts, with
nohz_full=1 on CPU 1 and its housekeeping SMT sibling on CPU 5. The stock
driver omitted Core 1 after module load and retained its readable sensor
after CPU 5 was offlined. The patched driver exposed Core 1, removed it
when CPU 5 went offline, and restored it when CPU 5 returned.

Fixes: 0f8b916bc5 ("hwmon: (coretemp) avoid RDMSR interrupts to isolated CPUs")
Cc: stable@vger.kernel.org
Cc: Marcelo Tosatti <mtosatti@redhat.com>
Signed-off-by: Ximing Zhang <xzhangjr@gmail.com>
Tested-by: Asaf Nuri Bertizlioğlu <ycistak@gmail.com>
Link: https://patch.msgid.link/20261016-codex-coretemp-housekeeping-v1-1-96618c5676b2@gmail.com
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
This commit is contained in:
Ximing Zhang 2026-10-16 12:36:37 +04:00 committed by Guenter Roeck
parent 8e9bd28236
commit 37c1974a0e

View File

@ -568,9 +568,6 @@ static int create_core_data(struct platform_device *pdev, unsigned int cpu,
u64 val;
int err;
if (!housekeeping_cpu(cpu, HK_TYPE_MISC))
return 0;
tdata = init_temp_data(pdata, cpu, pkg_flag);
if (!tdata)
return -ENOMEM;
@ -690,6 +687,14 @@ static int coretemp_cpu_online(unsigned int cpu)
if (!cpu_has(c, X86_FEATURE_DTHERM))
return -ENODEV;
/*
* Keep isolated CPUs out of pdata->cpumask. Besides tracking the CPUs
* available to this driver, the mask is used to select the CPU on which
* to read the temperature MSRs.
*/
if (!housekeeping_cpu(cpu, HK_TYPE_MISC))
return 0;
pdata = platform_get_drvdata(pdev);
if (!pdata->hwmon_dev) {
struct device *hwmon;
@ -719,8 +724,8 @@ static int coretemp_cpu_online(unsigned int cpu)
}
/*
* Check whether a thread sibling is already online. If not add the
* interface for this CPU core.
* Check whether a housekeeping thread sibling is already online. If
* not, add the interface for this CPU core.
*/
if (!cpumask_intersects(&pdata->cpumask, topology_sibling_cpumask(cpu)))
coretemp_add_core(pdev, cpu, 0);
@ -750,9 +755,9 @@ static int coretemp_cpu_offline(unsigned int cpu)
cpumask_clear_cpu(cpu, &pd->cpumask);
/*
* If this is the last thread sibling, remove the CPU core
* interface, If there is still a sibling online, transfer the
* target cpu of that core interface to it.
* If this is the last housekeeping thread sibling, remove the CPU core
* interface. If there is still a housekeeping sibling online, transfer
* the target CPU of that core interface to it.
*/
target = cpumask_any_and(&pd->cpumask, topology_sibling_cpumask(cpu));
if (target >= nr_cpu_ids) {
@ -764,7 +769,8 @@ static int coretemp_cpu_offline(unsigned int cpu)
}
/*
* If all cores in this pkg are offline, remove the interface.
* If all housekeeping cores in this pkg are offline, remove the
* interface.
*/
tdata = get_temp_data(pd, -1);
if (cpumask_empty(&pd->cpumask)) {
@ -777,7 +783,7 @@ static int coretemp_cpu_offline(unsigned int cpu)
/*
* Check whether this core is the target for the package
* interface. We need to assign it to some other cpu.
* interface. We need to assign it to some other housekeeping CPU.
*/
if (tdata && tdata->cpu == cpu) {
target = cpumask_first(&pd->cpumask);