* [PATCH 1/6] sched: decouple PREFERRED_CPU from PARAVIRT in Kconfig.preempt
2026-11-01 19:21 [PATCH 0/6] sched: Expose writable interface for preferred CPUs mask Yury Norov
@ 2026-11-01 19:21 ` Yury Norov
2026-11-02 10:16 ` Ilya Leoshkevich
2026-11-01 19:21 ` [PATCH 2/6] cpumask: Add reset_preferred_cpumask() helper Yury Norov
` (5 subsequent siblings)
6 siblings, 1 reply; 14+ messages in thread
From: Yury Norov @ 2026-11-01 19:21 UTC (permalink / raw)
To: Peter Zijlstra, Ingo Molnar, Thomas Gleixner, Juri Lelli,
Vincent Guittot, Shrikanth Hegde
Cc: Yury Norov, Yury Norov, Rafael J. Wysocki, Alexander Gordeev,
Andrea Righi, Ben Segall, Christian Borntraeger, Danilo Krummrich,
Dietmar Eggemann, Greg Kroah-Hartman, Heiko Carstens,
Johan Hovold, Jonathan Corbet, K Prateek Nayak, Mel Gorman,
Mete Durlu, Randy Dunlap, Rasmus Villemoes, Shuah Khan,
Steven Rostedt, Sven Schnelle, Valentin Schneider, Vasily Gorbik,
linux-kernel, linux-doc, driver-core, linux-s390
The IBM s390 doesn't enable PARAVIRT config for their hardware
virtualized Logical Partitions (LPAR). However, the steal time is
accounted for the LPARs, once the config VIRT_CPU_ACCOUNTING_NATIVE
is enabled.
Preferred cpumask doesn't rely on any feature gated by PARAVIRT config,
and requires it to minimize the configuration space and runtime overhead,
with the lack of non-paravirt user. Now that s390 wants to adopt preferred
cpumask, there's no reason to keep it coupled to paravirt.
Make PREFERRED_CPU a user-configurable option, even if paravirtualization
is not enabled, and drop PARAVIRT dependency on the steal governor.
Keep the default module selection conditional on PARAVIRT so other SMP
configurations can opt in without enabling the governor by default.
Link: https://lore.kernel.org/all/4605dad5-aab2-49e3-b919-bf9897181834@linux.ibm.com/
CC: Mete Durlu <meted@linux.ibm.com>
Signed-off-by: Yury Norov <ynorov@nvidia.com>
---
Can be applied independently from the rest of the series.
drivers/virt/Kconfig | 8 ++++++--
kernel/Kconfig.preempt | 12 ++++++++++--
2 files changed, 16 insertions(+), 4 deletions(-)
diff --git a/drivers/virt/Kconfig b/drivers/virt/Kconfig
index eeb84e578ddf..2e79ece24a77 100644
--- a/drivers/virt/Kconfig
+++ b/drivers/virt/Kconfig
@@ -43,9 +43,9 @@ config FSL_HV_MANAGER
config STEAL_GOVERNOR
tristate "Dynamic vCPU management based on steal time"
- depends on PARAVIRT && SMP
+ depends on SMP
select PREFERRED_CPU
- default m
+ default m if PARAVIRT
help
This driver helps to reduce the steal time in paravirtualized
environments, thereby reducing vCPU preemption costs.
@@ -55,6 +55,10 @@ config STEAL_GOVERNOR
preferred CPUs could become subset of active CPUs.
More details are at: Documentation/driver-api/steal-governor.rst
+ It doesn't depend on config PARAVIRT because certain architectures
+ like LPAR on s390 don't enable PARAVIRT for their hardware assisted
+ virtualization, while providing steal time accounting.
+
It is recommended to build it as module and load the module
to enable it.
diff --git a/kernel/Kconfig.preempt b/kernel/Kconfig.preempt
index edc067a0c422..fa6d0eba5b23 100644
--- a/kernel/Kconfig.preempt
+++ b/kernel/Kconfig.preempt
@@ -196,5 +196,13 @@ config SCHED_CLASS_EXT
https://github.com/sched-ext/scx
config PREFERRED_CPU
- bool
- depends on SMP && PARAVIRT
+ bool "Preferred CPU scheduling"
+ depends on SMP
+ help
+ Allow the fair scheduler to favor a subset of active CPUs while
+ 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.
+
+ If unsure, say N.
--
2.53.0
^ permalink raw reply related [flat|nested] 14+ messages in thread* Re: [PATCH 1/6] sched: decouple PREFERRED_CPU from PARAVIRT in Kconfig.preempt
2026-11-01 19:21 ` [PATCH 1/6] sched: decouple PREFERRED_CPU from PARAVIRT in Kconfig.preempt Yury Norov
@ 2026-11-02 10:16 ` Ilya Leoshkevich
2026-11-02 11:00 ` Peter Zijlstra
0 siblings, 1 reply; 14+ messages in thread
From: Ilya Leoshkevich @ 2026-11-02 10:16 UTC (permalink / raw)
To: Yury Norov, Peter Zijlstra, Ingo Molnar, Thomas Gleixner,
Juri Lelli, Vincent Guittot, Shrikanth Hegde
Cc: Yury Norov, Rafael J. Wysocki, Alexander Gordeev, Andrea Righi,
Ben Segall, Christian Borntraeger, Danilo Krummrich,
Dietmar Eggemann, Greg Kroah-Hartman, Heiko Carstens,
Johan Hovold, Jonathan Corbet, K Prateek Nayak, Mel Gorman,
Mete Durlu, Randy Dunlap, Rasmus Villemoes, Shuah Khan,
Steven Rostedt, Sven Schnelle, Valentin Schneider, Vasily Gorbik,
linux-kernel, linux-doc, driver-core, linux-s390
On 11/1/26 20:21, Yury Norov wrote:
> The IBM s390 doesn't enable PARAVIRT config for their hardware
> virtualized Logical Partitions (LPAR). However, the steal time is
> accounted for the LPARs, once the config VIRT_CPU_ACCOUNTING_NATIVE
> is enabled.
>
> Preferred cpumask doesn't rely on any feature gated by PARAVIRT config,
> and requires it to minimize the configuration space and runtime overhead,
> with the lack of non-paravirt user. Now that s390 wants to adopt preferred
> cpumask, there's no reason to keep it coupled to paravirt.
>
> Make PREFERRED_CPU a user-configurable option, even if paravirtualization
> is not enabled, and drop PARAVIRT dependency on the steal governor.
>
> Keep the default module selection conditional on PARAVIRT so other SMP
> configurations can opt in without enabling the governor by default.
>
> Link: https://lore.kernel.org/all/4605dad5-aab2-49e3-b919-bf9897181834@linux.ibm.com/
> CC: Mete Durlu <meted@linux.ibm.com>
> Signed-off-by: Yury Norov <ynorov@nvidia.com>
> ---
> Can be applied independently from the rest of the series.
>
> drivers/virt/Kconfig | 8 ++++++--
> kernel/Kconfig.preempt | 12 ++++++++++--
> 2 files changed, 16 insertions(+), 4 deletions(-)
This is really useful to us, since even though s390 is nominally
paravirtualized, it does not technically benefit from defining
CONFIG_PARAVIRT. Specifically, steal time accounting happens by
computing a difference between wall time and CPU time, and not by
explicitly querying the hypervisor.
Thanks!
Reviewed-by: Ilya Leoshkevich <iii@linux.ibm.com>
[...]
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 1/6] sched: decouple PREFERRED_CPU from PARAVIRT in Kconfig.preempt
2026-11-02 10:16 ` Ilya Leoshkevich
@ 2026-11-02 11:00 ` Peter Zijlstra
2026-11-02 11:34 ` Ilya Leoshkevich
0 siblings, 1 reply; 14+ messages in thread
From: Peter Zijlstra @ 2026-11-02 11:00 UTC (permalink / raw)
To: Ilya Leoshkevich
Cc: Yury Norov, Ingo Molnar, Thomas Gleixner, Juri Lelli,
Vincent Guittot, Shrikanth Hegde, Yury Norov, Rafael J. Wysocki,
Alexander Gordeev, Andrea Righi, Ben Segall,
Christian Borntraeger, Danilo Krummrich, Dietmar Eggemann,
Greg Kroah-Hartman, Heiko Carstens, Johan Hovold, Jonathan Corbet,
K Prateek Nayak, Mel Gorman, Mete Durlu, Randy Dunlap,
Rasmus Villemoes, Shuah Khan, Steven Rostedt, Sven Schnelle,
Valentin Schneider, Vasily Gorbik, linux-kernel, linux-doc,
driver-core, linux-s390
On Mon, Nov 02, 2026 at 11:16:30AM +0100, Ilya Leoshkevich wrote:
>
>
> On 11/1/26 20:21, Yury Norov wrote:
> > The IBM s390 doesn't enable PARAVIRT config for their hardware
> > virtualized Logical Partitions (LPAR). However, the steal time is
> > accounted for the LPARs, once the config VIRT_CPU_ACCOUNTING_NATIVE
> > is enabled.
> >
> > Preferred cpumask doesn't rely on any feature gated by PARAVIRT config,
> > and requires it to minimize the configuration space and runtime overhead,
> > with the lack of non-paravirt user. Now that s390 wants to adopt preferred
> > cpumask, there's no reason to keep it coupled to paravirt.
> >
> > Make PREFERRED_CPU a user-configurable option, even if paravirtualization
> > is not enabled, and drop PARAVIRT dependency on the steal governor.
> >
> > Keep the default module selection conditional on PARAVIRT so other SMP
> > configurations can opt in without enabling the governor by default.
> >
> > Link: https://lore.kernel.org/all/4605dad5-aab2-49e3-b919-bf9897181834@linux.ibm.com/
> > CC: Mete Durlu <meted@linux.ibm.com>
> > Signed-off-by: Yury Norov <ynorov@nvidia.com>
> > ---
> > Can be applied independently from the rest of the series.
> >
> > drivers/virt/Kconfig | 8 ++++++--
> > kernel/Kconfig.preempt | 12 ++++++++++--
> > 2 files changed, 16 insertions(+), 4 deletions(-)
>
> This is really useful to us, since even though s390 is nominally
> paravirtualized, it does not technically benefit from defining
> CONFIG_PARAVIRT.
And therefore removing PARAVIRT is the only possible solution?
> Specifically, steal time accounting happens by
> computing a difference between wall time and CPU time, and not by
> explicitly querying the hypervisor.
Nobody explicitly asks the hypervisor, that would be horrendously slow.
Something trivial like this should do.
---
arch/Kconfig | 9 +++++++++
arch/powerpc/platforms/pseries/Kconfig | 1 +
arch/s390/Kconfig | 1 +
drivers/virt/Kconfig | 2 +-
4 files changed, 12 insertions(+), 1 deletion(-)
diff --git a/arch/Kconfig b/arch/Kconfig
index 1163736de1f9..8980054beb52 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -1080,6 +1080,15 @@ config HAVE_IRQ_TIME_ACCOUNTING
config HAVE_PV_STEAL_CLOCK_GEN
bool
+#
+# Archs that can account CPUTIME_STEAL; normal route is through PARAVIRT which
+# selects HAVE_PV_STEAL_CLOCK_GEN. Directly selected by s390 and PPC-LPAR
+# which have their own thing and don't go through generic cputime accounting.
+#
+config HAVE_CPUTIME_STEAL
+ bool
+ default y if HAVE_PV_STEAL_CLOCK_GEN
+
config HAVE_MOVE_PUD
bool
help
diff --git a/arch/powerpc/platforms/pseries/Kconfig b/arch/powerpc/platforms/pseries/Kconfig
index 7d125e288f6e..3c49baf606d7 100644
--- a/arch/powerpc/platforms/pseries/Kconfig
+++ b/arch/powerpc/platforms/pseries/Kconfig
@@ -41,6 +41,7 @@ config PPC_SPLPAR
depends on PPC_PSERIES
select PARAVIRT_SPINLOCKS if PPC_QUEUED_SPINLOCKS
select PARAVIRT_TIME_ACCOUNTING if VIRT_CPU_ACCOUNTING_GEN
+ select HAVE_CPUTIME_STEAL
default y
help
Enabling this option will make the kernel run more efficiently
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
index 7138d923d86f..03a884355218 100644
--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -291,6 +291,7 @@ config S390
select USER_STACKTRACE_SUPPORT
select VDSO_GETRANDOM
select VIRT_CPU_ACCOUNTING
+ select HAVE_CPUTIME_STEAL
select VMAP_STACK
select ZONE_DMA
# Note: keep the above list sorted alphabetically
diff --git a/drivers/virt/Kconfig b/drivers/virt/Kconfig
index eeb84e578ddf..a3721d34a55c 100644
--- a/drivers/virt/Kconfig
+++ b/drivers/virt/Kconfig
@@ -43,7 +43,7 @@ config FSL_HV_MANAGER
config STEAL_GOVERNOR
tristate "Dynamic vCPU management based on steal time"
- depends on PARAVIRT && SMP
+ depends on SMP && HAVE_CPUTIME_STEAL
select PREFERRED_CPU
default m
help
^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [PATCH 1/6] sched: decouple PREFERRED_CPU from PARAVIRT in Kconfig.preempt
2026-11-02 11:00 ` Peter Zijlstra
@ 2026-11-02 11:34 ` Ilya Leoshkevich
2026-11-02 13:00 ` Shrikanth Hegde
0 siblings, 1 reply; 14+ messages in thread
From: Ilya Leoshkevich @ 2026-11-02 11:34 UTC (permalink / raw)
To: Peter Zijlstra
Cc: Yury Norov, Ingo Molnar, Thomas Gleixner, Juri Lelli,
Vincent Guittot, Shrikanth Hegde, Yury Norov, Rafael J. Wysocki,
Alexander Gordeev, Andrea Righi, Ben Segall,
Christian Borntraeger, Danilo Krummrich, Dietmar Eggemann,
Greg Kroah-Hartman, Heiko Carstens, Johan Hovold, Jonathan Corbet,
K Prateek Nayak, Mel Gorman, Mete Durlu, Randy Dunlap,
Rasmus Villemoes, Shuah Khan, Steven Rostedt, Sven Schnelle,
Valentin Schneider, Vasily Gorbik, linux-kernel, linux-doc,
driver-core, linux-s390
On 11/2/26 12:00, Peter Zijlstra wrote:
> On Mon, Nov 02, 2026 at 11:16:30AM +0100, Ilya Leoshkevich wrote:
>>
>>
>> On 11/1/26 20:21, Yury Norov wrote:
>>> The IBM s390 doesn't enable PARAVIRT config for their hardware
>>> virtualized Logical Partitions (LPAR). However, the steal time is
>>> accounted for the LPARs, once the config VIRT_CPU_ACCOUNTING_NATIVE
>>> is enabled.
>>>
>>> Preferred cpumask doesn't rely on any feature gated by PARAVIRT config,
>>> and requires it to minimize the configuration space and runtime overhead,
>>> with the lack of non-paravirt user. Now that s390 wants to adopt preferred
>>> cpumask, there's no reason to keep it coupled to paravirt.
>>>
>>> Make PREFERRED_CPU a user-configurable option, even if paravirtualization
>>> is not enabled, and drop PARAVIRT dependency on the steal governor.
>>>
>>> Keep the default module selection conditional on PARAVIRT so other SMP
>>> configurations can opt in without enabling the governor by default.
>>>
>>> Link: https://lore.kernel.org/all/4605dad5-aab2-49e3-b919-bf9897181834@linux.ibm.com/
>>> CC: Mete Durlu <meted@linux.ibm.com>
>>> Signed-off-by: Yury Norov <ynorov@nvidia.com>
>>> ---
>>> Can be applied independently from the rest of the series.
>>>
>>> drivers/virt/Kconfig | 8 ++++++--
>>> kernel/Kconfig.preempt | 12 ++++++++++--
>>> 2 files changed, 16 insertions(+), 4 deletions(-)
>>
>> This is really useful to us, since even though s390 is nominally
>> paravirtualized, it does not technically benefit from defining
>> CONFIG_PARAVIRT.
>
> And therefore removing PARAVIRT is the only possible solution?
>
>> Specifically, steal time accounting happens by
>> computing a difference between wall time and CPU time, and not by
>> explicitly querying the hypervisor.
>
> Nobody explicitly asks the hypervisor, that would be horrendously slow.
>
> Something trivial like this should do.
>
> ---
> arch/Kconfig | 9 +++++++++
> arch/powerpc/platforms/pseries/Kconfig | 1 +
> arch/s390/Kconfig | 1 +
> drivers/virt/Kconfig | 2 +-
> 4 files changed, 12 insertions(+), 1 deletion(-)
>
> diff --git a/arch/Kconfig b/arch/Kconfig
> index 1163736de1f9..8980054beb52 100644
> --- a/arch/Kconfig
> +++ b/arch/Kconfig
> @@ -1080,6 +1080,15 @@ config HAVE_IRQ_TIME_ACCOUNTING
> config HAVE_PV_STEAL_CLOCK_GEN
> bool
>
> +#
> +# Archs that can account CPUTIME_STEAL; normal route is through PARAVIRT which
> +# selects HAVE_PV_STEAL_CLOCK_GEN. Directly selected by s390 and PPC-LPAR
> +# which have their own thing and don't go through generic cputime accounting.
> +#
> +config HAVE_CPUTIME_STEAL
> + bool
> + default y if HAVE_PV_STEAL_CLOCK_GEN
> +
> config HAVE_MOVE_PUD
> bool
> help
> diff --git a/arch/powerpc/platforms/pseries/Kconfig b/arch/powerpc/platforms/pseries/Kconfig
> index 7d125e288f6e..3c49baf606d7 100644
> --- a/arch/powerpc/platforms/pseries/Kconfig
> +++ b/arch/powerpc/platforms/pseries/Kconfig
> @@ -41,6 +41,7 @@ config PPC_SPLPAR
> depends on PPC_PSERIES
> select PARAVIRT_SPINLOCKS if PPC_QUEUED_SPINLOCKS
> select PARAVIRT_TIME_ACCOUNTING if VIRT_CPU_ACCOUNTING_GEN
> + select HAVE_CPUTIME_STEAL
> default y
> help
> Enabling this option will make the kernel run more efficiently
> diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
> index 7138d923d86f..03a884355218 100644
> --- a/arch/s390/Kconfig
> +++ b/arch/s390/Kconfig
> @@ -291,6 +291,7 @@ config S390
> select USER_STACKTRACE_SUPPORT
> select VDSO_GETRANDOM
> select VIRT_CPU_ACCOUNTING
> + select HAVE_CPUTIME_STEAL
> select VMAP_STACK
> select ZONE_DMA
> # Note: keep the above list sorted alphabetically
> diff --git a/drivers/virt/Kconfig b/drivers/virt/Kconfig
> index eeb84e578ddf..a3721d34a55c 100644
> --- a/drivers/virt/Kconfig
> +++ b/drivers/virt/Kconfig
> @@ -43,7 +43,7 @@ config FSL_HV_MANAGER
>
> config STEAL_GOVERNOR
> tristate "Dynamic vCPU management based on steal time"
> - depends on PARAVIRT && SMP
> + depends on SMP && HAVE_CPUTIME_STEAL
> select PREFERRED_CPU
> default m
> help
I can't comment on the PPC part, but for s390 this works fine with the
following addition:
--- a/kernel/Kconfig.preempt
+++ b/kernel/Kconfig.preempt
@@ -197,4 +197,4 @@ config SCHED_CLASS_EXT
config PREFERRED_CPU
bool
- depends on SMP && PARAVIRT
+ depends on SMP && HAVE_CPUTIME_STEAL
^ permalink raw reply [flat|nested] 14+ messages in thread* Re: [PATCH 1/6] sched: decouple PREFERRED_CPU from PARAVIRT in Kconfig.preempt
2026-11-02 11:34 ` Ilya Leoshkevich
@ 2026-11-02 13:00 ` Shrikanth Hegde
2026-11-02 13:41 ` Ilya Leoshkevich
0 siblings, 1 reply; 14+ messages in thread
From: Shrikanth Hegde @ 2026-11-02 13:00 UTC (permalink / raw)
To: Ilya Leoshkevich, Peter Zijlstra, Mete Durlu, Yury Norov
Cc: Ingo Molnar, Thomas Gleixner, Juri Lelli, Vincent Guittot,
Yury Norov, Rafael J. Wysocki, Alexander Gordeev, Andrea Righi,
Ben Segall, Christian Borntraeger, Danilo Krummrich,
Dietmar Eggemann, Greg Kroah-Hartman, Heiko Carstens,
Johan Hovold, Jonathan Corbet, K Prateek Nayak, Mel Gorman,
Randy Dunlap, Rasmus Villemoes, Shuah Khan, Steven Rostedt,
Sven Schnelle, Valentin Schneider, Vasily Gorbik, linux-kernel,
linux-doc, driver-core, linux-s390
Hi.
On 11/2/26 5:04 PM, Ilya Leoshkevich wrote:
>
>
> On 11/2/26 12:00, Peter Zijlstra wrote:
>> On Mon, Nov 02, 2026 at 11:16:30AM +0100, Ilya Leoshkevich wrote:
>>>
>>>
>>> On 11/1/26 20:21, Yury Norov wrote:
>>>> The IBM s390 doesn't enable PARAVIRT config for their hardware
>>>> virtualized Logical Partitions (LPAR). However, the steal time is
>>>> accounted for the LPARs, once the config VIRT_CPU_ACCOUNTING_NATIVE
>>>> is enabled.
>>>>
>>>> Preferred cpumask doesn't rely on any feature gated by PARAVIRT config,
>>>> and requires it to minimize the configuration space and runtime overhead,
>>>> with the lack of non-paravirt user. Now that s390 wants to adopt preferred
>>>> cpumask, there's no reason to keep it coupled to paravirt.
>>>>
>>>> Make PREFERRED_CPU a user-configurable option, even if paravirtualization
>>>> is not enabled, and drop PARAVIRT dependency on the steal governor.
>>>>
>>>> Keep the default module selection conditional on PARAVIRT so other SMP
>>>> configurations can opt in without enabling the governor by default.
>>>>
>>>> Link: https://lore.kernel.org/all/4605dad5-aab2-49e3-b919-bf9897181834@linux.ibm.com/
>>>> CC: Mete Durlu <meted@linux.ibm.com>
>>>> Signed-off-by: Yury Norov <ynorov@nvidia.com>
>>>> ---
>>>> Can be applied independently from the rest of the series.
>>>>
>>>> drivers/virt/Kconfig | 8 ++++++--
>>>> kernel/Kconfig.preempt | 12 ++++++++++--
>>>> 2 files changed, 16 insertions(+), 4 deletions(-)
>>>
>>> This is really useful to us, since even though s390 is nominally
>>> paravirtualized, it does not technically benefit from defining
>>> CONFIG_PARAVIRT.
>>
>> And therefore removing PARAVIRT is the only possible solution?
>>
>>> Specifically, steal time accounting happens by
>>> computing a difference between wall time and CPU time, and not by
>>> explicitly querying the hypervisor.
>>
>> Nobody explicitly asks the hypervisor, that would be horrendously slow.
>>
>> Something trivial like this should do.
>>
>> ---
>> arch/Kconfig | 9 +++++++++
>> arch/powerpc/platforms/pseries/Kconfig | 1 +
>> arch/s390/Kconfig | 1 +
>> drivers/virt/Kconfig | 2 +-
>> 4 files changed, 12 insertions(+), 1 deletion(-)
>>
>> diff --git a/arch/Kconfig b/arch/Kconfig
>> index 1163736de1f9..8980054beb52 100644
>> --- a/arch/Kconfig
>> +++ b/arch/Kconfig
>> @@ -1080,6 +1080,15 @@ config HAVE_IRQ_TIME_ACCOUNTING
>> config HAVE_PV_STEAL_CLOCK_GEN
>> bool
>> +#
>> +# Archs that can account CPUTIME_STEAL; normal route is through PARAVIRT which
>> +# selects HAVE_PV_STEAL_CLOCK_GEN. Directly selected by s390 and PPC-LPAR
>> +# which have their own thing and don't go through generic cputime accounting.
>> +#
>> +config HAVE_CPUTIME_STEAL
>> + bool
>> + default y if HAVE_PV_STEAL_CLOCK_GEN
>> +
Can't PARAVIRT_TIME_ACCOUNTING be the kconfig we can rely upon.
s390 can add it to the config (similar to HAVE_CPUTIME_STEAL)?
I guess it is selected currently where the steal time reporting happens.
>> config HAVE_MOVE_PUD
>> bool
>> help
>> diff --git a/arch/powerpc/platforms/pseries/Kconfig b/arch/powerpc/platforms/pseries/Kconfig
>> index 7d125e288f6e..3c49baf606d7 100644
>> --- a/arch/powerpc/platforms/pseries/Kconfig
>> +++ b/arch/powerpc/platforms/pseries/Kconfig
>> @@ -41,6 +41,7 @@ config PPC_SPLPAR
>> depends on PPC_PSERIES
>> select PARAVIRT_SPINLOCKS if PPC_QUEUED_SPINLOCKS
>> select PARAVIRT_TIME_ACCOUNTING if VIRT_CPU_ACCOUNTING_GEN
>> + select HAVE_CPUTIME_STEAL
>> default y
>> help
>> Enabling this option will make the kernel run more efficiently
>> diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
>> index 7138d923d86f..03a884355218 100644
>> --- a/arch/s390/Kconfig
>> +++ b/arch/s390/Kconfig
>> @@ -291,6 +291,7 @@ config S390
>> select USER_STACKTRACE_SUPPORT
>> select VDSO_GETRANDOM
>> select VIRT_CPU_ACCOUNTING
>> + select HAVE_CPUTIME_STEAL
>> select VMAP_STACK
>> select ZONE_DMA
>> # Note: keep the above list sorted alphabetically
>> diff --git a/drivers/virt/Kconfig b/drivers/virt/Kconfig
>> index eeb84e578ddf..a3721d34a55c 100644
>> --- a/drivers/virt/Kconfig
>> +++ b/drivers/virt/Kconfig
>> @@ -43,7 +43,7 @@ config FSL_HV_MANAGER
>> config STEAL_GOVERNOR
>> tristate "Dynamic vCPU management based on steal time"
>> - depends on PARAVIRT && SMP
>> + depends on SMP && HAVE_CPUTIME_STEAL
>> select PREFERRED_CPU
>> default m
>> help
>
> I can't comment on the PPC part, but for s390 this works fine with the
> following addition:
>
> --- a/kernel/Kconfig.preempt
> +++ b/kernel/Kconfig.preempt
> @@ -197,4 +197,4 @@ config SCHED_CLASS_EXT
>
> config PREFERRED_CPU
> bool
> - depends on SMP && PARAVIRT
> + depends on SMP && HAVE_CPUTIME_STEAL
PS: I haven't read the series yet.
Will try to do so when it get little bit of time.
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 1/6] sched: decouple PREFERRED_CPU from PARAVIRT in Kconfig.preempt
2026-11-02 13:00 ` Shrikanth Hegde
@ 2026-11-02 13:41 ` Ilya Leoshkevich
2026-11-02 14:57 ` Shrikanth Hegde
0 siblings, 1 reply; 14+ messages in thread
From: Ilya Leoshkevich @ 2026-11-02 13:41 UTC (permalink / raw)
To: Shrikanth Hegde, Peter Zijlstra, Mete Durlu, Yury Norov
Cc: Ingo Molnar, Thomas Gleixner, Juri Lelli, Vincent Guittot,
Yury Norov, Rafael J. Wysocki, Alexander Gordeev, Andrea Righi,
Ben Segall, Christian Borntraeger, Danilo Krummrich,
Dietmar Eggemann, Greg Kroah-Hartman, Heiko Carstens,
Johan Hovold, Jonathan Corbet, K Prateek Nayak, Mel Gorman,
Randy Dunlap, Rasmus Villemoes, Shuah Khan, Steven Rostedt,
Sven Schnelle, Valentin Schneider, Vasily Gorbik, linux-kernel,
linux-doc, driver-core, linux-s390
On 11/2/26 14:00, Shrikanth Hegde wrote:
> Hi.
>
>
> On 11/2/26 5:04 PM, Ilya Leoshkevich wrote:
>>
>>
>> On 11/2/26 12:00, Peter Zijlstra wrote:
>>> On Mon, Nov 02, 2026 at 11:16:30AM +0100, Ilya Leoshkevich wrote:
>>>>
>>>>
>>>> On 11/1/26 20:21, Yury Norov wrote:
>>>>> The IBM s390 doesn't enable PARAVIRT config for their hardware
>>>>> virtualized Logical Partitions (LPAR). However, the steal time is
>>>>> accounted for the LPARs, once the config VIRT_CPU_ACCOUNTING_NATIVE
>>>>> is enabled.
>>>>>
>>>>> Preferred cpumask doesn't rely on any feature gated by PARAVIRT
>>>>> config,
>>>>> and requires it to minimize the configuration space and runtime
>>>>> overhead,
>>>>> with the lack of non-paravirt user. Now that s390 wants to adopt
>>>>> preferred
>>>>> cpumask, there's no reason to keep it coupled to paravirt.
>>>>>
>>>>> Make PREFERRED_CPU a user-configurable option, even if
>>>>> paravirtualization
>>>>> is not enabled, and drop PARAVIRT dependency on the steal governor.
>>>>>
>>>>> Keep the default module selection conditional on PARAVIRT so other SMP
>>>>> configurations can opt in without enabling the governor by default.
>>>>>
>>>>> Link: https://lore.kernel.org/all/4605dad5-aab2-49e3-b919-
>>>>> bf9897181834@linux.ibm.com/
>>>>> CC: Mete Durlu <meted@linux.ibm.com>
>>>>> Signed-off-by: Yury Norov <ynorov@nvidia.com>
>>>>> ---
>>>>> Can be applied independently from the rest of the series.
>>>>>
>>>>> drivers/virt/Kconfig | 8 ++++++--
>>>>> kernel/Kconfig.preempt | 12 ++++++++++--
>>>>> 2 files changed, 16 insertions(+), 4 deletions(-)
>>>>
>>>> This is really useful to us, since even though s390 is nominally
>>>> paravirtualized, it does not technically benefit from defining
>>>> CONFIG_PARAVIRT.
>>>
>>> And therefore removing PARAVIRT is the only possible solution?
>>>
>>>> Specifically, steal time accounting happens by
>>>> computing a difference between wall time and CPU time, and not by
>>>> explicitly querying the hypervisor.
>>>
>>> Nobody explicitly asks the hypervisor, that would be horrendously slow.
>>>
>>> Something trivial like this should do.
>>>
>>> ---
>>> arch/Kconfig | 9 +++++++++
>>> arch/powerpc/platforms/pseries/Kconfig | 1 +
>>> arch/s390/Kconfig | 1 +
>>> drivers/virt/Kconfig | 2 +-
>>> 4 files changed, 12 insertions(+), 1 deletion(-)
>>>
>>> diff --git a/arch/Kconfig b/arch/Kconfig
>>> index 1163736de1f9..8980054beb52 100644
>>> --- a/arch/Kconfig
>>> +++ b/arch/Kconfig
>>> @@ -1080,6 +1080,15 @@ config HAVE_IRQ_TIME_ACCOUNTING
>>> config HAVE_PV_STEAL_CLOCK_GEN
>>> bool
>>> +#
>>> +# Archs that can account CPUTIME_STEAL; normal route is through
>>> PARAVIRT which
>>> +# selects HAVE_PV_STEAL_CLOCK_GEN. Directly selected by s390 and
>>> PPC-LPAR
>>> +# which have their own thing and don't go through generic cputime
>>> accounting.
>>> +#
>>> +config HAVE_CPUTIME_STEAL
>>> + bool
>>> + default y if HAVE_PV_STEAL_CLOCK_GEN
>>> +
>
> Can't PARAVIRT_TIME_ACCOUNTING be the kconfig we can rely upon.
> s390 can add it to the config (similar to HAVE_CPUTIME_STEAL)?
>
> I guess it is selected currently where the steal time reporting happens.
Looking at update_rq_clock_task(), s390 would still need to provide a
pointless dummy paravirt_steal_clock() implementation in this case.
[...]
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 1/6] sched: decouple PREFERRED_CPU from PARAVIRT in Kconfig.preempt
2026-11-02 13:41 ` Ilya Leoshkevich
@ 2026-11-02 14:57 ` Shrikanth Hegde
0 siblings, 0 replies; 14+ messages in thread
From: Shrikanth Hegde @ 2026-11-02 14:57 UTC (permalink / raw)
To: Ilya Leoshkevich, Peter Zijlstra, Mete Durlu, Yury Norov
Cc: Ingo Molnar, Thomas Gleixner, Juri Lelli, Vincent Guittot,
Yury Norov, Rafael J. Wysocki, Alexander Gordeev, Andrea Righi,
Ben Segall, Christian Borntraeger, Danilo Krummrich,
Dietmar Eggemann, Greg Kroah-Hartman, Heiko Carstens,
Johan Hovold, Jonathan Corbet, K Prateek Nayak, Mel Gorman,
Randy Dunlap, Rasmus Villemoes, Shuah Khan, Steven Rostedt,
Sven Schnelle, Valentin Schneider, Vasily Gorbik, linux-kernel,
linux-doc, driver-core, linux-s390
On 11/2/26 7:11 PM, Ilya Leoshkevich wrote:
>
>
> On 11/2/26 14:00, Shrikanth Hegde wrote:
>> Hi.
>>
>>
>> On 11/2/26 5:04 PM, Ilya Leoshkevich wrote:
>>>
>>>
>>> On 11/2/26 12:00, Peter Zijlstra wrote:
>>>> On Mon, Nov 02, 2026 at 11:16:30AM +0100, Ilya Leoshkevich wrote:
>>>>>
>>>>>
>>>>> On 11/1/26 20:21, Yury Norov wrote:
>>>>>> The IBM s390 doesn't enable PARAVIRT config for their hardware
>>>>>> virtualized Logical Partitions (LPAR). However, the steal time is
>>>>>> accounted for the LPARs, once the config VIRT_CPU_ACCOUNTING_NATIVE
>>>>>> is enabled.
>>>>>>
>>>>>> Preferred cpumask doesn't rely on any feature gated by PARAVIRT config,
>>>>>> and requires it to minimize the configuration space and runtime overhead,
>>>>>> with the lack of non-paravirt user. Now that s390 wants to adopt preferred
>>>>>> cpumask, there's no reason to keep it coupled to paravirt.
>>>>>>
>>>>>> Make PREFERRED_CPU a user-configurable option, even if paravirtualization
>>>>>> is not enabled, and drop PARAVIRT dependency on the steal governor.
>>>>>>
>>>>>> Keep the default module selection conditional on PARAVIRT so other SMP
>>>>>> configurations can opt in without enabling the governor by default.
>>>>>>
>>>>>> Link: https://lore.kernel.org/all/4605dad5-aab2-49e3-b919- bf9897181834@linux.ibm.com/
>>>>>> CC: Mete Durlu <meted@linux.ibm.com>
>>>>>> Signed-off-by: Yury Norov <ynorov@nvidia.com>
>>>>>> ---
>>>>>> Can be applied independently from the rest of the series.
>>>>>>
>>>>>> drivers/virt/Kconfig | 8 ++++++--
>>>>>> kernel/Kconfig.preempt | 12 ++++++++++--
>>>>>> 2 files changed, 16 insertions(+), 4 deletions(-)
>>>>>
>>>>> This is really useful to us, since even though s390 is nominally
>>>>> paravirtualized, it does not technically benefit from defining
>>>>> CONFIG_PARAVIRT.
>>>>
>>>> And therefore removing PARAVIRT is the only possible solution?
>>>>
>>>>> Specifically, steal time accounting happens by
>>>>> computing a difference between wall time and CPU time, and not by
>>>>> explicitly querying the hypervisor.
>>>>
>>>> Nobody explicitly asks the hypervisor, that would be horrendously slow.
>>>>
>>>> Something trivial like this should do.
>>>>
>>>> ---
>>>> arch/Kconfig | 9 +++++++++
>>>> arch/powerpc/platforms/pseries/Kconfig | 1 +
>>>> arch/s390/Kconfig | 1 +
>>>> drivers/virt/Kconfig | 2 +-
>>>> 4 files changed, 12 insertions(+), 1 deletion(-)
>>>>
>>>> diff --git a/arch/Kconfig b/arch/Kconfig
>>>> index 1163736de1f9..8980054beb52 100644
>>>> --- a/arch/Kconfig
>>>> +++ b/arch/Kconfig
>>>> @@ -1080,6 +1080,15 @@ config HAVE_IRQ_TIME_ACCOUNTING
>>>> config HAVE_PV_STEAL_CLOCK_GEN
>>>> bool
>>>> +#
>>>> +# Archs that can account CPUTIME_STEAL; normal route is through PARAVIRT which
>>>> +# selects HAVE_PV_STEAL_CLOCK_GEN. Directly selected by s390 and PPC-LPAR
>>>> +# which have their own thing and don't go through generic cputime accounting.
>>>> +#
>>>> +config HAVE_CPUTIME_STEAL
>>>> + bool
>>>> + default y if HAVE_PV_STEAL_CLOCK_GEN
>>>> +
>>
>> Can't PARAVIRT_TIME_ACCOUNTING be the kconfig we can rely upon.
>> s390 can add it to the config (similar to HAVE_CPUTIME_STEAL)?
>>
>> I guess it is selected currently where the steal time reporting happens.
>
> Looking at update_rq_clock_task(), s390 would still need to provide a
> pointless dummy paravirt_steal_clock() implementation in this case.
>
> [...]
Ah. Peter's change seems fine to me.
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH 2/6] cpumask: Add reset_preferred_cpumask() helper
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 ` Yury Norov
2026-11-01 19:21 ` [PATCH 3/6] sched: Restore preferred CPUs when hotplug removes the last one Yury Norov
` (4 subsequent siblings)
6 siblings, 0 replies; 14+ messages in thread
From: Yury Norov @ 2026-11-01 19:21 UTC (permalink / raw)
To: Peter Zijlstra, Ingo Molnar, Thomas Gleixner, Juri Lelli,
Vincent Guittot, Shrikanth Hegde
Cc: Yury Norov, Yury Norov, Rafael J. Wysocki, Alexander Gordeev,
Andrea Righi, Ben Segall, Christian Borntraeger, Danilo Krummrich,
Dietmar Eggemann, Greg Kroah-Hartman, Heiko Carstens,
Johan Hovold, Jonathan Corbet, K Prateek Nayak, Mel Gorman,
Mete Durlu, Randy Dunlap, Rasmus Villemoes, Shuah Khan,
Steven Rostedt, Sven Schnelle, Valentin Schneider, Vasily Gorbik,
linux-kernel, linux-doc, driver-core, linux-s390
This series adds more flexibility to control the 'preferred' status of
CPUs. As a preparation, move the steal governor's preferred-mask reset
into cpumask.h to make it globally available.
While there, rename it to shorter "reset_preferred_cpumask()".
Signed-off-by: Yury Norov <ynorov@nvidia.com>
---
drivers/virt/steal_governor.c | 15 ++++-----------
include/linux/cpumask.h | 12 ++++++++++++
2 files changed, 16 insertions(+), 11 deletions(-)
diff --git a/drivers/virt/steal_governor.c b/drivers/virt/steal_governor.c
index 6e31f9923dea..4cd9971fec45 100644
--- a/drivers/virt/steal_governor.c
+++ b/drivers/virt/steal_governor.c
@@ -51,15 +51,6 @@ static struct steal_governor sg_ctx = {
.low_threshold = 200, /* 2% */
};
-static void restore_preferred_to_active(void)
-{
- int cpu;
-
- guard(cpus_read_lock)();
- for_each_cpu(cpu, cpu_active_mask)
- set_cpu_preferred(cpu, true);
-}
-
static int param_set_interval_ms(const char *val, const struct kernel_param *kp)
{
unsigned int interval;
@@ -247,7 +238,8 @@ static void steal_governor_loop(struct work_struct *work)
* module restores to active if CPU hotplug breaks those assumptions.
*/
if (!preferred_cpus_valid()) {
- restore_preferred_to_active();
+ scoped_guard(cpus_read_lock)
+ reset_preferred_cpumask();
return;
}
@@ -284,7 +276,8 @@ static int __init steal_governor_init(void)
static void __exit steal_governor_exit(void)
{
disable_delayed_work_sync(&sg_ctx.work);
- restore_preferred_to_active();
+ scoped_guard(cpus_read_lock)
+ reset_preferred_cpumask();
pr_info("disabled\n");
}
diff --git a/include/linux/cpumask.h b/include/linux/cpumask.h
index bf89bb3f30f6..c65abfc8a97f 100644
--- a/include/linux/cpumask.h
+++ b/include/linux/cpumask.h
@@ -1195,6 +1195,18 @@ void init_cpu_possible(const struct cpumask *src);
#define set_cpu_preferred(cpu, preferred) do { } while (0)
#endif
+/**
+ * reset_preferred_cpumask - reset preferred CPUs to the active mask.
+ *
+ * Callers must serialize against CPU hotplug and other preferred cpumask
+ * writers.
+ */
+static inline void reset_preferred_cpumask(void)
+{
+ if (IS_ENABLED(CONFIG_PREFERRED_CPU))
+ cpumask_copy(&__cpu_preferred_mask, cpu_active_mask);
+}
+
void set_cpu_online(unsigned int cpu, bool online);
void set_cpu_possible(unsigned int cpu, bool possible);
--
2.53.0
^ permalink raw reply related [flat|nested] 14+ messages in thread* [PATCH 3/6] sched: Restore preferred CPUs when hotplug removes the last one
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 ` Yury Norov
2026-11-01 19:22 ` [PATCH 4/6] sched: serialize preferred cpumask update better Yury Norov
` (3 subsequent siblings)
6 siblings, 0 replies; 14+ messages in thread
From: Yury Norov @ 2026-11-01 19:21 UTC (permalink / raw)
To: Peter Zijlstra, Ingo Molnar, Thomas Gleixner, Juri Lelli,
Vincent Guittot, Shrikanth Hegde
Cc: Yury Norov, Yury Norov, Rafael J. Wysocki, Alexander Gordeev,
Andrea Righi, Ben Segall, Christian Borntraeger, Danilo Krummrich,
Dietmar Eggemann, Greg Kroah-Hartman, Heiko Carstens,
Johan Hovold, Jonathan Corbet, K Prateek Nayak, Mel Gorman,
Mete Durlu, Randy Dunlap, Rasmus Villemoes, Shuah Khan,
Steven Rostedt, Sven Schnelle, Valentin Schneider, Vasily Gorbik,
linux-kernel, linux-doc, driver-core, linux-s390
Offlining the last preferred CPU leaves cpu_preferred_mask empty. Normal
fair load balancing stops, potentially leaving CPUs idle while tasks
remain queued.
Currently, the steal governor is the only module that may modify the mask,
so it takes care of this by resetting the mask to mirror the active
cpumask, but stops sampling after that.
This series adds more ways to control the preferred cpumask, so steal
governor may not be active.
Restore all remaining active CPUs as preferred in sched_cpu_deactivate()
path, without relying on the steal governor to recover.
Signed-off-by: Yury Norov <ynorov@nvidia.com>
---
kernel/sched/core.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index 04b62c16fa8c..98f4f9434965 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -8712,6 +8712,14 @@ int sched_cpu_deactivate(unsigned int cpu)
set_cpu_active(cpu, false);
+#ifdef CONFIG_PREFERRED_CPU
+ if (cpumask_empty(cpu_preferred_mask)) {
+ pr_notice("sched: last preferred CPU%u offlined; make all active CPUs preferred\n",
+ cpu);
+ reset_preferred_cpumask();
+ }
+#endif
+
/*
* From this point forward, this CPU will refuse to run any task that
* is not: migrate_disable() or KTHREAD_IS_PER_CPU, and will actively
--
2.53.0
^ permalink raw reply related [flat|nested] 14+ messages in thread* [PATCH 4/6] sched: serialize preferred cpumask update better
2026-11-01 19:21 [PATCH 0/6] sched: Expose writable interface for preferred CPUs mask Yury Norov
` (2 preceding siblings ...)
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 ` Yury Norov
2026-11-01 19:22 ` [PATCH 5/6] virt: steal_governor: Warn on unexpected preferred mask states Yury Norov
` (2 subsequent siblings)
6 siblings, 0 replies; 14+ messages in thread
From: Yury Norov @ 2026-11-01 19:22 UTC (permalink / raw)
To: Peter Zijlstra, Ingo Molnar, Thomas Gleixner, Juri Lelli,
Vincent Guittot, Shrikanth Hegde
Cc: Yury Norov, Yury Norov, Rafael J. Wysocki, Alexander Gordeev,
Andrea Righi, Ben Segall, Christian Borntraeger, Danilo Krummrich,
Dietmar Eggemann, Greg Kroah-Hartman, Heiko Carstens,
Johan Hovold, Jonathan Corbet, K Prateek Nayak, Mel Gorman,
Mete Durlu, Randy Dunlap, Rasmus Villemoes, Shuah Khan,
Steven Rostedt, Sven Schnelle, Valentin Schneider, Vasily Gorbik,
linux-kernel, linux-doc, driver-core, linux-s390
This series adds more flexibility to control the 'preferred' status of
CPUs, so that multiple modules may access the mask concurrently. Thus,
add the cpu_preferred_mutex.
With that, the scheme would look like this:
- if your code takes cpus_write_lock(), it's enough to write-access
the preferred cpumask;
- if your code takes cpus_read_lock(), you'd also take
cpu_preferred_mutex in order to modify the preferred mask.
This approach also fixes the existing race between steal governor
sampling and hotplug/unplug.
Fixes: 27d47ebce4d6 ("virt/steal_governor: Implement steal_governor policy loop")
Signed-off-by: Yury Norov <ynorov@nvidia.com>
---
drivers/virt/steal_governor.c | 21 ++++++++++++++++-----
include/linux/cpumask.h | 15 ++++++++++++---
kernel/cpu.c | 4 ++++
3 files changed, 32 insertions(+), 8 deletions(-)
diff --git a/drivers/virt/steal_governor.c b/drivers/virt/steal_governor.c
index 4cd9971fec45..bc3936e69eed 100644
--- a/drivers/virt/steal_governor.c
+++ b/drivers/virt/steal_governor.c
@@ -23,6 +23,7 @@
#include <linux/ktime.h>
#include <linux/math64.h>
#include <linux/module.h>
+#include <linux/mutex.h>
#include <linux/sched/isolation.h>
#include <linux/topology.h>
#include <linux/types.h>
@@ -134,7 +135,8 @@ static void decrease_preferred_cpus(void)
int target_cpu = nr_cpu_ids;
int cpu;
- guard(cpus_read_lock)();
+ lockdep_assert_cpus_held();
+ lockdep_assert_held(&cpu_preferred_mutex);
cpu = cpumask_first_and(housekeeping_cpumask(HK_TYPE_KERNEL_NOISE),
cpu_preferred_mask);
if (cpu >= nr_cpu_ids)
@@ -174,7 +176,8 @@ static void increase_preferred_cpus(void)
{
int first_cpu, cpu;
- guard(cpus_read_lock)();
+ lockdep_assert_cpus_held();
+ lockdep_assert_held(&cpu_preferred_mutex);
first_cpu = cpumask_first_andnot(cpu_active_mask, cpu_preferred_mask);
/* All CPUs are preferred. Nothing to increase further */
@@ -188,6 +191,9 @@ static void increase_preferred_cpus(void)
static bool preferred_cpus_valid(void)
{
+ lockdep_assert_cpus_held();
+ lockdep_assert_held(&cpu_preferred_mutex);
+
if (cpumask_empty(cpu_preferred_mask)) {
pr_err("empty preferred mask. stopping\n");
return false;
@@ -208,6 +214,9 @@ static void steal_governor_loop(struct work_struct *work)
u64 curr_steal, delta_steal, delta_ns, steal_ratio;
ktime_t now;
+ guard(cpus_read_lock)();
+ guard(mutex)(&cpu_preferred_mutex);
+
now = ktime_get();
delta_ns = ktime_to_ns(ktime_sub(now, sg_ctx.time));
@@ -238,8 +247,7 @@ static void steal_governor_loop(struct work_struct *work)
* module restores to active if CPU hotplug breaks those assumptions.
*/
if (!preferred_cpus_valid()) {
- scoped_guard(cpus_read_lock)
- reset_preferred_cpumask();
+ reset_preferred_cpumask();
return;
}
@@ -276,8 +284,11 @@ static int __init steal_governor_init(void)
static void __exit steal_governor_exit(void)
{
disable_delayed_work_sync(&sg_ctx.work);
- scoped_guard(cpus_read_lock)
+ scoped_guard(cpus_read_lock) {
+ guard(mutex)(&cpu_preferred_mutex);
+
reset_preferred_cpumask();
+ }
pr_info("disabled\n");
}
diff --git a/include/linux/cpumask.h b/include/linux/cpumask.h
index c65abfc8a97f..fc911a153b44 100644
--- a/include/linux/cpumask.h
+++ b/include/linux/cpumask.h
@@ -123,7 +123,14 @@ extern struct cpumask __cpu_active_mask;
extern struct cpumask __cpu_dying_mask;
#ifdef CONFIG_PREFERRED_CPU
+/*
+ * Drivers must take cpus_read_lock() before cpu_preferred_mutex and
+ * hold both across mask validation and updates. If cpus_write_lock()
+ * is held, it guarantees the exclusive access to the mask, thus
+ * holding cpu_preferred_mutex isn't necessary.
+ */
extern struct cpumask __cpu_preferred_mask;
+extern struct mutex cpu_preferred_mutex;
#else
#define __cpu_preferred_mask __cpu_active_mask
#endif
@@ -1199,12 +1206,14 @@ void init_cpu_possible(const struct cpumask *src);
* reset_preferred_cpumask - reset preferred CPUs to the active mask.
*
* Callers must serialize against CPU hotplug and other preferred cpumask
- * writers.
+ * writers. Requires cpus_read_lock() and cpu_preferred_mutex; or
+ * cpus_write_lock().
*/
static inline void reset_preferred_cpumask(void)
{
- if (IS_ENABLED(CONFIG_PREFERRED_CPU))
- cpumask_copy(&__cpu_preferred_mask, cpu_active_mask);
+#ifdef CONFIG_PREFERRED_CPU
+ cpumask_copy(&__cpu_preferred_mask, cpu_active_mask);
+#endif
}
void set_cpu_online(unsigned int cpu, bool online);
diff --git a/kernel/cpu.c b/kernel/cpu.c
index 376d297a6292..dec08a90ea77 100644
--- a/kernel/cpu.c
+++ b/kernel/cpu.c
@@ -3106,6 +3106,10 @@ EXPORT_SYMBOL(__num_online_cpus);
#ifdef CONFIG_PREFERRED_CPU
struct cpumask __cpu_preferred_mask __read_mostly;
EXPORT_SYMBOL_GPL(__cpu_preferred_mask);
+
+/* Serialize policy drivers; acquire inside cpus_read_lock(). */
+DEFINE_MUTEX(cpu_preferred_mutex);
+EXPORT_SYMBOL_GPL(cpu_preferred_mutex);
#endif
void init_cpu_present(const struct cpumask *src)
--
2.53.0
^ permalink raw reply related [flat|nested] 14+ messages in thread* [PATCH 5/6] virt: steal_governor: Warn on unexpected preferred mask states
2026-11-01 19:21 [PATCH 0/6] sched: Expose writable interface for preferred CPUs mask Yury Norov
` (3 preceding siblings ...)
2026-11-01 19:22 ` [PATCH 4/6] sched: serialize preferred cpumask update better Yury Norov
@ 2026-11-01 19:22 ` Yury Norov
2026-11-01 19:22 ` [PATCH 6/6] cpu: Add per-CPU preferred sysfs control Yury Norov
2026-11-02 8:47 ` [PATCH 0/6] sched: Expose writable interface for preferred CPUs mask Peter Zijlstra
6 siblings, 0 replies; 14+ messages in thread
From: Yury Norov @ 2026-11-01 19:22 UTC (permalink / raw)
To: Peter Zijlstra, Ingo Molnar, Thomas Gleixner, Juri Lelli,
Vincent Guittot, Shrikanth Hegde
Cc: Yury Norov, Yury Norov, Rafael J. Wysocki, Alexander Gordeev,
Andrea Righi, Ben Segall, Christian Borntraeger, Danilo Krummrich,
Dietmar Eggemann, Greg Kroah-Hartman, Heiko Carstens,
Johan Hovold, Jonathan Corbet, K Prateek Nayak, Mel Gorman,
Mete Durlu, Randy Dunlap, Rasmus Villemoes, Shuah Khan,
Steven Rostedt, Sven Schnelle, Valentin Schneider, Vasily Gorbik,
linux-kernel, linux-doc, driver-core, linux-s390
Now that preferred cpumask access is properly serialized, and CPU
hotplug restores all remaining active CPUs as preferred when the
last preferred CPU gets offlined, the corresponding logic in the
driver is redundant.
Instead of removing it completely, add WARN_ON()s in the corresponding
conditionals to harden the preferred CPUs mask management and highlight
that this condition is not expected during normal operation.
Signed-off-by: Yury Norov <ynorov@nvidia.com>
---
drivers/virt/steal_governor.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/drivers/virt/steal_governor.c b/drivers/virt/steal_governor.c
index bc3936e69eed..5679b7ddc078 100644
--- a/drivers/virt/steal_governor.c
+++ b/drivers/virt/steal_governor.c
@@ -145,7 +145,9 @@ static void decrease_preferred_cpus(void)
/* Always leave first housekeeping core as preferred. */
first_hk_core = topology_sibling_cpumask(cpu);
cpu = cpumask_last(cpu_preferred_mask);
- if (cpu >= nr_cpu_ids)
+
+ /* We can't end up with no preferred CPUs under normal conditions. */
+ if (WARN_ON(cpu >= nr_cpu_ids))
return;
/* Find the last CPU which doesn't belong to that first hk_core. */
@@ -246,7 +248,7 @@ static void steal_governor_loop(struct work_struct *work)
* else: steal ratio is within bounds. Still do design checks so that
* module restores to active if CPU hotplug breaks those assumptions.
*/
- if (!preferred_cpus_valid()) {
+ if (WARN_ON(!preferred_cpus_valid())) {
reset_preferred_cpumask();
return;
}
--
2.53.0
^ permalink raw reply related [flat|nested] 14+ messages in thread* [PATCH 6/6] cpu: Add per-CPU preferred sysfs control
2026-11-01 19:21 [PATCH 0/6] sched: Expose writable interface for preferred CPUs mask Yury Norov
` (4 preceding siblings ...)
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
2026-11-02 8:47 ` [PATCH 0/6] sched: Expose writable interface for preferred CPUs mask Peter Zijlstra
6 siblings, 0 replies; 14+ messages in thread
From: Yury Norov @ 2026-11-01 19:22 UTC (permalink / raw)
To: Peter Zijlstra, Ingo Molnar, Thomas Gleixner, Juri Lelli,
Vincent Guittot, Shrikanth Hegde
Cc: Yury Norov, Yury Norov, Rafael J. Wysocki, Alexander Gordeev,
Andrea Righi, Ben Segall, Christian Borntraeger, Danilo Krummrich,
Dietmar Eggemann, Greg Kroah-Hartman, Heiko Carstens,
Johan Hovold, Jonathan Corbet, K Prateek Nayak, Mel Gorman,
Mete Durlu, Randy Dunlap, Rasmus Villemoes, Shuah Khan,
Steven Rostedt, Sven Schnelle, Valentin Schneider, Vasily Gorbik,
linux-kernel, linux-doc, driver-core, linux-s390
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
^ permalink raw reply related [flat|nested] 14+ messages in thread* Re: [PATCH 0/6] sched: Expose writable interface for preferred CPUs mask
2026-11-01 19:21 [PATCH 0/6] sched: Expose writable interface for preferred CPUs mask Yury Norov
` (5 preceding siblings ...)
2026-11-01 19:22 ` [PATCH 6/6] cpu: Add per-CPU preferred sysfs control Yury Norov
@ 2026-11-02 8:47 ` Peter Zijlstra
6 siblings, 0 replies; 14+ messages in thread
From: Peter Zijlstra @ 2026-11-02 8:47 UTC (permalink / raw)
To: Yury Norov
Cc: Ingo Molnar, Thomas Gleixner, Juri Lelli, Vincent Guittot,
Shrikanth Hegde, Yury Norov, Rafael J. Wysocki, Alexander Gordeev,
Andrea Righi, Ben Segall, Christian Borntraeger, Danilo Krummrich,
Dietmar Eggemann, Greg Kroah-Hartman, Heiko Carstens,
Johan Hovold, Jonathan Corbet, K Prateek Nayak, Mel Gorman,
Mete Durlu, Randy Dunlap, Rasmus Villemoes, Shuah Khan,
Steven Rostedt, Sven Schnelle, Valentin Schneider, Vasily Gorbik,
linux-kernel, linux-doc, driver-core, linux-s390
On Sun, Nov 01, 2026 at 02:21:56PM -0500, Yury Norov wrote:
> The preferred CPU mask currently lets the steal governor reduce vCPU
> demand when physical CPUs are contended. This series adds manual control,
> opening more use cases.
Sceptical, I am.
> For example, setting CPUs aside for selected fair tasks at runtime while
> steering other fair tasks toward the remaining CPUs.
That's exactly the kind of nonsense we don't need and makes me want to
stop reading right here.
We already have cpusets that is more than capable of doing this.
> A user can mark a CPU non-preferred and pin a workload to it. Fair tasks
> whose affinity includes preferred CPUs are steered away, while tasks
> whose allowed CPUs contain no preferred CPU can still run there. The CPU
> stays online, task affinity is preserved, and the selection can be
> reversed without rebooting:
>
> # rmmod steal_governor
> # echo 0 > /sys/devices/system/cpu/cpu3/preferred
> # taskset -c 3 ./my_workload
> # echo 1 > /sys/devices/system/cpu/cpu3/preferred
>
> The current preferred list is still readable from:
>
> /sys/devices/system/cpu/preferred
>
> This provides task-placement isolation similar to a use of
> isolcpus=domain, with a runtime interface. Scheduling domains remain
> intact, tick suppression, RCU offloading, and managed-IRQ avoidance
> can be configured separately when needed.
>
> Different preferred cpumask governors may coexist; all update the
> same mask under common locking. Manual settings are not privileged,
> and later governor updates may override them.
That is a recipe for disaster.
Don't bother trying again, this isn't happening.
^ permalink raw reply [flat|nested] 14+ messages in thread