mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
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>


             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®