• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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