[PATCH 08/14] alpha: use generic syscall exit for new tasks

From: Magnus Lindholm

Date: Tue Nov 03 2026 - 16:49:42 EST


Move fork and kernel-thread startup into C and use
syscall_exit_to_user_mode() for the return to userspace, retaining the
saved user context for exit work.

This also supplies the child syscall-exit tracepoint for fork, vfork,
clone and clone3.

Signed-off-by: Magnus Lindholm <linmag7@xxxxxxxxx>
---
arch/alpha/kernel/entry.S | 23 ++++++++++-------------
arch/alpha/kernel/process.c | 16 ++++++++++++++++
arch/alpha/kernel/proto.h | 6 ++++--
arch/alpha/kernel/signal.c | 8 --------
4 files changed, 30 insertions(+), 23 deletions(-)

diff --git a/arch/alpha/kernel/entry.S b/arch/alpha/kernel/entry.S
index 2233eb6da7065e7d85cbc668a09e565bcfd75a52..5da8c0d17a1d893f59bee1a12f5782276432674d 100644
--- a/arch/alpha/kernel/entry.S
+++ b/arch/alpha/kernel/entry.S
@@ -417,11 +417,11 @@ ret_from_exception:
beq $0, restore_other
br restore_all

-ret_to_user_from_exception:
-
- mov $sp, $16
+ret_from_fork_common:
+ mov $17, $16
+ mov $sp, $17
DO_SWITCH_STACK
- jsr $26, alpha_exit_to_user_mode
+ jsr $26, alpha_ret_from_fork
ldgp $gp, 0($26)
UNDO_SWITCH_STACK
br restore_all
@@ -548,9 +548,9 @@ alpha_switch_to:
.align 4
.ent ret_from_fork
ret_from_fork:
- lda $26, ret_to_user_from_exception
- mov $17, $16
- jmp $31, schedule_tail
+ mov $31, $18
+ mov $31, $19
+ br $31, ret_from_fork_common
.end ret_from_fork

/*
@@ -560,10 +560,7 @@ ret_from_fork:
.globl ret_from_kernel_thread
.ent ret_from_kernel_thread
ret_from_kernel_thread:
- mov $17, $16
- jsr $26, schedule_tail
- mov $9, $27
- mov $10, $16
- jsr $26, ($9)
- br $31, ret_to_user_from_exception
+ mov $9, $18
+ mov $10, $19
+ br $31, ret_from_fork_common
.end ret_from_kernel_thread
diff --git a/arch/alpha/kernel/process.c b/arch/alpha/kernel/process.c
index 2182496c535661f399a73400e308c0a7fc6d76f1..c7e6e7b593af10305414ea30f5b944b9d21dd2e2 100644
--- a/arch/alpha/kernel/process.c
+++ b/arch/alpha/kernel/process.c
@@ -10,6 +10,7 @@
*/

#include <linux/cpu.h>
+#include <linux/entry-common.h>
#include <linux/errno.h>
#include <linux/module.h>
#include <linux/sched.h>
@@ -226,6 +227,21 @@ flush_thread(void)
current_thread_info()->pcb.unique = 0;
}

+/* The assembly stub keeps the complete user switch_stack below regs. */
+asmlinkage noinstr void alpha_ret_from_fork(struct task_struct *prev,
+ struct pt_regs *regs,
+ int (*fn)(void *), void *fn_arg)
+{
+ instrumentation_begin();
+ schedule_tail(prev);
+ if (fn)
+ fn(fn_arg);
+ instrumentation_end();
+
+ /* A kernel thread may return after a successful kernel_execve(). */
+ syscall_exit_to_user_mode(regs);
+}
+
/*
* Copy architecture-specific thread state
*/
diff --git a/arch/alpha/kernel/proto.h b/arch/alpha/kernel/proto.h
index 90af335cd6798ad4039ecc2a3c67505eadbd32a2..c418333d0b89d910ec59d1d57d6bcc0550efc4aa 100644
--- a/arch/alpha/kernel/proto.h
+++ b/arch/alpha/kernel/proto.h
@@ -164,14 +164,16 @@ extern void entDbg(void);
/* pci.c */
extern void pcibios_claim_one_bus(struct pci_bus *);

+/* process.c */
+extern void alpha_ret_from_fork(struct task_struct *prev, struct pt_regs *regs,
+ int (*fn)(void *), void *fn_arg);
+
/* ptrace.c */
extern int ptrace_set_bpt (struct task_struct *child);
extern int ptrace_cancel_bpt (struct task_struct *child);

/* signal.c */
-extern void alpha_schedule_user_work(void);
extern void do_signal(struct pt_regs *regs, unsigned long r0, unsigned long r19);
-extern void alpha_exit_to_user_mode(struct pt_regs *regs);

/* syscall.c */
extern void alpha_syscall(struct pt_regs *regs);
diff --git a/arch/alpha/kernel/signal.c b/arch/alpha/kernel/signal.c
index 244fec20294b81e0c749a07321f917befb62b1a7..e3cb1b50c83d9680032731799b644118b46803bc 100644
--- a/arch/alpha/kernel/signal.c
+++ b/arch/alpha/kernel/signal.c
@@ -538,14 +538,6 @@ do_signal(struct pt_regs *regs, unsigned long r0, unsigned long r19)
ptrace_set_bpt(current); /* re-set breakpoint */
}

-asmlinkage noinstr void alpha_exit_to_user_mode(struct pt_regs *regs)
-{
- instrumentation_begin();
- local_irq_disable();
- instrumentation_end();
- irqentry_exit_to_user_mode(regs);
-}
-
void arch_do_signal_or_restart(struct pt_regs *regs)
{
struct thread_info *ti = current_thread_info();
--
2.43.0