18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
28c2ecf20Sopenharmony_ci// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
38c2ecf20Sopenharmony_ci
48c2ecf20Sopenharmony_ci#ifndef __ASM_CSKY_PTRACE_H
58c2ecf20Sopenharmony_ci#define __ASM_CSKY_PTRACE_H
68c2ecf20Sopenharmony_ci
78c2ecf20Sopenharmony_ci#include <uapi/asm/ptrace.h>
88c2ecf20Sopenharmony_ci#include <asm/traps.h>
98c2ecf20Sopenharmony_ci#include <linux/types.h>
108c2ecf20Sopenharmony_ci#include <linux/compiler.h>
118c2ecf20Sopenharmony_ci
128c2ecf20Sopenharmony_ci#ifndef __ASSEMBLY__
138c2ecf20Sopenharmony_ci
148c2ecf20Sopenharmony_ci#define PS_S	0x80000000 /* Supervisor Mode */
158c2ecf20Sopenharmony_ci
168c2ecf20Sopenharmony_ci#define USR_BKPT	0x1464
178c2ecf20Sopenharmony_ci
188c2ecf20Sopenharmony_ci#define arch_has_single_step() (1)
198c2ecf20Sopenharmony_ci#define current_pt_regs() \
208c2ecf20Sopenharmony_ci({ (struct pt_regs *)((char *)current_thread_info() + THREAD_SIZE) - 1; })
218c2ecf20Sopenharmony_ci
228c2ecf20Sopenharmony_ci#define user_stack_pointer(regs) ((regs)->usp)
238c2ecf20Sopenharmony_ci
248c2ecf20Sopenharmony_ci#define user_mode(regs) (!((regs)->sr & PS_S))
258c2ecf20Sopenharmony_ci#define instruction_pointer(regs) ((regs)->pc)
268c2ecf20Sopenharmony_ci#define profile_pc(regs) instruction_pointer(regs)
278c2ecf20Sopenharmony_ci#define trap_no(regs) ((regs->sr >> 16) & 0xff)
288c2ecf20Sopenharmony_ci
298c2ecf20Sopenharmony_cistatic inline void instruction_pointer_set(struct pt_regs *regs,
308c2ecf20Sopenharmony_ci					   unsigned long val)
318c2ecf20Sopenharmony_ci{
328c2ecf20Sopenharmony_ci	regs->pc = val;
338c2ecf20Sopenharmony_ci}
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_ci#if defined(__CSKYABIV2__)
368c2ecf20Sopenharmony_ci#define MAX_REG_OFFSET offsetof(struct pt_regs, dcsr)
378c2ecf20Sopenharmony_ci#else
388c2ecf20Sopenharmony_ci#define MAX_REG_OFFSET offsetof(struct pt_regs, regs[9])
398c2ecf20Sopenharmony_ci#endif
408c2ecf20Sopenharmony_ci
418c2ecf20Sopenharmony_cistatic inline bool in_syscall(struct pt_regs const *regs)
428c2ecf20Sopenharmony_ci{
438c2ecf20Sopenharmony_ci	return ((regs->sr >> 16) & 0xff) == VEC_TRAP0;
448c2ecf20Sopenharmony_ci}
458c2ecf20Sopenharmony_ci
468c2ecf20Sopenharmony_cistatic inline void forget_syscall(struct pt_regs *regs)
478c2ecf20Sopenharmony_ci{
488c2ecf20Sopenharmony_ci	regs->sr &= ~(0xff << 16);
498c2ecf20Sopenharmony_ci}
508c2ecf20Sopenharmony_ci
518c2ecf20Sopenharmony_cistatic inline unsigned long regs_return_value(struct pt_regs *regs)
528c2ecf20Sopenharmony_ci{
538c2ecf20Sopenharmony_ci	return regs->a0;
548c2ecf20Sopenharmony_ci}
558c2ecf20Sopenharmony_ci
568c2ecf20Sopenharmony_cistatic inline void regs_set_return_value(struct pt_regs *regs,
578c2ecf20Sopenharmony_ci					 unsigned long val)
588c2ecf20Sopenharmony_ci{
598c2ecf20Sopenharmony_ci	regs->a0 = val;
608c2ecf20Sopenharmony_ci}
618c2ecf20Sopenharmony_ci
628c2ecf20Sopenharmony_ci/* Valid only for Kernel mode traps. */
638c2ecf20Sopenharmony_cistatic inline unsigned long kernel_stack_pointer(struct pt_regs *regs)
648c2ecf20Sopenharmony_ci{
658c2ecf20Sopenharmony_ci	return regs->usp;
668c2ecf20Sopenharmony_ci}
678c2ecf20Sopenharmony_ci
688c2ecf20Sopenharmony_cistatic inline unsigned long frame_pointer(struct pt_regs *regs)
698c2ecf20Sopenharmony_ci{
708c2ecf20Sopenharmony_ci	return regs->regs[4];
718c2ecf20Sopenharmony_ci}
728c2ecf20Sopenharmony_cistatic inline void frame_pointer_set(struct pt_regs *regs,
738c2ecf20Sopenharmony_ci				     unsigned long val)
748c2ecf20Sopenharmony_ci{
758c2ecf20Sopenharmony_ci	regs->regs[4] = val;
768c2ecf20Sopenharmony_ci}
778c2ecf20Sopenharmony_ci
788c2ecf20Sopenharmony_ciextern int regs_query_register_offset(const char *name);
798c2ecf20Sopenharmony_ciextern unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs,
808c2ecf20Sopenharmony_ci						unsigned int n);
818c2ecf20Sopenharmony_ci
828c2ecf20Sopenharmony_ci/*
838c2ecf20Sopenharmony_ci * regs_get_register() - get register value from its offset
848c2ecf20Sopenharmony_ci * @regs:      pt_regs from which register value is gotten
858c2ecf20Sopenharmony_ci * @offset:    offset of the register.
868c2ecf20Sopenharmony_ci *
878c2ecf20Sopenharmony_ci * regs_get_register returns the value of a register whose offset from @regs.
888c2ecf20Sopenharmony_ci * The @offset is the offset of the register in struct pt_regs.
898c2ecf20Sopenharmony_ci * If @offset is bigger than MAX_REG_OFFSET, this returns 0.
908c2ecf20Sopenharmony_ci */
918c2ecf20Sopenharmony_cistatic inline unsigned long regs_get_register(struct pt_regs *regs,
928c2ecf20Sopenharmony_ci						unsigned int offset)
938c2ecf20Sopenharmony_ci{
948c2ecf20Sopenharmony_ci	if (unlikely(offset > MAX_REG_OFFSET))
958c2ecf20Sopenharmony_ci		return 0;
968c2ecf20Sopenharmony_ci
978c2ecf20Sopenharmony_ci	return *(unsigned long *)((unsigned long)regs + offset);
988c2ecf20Sopenharmony_ci}
998c2ecf20Sopenharmony_ci
1008c2ecf20Sopenharmony_ci#endif /* __ASSEMBLY__ */
1018c2ecf20Sopenharmony_ci#endif /* __ASM_CSKY_PTRACE_H */
102