162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 262306a36Sopenharmony_ci 362306a36Sopenharmony_ci#ifndef __ASM_CSKY_PTRACE_H 462306a36Sopenharmony_ci#define __ASM_CSKY_PTRACE_H 562306a36Sopenharmony_ci 662306a36Sopenharmony_ci#include <uapi/asm/ptrace.h> 762306a36Sopenharmony_ci#include <asm/traps.h> 862306a36Sopenharmony_ci#include <linux/types.h> 962306a36Sopenharmony_ci#include <linux/compiler.h> 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci#ifndef __ASSEMBLY__ 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_ci#define PS_S 0x80000000 /* Supervisor Mode */ 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ci#define USR_BKPT 0x1464 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ci#define arch_has_single_step() (1) 1862306a36Sopenharmony_ci#define current_pt_regs() \ 1962306a36Sopenharmony_ci({ (struct pt_regs *)((char *)current_thread_info() + THREAD_SIZE) - 1; }) 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_ci#define user_stack_pointer(regs) ((regs)->usp) 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci#define user_mode(regs) (!((regs)->sr & PS_S)) 2462306a36Sopenharmony_ci#define instruction_pointer(regs) ((regs)->pc) 2562306a36Sopenharmony_ci#define profile_pc(regs) instruction_pointer(regs) 2662306a36Sopenharmony_ci#define trap_no(regs) ((regs->sr >> 16) & 0xff) 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_cistatic inline void instruction_pointer_set(struct pt_regs *regs, 2962306a36Sopenharmony_ci unsigned long val) 3062306a36Sopenharmony_ci{ 3162306a36Sopenharmony_ci regs->pc = val; 3262306a36Sopenharmony_ci} 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ci#if defined(__CSKYABIV2__) 3562306a36Sopenharmony_ci#define MAX_REG_OFFSET offsetof(struct pt_regs, dcsr) 3662306a36Sopenharmony_ci#else 3762306a36Sopenharmony_ci#define MAX_REG_OFFSET offsetof(struct pt_regs, regs[9]) 3862306a36Sopenharmony_ci#endif 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_cistatic inline bool in_syscall(struct pt_regs const *regs) 4162306a36Sopenharmony_ci{ 4262306a36Sopenharmony_ci return ((regs->sr >> 16) & 0xff) == VEC_TRAP0; 4362306a36Sopenharmony_ci} 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_cistatic inline void forget_syscall(struct pt_regs *regs) 4662306a36Sopenharmony_ci{ 4762306a36Sopenharmony_ci regs->sr &= ~(0xff << 16); 4862306a36Sopenharmony_ci} 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_cistatic inline unsigned long regs_return_value(struct pt_regs *regs) 5162306a36Sopenharmony_ci{ 5262306a36Sopenharmony_ci return regs->a0; 5362306a36Sopenharmony_ci} 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_cistatic inline void regs_set_return_value(struct pt_regs *regs, 5662306a36Sopenharmony_ci unsigned long val) 5762306a36Sopenharmony_ci{ 5862306a36Sopenharmony_ci regs->a0 = val; 5962306a36Sopenharmony_ci} 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci/* Valid only for Kernel mode traps. */ 6262306a36Sopenharmony_cistatic inline unsigned long kernel_stack_pointer(struct pt_regs *regs) 6362306a36Sopenharmony_ci{ 6462306a36Sopenharmony_ci return regs->usp; 6562306a36Sopenharmony_ci} 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_cistatic inline unsigned long frame_pointer(struct pt_regs *regs) 6862306a36Sopenharmony_ci{ 6962306a36Sopenharmony_ci return regs->regs[4]; 7062306a36Sopenharmony_ci} 7162306a36Sopenharmony_cistatic inline void frame_pointer_set(struct pt_regs *regs, 7262306a36Sopenharmony_ci unsigned long val) 7362306a36Sopenharmony_ci{ 7462306a36Sopenharmony_ci regs->regs[4] = val; 7562306a36Sopenharmony_ci} 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_ciextern int regs_query_register_offset(const char *name); 7862306a36Sopenharmony_ciextern unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs, 7962306a36Sopenharmony_ci unsigned int n); 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_ci/* 8262306a36Sopenharmony_ci * regs_get_register() - get register value from its offset 8362306a36Sopenharmony_ci * @regs: pt_regs from which register value is gotten 8462306a36Sopenharmony_ci * @offset: offset of the register. 8562306a36Sopenharmony_ci * 8662306a36Sopenharmony_ci * regs_get_register returns the value of a register whose offset from @regs. 8762306a36Sopenharmony_ci * The @offset is the offset of the register in struct pt_regs. 8862306a36Sopenharmony_ci * If @offset is bigger than MAX_REG_OFFSET, this returns 0. 8962306a36Sopenharmony_ci */ 9062306a36Sopenharmony_cistatic inline unsigned long regs_get_register(struct pt_regs *regs, 9162306a36Sopenharmony_ci unsigned int offset) 9262306a36Sopenharmony_ci{ 9362306a36Sopenharmony_ci if (unlikely(offset > MAX_REG_OFFSET)) 9462306a36Sopenharmony_ci return 0; 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_ci return *(unsigned long *)((unsigned long)regs + offset); 9762306a36Sopenharmony_ci} 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_ciasmlinkage int syscall_trace_enter(struct pt_regs *regs); 10062306a36Sopenharmony_ciasmlinkage void syscall_trace_exit(struct pt_regs *regs); 10162306a36Sopenharmony_ci#endif /* __ASSEMBLY__ */ 10262306a36Sopenharmony_ci#endif /* __ASM_CSKY_PTRACE_H */ 103