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