1 /*
2  * Copyright (c) 2012-2014 Wind River Systems, Inc.
3  * Copyright (c) 2020-2023, Intel Corporation.
4  *
5  * SPDX-License-Identifier: Apache-2.0
6  */
7 
8 #include <zephyr/kernel.h>
9 #include <zephyr/sys/printk.h>
10 
11 #include <zephyr/ztest.h>
12 #include <assert.h>
13 #include <zephyr/tc_util.h>
14 
15 #include <zephyr/debug/coredump.h>
16 
17 #define STACK_SIZE (1024 + CONFIG_TEST_EXTRA_STACK_SIZE)
18 
19 static struct k_thread dump_thread;
20 static K_THREAD_STACK_DEFINE(dump_stack, STACK_SIZE);
21 
k_sys_fatal_error_handler(unsigned int reason,const struct arch_esf * pEsf)22 void k_sys_fatal_error_handler(unsigned int reason, const struct arch_esf *pEsf)
23 {
24 	ARG_UNUSED(reason);
25 	ARG_UNUSED(pEsf);
26 }
27 
dump_entry(void * p1,void * p2,void * p3)28 void dump_entry(void *p1, void *p2, void *p3)
29 {
30 	unsigned int key;
31 
32 	key = irq_lock();
33 	k_oops();
34 	TC_ERROR("SHOULD NEVER SEE THIS\n");
35 	irq_unlock(key);
36 }
37 
check_error(void)38 void check_error(void)
39 {
40 	int ret;
41 
42 	/* Check backend error if backend supports this query */
43 	ret = coredump_query(COREDUMP_QUERY_GET_ERROR, NULL);
44 	if (ret != -ENOTSUP) {
45 		zassert_equal(ret, 0, "Error encountered! (%d)", ret);
46 	}
47 }
48 
clear_error(void)49 void clear_error(void)
50 {
51 	int ret;
52 
53 	/* Clear backend error if backend supports this query */
54 	ret = coredump_cmd(COREDUMP_CMD_CLEAR_ERROR, NULL);
55 	if (ret != -ENOTSUP) {
56 		zassert_equal(ret, 0, "Error encountered! (%d)", ret);
57 	}
58 }
59 
raise_coredump(void)60 static void *raise_coredump(void)
61 {
62 	k_tid_t tid;
63 
64 	clear_error();
65 
66 	/* Create a thread that crashes */
67 	tid = k_thread_create(&dump_thread, dump_stack,
68 			      K_THREAD_STACK_SIZEOF(dump_stack),
69 			      dump_entry, NULL, NULL, NULL,
70 			      0, 0, K_NO_WAIT);
71 
72 	k_thread_join(tid, K_FOREVER);
73 
74 	return &dump_thread;
75 }
76 
test_has_stored_dump(bool is_expected)77 void test_has_stored_dump(bool is_expected)
78 {
79 	int ret;
80 
81 	/* Cannot proceed with previous errors */
82 	check_error();
83 
84 	/* There should be a stored coredump now if backend has storage */
85 	ret = coredump_query(COREDUMP_QUERY_HAS_STORED_DUMP, NULL);
86 	if (ret == -ENOTSUP) {
87 #ifdef CONFIG_TEST_STORED_COREDUMP
88 		TC_ERROR("Can't query stored dump: unexpectedly not supported.\n");
89 		ztest_test_fail();
90 #else
91 		TC_PRINT("Can't query stored dump: expectedly not supported.\n");
92 		ztest_test_skip();
93 #endif
94 	} else if (ret == 1) {
95 #ifdef CONFIG_TEST_STORED_COREDUMP
96 		check_error();
97 		zassert_true(is_expected, "Unexpected coredump found.\n");
98 		ztest_test_pass();
99 #else
100 		TC_ERROR("Can't have a stored dump: not supported.\n");
101 		ztest_test_fail();
102 #endif
103 	} else if (ret == 0) {
104 #ifdef CONFIG_TEST_STORED_COREDUMP
105 		check_error();
106 		zassert_false(is_expected, "Should have stored dump!\n");
107 		ztest_test_pass();
108 #else
109 		TC_ERROR("Can't have an empty stored dump: not supported.\n");
110 		ztest_test_fail();
111 #endif
112 	} else {
113 		TC_ERROR("Error reading stored dump! (%d)\n", ret);
114 		ztest_test_fail();
115 	}
116 }
117 
test_verify_stored_dump(void)118 void test_verify_stored_dump(void)
119 {
120 	int ret;
121 
122 	/* Cannot proceed with previous errors */
123 	check_error();
124 
125 	/* There should be a stored coredump now if backend has storage */
126 	ret = coredump_cmd(COREDUMP_CMD_VERIFY_STORED_DUMP, NULL);
127 	if (ret == -ENOTSUP) {
128 #ifdef CONFIG_TEST_STORED_COREDUMP
129 		TC_ERROR("Can't verify stored dump: unexpectedly not supported.\n");
130 		ztest_test_fail();
131 #else
132 		TC_PRINT("Can't verify stored dump: expectedly not supported.\n");
133 		ztest_test_skip();
134 #endif
135 	} else if (ret == 1) {
136 #ifdef CONFIG_TEST_STORED_COREDUMP
137 		check_error();
138 		ztest_test_pass();
139 #else
140 		TC_ERROR("Can't have a stored dump: not supported.\n");
141 		ztest_test_fail();
142 #endif
143 	} else if (ret == 0) {
144 #ifdef CONFIG_TEST_STORED_COREDUMP
145 		TC_ERROR("Verification of stored dump failed!\n");
146 		ztest_test_fail();
147 #else
148 		TC_ERROR("Can't have a stored dump: not supported.\n");
149 		ztest_test_fail();
150 #endif
151 	} else {
152 		TC_ERROR("Error reading stored dump! (%d)\n", ret);
153 		ztest_test_fail();
154 	}
155 }
156 
test_invalidate_stored_dump(void)157 void test_invalidate_stored_dump(void)
158 {
159 	int ret;
160 
161 	/* Cannot proceed with previous errors */
162 	check_error();
163 
164 	/* There should be a stored coredump now if backend has storage */
165 	ret = coredump_cmd(COREDUMP_CMD_INVALIDATE_STORED_DUMP, NULL);
166 	if (ret == -ENOTSUP) {
167 #ifdef CONFIG_TEST_STORED_COREDUMP
168 		TC_ERROR("Can't invalidate stored dump: unexpectedly not supported.\n");
169 		ztest_test_fail();
170 #else
171 		TC_PRINT("Can't invalidate stored dump: expectedly not supported.\n");
172 		ztest_test_skip();
173 #endif
174 	} else if (ret == 0) {
175 #ifdef CONFIG_TEST_STORED_COREDUMP
176 		check_error();
177 		ztest_test_pass();
178 #else
179 		TC_ERROR("Can't invalidate the stored dump: not supported.\n");
180 		ztest_test_fail();
181 #endif
182 	} else {
183 		TC_ERROR("Error invalidating stored dump! (%d)\n", ret);
184 		ztest_test_fail();
185 	}
186 }
187 
test_erase_stored_dump(void)188 void test_erase_stored_dump(void)
189 {
190 	int ret;
191 
192 	/* Cannot proceed with previous errors */
193 	check_error();
194 
195 	/* There should be a stored coredump now if backend has storage */
196 	ret = coredump_cmd(COREDUMP_CMD_ERASE_STORED_DUMP, NULL);
197 	if (ret == -ENOTSUP) {
198 #ifdef CONFIG_TEST_STORED_COREDUMP
199 		TC_ERROR("Can't erase stored dump: unexpectedly not supported.\n");
200 		ztest_test_fail();
201 #else
202 		TC_PRINT("Can't erase stored dump: expectedly not supported.\n");
203 		ztest_test_skip();
204 #endif
205 	} else if (ret == 0) {
206 #ifdef CONFIG_TEST_STORED_COREDUMP
207 		check_error();
208 		ztest_test_pass();
209 #else
210 		TC_ERROR("Can't erase the stored dump: not supported.\n");
211 		ztest_test_fail();
212 #endif
213 	} else {
214 		TC_ERROR("Error erasing stored dump! (%d)\n", ret);
215 		ztest_test_fail();
216 	}
217 }
218 
test_get_stored_dump_size(int size_expected)219 void test_get_stored_dump_size(int size_expected)
220 {
221 	int ret;
222 
223 	/* Cannot proceed with previous errors */
224 	check_error();
225 
226 	ret = coredump_query(COREDUMP_QUERY_GET_STORED_DUMP_SIZE, NULL);
227 	if (ret == -ENOTSUP) {
228 #ifdef CONFIG_TEST_STORED_COREDUMP
229 		TC_ERROR("Can't query stored dump size: unexpectedly not supported.\n");
230 		ztest_test_fail();
231 #else
232 		TC_PRINT("Can't query stored dump size: expectedly not supported.\n");
233 		ztest_test_skip();
234 #endif
235 	} else if (ret >= 0) {
236 #ifdef CONFIG_TEST_STORED_COREDUMP
237 		check_error();
238 		if (size_expected > 0) {
239 			zassert_equal(ret, size_expected,
240 				      "Coredump size %d != %d size expected.\n",
241 				      ret, size_expected);
242 		}
243 		ztest_test_pass();
244 #else
245 		TC_ERROR("Can't have a stored dump: not supported.\n");
246 		ztest_test_fail();
247 #endif
248 	} else {
249 		TC_ERROR("Error reading stored dump size! (%d)\n", ret);
250 		ztest_test_fail();
251 	}
252 }
253 
254 /* Excecute tests in exact sequence with the stored core dump. */
255 
ZTEST(coredump_backends,test_coredump_0_ready)256 ZTEST(coredump_backends, test_coredump_0_ready) {
257 	check_error();
258 	ztest_test_pass();
259 }
260 
ZTEST(coredump_backends,test_coredump_1_stored)261 ZTEST(coredump_backends, test_coredump_1_stored) {
262 	test_has_stored_dump(true);
263 }
264 
ZTEST(coredump_backends,test_coredump_2_size)265 ZTEST(coredump_backends, test_coredump_2_size) {
266 	test_get_stored_dump_size(CONFIG_TEST_STORED_DUMP_SIZE);
267 }
268 
ZTEST(coredump_backends,test_coredump_3_verify)269 ZTEST(coredump_backends, test_coredump_3_verify) {
270 	test_verify_stored_dump();
271 }
272 
ZTEST(coredump_backends,test_coredump_4_invalidate)273 ZTEST(coredump_backends, test_coredump_4_invalidate) {
274 	test_invalidate_stored_dump();
275 }
276 
ZTEST(coredump_backends,test_coredump_5_erase)277 ZTEST(coredump_backends, test_coredump_5_erase) {
278 	test_erase_stored_dump();
279 }
280 
281 ZTEST_SUITE(coredump_backends, NULL, raise_coredump, NULL, NULL, NULL);
282