summaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel
diff options
context:
space:
mode:
authorNicholas Piggin <npiggin@gmail.com>2022-11-27 13:49:37 +0100
committerMichael Ellerman <mpe@ellerman.id.au>2022-12-02 07:54:08 +0100
commit6895dfc0474170c492191c126fcfc420f7771a09 (patch)
tree9ec46c9a349e97e9d7d09c28c1edd1c79692c2b4 /arch/powerpc/kernel
parentpowerpc: add a define for the switch frame size and regs offset (diff)
downloadlinux-6895dfc0474170c492191c126fcfc420f7771a09.tar.xz
linux-6895dfc0474170c492191c126fcfc420f7771a09.zip
powerpc: copy_thread fill in interrupt frame marker and back chain
Backtraces will not recognise the fork system call interrupt without the regs marker. And regular interrupt entry from userspace creates the back chain to the user stack, so do this for the initial fork frame too, to be consistent. Signed-off-by: Nicholas Piggin <npiggin@gmail.com> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au> Link: https://lore.kernel.org/r/20221127124942.1665522-13-npiggin@gmail.com
Diffstat (limited to 'arch/powerpc/kernel')
-rw-r--r--arch/powerpc/kernel/process.c4
1 files changed, 3 insertions, 1 deletions
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
index 0cb5296c6c41..6b1d80bd370e 100644
--- a/arch/powerpc/kernel/process.c
+++ b/arch/powerpc/kernel/process.c
@@ -1757,12 +1757,13 @@ int copy_thread(struct task_struct *p, const struct kernel_clone_args *args)
/* Create initial stack frame. */
sp -= STACK_USER_INT_FRAME_SIZE;
- ((unsigned long *)sp)[0] = 0;
+ *(unsigned long *)(sp + STACK_INT_FRAME_MARKER) = STACK_FRAME_REGS_MARKER;
/* Copy registers */
childregs = (struct pt_regs *)(sp + STACK_INT_FRAME_REGS);
if (unlikely(args->fn)) {
/* kernel thread */
+ ((unsigned long *)sp)[0] = 0;
memset(childregs, 0, sizeof(struct pt_regs));
childregs->gpr[1] = sp + STACK_USER_INT_FRAME_SIZE;
/* function */
@@ -1782,6 +1783,7 @@ int copy_thread(struct task_struct *p, const struct kernel_clone_args *args)
*childregs = *regs;
if (usp)
childregs->gpr[1] = usp;
+ ((unsigned long *)sp)[0] = childregs->gpr[1];
p->thread.regs = childregs;
/* 64s sets this in ret_from_fork */
if (!IS_ENABLED(CONFIG_PPC_BOOK3S_64))