summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/alpha/include/asm/ptrace.h7
-rw-r--r--arch/alpha/kernel/ptrace.c12
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. */