1 /*
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 #define COREDUMP_BEGIN_STR "BEGIN#"
19 #define COREDUMP_END_STR "END#"
20 #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 #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 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 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 struct coredump_cmd_copy_arg {
129 /** Copy offset */
130 off_t offset;
131
132 /** Copy destination buffer */
133 uint8_t *buffer;
134
135 /** Copy length */
136 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
coredump(unsigned int reason,const struct arch_esf * esf,struct k_thread * thread)260 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
coredump_memory_dump(uintptr_t start_addr,uintptr_t end_addr)268 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
coredump_buffer_output(uint8_t * buf,size_t buflen)274 static inline void coredump_buffer_output(uint8_t *buf, size_t buflen)
275 {
276 ARG_UNUSED(buf);
277 ARG_UNUSED(buflen);
278 }
279
coredump_query(enum coredump_query_id query_id,void * arg)280 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
coredump_cmd(enum coredump_cmd_id query_id,void * arg)287 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_ */
358