Line data Source code
1 0 : /*
2 : * Copyright (c) 2020 Intel Corporation.
3 : *
4 : * SPDX-License-Identifier: Apache-2.0
5 : */
6 :
7 : #ifndef ZEPHYR_INCLUDE_DEBUG_COREDUMP_H_
8 : #define ZEPHYR_INCLUDE_DEBUG_COREDUMP_H_
9 :
10 : #include <stddef.h>
11 : #include <stdint.h>
12 : #include <sys/types.h>
13 :
14 : /*
15 : * Define COREDUMP_*_STR as public to allow coredump_backend_other to re-use
16 : * these strings if necessary
17 : */
18 0 : #define COREDUMP_BEGIN_STR "BEGIN#"
19 0 : #define COREDUMP_END_STR "END#"
20 0 : #define COREDUMP_ERROR_STR "ERROR CANNOT DUMP#"
21 :
22 : /*
23 : * Need to prefix coredump strings to make it easier to parse
24 : * as log module adds its own prefixes.
25 : */
26 0 : #define COREDUMP_PREFIX_STR "#CD:"
27 :
28 : /**
29 : * @file
30 : *
31 : * @defgroup coredump_apis Coredump APIs
32 : * @ingroup os_services
33 : * @brief Coredump APIs
34 : * @{
35 : */
36 :
37 :
38 : /** Query ID */
39 1 : enum coredump_query_id {
40 : /**
41 : * Returns error code from backend.
42 : */
43 : COREDUMP_QUERY_GET_ERROR,
44 :
45 : /**
46 : * Check if there is a stored coredump from backend.
47 : *
48 : * Returns:
49 : * - 1 if there is a stored coredump, 0 if none.
50 : * - -ENOTSUP if this query is not supported.
51 : * - Otherwise, error code from backend.
52 : */
53 : COREDUMP_QUERY_HAS_STORED_DUMP,
54 :
55 : /**
56 : * Returns:
57 : * - coredump raw size from backend, 0 if none.
58 : * - -ENOTSUP if this query is not supported.
59 : * - Otherwise, error code from backend.
60 : */
61 : COREDUMP_QUERY_GET_STORED_DUMP_SIZE,
62 :
63 : /**
64 : * Max value for query ID.
65 : */
66 : COREDUMP_QUERY_MAX
67 : };
68 :
69 : /** Command ID */
70 1 : enum coredump_cmd_id {
71 : /**
72 : * Clear error code from backend.
73 : *
74 : * Returns 0 if successful, failed otherwise.
75 : */
76 : COREDUMP_CMD_CLEAR_ERROR,
77 :
78 : /**
79 : * Verify that the stored coredump is valid.
80 : *
81 : * Returns:
82 : * - 1 if valid.
83 : * - 0 if not valid or no stored coredump.
84 : * - -ENOTSUP if this command is not supported.
85 : * - Otherwise, error code from backend.
86 : */
87 : COREDUMP_CMD_VERIFY_STORED_DUMP,
88 :
89 : /**
90 : * Erase the stored coredump.
91 : *
92 : * Returns:
93 : * - 0 if successful.
94 : * - -ENOTSUP if this command is not supported.
95 : * - Otherwise, error code from backend.
96 : */
97 : COREDUMP_CMD_ERASE_STORED_DUMP,
98 :
99 : /**
100 : * Copy the raw stored coredump.
101 : *
102 : * Returns:
103 : * - copied size if successful
104 : * - 0 if stored coredump is not found
105 : * - -ENOTSUP if this command is not supported.
106 : * - Otherwise, error code from backend.
107 : */
108 : COREDUMP_CMD_COPY_STORED_DUMP,
109 :
110 : /**
111 : * Invalidate the stored coredump. This is faster than
112 : * erasing the whole partition.
113 : *
114 : * Returns:
115 : * - 0 if successful.
116 : * - -ENOTSUP if this command is not supported.
117 : * - Otherwise, error code from backend.
118 : */
119 : COREDUMP_CMD_INVALIDATE_STORED_DUMP,
120 :
121 : /**
122 : * Max value for command ID.
123 : */
124 : COREDUMP_CMD_MAX
125 : };
126 :
127 : /** Coredump copy command (@ref COREDUMP_CMD_COPY_STORED_DUMP) argument definition */
128 1 : struct coredump_cmd_copy_arg {
129 : /** Copy offset */
130 1 : off_t offset;
131 :
132 : /** Copy destination buffer */
133 1 : uint8_t *buffer;
134 :
135 : /** Copy length */
136 1 : size_t length;
137 : };
138 :
139 : #ifdef CONFIG_DEBUG_COREDUMP
140 :
141 : #include <zephyr/toolchain.h>
142 : #include <zephyr/arch/cpu.h>
143 : #include <zephyr/sys/byteorder.h>
144 :
145 : #define COREDUMP_HDR_VER 2
146 :
147 : #define COREDUMP_ARCH_HDR_ID 'A'
148 :
149 : #define THREADS_META_HDR_ID 'T'
150 : #define THREADS_META_HDR_VER 1
151 :
152 : #define COREDUMP_MEM_HDR_ID 'M'
153 : #define COREDUMP_MEM_HDR_VER 1
154 :
155 : /* Target code */
156 : enum coredump_tgt_code {
157 : COREDUMP_TGT_UNKNOWN = 0,
158 : COREDUMP_TGT_X86,
159 : COREDUMP_TGT_X86_64,
160 : COREDUMP_TGT_ARM_CORTEX_M,
161 : COREDUMP_TGT_RISC_V,
162 : COREDUMP_TGT_XTENSA,
163 : COREDUMP_TGT_ARM64,
164 : };
165 :
166 : /* Coredump header */
167 : struct coredump_hdr_t {
168 : /* 'Z', 'E' */
169 : char id[2];
170 :
171 : /* Header version */
172 : uint16_t hdr_version;
173 :
174 : /* Target code */
175 : uint16_t tgt_code;
176 :
177 : /* Pointer size in Log2 */
178 : uint8_t ptr_size_bits;
179 :
180 : uint8_t flag;
181 :
182 : /* Coredump Reason given */
183 : unsigned int reason;
184 : } __packed;
185 :
186 : /* Architecture-specific block header */
187 : struct coredump_arch_hdr_t {
188 : /* COREDUMP_ARCH_HDR_ID */
189 : char id;
190 :
191 : /* Header version */
192 : uint16_t hdr_version;
193 :
194 : /* Number of bytes in this block (excluding header) */
195 : uint16_t num_bytes;
196 : } __packed;
197 :
198 : /* Threads metadata header */
199 : struct coredump_threads_meta_hdr_t {
200 : /* THREADS_META_HDR_ID */
201 : char id;
202 :
203 : /* Header version */
204 : uint16_t hdr_version;
205 :
206 : /* Number of bytes in this block (excluding header) */
207 : uint16_t num_bytes;
208 : } __packed;
209 :
210 : /* Memory block header */
211 : struct coredump_mem_hdr_t {
212 : /* COREDUMP_MEM_HDR_ID */
213 : char id;
214 :
215 : /* Header version */
216 : uint16_t hdr_version;
217 :
218 : /* Address of start of memory region */
219 : uintptr_t start;
220 :
221 : /* Address of end of memory region */
222 : uintptr_t end;
223 : } __packed;
224 :
225 : typedef void (*coredump_backend_start_t)(void);
226 : typedef void (*coredump_backend_end_t)(void);
227 : typedef void (*coredump_backend_buffer_output_t)(uint8_t *buf, size_t buflen);
228 : typedef int (*coredump_backend_query_t)(enum coredump_query_id query_id,
229 : void *arg);
230 : typedef int (*coredump_backend_cmd_t)(enum coredump_cmd_id cmd_id,
231 : void *arg);
232 :
233 : struct coredump_backend_api {
234 : /* Signal to backend of the start of coredump. */
235 : coredump_backend_start_t start;
236 :
237 : /* Signal to backend of the end of coredump. */
238 : coredump_backend_end_t end;
239 :
240 : /* Raw buffer output */
241 : coredump_backend_buffer_output_t buffer_output;
242 :
243 : /* Perform query on backend */
244 : coredump_backend_query_t query;
245 :
246 : /* Perform command on backend */
247 : coredump_backend_cmd_t cmd;
248 : };
249 :
250 : void coredump(unsigned int reason, const struct arch_esf *esf,
251 : struct k_thread *thread);
252 : void coredump_memory_dump(uintptr_t start_addr, uintptr_t end_addr);
253 : void coredump_buffer_output(uint8_t *buf, size_t buflen);
254 :
255 : int coredump_query(enum coredump_query_id query_id, void *arg);
256 : int coredump_cmd(enum coredump_cmd_id cmd_id, void *arg);
257 :
258 : #else
259 :
260 1 : static inline void coredump(unsigned int reason, const struct arch_esf *esf,
261 : struct k_thread *thread)
262 : {
263 : ARG_UNUSED(reason);
264 : ARG_UNUSED(esf);
265 : ARG_UNUSED(thread);
266 : }
267 :
268 1 : static inline void coredump_memory_dump(uintptr_t start_addr, uintptr_t end_addr)
269 : {
270 : ARG_UNUSED(start_addr);
271 : ARG_UNUSED(end_addr);
272 : }
273 :
274 1 : static inline void coredump_buffer_output(uint8_t *buf, size_t buflen)
275 : {
276 : ARG_UNUSED(buf);
277 : ARG_UNUSED(buflen);
278 : }
279 :
280 1 : static inline int coredump_query(enum coredump_query_id query_id, void *arg)
281 : {
282 : ARG_UNUSED(query_id);
283 : ARG_UNUSED(arg);
284 : return -ENOTSUP;
285 : }
286 :
287 1 : static inline int coredump_cmd(enum coredump_cmd_id query_id, void *arg)
288 : {
289 : ARG_UNUSED(query_id);
290 : ARG_UNUSED(arg);
291 : return -ENOTSUP;
292 : }
293 :
294 : #endif /* CONFIG_DEBUG_COREDUMP */
295 :
296 : /**
297 : * @fn void coredump(unsigned int reason, const struct arch_esf *esf, struct k_thread *thread);
298 : * @brief Perform coredump.
299 : *
300 : * Normally, this is called inside z_fatal_error() to generate coredump
301 : * when a fatal error is encountered. This can also be called on demand
302 : * whenever a coredump is desired.
303 : *
304 : * @param reason Reason for the fatal error
305 : * @param esf Exception context
306 : * @param thread Thread information to dump
307 : */
308 :
309 : /**
310 : * @fn void coredump_memory_dump(uintptr_t start_addr, uintptr_t end_addr);
311 : * @brief Dump memory region
312 : *
313 : * @param start_addr Start address of memory region to be dumped
314 : * @param end_addr End address of memory region to be dumped
315 : */
316 :
317 : /**
318 : * @fn int coredump_buffer_output(uint8_t *buf, size_t buflen);
319 : * @brief Output the buffer via coredump
320 : *
321 : * This outputs the buffer of byte array to the coredump backend.
322 : * For example, this can be called to output the coredump section
323 : * containing registers, or a section for memory dump.
324 : *
325 : * @param buf Buffer to be send to coredump output
326 : * @param buflen Buffer length
327 : */
328 :
329 : /**
330 : * @fn int coredump_query(enum coredump_query_id query_id, void *arg);
331 : * @brief Perform query on coredump subsystem.
332 : *
333 : * Query the coredump subsystem for information, for example, if there is
334 : * an error.
335 : *
336 : * @param[in] query_id Query ID
337 : * @param[in,out] arg Pointer to argument for exchanging information
338 : * @return Depends on the query
339 : */
340 :
341 : /**
342 : * @fn int coredump_cmd(enum coredump_cmd_id cmd_id, void *arg);
343 : * @brief Perform command on coredump subsystem.
344 : *
345 : * Perform command on coredump subsystem, for example, output the stored
346 : * coredump via logging.
347 : *
348 : * @param[in] cmd_id Command ID
349 : * @param[in,out] arg Pointer to argument for exchanging information
350 : * @return Depends on the command
351 : */
352 :
353 : /**
354 : * @}
355 : */
356 :
357 : #endif /* ZEPHYR_INCLUDE_DEBUG_COREDUMP_H_ */
|