Gentle ping. On 2024/6/20 17:00, Jinjie Ruan wrote: > Enable support for PREEMPT_DYNAMIC on arm32, allowing the preemption model > to be chosen at boot time. > > Similar to arm64, arm32 does not yet use the generic entry code, we must > define our own `sk_dynamic_irqentry_exit_cond_resched`, which will be > enabled/disabled by the common code in kernel/sched/core.c. > > And arm32 use generic preempt.h, so declare > `sk_dynamic_irqentry_exit_cond_resched` if the arch do not use generic > entry. Other architectures which use generic preempt.h but not use generic > entry can benefit from it. > > Test ok with the below cmdline parameters on Qemu versatilepb board: > `preempt=none` > `preempt=voluntary` > `preempt=full` > > Update preempt mode with debugfs interface on above Qemu board is also > tested ok: > # cd /sys/kernel/debug/sched > # echo none > preempt > # echo voluntary > preempt > # echo full > preempt > > Signed-off-by: Jinjie Ruan <ruanjinjie@xxxxxxxxxx> > --- > arch/arm/Kconfig | 1 + > arch/arm/include/asm/exception.h | 2 ++ > arch/arm/kernel/Makefile | 2 +- > arch/arm/kernel/common.c | 13 +++++++++++++ > arch/arm/kernel/entry-armv.S | 7 ++++++- > include/asm-generic/preempt.h | 5 +++++ > 6 files changed, 28 insertions(+), 2 deletions(-) > create mode 100644 arch/arm/kernel/common.c > > diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig > index 036381c5d42f..843f320dde7f 100644 > --- a/arch/arm/Kconfig > +++ b/arch/arm/Kconfig > @@ -124,6 +124,7 @@ config ARM > select HAVE_PERF_EVENTS > select HAVE_PERF_REGS > select HAVE_PERF_USER_STACK_DUMP > + select HAVE_PREEMPT_DYNAMIC_KEY > select MMU_GATHER_RCU_TABLE_FREE if SMP && ARM_LPAE > select HAVE_REGS_AND_STACK_ACCESS_API > select HAVE_RSEQ > diff --git a/arch/arm/include/asm/exception.h b/arch/arm/include/asm/exception.h > index 3c82975d46db..ac96b76b394e 100644 > --- a/arch/arm/include/asm/exception.h > +++ b/arch/arm/include/asm/exception.h > @@ -12,4 +12,6 @@ > > #define __exception_irq_entry __irq_entry > > +bool need_irq_preemption(void); > + > #endif /* __ASM_ARM_EXCEPTION_H */ > diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile > index 89a77e3f51d2..58acd62dc5e9 100644 > --- a/arch/arm/kernel/Makefile > +++ b/arch/arm/kernel/Makefile > @@ -17,7 +17,7 @@ CFLAGS_REMOVE_return_address.o = -pg > > # Object file lists. > > -obj-y := elf.o entry-common.o irq.o opcodes.o \ > +obj-y := common.o elf.o entry-common.o irq.o opcodes.o \ > process.o ptrace.o reboot.o io.o \ > setup.o signal.o sigreturn_codes.o \ > stacktrace.o sys_arm.o time.o traps.o > diff --git a/arch/arm/kernel/common.c b/arch/arm/kernel/common.c > new file mode 100644 > index 000000000000..52b0abcae07e > --- /dev/null > +++ b/arch/arm/kernel/common.c > @@ -0,0 +1,13 @@ > +// SPDX-License-Identifier: GPL-2.0 > + > +#include <linux/jump_label.h> > +#include <asm/exception.h> > + > +#ifdef CONFIG_PREEMPT_DYNAMIC > +DEFINE_STATIC_KEY_TRUE(sk_dynamic_irqentry_exit_cond_resched); > + > +bool need_irq_preemption(void) > +{ > + return static_branch_unlikely(&sk_dynamic_irqentry_exit_cond_resched); > +} > +#endif > diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S > index 6150a716828c..571e86433833 100644 > --- a/arch/arm/kernel/entry-armv.S > +++ b/arch/arm/kernel/entry-armv.S > @@ -221,6 +221,11 @@ __irq_svc: > irq_handler from_user=0 > > #ifdef CONFIG_PREEMPTION > +#ifdef CONFIG_PREEMPT_DYNAMIC > + bl need_irq_preemption > + cmp r0, #0 > + beq 2f > +#endif > ldr r8, [tsk, #TI_PREEMPT] @ get preempt count > ldr r0, [tsk, #TI_FLAGS] @ get flags > teq r8, #0 @ if preempt count != 0 > @@ -228,7 +233,7 @@ __irq_svc: > tst r0, #_TIF_NEED_RESCHED > blne svc_preempt > #endif > - > +2: > svc_exit r5, irq = 1 @ return from exception > UNWIND(.fnend ) > ENDPROC(__irq_svc) > diff --git a/include/asm-generic/preempt.h b/include/asm-generic/preempt.h > index 51f8f3881523..2db7a3e86303 100644 > --- a/include/asm-generic/preempt.h > +++ b/include/asm-generic/preempt.h > @@ -2,6 +2,7 @@ > #ifndef __ASM_PREEMPT_H > #define __ASM_PREEMPT_H > > +#include <linux/jump_label.h> > #include <linux/thread_info.h> > > #define PREEMPT_ENABLED (0) > @@ -89,6 +90,10 @@ void dynamic_preempt_schedule_notrace(void); > #define __preempt_schedule() dynamic_preempt_schedule() > #define __preempt_schedule_notrace() dynamic_preempt_schedule_notrace() > > +#ifndef CONFIG_GENERIC_ENTRY > +DECLARE_STATIC_KEY_TRUE(sk_dynamic_irqentry_exit_cond_resched); > +#endif > + > #else /* !CONFIG_PREEMPT_DYNAMIC || !CONFIG_HAVE_PREEMPT_DYNAMIC_KEY*/ > > #define __preempt_schedule() preempt_schedule()