diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 10:05:51 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 10:05:51 +0000 |
commit | 5d1646d90e1f2cceb9f0828f4b28318cd0ec7744 (patch) | |
tree | a94efe259b9009378be6d90eb30d2b019d95c194 /arch/sparc/include/asm/ptrace.h | |
parent | Initial commit. (diff) | |
download | linux-430c2fc249ea5c0536abd21c23382884005c9093.tar.xz linux-430c2fc249ea5c0536abd21c23382884005c9093.zip |
Adding upstream version 5.10.209.upstream/5.10.209upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'arch/sparc/include/asm/ptrace.h')
-rw-r--r-- | arch/sparc/include/asm/ptrace.h | 162 |
1 files changed, 162 insertions, 0 deletions
diff --git a/arch/sparc/include/asm/ptrace.h b/arch/sparc/include/asm/ptrace.h new file mode 100644 index 000000000..71dd82b43 --- /dev/null +++ b/arch/sparc/include/asm/ptrace.h @@ -0,0 +1,162 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __SPARC_PTRACE_H +#define __SPARC_PTRACE_H + +#include <uapi/asm/ptrace.h> + +#if defined(__sparc__) && defined(__arch64__) +#ifndef __ASSEMBLY__ + +#include <linux/compiler.h> +#include <linux/threads.h> +#include <asm/switch_to.h> + +static inline int pt_regs_trap_type(struct pt_regs *regs) +{ + return regs->magic & 0x1ff; +} + +static inline bool pt_regs_is_syscall(struct pt_regs *regs) +{ + return (regs->tstate & TSTATE_SYSCALL); +} + +static inline bool pt_regs_clear_syscall(struct pt_regs *regs) +{ + return (regs->tstate &= ~TSTATE_SYSCALL); +} + +#define arch_ptrace_stop_needed(exit_code, info) \ +({ flush_user_windows(); \ + get_thread_wsaved() != 0; \ +}) + +#define arch_ptrace_stop(exit_code, info) \ + synchronize_user_stack() + +#define current_pt_regs() \ + ((struct pt_regs *)((unsigned long)current_thread_info() + THREAD_SIZE) - 1) + +struct global_reg_snapshot { + unsigned long tstate; + unsigned long tpc; + unsigned long tnpc; + unsigned long o7; + unsigned long i7; + unsigned long rpc; + struct thread_info *thread; + unsigned long pad1; +}; + +struct global_pmu_snapshot { + unsigned long pcr[4]; + unsigned long pic[4]; +}; + +union global_cpu_snapshot { + struct global_reg_snapshot reg; + struct global_pmu_snapshot pmu; +}; + +extern union global_cpu_snapshot global_cpu_snapshot[NR_CPUS]; + +#define force_successful_syscall_return() set_thread_noerror(1) +#define user_mode(regs) (!((regs)->tstate & TSTATE_PRIV)) +#define instruction_pointer(regs) ((regs)->tpc) +#define instruction_pointer_set(regs, val) do { \ + (regs)->tpc = (val); \ + (regs)->tnpc = (val)+4; \ + } while (0) +#define user_stack_pointer(regs) ((regs)->u_regs[UREG_FP]) +static inline int is_syscall_success(struct pt_regs *regs) +{ + return !(regs->tstate & (TSTATE_XCARRY | TSTATE_ICARRY)); +} + +static inline long regs_return_value(struct pt_regs *regs) +{ + return regs->u_regs[UREG_I0]; +} +#ifdef CONFIG_SMP +unsigned long profile_pc(struct pt_regs *); +#else +#define profile_pc(regs) instruction_pointer(regs) +#endif + +#define MAX_REG_OFFSET (offsetof(struct pt_regs, magic)) + +int regs_query_register_offset(const char *name); +unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs, unsigned int n); + +/** + * regs_get_register() - get register value from its offset + * @regs: pt_regs from which register value is gotten + * @offset: offset number of the register. + * + * regs_get_register returns the value of a register whose + * offset from @regs. The @offset is the offset of the register + * in struct pt_regs. If @offset is bigger than MAX_REG_OFFSET, + * this returns 0. + */ +static inline unsigned long regs_get_register(struct pt_regs *regs, + unsigned long offset) +{ + if (unlikely(offset >= MAX_REG_OFFSET)) + return 0; + if (offset == PT_V9_Y) + return *(unsigned int *)((unsigned long)regs + offset); + return *(unsigned long *)((unsigned long)regs + offset); +} + +/* Valid only for Kernel mode traps. */ +static inline unsigned long kernel_stack_pointer(struct pt_regs *regs) +{ + return regs->u_regs[UREG_I6]; +} +#else /* __ASSEMBLY__ */ +#endif /* __ASSEMBLY__ */ +#else /* (defined(__sparc__) && defined(__arch64__)) */ +#ifndef __ASSEMBLY__ +#include <asm/switch_to.h> + +static inline bool pt_regs_is_syscall(struct pt_regs *regs) +{ + return (regs->psr & PSR_SYSCALL); +} + +static inline bool pt_regs_clear_syscall(struct pt_regs *regs) +{ + return (regs->psr &= ~PSR_SYSCALL); +} + +#define arch_ptrace_stop_needed(exit_code, info) \ +({ flush_user_windows(); \ + current_thread_info()->w_saved != 0; \ +}) + +#define arch_ptrace_stop(exit_code, info) \ + synchronize_user_stack() + +#define current_pt_regs() \ + ((struct pt_regs *)((unsigned long)current_thread_info() + THREAD_SIZE) - 1) + +#define user_mode(regs) (!((regs)->psr & PSR_PS)) +#define instruction_pointer(regs) ((regs)->pc) +#define user_stack_pointer(regs) ((regs)->u_regs[UREG_FP]) +unsigned long profile_pc(struct pt_regs *); +#else /* (!__ASSEMBLY__) */ +#endif /* (!__ASSEMBLY__) */ +#endif /* (defined(__sparc__) && defined(__arch64__)) */ +#define STACK_BIAS 2047 + +/* global_reg_snapshot offsets */ +#define GR_SNAP_TSTATE 0x00 +#define GR_SNAP_TPC 0x08 +#define GR_SNAP_TNPC 0x10 +#define GR_SNAP_O7 0x18 +#define GR_SNAP_I7 0x20 +#define GR_SNAP_RPC 0x28 +#define GR_SNAP_THREAD 0x30 +#define GR_SNAP_PAD1 0x38 + +#endif /* !(__SPARC_PTRACE_H) */ |