xref: /openbmc/u-boot/arch/mips/include/asm/ptrace.h (revision e8f80a5a)
1*83d290c5STom Rini /* SPDX-License-Identifier: GPL-2.0 */
2819833afSPeter Tyser /*
3819833afSPeter Tyser  * Copyright (C) 1994, 95, 96, 97, 98, 99, 2000 by Ralf Baechle
4819833afSPeter Tyser  * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
5819833afSPeter Tyser  */
6819833afSPeter Tyser #ifndef _ASM_PTRACE_H
7819833afSPeter Tyser #define _ASM_PTRACE_H
8819833afSPeter Tyser 
9a3ab2ae7SDaniel Schwierzeck #include <linux/compiler.h>
10a3ab2ae7SDaniel Schwierzeck #include <linux/types.h>
11a3ab2ae7SDaniel Schwierzeck #include <asm/isadep.h>
12819833afSPeter Tyser 
13819833afSPeter Tyser /*
14819833afSPeter Tyser  * This struct defines the way the registers are stored on the stack during a
15819833afSPeter Tyser  * system call/exception. As usual the registers k0/k1 aren't being saved.
16a3ab2ae7SDaniel Schwierzeck  *
17a3ab2ae7SDaniel Schwierzeck  * If you add a register here, also add it to regoffset_table[] in
18a3ab2ae7SDaniel Schwierzeck  * arch/mips/kernel/ptrace.c.
19819833afSPeter Tyser  */
20819833afSPeter Tyser struct pt_regs {
21819833afSPeter Tyser #ifdef CONFIG_32BIT
22819833afSPeter Tyser 	/* Pad bytes for argument save space on the stack. */
23a3ab2ae7SDaniel Schwierzeck 	unsigned long pad0[8];
24819833afSPeter Tyser #endif
25819833afSPeter Tyser 
26819833afSPeter Tyser 	/* Saved main processor registers. */
27819833afSPeter Tyser 	unsigned long regs[32];
28819833afSPeter Tyser 
29819833afSPeter Tyser 	/* Saved special registers. */
30819833afSPeter Tyser 	unsigned long cp0_status;
31819833afSPeter Tyser 	unsigned long hi;
32819833afSPeter Tyser 	unsigned long lo;
33819833afSPeter Tyser #ifdef CONFIG_CPU_HAS_SMARTMIPS
34819833afSPeter Tyser 	unsigned long acx;
35819833afSPeter Tyser #endif
36819833afSPeter Tyser 	unsigned long cp0_badvaddr;
37819833afSPeter Tyser 	unsigned long cp0_cause;
38819833afSPeter Tyser 	unsigned long cp0_epc;
39a3ab2ae7SDaniel Schwierzeck #ifdef CONFIG_CPU_CAVIUM_OCTEON
40a3ab2ae7SDaniel Schwierzeck 	unsigned long long mpl[6];        /* MTM{0-5} */
41a3ab2ae7SDaniel Schwierzeck 	unsigned long long mtp[6];        /* MTP{0-5} */
42a3ab2ae7SDaniel Schwierzeck #endif
43a3ab2ae7SDaniel Schwierzeck 	unsigned long __last[0];
44a3ab2ae7SDaniel Schwierzeck } __aligned(8);
45819833afSPeter Tyser 
kernel_stack_pointer(struct pt_regs * regs)46a3ab2ae7SDaniel Schwierzeck static inline unsigned long kernel_stack_pointer(struct pt_regs *regs)
47a3ab2ae7SDaniel Schwierzeck {
48a3ab2ae7SDaniel Schwierzeck 	return regs->regs[31];
49a3ab2ae7SDaniel Schwierzeck }
50819833afSPeter Tyser 
51a3ab2ae7SDaniel Schwierzeck /*
52a3ab2ae7SDaniel Schwierzeck  * Don't use asm-generic/ptrace.h it defines FP accessors that don't make
53a3ab2ae7SDaniel Schwierzeck  * sense on MIPS.  We rather want an error if they get invoked.
54a3ab2ae7SDaniel Schwierzeck  */
55819833afSPeter Tyser 
instruction_pointer_set(struct pt_regs * regs,unsigned long val)56a3ab2ae7SDaniel Schwierzeck static inline void instruction_pointer_set(struct pt_regs *regs,
57a3ab2ae7SDaniel Schwierzeck 						unsigned long val)
58a3ab2ae7SDaniel Schwierzeck {
59a3ab2ae7SDaniel Schwierzeck 	regs->cp0_epc = val;
60a3ab2ae7SDaniel Schwierzeck }
61819833afSPeter Tyser 
62a3ab2ae7SDaniel Schwierzeck /* Query offset/name of register from its name/offset */
63a3ab2ae7SDaniel Schwierzeck extern int regs_query_register_offset(const char *name);
64a3ab2ae7SDaniel Schwierzeck #define MAX_REG_OFFSET (offsetof(struct pt_regs, __last))
65819833afSPeter Tyser 
66a3ab2ae7SDaniel Schwierzeck /**
67a3ab2ae7SDaniel Schwierzeck  * regs_get_register() - get register value from its offset
68a3ab2ae7SDaniel Schwierzeck  * @regs:       pt_regs from which register value is gotten.
69a3ab2ae7SDaniel Schwierzeck  * @offset:     offset number of the register.
70a3ab2ae7SDaniel Schwierzeck  *
71a3ab2ae7SDaniel Schwierzeck  * regs_get_register returns the value of a register. The @offset is the
72a3ab2ae7SDaniel Schwierzeck  * offset of the register in struct pt_regs address which specified by @regs.
73a3ab2ae7SDaniel Schwierzeck  * If @offset is bigger than MAX_REG_OFFSET, this returns 0.
74a3ab2ae7SDaniel Schwierzeck  */
regs_get_register(struct pt_regs * regs,unsigned int offset)75a3ab2ae7SDaniel Schwierzeck static inline unsigned long regs_get_register(struct pt_regs *regs,
76a3ab2ae7SDaniel Schwierzeck 						unsigned int offset)
77a3ab2ae7SDaniel Schwierzeck {
78a3ab2ae7SDaniel Schwierzeck 	if (unlikely(offset > MAX_REG_OFFSET))
79a3ab2ae7SDaniel Schwierzeck 		return 0;
80819833afSPeter Tyser 
81a3ab2ae7SDaniel Schwierzeck 	return *(unsigned long *)((unsigned long)regs + offset);
82a3ab2ae7SDaniel Schwierzeck }
83819833afSPeter Tyser 
84819833afSPeter Tyser /*
85819833afSPeter Tyser  * Does the process account for user or for system time?
86819833afSPeter Tyser  */
87819833afSPeter Tyser #define user_mode(regs) (((regs)->cp0_status & KU_MASK) == KU_USER)
88819833afSPeter Tyser 
89819833afSPeter Tyser #define instruction_pointer(regs) ((regs)->cp0_epc)
90819833afSPeter Tyser #define profile_pc(regs) instruction_pointer(regs)
91819833afSPeter Tyser 
92a3ab2ae7SDaniel Schwierzeck /* Helpers for working with the user stack pointer */
93a3ab2ae7SDaniel Schwierzeck 
user_stack_pointer(struct pt_regs * regs)94a3ab2ae7SDaniel Schwierzeck static inline unsigned long user_stack_pointer(struct pt_regs *regs)
95a3ab2ae7SDaniel Schwierzeck {
96a3ab2ae7SDaniel Schwierzeck 	return regs->regs[29];
97a3ab2ae7SDaniel Schwierzeck }
98a3ab2ae7SDaniel Schwierzeck 
user_stack_pointer_set(struct pt_regs * regs,unsigned long val)99a3ab2ae7SDaniel Schwierzeck static inline void user_stack_pointer_set(struct pt_regs *regs,
100a3ab2ae7SDaniel Schwierzeck 						unsigned long val)
101a3ab2ae7SDaniel Schwierzeck {
102a3ab2ae7SDaniel Schwierzeck 	regs->regs[29] = val;
103a3ab2ae7SDaniel Schwierzeck }
104819833afSPeter Tyser 
105819833afSPeter Tyser #endif /* _ASM_PTRACE_H */
106