Re: [patch V4 12/36] entry: Inline irqentry_enter/exit_from/to_user_mode()

Mathieu Desnoyers
2025-09-09T13:38:37Z

On 2025-09-08 17:31, Thomas Gleixner wrote:
> There is no point to have this as a function which just inlines
> enter_from_user_mode(). The function call overhead is larger than the
> function itself.

I'm wondering if there is a reason for making those actual functions and
not inlines.

The functions sit in kernel/entry/common.c, which are built with
specific compiler flags in kernel/entry/Makefile:

# Prevent the noinstr section from being pestered by sanitizer and other
goodies
# as long as these things cannot be disabled per function.
KASAN_SANITIZE := n
UBSAN_SANITIZE := n
KCOV_INSTRUMENT := n

# Branch profiling isn't noinstr-safe
ccflags-$(CONFIG_TRACE_BRANCH_PROFILING) += -DDISABLE_BRANCH_PROFILING

CFLAGS_REMOVE_common.o = -fstack-protector -fstack-protector-strong
CFLAGS_common.o += -fno-stack-protector

So I wonder if we're not breaking something in the area of "noinstr"
tagging by inlining those into their caller ?

Thanks,

Mathieu

>
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
>
> ---
> include/linux/irq-entry-common.h | 13 +++++++++++--
> kernel/entry/common.c | 13 -------------
> 2 files changed, 11 insertions(+), 15 deletions(-)
>
> --- a/include/linux/irq-entry-common.h
> +++ b/include/linux/irq-entry-common.h
> @@ -278,7 +278,10 @@ static __always_inline void exit_to_user
> *
> * The function establishes state (lockdep, RCU (context tracking), tracing)
> */
> -void irqentry_enter_from_user_mode(struct pt_regs *regs);
> +static __always_inline void irqentry_enter_from_user_mode(struct pt_regs *regs)
> +{
> + enter_from_user_mode(regs);
> +}
>
> /**
> * irqentry_exit_to_user_mode - Interrupt exit work
> @@ -293,7 +296,13 @@ void irqentry_enter_from_user_mode(struc
> * Interrupt exit is not invoking #1 which is the syscall specific one time
> * work.
> */
> -void irqentry_exit_to_user_mode(struct pt_regs *regs);
> +static __always_inline void irqentry_exit_to_user_mode(struct pt_regs *regs)
> +{
> + instrumentation_begin();
> + exit_to_user_mode_prepare(regs);
> + instrumentation_end();
> + exit_to_user_mode();
> +}
>
> #ifndef irqentry_state
> /**
> --- a/kernel/entry/common.c
> +++ b/kernel/entry/common.c
> @@ -62,19 +62,6 @@ void __weak arch_do_signal_or_restart(st
> return ti_work;
> }
>
> -noinstr void irqentry_enter_from_user_mode(struct pt_regs *regs)
> -{
> - enter_from_user_mode(regs);
> -}
> -
> -noinstr void irqentry_exit_to_user_mode(struct pt_regs *regs)
> -{
> - instrumentation_begin();
> - exit_to_user_mode_prepare(regs);
> - instrumentation_end();
> - exit_to_user_mode();
> -}
> -
> noinstr irqentry_state_t irqentry_enter(struct pt_regs *regs)
> {
> irqentry_state_t ret = {
>
>

--
Mathieu Desnoyers
EfficiOS Inc.