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