[PATCH RFC 23/28] ARM: entry: Stop exiting syscalls like IRQs

From: Linus Walleij
Date: Thu Oct 10 2024 - 07:37:51 EST


The syscalls are issued as software interrupts, and to this point
they were sharing code with the other exception handlers, but
this does not work with generic entry.

Make syscall_exit_to_user_mode do what irqentry_exit_to_user_mode
does at it's tail, and drop the invocations of
irqentry_exit_to_user_mode from the syscall path so that these
are now exception-exclusive.

Split ret_to_user and ret_to_user_from_irq into two distinct
execution paths.

Signed-off-by: Linus Walleij <linus.walleij@xxxxxxxxxx>
---
arch/arm/kernel/entry-common.S | 14 ++++++++++++--
arch/arm/kernel/entry.c | 4 ++++
2 files changed, 16 insertions(+), 2 deletions(-)

diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S
index 5385574c4339..e2ac6d3216b6 100644
--- a/arch/arm/kernel/entry-common.S
+++ b/arch/arm/kernel/entry-common.S
@@ -42,7 +42,6 @@ ret_fast_syscall:
/* do_rseq_syscall needs interrupts enabled. */
mov r0, sp @ 'regs'
bl syscall_exit_to_user_mode
- asm_irqentry_exit_to_user_mode

#ifdef CONFIG_GCC_PLUGIN_STACKLEAK
bl stackleak_erase_on_task_stack
@@ -62,6 +61,18 @@ ENTRY(ret_to_user)
enable_irq_notrace @ enable interrupts
mov r0, sp @ 'regs'
bl syscall_exit_to_user_mode
+ ldr r1, [tsk, #TI_FLAGS]
+ movs r1, r1, lsl #16
+ beq 1f
+ mov r0, sp @ 'regs'
+ bl do_work_pending
+1:
+#ifdef CONFIG_GCC_PLUGIN_STACKLEAK
+ bl stackleak_erase_on_task_stack
+#endif
+ restore_user_regs
+ENDPROC(ret_to_user)
+
ENTRY(ret_to_user_from_irq)
ldr r1, [tsk, #TI_FLAGS]
movs r1, r1, lsl #16
@@ -76,7 +87,6 @@ no_work_pending:
#endif
restore_user_regs
ENDPROC(ret_to_user_from_irq)
-ENDPROC(ret_to_user)

/*
* This is how we return from a fork.
diff --git a/arch/arm/kernel/entry.c b/arch/arm/kernel/entry.c
index 0e3960844b94..88a7a699306a 100644
--- a/arch/arm/kernel/entry.c
+++ b/arch/arm/kernel/entry.c
@@ -30,6 +30,10 @@ void syscall_exit_to_user_mode(struct pt_regs *regs)
local_irq_disable();
if (has_syscall_work(flags))
do_work_pending(regs, flags);
+
+ trace_hardirqs_on();
+ /* This context tracking call has inverse naming */
+ user_enter_callable();
}

noinstr void irqentry_enter_from_user_mode(struct pt_regs *regs)

--
2.46.2