From: Yury Norov <ynorov@nvidia.com>
To: Peter Zijlstra <peterz@infradead.org>,
Ingo Molnar <mingo@redhat.com>, Thomas Gleixner <tglx@kernel.org>,
Juri Lelli <juri.lelli@redhat.com>,
Vincent Guittot <vincent.guittot@linaro.org>,
Shrikanth Hegde <sshegde@linux.ibm.com>
Cc: Yury Norov <ynorov@nvidia.com>, Yury Norov <yury.norov@gmail.com>,
"Rafael J. Wysocki" <rafael@kernel.org>,
Alexander Gordeev <agordeev@linux.ibm.com>,
Andrea Righi <arighi@nvidia.com>, Ben Segall <bsegall@google.com>,
Christian Borntraeger <borntraeger@linux.ibm.com>,
Danilo Krummrich <dakr@kernel.org>,
Dietmar Eggemann <dietmar.eggemann@arm.com>,
Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
Heiko Carstens <hca@linux.ibm.com>,
Johan Hovold <johan@kernel.org>, Jonathan Corbet <corbet@lwn.net>,
K Prateek Nayak <kprateek.nayak@amd.com>,
Mel Gorman <mgorman@suse.de>, Mete Durlu <meted@linux.ibm.com>,
Randy Dunlap <rdunlap@infradead.org>,
Rasmus Villemoes <linux@rasmusvillemoes.dk>,
Shuah Khan <skhan@linuxfoundation.org>,
Steven Rostedt <rostedt@goodmis.org>,
Sven Schnelle <svens@linux.ibm.com>,
Valentin Schneider <vschneid@redhat.com>,
Vasily Gorbik <gor@linux.ibm.com>,
linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org,
driver-core@lists.linux.dev, linux-s390@vger.kernel.org
Subject: [PATCH 6/6] cpu: Add per-CPU preferred sysfs control
Date: Sun, 1 Nov 2026 14:22:02 -0500 [thread overview]
Message-ID: <20261101192203.6979-7-ynorov@nvidia.com> (raw)
In-Reply-To: <20261101192203.6979-1-ynorov@nvidia.com>
Expose a writable preferred attribute for each CPU so users can manually
select CPUs for scheduler placement. This allows users to select any
desired combination of preferred CPUs, except for selecting inactive
CPUs and deselecting the last preferred CPU.
The manual method doesn't imply any preference over automated governors.
If an automated module is loaded, it may override user preferences, and
vice versa.
Fair tasks whose allowed CPUs contain no preferred CPU can still run
on active non-preferred CPUs. Other scheduling classes are unaffected.
This creates an environment similar to isolcpus, except that the list of
isolated CPUs can't be changed at runtime. Tick suppression, RCU
offloading, and managed-IRQ avoidance are compatible with preferred CPUs,
but may require separate configuration.
Signed-off-by: Yury Norov <ynorov@nvidia.com>
---
.../ABI/testing/sysfs-devices-system-cpu | 14 ++---
.../sysfs-devices-system-cpu-preferred | 37 +++++++++++++
Documentation/scheduler/sched-paravirt.rst | 26 +++++++--
drivers/base/cpu.c | 55 +++++++++++++++++++
kernel/Kconfig.preempt | 9 ++-
5 files changed, 128 insertions(+), 13 deletions(-)
create mode 100644 Documentation/ABI/testing/sysfs-devices-system-cpu-preferred
diff --git a/Documentation/ABI/testing/sysfs-devices-system-cpu b/Documentation/ABI/testing/sysfs-devices-system-cpu
index 545687ebadcc..0af57b55ed30 100644
--- a/Documentation/ABI/testing/sysfs-devices-system-cpu
+++ b/Documentation/ABI/testing/sysfs-devices-system-cpu
@@ -821,12 +821,10 @@ What: /sys/devices/system/cpu/preferred
Date: Sep 2026
Contact: Linux kernel mailing list <linux-kernel@vger.kernel.org>
Description:
- (RO) the list of preferred CPUs applicable in
- paravirtualized environments.
+ (RO) the list of CPUs preferred for fair-task placement.
+ Fair tasks whose allowed CPUs contain no preferred CPU can
+ still run on active non-preferred CPUs. Other scheduling
+ classes are unaffected.
- The steal governor driver dynamically adjusts this mask
- based on observed steal time. Scheduling tasks on
- CPUs outside of this list may lead to performance
- degradations due to underlying physical CPU contention.
-
- See Documentation/scheduler/sched-paravirt.rst for more details.
+ See: Documentation/ABI/testing/sysfs-devices-system-cpu-preferred;
+ Documentation/scheduler/sched-paravirt.rst for more details.
diff --git a/Documentation/ABI/testing/sysfs-devices-system-cpu-preferred b/Documentation/ABI/testing/sysfs-devices-system-cpu-preferred
new file mode 100644
index 000000000000..39ebfbdef365
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-devices-system-cpu-preferred
@@ -0,0 +1,37 @@
+What: /sys/devices/system/cpu/cpu[0-9]*/preferred
+Date: October 2026
+Contact: Yury Norov <yury.norov@gmail.com>
+Description:
+ Control the availability of a given CPU for fair scheduler to
+ place tasks. Reads 1 if this CPU is preferred, 0 otherwise.
+ Fair tasks whose allowed CPUs contain no preferred CPU can
+ still run on active non-preferred CPUs. Other scheduling
+ classes are unaffected.
+
+ As for the online attribute, boolean spellings such as 1/0, y/n
+ or on/off are accepted to set the preferred status of the CPU.
+
+ Removing a CPU from the preferred list and pinning a certain
+ task(s) on it provides a runtime environment similar to
+ isolcpus. Tick suppression, RCU offloading, and managed-IRQ
+ avoidance are compatible with preferred CPUs as well.
+
+ Selecting an inactive CPU, deselecting the last preferred CPU,
+ or writing an invalid boolean fails with EINVAL without changing
+ the mask. Writing the current value is a no-op. Writes across
+ all CPUs are serialized. To replace a selection, select new CPUs
+ before deselecting the old ones.
+
+ The list of preferred CPUs can be found in:
+
+ /sys/devices/system/cpu/preferred.
+
+ CPU hotplug sets the status of new active CPU as preferred, and
+ deactivated CPUs become non-preferred. Offlining the last
+ preferred CPU resets the status such that all remaining active
+ CPUs become preferred; and emits a notice in the kernel log.
+
+ This interface can be used together with automated interfaces,
+ like steal governor. All interfaces have the same priority: if
+ running in parallel, they may override each other's policy in
+ any order.
diff --git a/Documentation/scheduler/sched-paravirt.rst b/Documentation/scheduler/sched-paravirt.rst
index 311cdbf2722b..2d8e83194c48 100644
--- a/Documentation/scheduler/sched-paravirt.rst
+++ b/Documentation/scheduler/sched-paravirt.rst
@@ -42,13 +42,31 @@ This is achieved by:
``/sys/devices/system/cpu/preferred`` prints the current ``cpu_preferred_mask``
in cpulist format.
+Manual selection is available with ``CONFIG_PREFERRED_CPU`` (which can coexist
+with ``CONFIG_STEAL_GOVERNOR``). Write ``1`` or ``0`` to a CPU's ``preferred``
+attribute as root, for example::
+
+ echo 1 > /sys/devices/system/cpu/cpu1/preferred
+ echo 0 > /sys/devices/system/cpu/cpu0/preferred
+
+Only active CPUs can be selected, and the last preferred CPU cannot be
+deselected. The attribute is available even for CPUs without an ``online``
+attribute. The aggregate ``/sys/devices/system/cpu/preferred`` remains
+read-only.
+
+Manual writes and steal governor updates are serialized. Manual selections
+are not persistent constraints: subsequent governor samples may change them.
+
+See ``Documentation/ABI/testing/sysfs-devices-system-cpu-preferred`` for the
+interface and CPU hotplug semantics.
+
Notes:
1. This feature is available under ``CONFIG_PREFERRED_CPU``. Driver which
makes decisions should enable it. For example, steal_governor driver
(``CONFIG_STEAL_GOVERNOR``). On enabling the driver, CPU preferred state
- can change based on steal time. Without the driver, preferred CPUs is
- same as active CPUs.
+ can change based on steal time. Initially, all active CPUs are preferred.
+ Manual sysfs writes can change the mask without a policy driver.
2. This feature works for the FAIR class only.
@@ -56,8 +74,8 @@ Notes:
to run based on its affinity. But no load balancing happens if it is affined
only on non-preferred CPUs.
-4. Decision to change the preferred CPU state is driven by the kernel.
- Hence it shouldn't break user affinities. One of the main reasons why
+4. Preferred CPU state can be changed by a kernel policy driver or through
+ sysfs, while preserving task affinity. One of the main reasons why
CPU hotplug or Isolated cpuset partitions was not a solution.
5. This feature works best only when all the Guest VMs enable the feature as
diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c
index 747915ff974f..79896dae92f3 100644
--- a/drivers/base/cpu.c
+++ b/drivers/base/cpu.c
@@ -5,6 +5,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
+#include <linux/mutex.h>
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/cpu.h>
@@ -145,6 +146,54 @@ static DEVICE_ATTR(release, S_IWUSR, NULL, cpu_release_store);
#endif /* CONFIG_ARCH_CPU_PROBE_RELEASE */
#endif /* CONFIG_HOTPLUG_CPU */
+#ifdef CONFIG_PREFERRED_CPU
+static ssize_t preferred_cpu_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ guard(cpus_read_lock)();
+ guard(mutex)(&cpu_preferred_mutex);
+
+ return sysfs_emit(buf, "%u\n", cpu_preferred(dev->id));
+}
+
+static ssize_t preferred_cpu_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned int cpu = dev->id;
+ bool preferred;
+ int ret;
+
+ ret = kstrtobool(buf, &preferred);
+ if (ret)
+ return ret;
+
+ guard(cpus_read_lock)();
+ guard(mutex)(&cpu_preferred_mutex);
+
+ if (preferred && !cpu_active(cpu))
+ return -EINVAL;
+ if (!preferred && cpu_preferred(cpu) &&
+ cpumask_weight(cpu_preferred_mask) == 1)
+ return -EINVAL;
+
+ set_cpu_preferred(cpu, preferred);
+ return count;
+}
+
+static struct device_attribute dev_attr_cpu_preferred =
+ __DEVICE_ATTR(preferred, 0644, preferred_cpu_show, preferred_cpu_store);
+
+static struct attribute *preferred_cpu_attrs[] = {
+ &dev_attr_cpu_preferred.attr,
+ NULL
+};
+
+static const struct attribute_group preferred_cpu_attr_group = {
+ .attrs = preferred_cpu_attrs,
+};
+#endif /* CONFIG_PREFERRED_CPU */
+
#ifdef CONFIG_CRASH_DUMP
#include <linux/kexec.h>
@@ -190,6 +239,9 @@ static const struct attribute_group crash_note_cpu_attr_group = {
#endif
static const struct attribute_group *common_cpu_attr_groups[] = {
+#ifdef CONFIG_PREFERRED_CPU
+ &preferred_cpu_attr_group,
+#endif
#ifdef CONFIG_CRASH_DUMP
&crash_note_cpu_attr_group,
#endif
@@ -197,6 +249,9 @@ static const struct attribute_group *common_cpu_attr_groups[] = {
};
static const struct attribute_group *hotplugable_cpu_attr_groups[] = {
+#ifdef CONFIG_PREFERRED_CPU
+ &preferred_cpu_attr_group,
+#endif
#ifdef CONFIG_CRASH_DUMP
&crash_note_cpu_attr_group,
#endif
diff --git a/kernel/Kconfig.preempt b/kernel/Kconfig.preempt
index fa6d0eba5b23..606aba68590f 100644
--- a/kernel/Kconfig.preempt
+++ b/kernel/Kconfig.preempt
@@ -203,6 +203,13 @@ config PREFERRED_CPU
respecting task CPU affinity. Non-preferred CPUs remain online
and can still run tasks whose affinity requires it.
- See Documentation/scheduler/sched-paravirt.rst for details.
+ Preferred CPUs can be selected manually through the per-CPU
+ preferred sysfs attribute or managed automatically, e.g. by the
+ steal governor to reduce CPU contention in virtual machines. All
+ active CPUs are preferred initially.
+
+ See Documentation/scheduler/sched-paravirt.rst and
+ Documentation/ABI/testing/sysfs-devices-system-cpu-preferred
+ for details.
If unsure, say N.
--
2.53.0
next prev parent reply other threads:[~2026-11-01 19:22 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-01 19:21 [PATCH 0/6] sched: Expose writable interface for preferred CPUs mask Yury Norov
2026-11-01 19:21 ` [PATCH 1/6] sched: decouple PREFERRED_CPU from PARAVIRT in Kconfig.preempt Yury Norov
2026-11-01 19:21 ` [PATCH 2/6] cpumask: Add reset_preferred_cpumask() helper Yury Norov
2026-11-01 19:21 ` [PATCH 3/6] sched: Restore preferred CPUs when hotplug removes the last one Yury Norov
2026-11-01 19:22 ` [PATCH 4/6] sched: serialize preferred cpumask update better Yury Norov
2026-11-01 19:22 ` [PATCH 5/6] virt: steal_governor: Warn on unexpected preferred mask states Yury Norov
2026-11-01 19:22 ` Yury Norov [this message]
2026-11-02 8:47 ` [PATCH 0/6] sched: Expose writable interface for preferred CPUs mask Peter Zijlstra
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=20261101192203.6979-7-ynorov@nvidia.com \
--to=ynorov@nvidia.com \
--cc=agordeev@linux.ibm.com \
--cc=arighi@nvidia.com \
--cc=borntraeger@linux.ibm.com \
--cc=bsegall@google.com \
--cc=corbet@lwn.net \
--cc=dakr@kernel.org \
--cc=dietmar.eggemann@arm.com \
--cc=driver-core@lists.linux.dev \
--cc=gor@linux.ibm.com \
--cc=gregkh@linuxfoundation.org \
--cc=hca@linux.ibm.com \
--cc=johan@kernel.org \
--cc=juri.lelli@redhat.com \
--cc=kprateek.nayak@amd.com \
--cc=linux-doc@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-s390@vger.kernel.org \
--cc=linux@rasmusvillemoes.dk \
--cc=meted@linux.ibm.com \
--cc=mgorman@suse.de \
--cc=mingo@redhat.com \
--cc=peterz@infradead.org \
--cc=rafael@kernel.org \
--cc=rdunlap@infradead.org \
--cc=rostedt@goodmis.org \
--cc=skhan@linuxfoundation.org \
--cc=sshegde@linux.ibm.com \
--cc=svens@linux.ibm.com \
--cc=tglx@kernel.org \
--cc=vincent.guittot@linaro.org \
--cc=vschneid@redhat.com \
--cc=yury.norov@gmail.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