From: Ricardo Neri <ricardo.neri-calderon@linux.intel.com>
To: "Rafael J. Wysocki" <rafael@kernel.org>,
Daniel Lezcano <daniel.lezcano@kernel.org>,
Zhang Rui <rui.zhang@intel.com>,
Lukasz Luba <lukasz.luba@arm.com>,
Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
Cc: linux-pm@vger.kernel.org, linux-api@vger.kernel.org,
linux-kernel@vger.kernel.org, ricardo.neri@intel.com,
Ricardo Neri <ricardo.neri-calderon@linux.intel.com>
Subject: [PATCH 00/13] thermal: intel: dpti: Direct the package thermal interrupt to a chosen CPU
Date: Mon, 09 Nov 2026 19:36:27 -0800 [thread overview]
Message-ID: <20261109-dpti-custom-cpu-v1-0-ead8e2d2067e@linux.intel.com> (raw)
The directed package-level thermal interrupt (DPTI) lets a single CPU per
package receive the package thermal interrupt instead of broadcasting it to
every CPU in the package. Today that CPU is chosen with no regard for the
user's intent: the first CPU of a package to come online claims the
interrupt, and on offline it is redirected to another CPU of the package.
As a result, the interrupt can land on a CPU the user would rather keep
undisturbed, such as a nohz_full CPU, whose tickless isolation it breaks.
This series gives the user explicit control over the interrupt owner
through sysfs. It also updates automatic selection of the owner CPU to
avoid CPUs isolated at boot through the nohz_full and isolcpus=nohz
command-line options.
CPUs isolated through isolcpus=domain or a cpuset isolated partition are
left for a follow-up series, if there is interest.
The sysfs interface
-------------------
On a system with DPTI, every online CPU gets a boolean attribute in its
existing thermal_throttle group:
/sys/devices/system/cpu/cpuX/thermal_throttle/package_interrupt_owner
Reading it answers a question about cpuX alone: 1 if cpuX is the CPU
currently programmed to receive its package's thermal interrupt, 0
otherwise. The owner is a per-package property, so at most one CPU of a
package reads 1, and all of them read 0 while the interrupt is not directed
to any CPU.
Writing 1 migrates the interrupt to cpuX and pins it there, overriding
automatic selection. The request is honored even if cpuX is
nohz_full-isolated, in which case a warning is logged. The write fails if
the hardware does not acknowledge the new owner.
Writing 0 releases a pin on cpuX and returns the package to automatic
selection. If cpuX is nohz_full-isolated, the interrupt moves to a CPU of
the package that is not, when one is online. Otherwise it stays on cpuX.
Writing 0 to a CPU that is not pinned has no effect.
# Direct this package's thermal interrupt to CPU 3 and keep it there
echo 1 > \
/sys/devices/system/cpu/cpu3/thermal_throttle/package_interrupt_owner
# Let automatic selection govern that package again
echo 0 > \
/sys/devices/system/cpu/cpu3/thermal_throttle/package_interrupt_owner
# List the CPUs that own their package's interrupt
grep -l '^1$' \
/sys/devices/system/cpu/cpu*/thermal_throttle/package_interrupt_owner
Known limitations
-----------------
To keep the interface and the implementation simple, the interface accepts
these limitations:
- The file reports owner state, not pin state. Writing 0 to a CPU that is
not isolated unpins without migrating: cpuX keeps the interrupt and
keeps reading 1 until the placement changes, for example when cpuX goes
offline.
- There is no request to move the interrupt away from cpuX. Pin another
CPU of the package instead.
- A write to one CPU changes what another CPU's file reads: pinning cpuY
makes the previous owner, cpuX, read 0 without cpuX's file being
written.
- Finding which CPU owns a given package's interrupt takes one read per
CPU of the package instead of a single read.
- The pinned preference is not observable. While a pinned CPU is offline,
the remaining CPUs of the package report the automatically chosen
fallback. The pin is silently restored when the pinned CPU comes back
online.
- The same file appears under every CPU of a package, because per-package
state is exposed through the per-CPU device. This reuses the existing
per-CPU device infrastructure and mirrors package_throttle_count, which
is also per-package state shown per-CPU.
Organization
------------
The series is organized as follows:
* Fix (patch 1): an existing race between kernel_kexec() and CPU hotplug
can program a new owner after the syscore shutdown has cleared the DPTI
in all packages and leave it enabled in the next kernel. Independent of
the rest of the series.
* Preparation (patches 2-4): prefix the log messages of therm_throt.c
with pr_fmt(), move the sysfs device helpers next to their callers, and
give the DPTI code a consistent dpti_ naming scheme.
* Groundwork (patches 5-9): owner changes become more likely once the
selection and sysfs patches land. Limit the full teardown to boot, so
that a later failure affects only its package; group per-package state
in struct dpti_pkg; and factor the programming sequence into helpers
that run it on the target CPU, from any CPU and entry point.
* Rank-based owner selection (patch 10): instead of special-casing pinned
and isolated CPUs, rank every CPU and move the interrupt only on a
strict rank improvement.
* Serialization (patch 11): introduce dpti_mutex ahead of the sysfs
writer, which runs concurrently with the CPU hotplug callbacks.
* Avoid nohz_full-isolated CPUs (patch 12): rank housekeeping CPUs above
isolated ones, and migrate as soon as a housekeeping CPU comes online.
* The sysfs interface (patch 13): let the user pin the owner.
Summary of testing
------------------
Tested on a 1-socket system with DPTI and on a 2-socket system without it,
where test-only patches emulate DPTI.
- CPU hotplug:
- Sweeps that offline and then online each CPU in turn, checking the
owner in MSR_IA32_THERM_INTERRUPT (and in sysfs from patch 13) after
every step: about 750 transitions across the kernels of every patch on
the 1-socket system, and about 950 on the 2-socket system, where
package owners go offline and the interrupt migrates.
- lockdep stress runs of up to 10,000 offline/online cycles against
sysfs writes, with no deadlocks.
- Injected handover failures always ended with either the old owner
kept or the package broadcasting.
- Isolation (nohz_full):
- The owner stayed on housekeeping CPUs and fell back to an isolated CPU,
with a warning, only when it had to. Ownership migrated back to a
housekeeping CPU as soon as one came online.
- 0 of 36 package interrupts reached an isolated CPU with DPTI, against
26 of 26 without it.
- Hibernation (S4):
- One cycle on every patch kernel, with the owner restored each time,
and a pin restored where one was set.
- All four combinations of image and boot kernel, with and without DPTI,
left no stale state.
- kexec:
- The sysfs race went from 22 of 22 failing to 20 of 20 clean with the
fix in patches 1 and 11. The CPU hotplug race went from 4 of 4 failing
to 0 of 5 with patch 1.
- A kexec into a kernel without DPTI always found the hardware clean.
- Configurations:
- Every patch builds cleanly in an x86_64_defconfig-based configuration,
with each of NO_HZ_FULL, SYSFS, SMP, CPU_ISOLATION, PM_SLEEP, lockdep
and X86_THERMAL_VECTOR turned off one at a time, and in a 32-bit
build. On hardware, I ran the test systems' distribution configuration
with debug options, plus three variants: NO_HZ_FULL=n, KASAN with
kmemleak, and a no-debug performance build.
Thanks and BR,
Ricardo
Signed-off-by: Ricardo Neri <ricardo.neri-calderon@linux.intel.com>
---
Ricardo Neri (13):
thermal: intel: Keep directed package interrupts off after syscore shutdown
thermal: intel: Prefix log messages via pr_fmt()
thermal: intel: Move the sysfs device helpers next to their callers
thermal: intel: dpti: Adopt the dpti_ prefix and the owner terminology
thermal: intel: dpti: Tear down DPTI only during boot
thermal: intel: dpti: Introduce struct dpti_pkg for per-package state
thermal: intel: dpti: Configure the local CPU by value
thermal: intel: dpti: Factor the programming sequence out into a helper
thermal: intel: dpti: Program the directed interrupt on the target CPU
thermal: intel: dpti: Add rank-based owner selection
thermal: intel: dpti: Serialize updates to the directed interrupt state
thermal: intel: dpti: Avoid nohz_full CPUs when possible
thermal: intel: dpti: Add sysfs control of interrupt owner
Documentation/ABI/testing/sysfs-devices-system-cpu | 40 ++
drivers/thermal/intel/therm_throt.c | 739 ++++++++++++++++-----
2 files changed, 606 insertions(+), 173 deletions(-)
---
base-commit: b76a128501206bf16467a918f09b9f07ec239429
change-id: 20260720-dpti-custom-cpu-543837e32275
Best regards,
--
Ricardo Neri <ricardo.neri-calderon@linux.intel.com>
next reply other threads:[~2026-11-10 3:36 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-10 3:36 Ricardo Neri [this message]
2026-11-10 3:36 ` [PATCH 01/13] thermal: intel: Keep directed package interrupts off after syscore shutdown Ricardo Neri
2026-11-10 3:36 ` [PATCH 02/13] thermal: intel: Prefix log messages via pr_fmt() Ricardo Neri
2026-11-10 3:36 ` [PATCH 03/13] thermal: intel: Move the sysfs device helpers next to their callers Ricardo Neri
2026-11-10 3:36 ` [PATCH 04/13] thermal: intel: dpti: Adopt the dpti_ prefix and the owner terminology Ricardo Neri
2026-11-10 3:36 ` [PATCH 05/13] thermal: intel: dpti: Tear down DPTI only during boot Ricardo Neri
2026-11-10 3:36 ` [PATCH 06/13] thermal: intel: dpti: Introduce struct dpti_pkg for per-package state Ricardo Neri
2026-11-10 3:36 ` [PATCH 07/13] thermal: intel: dpti: Configure the local CPU by value Ricardo Neri
2026-11-10 3:36 ` [PATCH 08/13] thermal: intel: dpti: Factor the programming sequence out into a helper Ricardo Neri
2026-11-10 3:36 ` [PATCH 09/13] thermal: intel: dpti: Program the directed interrupt on the target CPU Ricardo Neri
2026-11-10 3:36 ` [PATCH 10/13] thermal: intel: dpti: Add rank-based owner selection Ricardo Neri
2026-11-10 3:36 ` [PATCH 11/13] thermal: intel: dpti: Serialize updates to the directed interrupt state Ricardo Neri
2026-11-10 3:36 ` [PATCH 12/13] thermal: intel: dpti: Avoid nohz_full CPUs when possible Ricardo Neri
2026-11-10 3:36 ` [PATCH 13/13] thermal: intel: dpti: Add sysfs control of interrupt owner Ricardo Neri
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261109-dpti-custom-cpu-v1-0-ead8e2d2067e@linux.intel.com \
--to=ricardo.neri-calderon@linux.intel.com \
--cc=daniel.lezcano@kernel.org \
--cc=linux-api@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-pm@vger.kernel.org \
--cc=lukasz.luba@arm.com \
--cc=rafael@kernel.org \
--cc=ricardo.neri@intel.com \
--cc=rui.zhang@intel.com \
--cc=srinivas.pandruvada@linux.intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®