diff options
| author | Matt Turner <mattst88@gmail.com> | 2026-10-18 10:22:01 -0400 |
|---|---|---|
| committer | Magnus Lindholm <linmag7@gmail.com> | 2026-10-18 20:09:29 +0200 |
| commit | bceba446fa2bc66a905ec0bbf6fd80e98701c1d1 (patch) | |
| tree | b73673c83ff0e55ab715ac0a74b04ea5ea8ddb95 | |
| parent | b9fad53a62776359d3bb607bd0ba66e37d198260 (diff) | |
alpha: fix stale user_stack_pointer()
PALcode keeps the user stack pointer in the PCB, not the trap frame, so
pt_regs->usp is only valid where entry code stores it: entSys,
do_entArith() and do_entIF(). Interrupts, page faults and unaligned
traps leave it stale, and ptrace and /proc/<pid>/syscall read it
through user_stack_pointer().
A user-mode pt_regs is at the top of its task's stack, so find the
thread_info from it and use rdusp() for current or pcb.usp otherwise,
as KSTK_ESP() and the regset code already do.
Fixes: 8a2857bc2b30 ("alpha: enable regset-based ptrace and core dumps")
Assisted-by: Claude:claude-opus-5-5
Reviewed-by: Magnus Lindholm <linmag7@gmail.com>
Tested-by: Magnus Lindholm <linmag7@gmail.com>
Acked-by: Ian Rogers <irogers@google.com>
Signed-off-by: Matt Turner <mattst88@gmail.com>
Link: https://lore.kernel.org/r/20261018-alpha-perf-regs-v3-v3-1-52be85332c57@gmail.com
Signed-off-by: Magnus Lindholm <linmag7@gmail.com>
| -rw-r--r-- | arch/alpha/include/asm/ptrace.h | 7 | ||||
| -rw-r--r-- | arch/alpha/kernel/ptrace.c | 12 |
2 files changed, 13 insertions, 6 deletions
diff --git a/arch/alpha/include/asm/ptrace.h b/arch/alpha/include/asm/ptrace.h index 430e8dc27ff7..45d1229344b6 100644 --- a/arch/alpha/include/asm/ptrace.h +++ b/arch/alpha/include/asm/ptrace.h @@ -26,12 +26,7 @@ static inline unsigned long regs_return_value(struct pt_regs *regs) return regs->r0; } -/* Helpers for working with the user stack pointer */ -static inline unsigned long user_stack_pointer(struct pt_regs *regs) -{ - /* Valid for user-mode regs */ - return regs->usp; -} +unsigned long user_stack_pointer(struct pt_regs *regs); static __always_inline bool regs_irqs_disabled(struct pt_regs *regs) { diff --git a/arch/alpha/kernel/ptrace.c b/arch/alpha/kernel/ptrace.c index e1d8c2f69688..dba7e9905cfa 100644 --- a/arch/alpha/kernel/ptrace.c +++ b/arch/alpha/kernel/ptrace.c @@ -440,6 +440,18 @@ ptrace_cancel_bpt(struct task_struct * child) return (nsaved != 0); } +/* + * PALcode keeps the user stack pointer in the PCB, not the trap frame. + * A user-mode pt_regs sits at the top of its task's stack, so the + * thread_info is at the base. + */ +unsigned long user_stack_pointer(struct pt_regs *regs) +{ + struct thread_info *ti = (void *)((unsigned long)regs & -THREAD_SIZE); + + return ti == current_thread_info() ? rdusp() : ti->pcb.usp; +} + void user_enable_single_step(struct task_struct *child) { /* Mark single stepping. */ |
