diff options
Diffstat (limited to 'arch/powerpc/include/asm/ptrace.h')
-rw-r--r-- | arch/powerpc/include/asm/ptrace.h | 91 |
1 files changed, 63 insertions, 28 deletions
diff --git a/arch/powerpc/include/asm/ptrace.h b/arch/powerpc/include/asm/ptrace.h index 9c9ab2746168..3e5d470a6155 100644 --- a/arch/powerpc/include/asm/ptrace.h +++ b/arch/powerpc/include/asm/ptrace.h @@ -19,6 +19,7 @@ #ifndef _ASM_POWERPC_PTRACE_H #define _ASM_POWERPC_PTRACE_H +#include <linux/err.h> #include <uapi/asm/ptrace.h> #include <asm/asm-const.h> @@ -47,11 +48,12 @@ struct pt_regs unsigned long result; }; }; - +#if defined(CONFIG_PPC64) || defined(CONFIG_PPC_KUAP) union { struct { #ifdef CONFIG_PPC64 unsigned long ppr; + unsigned long exit_result; #endif union { #ifdef CONFIG_PPC_KUAP @@ -67,6 +69,7 @@ struct pt_regs }; unsigned long __pad[4]; /* Maintain 16 byte interrupt stack alignment */ }; +#endif }; #endif @@ -121,54 +124,61 @@ struct pt_regs #endif /* __powerpc64__ */ #ifndef __ASSEMBLY__ +#include <asm/paca.h> -static inline unsigned long instruction_pointer(struct pt_regs *regs) +#ifdef CONFIG_SMP +extern unsigned long profile_pc(struct pt_regs *regs); +#else +#define profile_pc(regs) instruction_pointer(regs) +#endif + +long do_syscall_trace_enter(struct pt_regs *regs); +void do_syscall_trace_leave(struct pt_regs *regs); + +static inline void set_return_regs_changed(void) { - return regs->nip; +#ifdef CONFIG_PPC_BOOK3S_64 + local_paca->hsrr_valid = 0; + local_paca->srr_valid = 0; +#endif } -static inline void instruction_pointer_set(struct pt_regs *regs, - unsigned long val) +static inline void regs_set_return_ip(struct pt_regs *regs, unsigned long ip) { - regs->nip = val; + regs->nip = ip; + set_return_regs_changed(); } -static inline unsigned long user_stack_pointer(struct pt_regs *regs) +static inline void regs_set_return_msr(struct pt_regs *regs, unsigned long msr) { - return regs->gpr[1]; + regs->msr = msr; + set_return_regs_changed(); } -static inline unsigned long frame_pointer(struct pt_regs *regs) +static inline void regs_add_return_ip(struct pt_regs *regs, long offset) { - return 0; + regs_set_return_ip(regs, regs->nip + offset); } -#ifdef CONFIG_SMP -extern unsigned long profile_pc(struct pt_regs *regs); -#else -#define profile_pc(regs) instruction_pointer(regs) -#endif - -long do_syscall_trace_enter(struct pt_regs *regs); -void do_syscall_trace_leave(struct pt_regs *regs); +static inline unsigned long instruction_pointer(struct pt_regs *regs) +{ + return regs->nip; +} -#define kernel_stack_pointer(regs) ((regs)->gpr[1]) -static inline int is_syscall_success(struct pt_regs *regs) +static inline void instruction_pointer_set(struct pt_regs *regs, + unsigned long val) { - return !(regs->ccr & 0x10000000); + regs_set_return_ip(regs, val); } -static inline long regs_return_value(struct pt_regs *regs) +static inline unsigned long user_stack_pointer(struct pt_regs *regs) { - if (is_syscall_success(regs)) - return regs->gpr[3]; - else - return -regs->gpr[3]; + return regs->gpr[1]; } -static inline void regs_set_return_value(struct pt_regs *regs, unsigned long rc) +static inline unsigned long frame_pointer(struct pt_regs *regs) { - regs->gpr[3] = rc; + return 0; } #ifdef __powerpc64__ @@ -235,6 +245,31 @@ static __always_inline void set_trap_norestart(struct pt_regs *regs) regs->trap |= 0x1; } +#define kernel_stack_pointer(regs) ((regs)->gpr[1]) +static inline int is_syscall_success(struct pt_regs *regs) +{ + if (trap_is_scv(regs)) + return !IS_ERR_VALUE((unsigned long)regs->gpr[3]); + else + return !(regs->ccr & 0x10000000); +} + +static inline long regs_return_value(struct pt_regs *regs) +{ + if (trap_is_scv(regs)) + return regs->gpr[3]; + + if (is_syscall_success(regs)) + return regs->gpr[3]; + else + return -regs->gpr[3]; +} + +static inline void regs_set_return_value(struct pt_regs *regs, unsigned long rc) +{ + regs->gpr[3] = rc; +} + #define arch_has_single_step() (1) #define arch_has_block_step() (true) #define ARCH_HAS_USER_SINGLE_STEP_REPORT |