1 /*
2 * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
3 * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without modification,
6 * are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice, this list of
9 * conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
12 * of conditions and the following disclaimer in the documentation and/or other materials
13 * provided with the distribution.
14 *
15 * 3. Neither the name of the copyright holder nor the names of its contributors may be used
16 * to endorse or promote products derived from this software without specific prior written
17 * permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
26 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
28 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
29 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 #include "los_exc_info.h"
33 #include "securec.h"
34 #include "los_debug.h"
35 #include "los_interrupt.h"
36 #include "los_task.h"
37 #include "los_exchook.h"
38 #include "los_membox.h"
39 #include "los_memory.h"
40
41
42 #if (LOSCFG_PLATFORM_EXC == 1)
43 #define EXC_MSG_ARRAY_INIT_VALUE 0xff
44 #define EXC_INT_STATUS_LEN (OS_NVIC_INT_ENABLE_SIZE + OS_NVIC_INT_PEND_SIZE + \
45 OS_NVIC_INT_ACT_SIZE + OS_NVIC_INT_PRI_SIZE + \
46 OS_NVIC_EXCPRI_SIZE + OS_NVIC_SHCSR_SIZE + \
47 OS_NVIC_INT_CTRL_SIZE)
48
49 UINT32 g_excQueueMaxNum;
50 UINT32 g_excMemMaxNum;
51 VOID *g_excContent = NULL;
52 UINT32 g_excArraySize = MAX_EXC_MEM_SIZE;
53 UINT8 g_excMsgArray[MAX_EXC_MEM_SIZE];
54 STATIC ExcInfoArray g_excArray[OS_EXC_TYPE_MAX];
55
OsExcSaveIntStatus(UINT32 type,VOID * arg)56 STATIC UINT32 OsExcSaveIntStatus(UINT32 type, VOID *arg)
57 {
58 errno_t ret;
59 UINTPTR excContentEnd = (UINTPTR)MAX_INT_INFO_SIZE + (UINTPTR)g_excContent;
60
61 (VOID)arg;
62
63 *((UINT32 *)g_excContent) = type;
64 g_excContent = (UINT8 *)g_excContent + sizeof(UINT32);
65
66 *((UINT32 *)g_excContent) = EXC_INT_STATUS_LEN;
67 g_excContent = (UINT8 *)g_excContent + sizeof(UINT32);
68 /* save IRQ ENABLE reg group */
69 ret = memcpy_s(g_excContent, excContentEnd - (UINTPTR)g_excContent,
70 (const VOID *)OS_NVIC_SETENA_BASE, OS_NVIC_INT_ENABLE_SIZE);
71 if (ret != EOK) {
72 return LOS_NOK;
73 }
74 g_excContent = (UINT8 *)g_excContent + OS_NVIC_INT_ENABLE_SIZE;
75
76 /* save IRQ PEND reg group */
77 ret = memcpy_s(g_excContent, excContentEnd - (UINTPTR)g_excContent,
78 (const VOID *)OS_NVIC_SETPEND_BASE, OS_NVIC_INT_PEND_SIZE);
79 if (ret != EOK) {
80 return LOS_NOK;
81 }
82 g_excContent = (UINT8 *)g_excContent + OS_NVIC_INT_PEND_SIZE;
83
84 /* save IRQ ACTIVE reg group */
85 ret = memcpy_s(g_excContent, excContentEnd - (UINTPTR)g_excContent,
86 (const VOID *)OS_NVIC_INT_ACT_BASE, OS_NVIC_INT_ACT_SIZE);
87 if (ret != EOK) {
88 return LOS_NOK;
89 }
90 g_excContent = (UINT8 *)g_excContent + OS_NVIC_INT_ACT_SIZE;
91
92 /* save IRQ Priority reg group */
93 ret = memcpy_s(g_excContent, excContentEnd - (UINTPTR)g_excContent,
94 (const VOID *)OS_NVIC_PRI_BASE, OS_NVIC_INT_PRI_SIZE);
95 if (ret != EOK) {
96 return LOS_NOK;
97 }
98 g_excContent = (UINT8 *)g_excContent + OS_NVIC_INT_PRI_SIZE;
99
100 /* save Exception Priority reg group */
101 ret = memcpy_s(g_excContent, excContentEnd - (UINTPTR)g_excContent,
102 (const VOID *)OS_NVIC_EXCPRI_BASE, OS_NVIC_EXCPRI_SIZE);
103 if (ret != EOK) {
104 return LOS_NOK;
105 }
106 g_excContent = (UINT8 *)g_excContent + OS_NVIC_EXCPRI_SIZE;
107
108 /* save IRQ Handler & SHCSR */
109 ret = memcpy_s(g_excContent, excContentEnd - (UINTPTR)g_excContent,
110 (const VOID *)OS_NVIC_SHCSR, OS_NVIC_SHCSR_SIZE);
111 if (ret != EOK) {
112 return LOS_NOK;
113 }
114 g_excContent = (UINT8 *)g_excContent + OS_NVIC_SHCSR_SIZE;
115
116 /* save IRQ Control & ICSR */
117 ret = memcpy_s(g_excContent, excContentEnd - (UINTPTR)g_excContent,
118 (const VOID *)OS_NVIC_INT_CTRL, OS_NVIC_INT_CTRL_SIZE);
119 if (ret != EOK) {
120 return LOS_NOK;
121 }
122 g_excContent = (UINT8 *)g_excContent + OS_NVIC_INT_CTRL_SIZE;
123
124 return LOS_OK;
125 }
126
OsExcMemMsgGet(UINT32 type,VOID * arg)127 STATIC UINT32 OsExcMemMsgGet(UINT32 type, VOID *arg)
128 {
129 UINT32 count;
130 UINT32 memNum = *(UINT32 *)arg;
131 UINTPTR memMsgEnd = (UINTPTR)g_excContent + MAX_MEM_INFO_SIZE;
132
133 *((UINT32 *)g_excContent) = type;
134 g_excContent = (UINT8 *)g_excContent + sizeof(UINT32);
135
136 *((UINT32 *)g_excContent) = sizeof(MemInfoCB) * memNum;
137 g_excContent = (UINT8 *)g_excContent + sizeof(UINT32);
138
139 count = OsMemboxExcInfoGet(memNum, g_excContent);
140 if (count < memNum) {
141 g_excContent = (UINT8 *)g_excContent + sizeof(MemInfoCB) * count;
142 (VOID)OsMemExcInfoGet(memNum - count, g_excContent);
143 }
144 g_excContent = (VOID *)memMsgEnd;
145
146 return LOS_OK;
147 }
148
OsExcContentGet(UINT32 type,VOID * arg)149 STATIC UINT32 OsExcContentGet(UINT32 type, VOID *arg)
150 {
151 UINTPTR excContentEnd = MAX_EXC_MEM_SIZE + (UINTPTR)g_excMsgArray;
152 errno_t ret;
153
154 (VOID)arg;
155
156 /* save exception info */
157 *((UINT32 *)g_excContent) = type;
158 g_excContent = (UINT8 *)g_excContent + sizeof(UINT32);
159 *((UINT32 *)g_excContent) = sizeof(ExcInfo) + sizeof(EXC_CONTEXT_S);
160
161 g_excContent = (UINT8 *)g_excContent + sizeof(UINT32);
162 ret = memcpy_s((VOID *)g_excContent, excContentEnd - (UINTPTR)g_excContent,
163 (VOID *)&g_excInfo, sizeof(ExcInfo));
164 if (ret != EOK) {
165 return LOS_NOK;
166 }
167 g_excContent = (UINT8 *)g_excContent + sizeof(ExcInfo);
168
169 ret = memcpy_s((VOID *)g_excContent, excContentEnd - (UINTPTR)g_excContent,
170 g_excInfo.context, sizeof(EXC_CONTEXT_S));
171 if (ret != EOK) {
172 return LOS_NOK;
173 }
174 g_excContent = (UINT8 *)g_excContent + sizeof(EXC_CONTEXT_S);
175
176 return LOS_OK;
177 }
178
OsExcHookFunc(UINT32 type,UINT32 index,UINT32 loop,UINT32 len,EXC_INFO_SAVE_CALLBACK func)179 STATIC UINT32 OsExcHookFunc(UINT32 type, UINT32 index, UINT32 loop, UINT32 len, EXC_INFO_SAVE_CALLBACK func)
180 {
181 UINT32 i;
182
183 *((UINT32 *)g_excContent) = (UINT32)type;
184 g_excContent = (UINT8 *)g_excContent + sizeof(UINT32);
185
186 *((UINT32 *)g_excContent) = len * loop;
187 g_excContent = (UINT8 *)g_excContent + sizeof(UINT32);
188
189 for (i = index; i < loop; i++) {
190 (VOID)func(i, g_excContent);
191 g_excContent = (UINT8 *)g_excContent + len;
192 }
193
194 return LOS_OK;
195 }
196
197 #if (LOSCFG_BASE_IPC_QUEUE == 1)
OsExcQueueMsgGet(UINT32 type,VOID * arg)198 STATIC UINT32 OsExcQueueMsgGet(UINT32 type, VOID *arg)
199 {
200 UINT32 len = sizeof(QUEUE_INFO_S);
201 UINT32 loop = *(UINT32 *)arg;
202
203 return OsExcHookFunc(type, 1, loop, len, (EXC_INFO_SAVE_CALLBACK)LOS_QueueInfoGet);
204 }
205 #endif
206
OsExcTaskMsgGet(UINT32 type,VOID * arg)207 STATIC UINT32 OsExcTaskMsgGet(UINT32 type, VOID *arg)
208 {
209 UINT32 len = sizeof(TSK_INFO_S);
210 UINT32 loop = *(UINT32 *)arg;
211
212 return OsExcHookFunc(type, 0, loop, len, (EXC_INFO_SAVE_CALLBACK)LOS_TaskInfoGet);
213 }
214
215 #if (LOSCFG_BASE_CORE_EXC_TSK_SWITCH == 1)
OsExcTskSwitchMsgGet(UINT32 type,VOID * arg)216 STATIC UINT32 OsExcTskSwitchMsgGet(UINT32 type, VOID *arg)
217 {
218 UINT32 len;
219 UINT32 loop;
220 UINT32 taskSwitchCount;
221 TaskSwitchInfo *taskSwitchInfo = NULL;
222 UINT32 i;
223
224 /* not necessary, just for macro int library */
225 taskSwitchInfo = (TaskSwitchInfo *)arg;
226 taskSwitchCount = taskSwitchInfo->cntInfo.maxCnt;
227 len = sizeof(UINT32) + (sizeof(CHAR) * LOS_TASK_NAMELEN);
228 if (taskSwitchInfo->cntInfo.isFull) {
229 i = taskSwitchInfo->idx;
230 loop = i + taskSwitchCount;
231 } else {
232 i = 0;
233 loop = taskSwitchInfo->idx;
234 }
235
236 return OsExcHookFunc(type, i, loop, len, (EXC_INFO_SAVE_CALLBACK)LOS_TaskSwitchInfoGet);
237 }
238 #endif
239
OsExcRegister(ExcInfoType type,EXC_INFO_SAVE_CALLBACK func,VOID * arg)240 VOID OsExcRegister(ExcInfoType type, EXC_INFO_SAVE_CALLBACK func, VOID *arg)
241 {
242 ExcInfoArray *excInfo = NULL;
243 if ((type >= OS_EXC_TYPE_MAX) || (func == NULL)) {
244 PRINT_ERR("OsExcRegister ERROR!\n");
245 return;
246 }
247 excInfo = &(g_excArray[type]);
248 if (excInfo->valid == TRUE) {
249 return;
250 }
251
252 excInfo->type = type;
253 excInfo->fnExcInfoCb = func;
254 excInfo->arg = arg;
255 excInfo->valid = TRUE;
256 }
257
OsExcMsgDump(VOID)258 STATIC VOID OsExcMsgDump(VOID)
259 {
260 UINT32 index;
261
262 /* Ignore the return code when matching CSEC rule 6.6(4). */
263 (VOID)memset_s(g_excMsgArray, g_excArraySize, EXC_MSG_ARRAY_INIT_VALUE, g_excArraySize);
264
265 *((UINT32 *)g_excContent) = MAX_EXC_MEM_SIZE; /* The total length of exception information. */
266 g_excContent = (UINT8 *)g_excContent + sizeof(UINT32);
267
268 for (index = 0; index < OS_EXC_TYPE_MAX; index++) {
269 if (!g_excArray[index].valid) {
270 continue;
271 }
272 g_excArray[index].fnExcInfoCb(g_excArray[index].type, g_excArray[index].arg);
273 }
274
275 *((UINT32 *)g_excContent) = OS_EXC_TYPE_MAX;
276 g_excContent = (UINT8 *)g_excContent + sizeof(UINT32);
277 return;
278 }
279
OsExcMsgDumpInit(VOID)280 VOID OsExcMsgDumpInit(VOID)
281 {
282 g_excQueueMaxNum = LOSCFG_BASE_IPC_QUEUE_LIMIT;
283 g_excMemMaxNum = OS_SYS_MEM_NUM;
284 g_excContent = (VOID *)g_excMsgArray;
285
286 OsExcRegister(OS_EXC_TYPE_CONTEXT, OsExcContentGet, NULL);
287 OsExcRegister(OS_EXC_TYPE_TSK, OsExcTaskMsgGet, &g_taskMaxNum);
288 #if (LOSCFG_BASE_IPC_QUEUE == 1)
289 OsExcRegister(OS_EXC_TYPE_QUE, OsExcQueueMsgGet, &g_excQueueMaxNum);
290 #endif
291 OsExcRegister(OS_EXC_TYPE_NVIC, OsExcSaveIntStatus, NULL);
292 #if (LOSCFG_BASE_CORE_EXC_TSK_SWITCH == 1)
293 OsExcRegister(OS_EXC_TYPE_TSK_SWITCH, OsExcTskSwitchMsgGet, &g_taskSwitchInfo);
294 #endif
295 OsExcRegister(OS_EXC_TYPE_MEM, OsExcMemMsgGet, &g_excMemMaxNum);
296
297 (VOID)LOS_RegExcHook(EXC_INTERRUPT, (ExcHookFn)OsExcMsgDump);
298 }
299 #endif
300