[tip: sched/core] sched: dynamic: Make PREEMPT_DYNAMIC depend on ARCH_HAS_PREEMPT_LAZY

From: tip-bot2 for Mark Rutland

Date: Wed Sep 02 2026 - 04:08:49 EST


The following commit has been merged into the sched/core branch of tip:

Commit-ID: d3d16750693b540299cd105968174556012aba09
Gitweb: https://git.kernel.org/tip/d3d16750693b540299cd105968174556012aba09
Author: Mark Rutland <mark.rutland@xxxxxxx>
AuthorDate: Mon, 03 Aug 2026 20:17:26 +01:00
Committer: Peter Zijlstra <peterz@xxxxxxxxxxxxx>
CommitterDate: Wed, 02 Sep 2026 09:37:22 +02:00

sched: dynamic: Make PREEMPT_DYNAMIC depend on ARCH_HAS_PREEMPT_LAZY

On architectures which select ARCH_HAS_PREEMPT_LAZY, it has not been
possible to select the NONE and VOLUNTARY preemption models since
commit:

7dadeaa6e851 ("sched: Further restrict the preemption modes")

... which was merged in v7.0.

All architectures which currently support PREEMPT_DYNAMIC select
ARCH_HAS_PREEMPT_LAZY:

[mark@lakrids:~/src/linux]% git describe HEAD
v7.2-rc1-1-g871a4586ea2e1
[mark@lakrids:~/src/linux]% git grep 'select HAVE_PREEMPT_DYNAMIC_' -- arch
arch/arm64/Kconfig: select HAVE_PREEMPT_DYNAMIC_KEY
arch/loongarch/Kconfig: select HAVE_PREEMPT_DYNAMIC_KEY
arch/powerpc/Kconfig: select HAVE_PREEMPT_DYNAMIC_KEY
arch/riscv/Kconfig: select HAVE_PREEMPT_DYNAMIC_KEY
arch/s390/Kconfig: select HAVE_PREEMPT_DYNAMIC_KEY
arch/x86/Kconfig: select HAVE_PREEMPT_DYNAMIC_CALL
[mark@lakrids:~/src/linux]% git grep 'select ARCH_HAS_PREEMPT_LAZY' -- arch
arch/arm64/Kconfig: select ARCH_HAS_PREEMPT_LAZY
arch/loongarch/Kconfig: select ARCH_HAS_PREEMPT_LAZY
arch/powerpc/Kconfig: select ARCH_HAS_PREEMPT_LAZY
arch/riscv/Kconfig: select ARCH_HAS_PREEMPT_LAZY
arch/s390/Kconfig: select ARCH_HAS_PREEMPT_LAZY
arch/x86/Kconfig: select ARCH_HAS_PREEMPT_LAZY

... and hence in practice PREEMPT_DYNAMIC no longer supports the NONE or
VOLUNTARY preemption models.

Make this official: have PREEMPT_DYNAMIC depend on
ARCH_HAS_PREEMPT_LAZY, and remove the trivially unreachable code.
Further simplifications will be made in subsequent patches.

Signed-off-by: Mark Rutland <mark.rutland@xxxxxxx>
Signed-off-by: Peter Zijlstra (Intel) <peterz@xxxxxxxxxxxxx>
Reviewed-by: Shrikanth Hegde <sshegde@xxxxxxxxxxxxx>
Reviewed-by: Jinjie Ruan <ruanjinjie@xxxxxxxxxx>
Tested-by: Mete Durlu <meted@xxxxxxxxxxxxx>
Tested-by: Shrikanth Hegde <sshegde@xxxxxxxxxxxxx>
Tested-by: Jinjie Ruan <ruanjinjie@xxxxxxxxxx>
Link: https://patch.msgid.link/20260803191731.3244294-2-mark.rutland@xxxxxxx
---
kernel/Kconfig.preempt | 1 +-
kernel/sched/core.c | 63 +----------------------------------------
2 files changed, 4 insertions(+), 60 deletions(-)

