1 /* SPDX-License-Identifier: (BSD-2-Clause AND MIT-CMU) */
2 /*-
3  * Copyright (c) 2023 Andes Technology Corporation
4  * Copyright (c) 2015-2019, Linaro Limited
5  * Copyright (c) 2000, 2001 Ben Harris
6  * Copyright (c) 1996 Scott K. Stevens
7  *
8  * Mach Operating System
9  * Copyright (c) 1991,1990 Carnegie Mellon University
10  * All Rights Reserved.
11  *
12  * Permission to use, copy, modify and distribute this software and its
13  * documentation is hereby granted, provided that both the copyright
14  * notice and this permission notice appear in all copies of the
15  * software, derivative works or modified versions, and any portions
16  * thereof, and that both notices appear in supporting documentation.
17  *
18  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
19  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
20  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
21  *
22  * Carnegie Mellon requests users of this software to return to
23  *
24  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
25  *  School of Computer Science
26  *  Carnegie Mellon University
27  *  Pittsburgh PA 15213-3890
28  *
29  * any improvements or extensions that they make and grant Carnegie the
30  * rights to redistribute these changes.
31  *
32  * $FreeBSD$
33  */
34 
35 #ifndef UNW_UNWIND_H
36 #define UNW_UNWIND_H
37 
38 #include <compiler.h>
39 #include <types_ext.h>
40 
41 /* The state of the unwind process (32-bit mode) */
42 struct unwind_state_arm32 {
43 	uint32_t registers[16];
44 	uint32_t start_pc;
45 	vaddr_t insn;
46 	unsigned int entries;
47 	unsigned int byte;
48 	uint16_t update_mask;
49 };
50 
51 #ifdef CFG_UNWIND
52 /*
53  * Unwind a 32-bit stack.
54  * @stack, @stack_size: the bottom of the stack and its size, respectively.
55  * Returns false when there is nothing more to unwind.
56  */
57 bool unwind_stack_arm32(struct unwind_state_arm32 *state,
58 			vaddr_t stack, size_t stack_size);
59 
60 void print_stack_arm32(struct unwind_state_arm32 *state,
61 		       vaddr_t stack, size_t stack_size);
62 #else
unwind_stack_arm32(struct unwind_state_arm32 * state __unused,vaddr_t stack __unused,size_t stack_size __unused)63 static inline bool unwind_stack_arm32(struct unwind_state_arm32 *state __unused,
64 				      vaddr_t stack __unused,
65 				      size_t stack_size __unused)
66 {
67 	return false;
68 }
69 
print_stack_arm32(struct unwind_state_arm32 * state __unused,vaddr_t stack __unused,size_t stack_size __unused)70 static inline void print_stack_arm32(struct unwind_state_arm32 *state __unused,
71 				     vaddr_t stack __unused,
72 				     size_t stack_size __unused)
73 {
74 }
75 #endif
76 
77 /*
78  * External helper function. Must be implemented by the caller of the 32-bit
79  * stack unwinding functions.
80  */
81 bool find_exidx(vaddr_t addr, vaddr_t *idx_start, vaddr_t *idx_end);
82 
83 /* The state of the unwind process (64-bit mode) */
84 struct unwind_state_arm64 {
85 	uint64_t fp;
86 	uint64_t sp;
87 	uint64_t pc;
88 };
89 
90 #if defined(ARM64) && defined(CFG_UNWIND)
91 /*
92  * Unwind a 64-bit stack.
93  * @stack, @stack_size: the bottom of the stack and its size, respectively.
94  * Returns false when there is nothing more to unwind.
95  */
96 bool unwind_stack_arm64(struct unwind_state_arm64 *state,
97 			vaddr_t stack, size_t stack_size);
98 
99 void print_stack_arm64(struct unwind_state_arm64 *state,
100 		       vaddr_t stack, size_t stack_size);
101 #else
unwind_stack_arm64(struct unwind_state_arm64 * state __unused,vaddr_t stack __unused,size_t stack_size __unused)102 static inline bool unwind_stack_arm64(struct unwind_state_arm64 *state __unused,
103 				      vaddr_t stack __unused,
104 				      size_t stack_size __unused)
105 {
106 	return false;
107 }
108 
print_stack_arm64(struct unwind_state_arm64 * state __unused,vaddr_t stack __unused,size_t stack_size __unused)109 static inline void print_stack_arm64(struct unwind_state_arm64 *state __unused,
110 				     vaddr_t stack __unused,
111 				     size_t stack_size __unused)
112 {
113 }
114 #endif
115 
116 /* The state of the unwind process */
117 struct unwind_state_riscv {
118 	unsigned long fp;
119 	unsigned long pc;
120 };
121 
122 #if (defined(RV32) || defined(RV64)) && defined(CFG_UNWIND)
123 /*
124  * Unwind stack.
125  * @stack, @stack_size: the bottom of the stack and its size, respectively.
126  * Returns false when there is nothing more to unwind.
127  */
128 bool unwind_stack_riscv(struct unwind_state_riscv *state,
129 			vaddr_t stack, size_t stack_size);
130 
131 void print_stack_riscv(struct unwind_state_riscv *state,
132 		       vaddr_t stack, size_t stack_size);
133 #else
unwind_stack_riscv(struct unwind_state_riscv * state __unused,vaddr_t stack __unused,size_t stack_size __unused)134 static inline bool unwind_stack_riscv(struct unwind_state_riscv *state __unused,
135 				      vaddr_t stack __unused,
136 				      size_t stack_size __unused)
137 {
138 	return false;
139 }
140 
print_stack_riscv(struct unwind_state_riscv * state __unused,vaddr_t stack __unused,size_t stack_size __unused)141 static inline void print_stack_riscv(struct unwind_state_riscv *state __unused,
142 				     vaddr_t stack __unused,
143 				     size_t stack_size __unused)
144 {
145 }
146 #endif
147 
148 /*
149  * External helper function optionally implemented by the caller of the 64-bit
150  * stack unwinding functions.
151  */
152 void ftrace_map_lr(uint64_t *lr);
153 
154 /* Strip out PAuth tags from LR content if applicable */
155 void pauth_strip_pac(uint64_t *lr);
156 
157 #endif /*UNW_UNWIND_H*/
158