Currently the signal handling code has its own struct frame_record,
the definition of struct pt_regs open-codes a frame record as an array,
and the kernel unwinder hard-codes frame record offsets.
Move to a common struct frame_record that can be used throughout the
kernel.
Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Reviewed-by: Mark Brown <broonie@kernel.org>
Reviewed-by: Miroslav Benes <mbenes@suse.cz>
Reviewed-by: Puranjay Mohan <puranjay12@gmail.com>
Cc: Ard Biesheuvel <ardb@kernel.org>
Cc: Josh Poimboeuf <jpoimboe@kernel.org>
Cc: Kalesh Singh <kaleshsingh@google.com>
Cc: Madhavan T. Venkataraman <madvenka@linux.microsoft.com>
Cc: Marc Zyngier <maz@kernel.org>
Cc: Will Deacon <will@kernel.org>
Link: https://lore.kernel.org/r/20241017092538.1859841-6-mark.rutland@arm.com
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
 
 #include <linux/bug.h>
 #include <linux/types.h>
 
+#include <asm/stacktrace/frame.h>
+
 /* sizeof(struct user) for AArch32 */
 #define COMPAT_USER_SZ 296
 
        u64 sdei_ttbr1;
        u64 unused;
 
-       u64 stackframe[2];
+       struct frame_record stackframe;
 
        /* Only valid for some EL1 exceptions. */
        u64 lockdep_hardirqs;
 
 static inline int
 unwind_next_frame_record(struct unwind_state *state)
 {
+       struct frame_record *record;
        unsigned long fp = state->fp;
        int err;
 
        if (fp & 0x7)
                return -EINVAL;
 
-       err = unwind_consume_stack(state, fp, 16);
+       err = unwind_consume_stack(state, fp, sizeof(*record));
        if (err)
                return err;
 
        /*
         * Record this frame record's values.
         */
-       state->fp = READ_ONCE(*(unsigned long *)(fp));
-       state->pc = READ_ONCE(*(unsigned long *)(fp + 8));
+       record = (struct frame_record *)fp;
+       state->fp = READ_ONCE(record->fp);
+       state->pc = READ_ONCE(record->lr);
 
        return 0;
 }
 
--- /dev/null
+/* SPDX-License-Identifier: GPL-2.0-only */
+#ifndef __ASM_STACKTRACE_FRAME_H
+#define __ASM_STACKTRACE_FRAME_H
+
+/*
+ * A standard AAPCS64 frame record.
+ */
+struct frame_record {
+       u64 fp;
+       u64 lr;
+};
+
+#endif /* __ASM_STACKTRACE_FRAME_H */
 
         * For the benefit of the unwinder, set up childregs->stackframe
         * as the final frame for the new task.
         */
-       p->thread.cpu_context.fp = (unsigned long)childregs->stackframe;
+       p->thread.cpu_context.fp = (unsigned long)&childregs->stackframe;
 
        ptrace_hw_copy_thread(p);
 
 
        struct ucontext uc;
 };
 
-struct frame_record {
-       u64 fp;
-       u64 lr;
-};
-
 struct rt_sigframe_user_layout {
        struct rt_sigframe __user *sigframe;
        struct frame_record __user *next_frame;
 
        int err;
 
        /* Final frame; nothing to unwind */
-       if (fp == (unsigned long)task_pt_regs(tsk)->stackframe)
+       if (fp == (unsigned long)&task_pt_regs(tsk)->stackframe)
                return -ENOENT;
 
        err = unwind_next_frame_record(&state->common);