diff --git a/kernel/Kconfig.preempt b/kernel/Kconfig.preempt
index f294dad..68f3218 100644
--- a/kernel/Kconfig.preempt
+++ b/kernel/Kconfig.preempt
@@ -133,6 +133,7 @@ config PREEMPTION
config PREEMPT_DYNAMIC
bool "Preemption behaviour defined on boot"
depends on HAVE_PREEMPT_DYNAMIC
+ depends on ARCH_HAS_PREEMPT_LAZY
select JUMP_LABEL if HAVE_PREEMPT_DYNAMIC_KEY
select PREEMPT_BUILD
default y if HAVE_PREEMPT_DYNAMIC_CALL
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index 9841043..84e7685 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -7931,20 +7931,10 @@ EXPORT_SYMBOL(__cond_resched_rwlock_write);
*
*
* NONE:
- * cond_resched <- __cond_resched
- * might_resched <- RET0
- * preempt_schedule <- NOP
- * preempt_schedule_notrace <- NOP
- * irqentry_exit_cond_resched <- NOP
- * dynamic_preempt_lazy <- false
+ * (unselectable)
*
* VOLUNTARY:
- * cond_resched <- __cond_resched
- * might_resched <- __cond_resched
- * preempt_schedule <- NOP
- * preempt_schedule_notrace <- NOP
- * irqentry_exit_cond_resched <- NOP
- * dynamic_preempt_lazy <- false
+ * (unselectable)
*
* FULL:
* cond_resched <- RET0
@@ -7975,21 +7965,11 @@ int preempt_dynamic_mode = preempt_dynamic_undefined;

int sched_dynamic_mode(const char *str)
{
-# if !(defined(CONFIG_PREEMPT_RT) || defined(CONFIG_ARCH_HAS_PREEMPT_LAZY))
- if (!strcmp(str, "none"))
- return preempt_dynamic_none;
-
- if (!strcmp(str, "voluntary"))
- return preempt_dynamic_voluntary;
-# endif
-
if (!strcmp(str, "full"))
return preempt_dynamic_full;

-# ifdef CONFIG_ARCH_HAS_PREEMPT_LAZY
if (!strcmp(str, "lazy"))
return preempt_dynamic_lazy;
-# endif

return -EINVAL;
}
@@ -8011,40 +7991,7 @@ static DEFINE_MUTEX(sched_dynamic_mutex);

static void __sched_dynamic_update(int mode)
{
- /*
- * Avoid {NONE,VOLUNTARY} -> FULL transitions from ever ending up in
- * the ZERO state, which is invalid.
- */
- preempt_dynamic_enable(cond_resched);
- preempt_dynamic_enable(might_resched);
- preempt_dynamic_enable(preempt_schedule);
- preempt_dynamic_enable(preempt_schedule_notrace);
- preempt_dynamic_enable(irqentry_exit_cond_resched);
- preempt_dynamic_key_disable(preempt_lazy);
-
switch (mode) {
- case preempt_dynamic_none:
- preempt_dynamic_enable(cond_resched);
- preempt_dynamic_disable(might_resched);
- preempt_dynamic_disable(preempt_schedule);
- preempt_dynamic_disable(preempt_schedule_notrace);
- preempt_dynamic_disable(irqentry_exit_cond_resched);
- preempt_dynamic_key_disable(preempt_lazy);
- if (mode != preempt_dynamic_mode)
- pr_info("Dynamic Preempt: none\n");
- break;
-
- case preempt_dynamic_voluntary:
- preempt_dynamic_enable(cond_resched);
- preempt_dynamic_enable(might_resched);
- preempt_dynamic_disable(preempt_schedule);
- preempt_dynamic_disable(preempt_schedule_notrace);
- preempt_dynamic_disable(irqentry_exit_cond_resched);
- preempt_dynamic_key_disable(preempt_lazy);
- if (mode != preempt_dynamic_mode)
- pr_info("Dynamic Preempt: voluntary\n");
- break;
-
case preempt_dynamic_full:
preempt_dynamic_disable(cond_resched);
preempt_dynamic_disable(might_resched);
@@ -8094,11 +8041,7 @@ __setup("preempt=", setup_preempt_mode);
static void __init preempt_dynamic_init(void)
{
if (preempt_dynamic_mode == preempt_dynamic_undefined) {
- if (IS_ENABLED(CONFIG_PREEMPT_NONE)) {
- sched_dynamic_update(preempt_dynamic_none);
- } else if (IS_ENABLED(CONFIG_PREEMPT_VOLUNTARY)) {
- sched_dynamic_update(preempt_dynamic_voluntary);
- } else if (IS_ENABLED(CONFIG_PREEMPT_LAZY)) {
+ if (IS_ENABLED(CONFIG_PREEMPT_LAZY)) {
sched_dynamic_update(preempt_dynamic_lazy);
} else {
/* Default static call setting, nothing to do */