[PATCH v2 34/35] kconfig: decompose ARCH_NO_PREEMPT

From: Ankur Arora
Date: Mon May 27 2024 - 20:43:39 EST


We have two sets of preemption points where we evaluate preempt_count
to decide if scheduling is safe:

- preempt_enable()
- irqentry_exit_cond_resched()

Architectures with untested/incomplete preempt_count support define
ARCH_NO_PREEMPT.

Now, if an architecture did want to support preemption, ensuring that
preemption at irqentry_exit_cond_resched() is safe is difficult --
preemption can happen at any arbitrary location where preempt_count
evaluates to zero.

The preempt_enable() case -- whether executed in common code or in
architecture specific code mostly requires verification of local context
and can be done piecewise.

So, decompose ARCH_NO_PREEMPT into ARCH_NO_PREEMPT_IRQ and
ARCH_NO_PREEMPT_TOGGLE, with the first stating that the architecture
code has possibly incomplete preempt_count accounting and thus
preempting in irqentry_exit_cond_resched() is unsafe, and the second
stating that the preempt_count accounting is incorrect so preempting
anywhere is unsafe.

ARCH_NO_PREEMPT now only depends on the ARCH_NO_PREEMPT_TOGGLE.
Additionally, only invoke irqentry_exit_cond_resched() if
ARCH_NO_PREEMPT_IRQ=n.

Cc: Thomas Gleixner <tglx@xxxxxxxxxxxxx>
Cc: Peter Zijlstra <peterz@xxxxxxxxxxxxx>
Cc: Andy Lutomirski <luto@xxxxxxxxxx>
Cc: Andrew Morton <akpm@xxxxxxxxxxxxxxxxxxxx>
Cc: Arnd Bergmann <arnd@xxxxxxxx>
Cc: Richard Henderson <richard.henderson@xxxxxxxxxx>
Cc: Ivan Kokshaysky <ink@xxxxxxxxxxxxxxxxxxxx>
Cc: Matt Turner <mattst88@xxxxxxxxx>
Cc: Brian Cain <bcain@xxxxxxxxxxx>
Cc: Geert Uytterhoeven <geert@xxxxxxxxxxxxxx>
Cc: Richard Weinberger <richard@xxxxxx>
Cc: Anton Ivanov <anton.ivanov@xxxxxxxxxxxxxxxxxx>
Cc: Johannes Berg <johannes@xxxxxxxxxxxxxxxx>
Signed-off-by: Ankur Arora <ankur.a.arora@xxxxxxxxxx>
---
arch/Kconfig | 7 +++++++
kernel/entry/common.c | 3 ++-
2 files changed, 9 insertions(+), 1 deletion(-)

diff --git a/arch/Kconfig b/arch/Kconfig
index 30f7930275d8..dc09306aeca0 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -1295,8 +1295,15 @@ config COMPAT_32BIT_TIME
This is relevant on all 32-bit architectures, and 64-bit architectures
as part of compat syscall handling.

+config ARCH_NO_PREEMPT_IRQ
+ bool
+
+config ARCH_NO_PREEMPT_TOGGLE
+ bool
+
config ARCH_NO_PREEMPT
bool
+ default y if ARCH_NO_PREEMPT_TOGGLE

config ARCH_SUPPORTS_RT
bool
diff --git a/kernel/entry/common.c b/kernel/entry/common.c
index c684385921de..b18175961374 100644
--- a/kernel/entry/common.c
+++ b/kernel/entry/common.c
@@ -359,7 +359,8 @@ noinstr void irqentry_exit(struct pt_regs *regs, irqentry_state_t state)
}

instrumentation_begin();
- if (IS_ENABLED(CONFIG_PREEMPTION))
+ if (IS_ENABLED(CONFIG_PREEMPTION) &&
+ !IS_ENABLED(CONFIG_ARCH_NO_PREEMPT_IRQ))
irqentry_exit_cond_resched();

/* Covers both tracing and lockdep */
--
2.31.1