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.
Acked-by: Thomas Gleixner <tglx@linutronix.de>
Acked-by: Paul E. McKenney <paulmck@kernel.org>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
---
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 5385574c4339714f3d8b5ab6894f27466b89f932..e2ac6d3216b6828d948d60c424ff95ccdad12331 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 0e3960844b94b14325eb00ce7dd791b36c43ac3c..88a7a699306ab61153d57333c26266b9161f5466 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.49.0