1 /*
2 * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
3 * Copyright (c) 2020-2023 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 <stdarg.h>
33 #include "securec.h"
34 #include "los_context.h"
35 #include "los_arch_context.h"
36 #include "los_arch_interrupt.h"
37 #include "los_debug.h"
38 #include "los_hook.h"
39 #include "los_task.h"
40 #include "los_sched.h"
41 #include "los_memory.h"
42 #include "los_membox.h"
43
44 #define INT_OFFSET 6
45 #define PRI_OFF_PER_INT 8
46 #define PRI_PER_REG 4
47 #define PRI_OFF_IN_REG 6
48 #define PRI_BITS 2
49 #define PRI_HI 0
50 #define PRI_LOW 7
51 #define MASK_8_BITS 0xFF
52 #define MASK_32_BITS 0xFFFFFFFF
53 #define BYTES_OF_128_INT 4
54
55 CHAR g_trapStackBase[OS_TRAP_STACK_SIZE];
56
57 VIC_TYPE *VIC_REG = (VIC_TYPE *)VIC_REG_BASE;
58
HalGetPsr(VOID)59 UINT32 HalGetPsr(VOID)
60 {
61 UINT32 intSave;
62 __asm__ volatile("mfcr %0, psr" : "=r" (intSave) : : "memory");
63 return intSave;
64 }
65
HalSetVbr(UINT32 intSave)66 UINT32 HalSetVbr(UINT32 intSave)
67 {
68 __asm__ volatile("mtcr %0, vbr" : : "r"(intSave) : "memory");
69 return intSave;
70 }
71
ArchIntLock(VOID)72 UINT32 ArchIntLock(VOID)
73 {
74 UINT32 intSave;
75 __asm__ __volatile__(
76 "mfcr %0, psr \n"
77 "psrclr ie"
78 : "=r"(intSave)
79 :
80 : "memory");
81 return intSave;
82 }
83
ArchIntUnLock(VOID)84 UINT32 ArchIntUnLock(VOID)
85 {
86 UINT32 intSave;
87 __asm__ __volatile__(
88 "mfcr %0, psr \n"
89 "psrset ie"
90 : "=r"(intSave)
91 :
92 : "memory");
93 return intSave;
94 }
95
ArchIntRestore(UINT32 intSave)96 VOID ArchIntRestore(UINT32 intSave)
97 {
98 __asm__ __volatile__("mtcr %0, psr" : : "r"(intSave));
99 }
100
ArchIntLocked(VOID)101 UINT32 ArchIntLocked(VOID)
102 {
103 UINT32 intSave;
104 __asm__ volatile("mfcr %0, psr" : "=r" (intSave) : : "memory");
105 return !(intSave & (1 << INT_OFFSET));
106 }
107
HwiUnmask(HWI_HANDLE_T hwiNum)108 STATIC UINT32 HwiUnmask(HWI_HANDLE_T hwiNum)
109 {
110 UINT32 intSave;
111
112 intSave = LOS_IntLock();
113 VIC_REG->ISER[hwiNum / OS_SYS_VECTOR_CNT] = (UINT32)(1UL << (hwiNum % OS_SYS_VECTOR_CNT));
114 VIC_REG->ISSR[hwiNum / OS_SYS_VECTOR_CNT] = (UINT32)(1UL << (hwiNum % OS_SYS_VECTOR_CNT));
115 LOS_IntRestore(intSave);
116
117 return LOS_OK;
118 }
119
HwiSetPriority(HWI_HANDLE_T hwiNum,UINT8 priority)120 STATIC UINT32 HwiSetPriority(HWI_HANDLE_T hwiNum, UINT8 priority)
121 {
122 UINT32 intSave;
123
124 intSave = LOS_IntLock();
125 VIC_REG->IPR[hwiNum / PRI_PER_REG] |= (((priority << PRI_OFF_IN_REG) << (hwiNum % PRI_PER_REG)) * PRI_OFF_PER_INT);
126 LOS_IntRestore(intSave);
127
128 return LOS_OK;
129 }
130
HwiMask(HWI_HANDLE_T hwiNum)131 STATIC UINT32 HwiMask(HWI_HANDLE_T hwiNum)
132 {
133 UINT32 intSave;
134
135 intSave = LOS_IntLock();
136 VIC_REG->ICER[hwiNum / OS_SYS_VECTOR_CNT] = (UINT32)(1UL << (hwiNum % OS_SYS_VECTOR_CNT));
137 LOS_IntRestore(intSave);
138
139 return LOS_OK;
140 }
141
HwiPending(HWI_HANDLE_T hwiNum)142 STATIC UINT32 HwiPending(HWI_HANDLE_T hwiNum)
143 {
144 UINT32 intSave;
145
146 intSave = LOS_IntLock();
147 VIC_REG->ISPR[hwiNum / OS_SYS_VECTOR_CNT] = (UINT32)(1UL << (hwiNum % OS_SYS_VECTOR_CNT));
148 LOS_IntRestore(intSave);
149
150 return LOS_OK;
151 }
152
HwiClear(HWI_HANDLE_T hwiNum)153 STATIC UINT32 HwiClear(HWI_HANDLE_T hwiNum)
154 {
155 VIC_REG->ICPR[hwiNum / OS_SYS_VECTOR_CNT] = (UINT32)(1UL << (hwiNum % OS_SYS_VECTOR_CNT));
156
157 return LOS_OK;
158 }
159
160 /* ****************************************************************************
161 Function : HwiNumGet
162 Description : Get an interrupt number
163 Input : None
164 Output : None
165 Return : Interrupt Indexes number
166 **************************************************************************** */
HwiNumGet(VOID)167 STATIC UINT32 HwiNumGet(VOID)
168 {
169 return (HalGetPsr() >> PSR_VEC_OFFSET) & MASK_8_BITS;
170 }
171
HwiCreate(HWI_HANDLE_T hwiNum,HWI_PRIOR_T hwiPrio)172 STATIC UINT32 HwiCreate(HWI_HANDLE_T hwiNum, HWI_PRIOR_T hwiPrio)
173 {
174 HwiSetPriority(hwiNum, (UINT8)hwiPrio);
175 HwiUnmask(hwiNum);
176 return LOS_OK;
177 }
178
179 STATIC HwiControllerOps g_archHwiOps = {
180 .enableIrq = HwiUnmask,
181 .disableIrq = HwiMask,
182 .setIrqPriority = HwiSetPriority,
183 .getCurIrqNum = HwiNumGet,
184 .triggerIrq = HwiPending,
185 .clearIrq = HwiClear,
186 .createIrq = HwiCreate,
187 };
188
ArchIntOpsGet(VOID)189 HwiControllerOps *ArchIntOpsGet(VOID)
190 {
191 return &g_archHwiOps;
192 }
193
194 /* ****************************************************************************
195 Function : HalInterrupt
196 Description : Hardware interrupt entry function
197 Input : None
198 Output : None
199 Return : None
200 **************************************************************************** */
HalInterrupt(VOID)201 LITE_OS_SEC_TEXT VOID HalInterrupt(VOID)
202 {
203 UINT32 hwiIndex;
204 UINT32 intSave;
205
206 intSave = LOS_IntLock();
207 g_intCount++;
208 LOS_IntRestore(intSave);
209
210 hwiIndex = HwiNumGet();
211 OsHookCall(LOS_HOOK_TYPE_ISR_ENTER, hwiIndex);
212
213 HalPreInterruptHandler(hwiIndex);
214 #if (LOSCFG_PLATFORM_HWI_WITH_ARG == 1)
215 if (g_hwiHandlerForm[hwiIndex].pfnHandler != 0) {
216 g_hwiHandlerForm[hwiIndex].pfnHandler((VOID *)g_hwiHandlerForm[hwiIndex].pParm);
217 }
218 #else
219 if (g_hwiHandlerForm[hwiIndex] != 0) {
220 g_hwiHandlerForm[hwiIndex]();
221 }
222 #endif
223
224 HalAftInterruptHandler(hwiIndex);
225
226 OsHookCall(LOS_HOOK_TYPE_ISR_EXIT, hwiIndex);
227
228 intSave = LOS_IntLock();
229 g_intCount--;
230 #ifndef CPU_CK804
231 HalIrqEndCheckNeedSched();
232 #endif
233 LOS_IntRestore(intSave);
234 }
235
236 ExcInfo g_excInfo = {0};
237
238 #if (LOSCFG_KERNEL_PRINTF != 0)
OsExcTypeInfo(const ExcInfo * excInfo)239 STATIC VOID OsExcTypeInfo(const ExcInfo *excInfo)
240 {
241 CHAR *phaseStr[] = {"exc in init", "exc in task", "exc in hwi"};
242
243 PRINTK("Type = %d\n", excInfo->type);
244 PRINTK("ThrdPid = %d\n", excInfo->thrdPid);
245 PRINTK("Phase = %s\n", phaseStr[excInfo->phase]);
246 PRINTK("FaultAddr = 0x%x\n", excInfo->faultAddr);
247 }
248
OsExcCurTaskInfo(const ExcInfo * excInfo)249 STATIC VOID OsExcCurTaskInfo(const ExcInfo *excInfo)
250 {
251 PRINTK("Current task info:\n");
252 if (excInfo->phase == OS_EXC_IN_TASK) {
253 LosTaskCB *taskCB = OS_TCB_FROM_TID(LOS_CurTaskIDGet());
254 PRINTK("Task name = %s\n", taskCB->taskName);
255 PRINTK("Task ID = %d\n", taskCB->taskID);
256 PRINTK("Task SP = 0x%x\n", (UINTPTR)taskCB->stackPointer);
257 PRINTK("Task ST = 0x%x\n", taskCB->topOfStack);
258 PRINTK("Task SS = 0x%x\n", taskCB->stackSize);
259 } else if (excInfo->phase == OS_EXC_IN_HWI) {
260 PRINTK("Exception occur in interrupt phase!\n");
261 } else {
262 PRINTK("Exception occur in system init phase!\n");
263 }
264 }
265
OsExcRegInfo(const ExcInfo * excInfo)266 STATIC VOID OsExcRegInfo(const ExcInfo *excInfo)
267 {
268 EXC_CONTEXT_S *excContext = excInfo->context;
269 PRINTK("Exception reg dump:\n");
270 PRINTK("R0 = 0x%x\n"
271 "R1 = 0x%x\n"
272 "R2 = 0x%x\n"
273 "R3 = 0x%x\n"
274 "R4 = 0x%x\n"
275 "R5 = 0x%x\n"
276 "R6 = 0x%x\n"
277 "R7 = 0x%x\n"
278 "R8 = 0x%x\n"
279 "R9 = 0x%x\n"
280 "R10 = 0x%x\n"
281 "R11 = 0x%x\n"
282 "R12 = 0x%x\n"
283 "R13 = 0x%x\n"
284 "R14 = 0x%x\n"
285 "R15 = 0x%x\n"
286 "EPSR = 0x%x\n"
287 "EPC = 0x%x\n",
288 excContext->R0, excContext->R1, excContext->R2, excContext->R3, excContext->R4, excContext->R5,
289 excContext->R6, excContext->R7, excContext->R8, excContext->R9, excContext->R10, excContext->R11,
290 excContext->R12, excContext->R13, excContext->R14, excContext->R15, excContext->EPSR,
291 excContext->EPC);
292 }
293
294 #if (LOSCFG_KERNEL_BACKTRACE == 1)
OsExcBackTraceInfo(const ExcInfo * excInfo)295 STATIC VOID OsExcBackTraceInfo(const ExcInfo *excInfo)
296 {
297 UINTPTR LR[LOSCFG_BACKTRACE_DEPTH] = {0};
298 UINT32 index;
299
300 OsBackTraceHookCall(LR, LOSCFG_BACKTRACE_DEPTH, 0, excInfo->context->R14);
301
302 PRINTK("----- backtrace start -----\n");
303 for (index = 0; index < LOSCFG_BACKTRACE_DEPTH; index++) {
304 if (LR[index] == 0) {
305 break;
306 }
307 PRINTK("backtrace %d -- lr = 0x%x\n", index, LR[index]);
308 }
309 PRINTK("----- backtrace end -----\n");
310 }
311 #endif
312
OsExcMemPoolCheckInfo(VOID)313 STATIC VOID OsExcMemPoolCheckInfo(VOID)
314 {
315 PRINTK("\r\nmemory pools check:\n");
316 #if (LOSCFG_PLATFORM_EXC == 1)
317 MemInfoCB memExcInfo[OS_SYS_MEM_NUM];
318 UINT32 errCnt;
319 UINT32 i;
320
321 (VOID)memset_s(memExcInfo, sizeof(memExcInfo), 0, sizeof(memExcInfo));
322
323 errCnt = OsMemExcInfoGet(OS_SYS_MEM_NUM, memExcInfo);
324 if (errCnt < OS_SYS_MEM_NUM) {
325 errCnt += OsMemboxExcInfoGet(OS_SYS_MEM_NUM - errCnt, memExcInfo + errCnt);
326 }
327
328 if (errCnt == 0) {
329 PRINTK("all memory pool check passed!\n");
330 return;
331 }
332
333 for (i = 0; i < errCnt; i++) {
334 PRINTK("pool num = %d\n", i);
335 PRINTK("pool type = %d\n", memExcInfo[i].type);
336 PRINTK("pool addr = 0x%x\n", memExcInfo[i].startAddr);
337 PRINTK("pool size = 0x%x\n", memExcInfo[i].size);
338 PRINTK("pool free = 0x%x\n", memExcInfo[i].free);
339 PRINTK("pool blkNum = %d\n", memExcInfo[i].blockSize);
340 PRINTK("pool error node addr = 0x%x\n", memExcInfo[i].errorAddr);
341 PRINTK("pool error node len = 0x%x\n", memExcInfo[i].errorLen);
342 PRINTK("pool error node owner = %d\n", memExcInfo[i].errorOwner);
343 }
344 #endif
345 UINT32 ret = LOS_MemIntegrityCheck(LOSCFG_SYS_HEAP_ADDR);
346 if (ret == LOS_OK) {
347 PRINTK("system heap memcheck over, all passed!\n");
348 }
349
350 PRINTK("memory pool check end!\n");
351 }
352 #endif
353
OsExcInfoDisplay(const ExcInfo * excInfo)354 STATIC VOID OsExcInfoDisplay(const ExcInfo *excInfo)
355 {
356 #if (LOSCFG_KERNEL_PRINTF != 0)
357 PRINTK("*************Exception Information**************\n");
358 OsExcTypeInfo(excInfo);
359 OsExcCurTaskInfo(excInfo);
360 OsExcRegInfo(excInfo);
361 #if (LOSCFG_KERNEL_BACKTRACE == 1)
362 OsExcBackTraceInfo(excInfo);
363 #endif
364 OsGetAllTskInfo();
365 OsExcMemPoolCheckInfo();
366 #endif
367 }
368
HalExcHandleEntry(EXC_CONTEXT_S * excBufAddr,UINT32 faultAddr)369 LITE_OS_SEC_TEXT_INIT VOID HalExcHandleEntry(EXC_CONTEXT_S *excBufAddr, UINT32 faultAddr)
370 {
371 UINT16 tmpFlag = ((excBufAddr->EPSR >> PSR_VEC_OFFSET) & MASK_8_BITS);
372 g_excInfo.nestCnt++;
373 UINT32 excType = (HalGetPsr() >> PSR_VEC_OFFSET) & MASK_8_BITS;
374 g_excInfo.type = excType;
375
376 g_excInfo.faultAddr = faultAddr;
377
378 if (g_losTask.runTask != NULL) {
379 if (tmpFlag > 0) {
380 g_excInfo.phase = OS_EXC_IN_HWI;
381 g_excInfo.thrdPid = tmpFlag;
382 } else {
383 g_excInfo.phase = OS_EXC_IN_TASK;
384 g_excInfo.thrdPid = g_losTask.runTask->taskID;
385 }
386 } else {
387 g_excInfo.phase = OS_EXC_IN_INIT;
388 g_excInfo.thrdPid = OS_NULL_INT;
389 }
390 g_excInfo.context = excBufAddr;
391
392 OsDoExcHook(EXC_INTERRUPT);
393 OsExcInfoDisplay(&g_excInfo);
394 ArchSysExit();
395 }
396
397 /* stack protector */
398 WEAK UINT32 __stack_chk_guard = 0xd00a0dff;
399
__stack_chk_fail(VOID)400 WEAK VOID __stack_chk_fail(VOID)
401 {
402 /* __builtin_return_address is a builtin function, building in gcc */
403 LOS_Panic("stack-protector: Kernel stack is corrupted in: %x\n",
404 __builtin_return_address(0));
405 }
406
HalHwiHandleReInit(UINT32 hwiFormAddr)407 WEAK void HalHwiHandleReInit(UINT32 hwiFormAddr)
408 {
409 }
410
411 /* ****************************************************************************
412 Function : HalHwiInit
413 Description : initialization of the hardware interrupt
414 Input : None
415 Output : None
416 Return : None
417 **************************************************************************** */
HalHwiInit(VOID)418 LITE_OS_SEC_TEXT_INIT VOID HalHwiInit(VOID)
419 {
420 UINT32 i;
421
422 HWI_PROC_FUNC *hwiForm = (HWI_PROC_FUNC *)ArchGetHwiFrom();
423 for (i = 1; i < OS_SYS_VECTOR_CNT; i++) {
424 hwiForm[i] = (HWI_PROC_FUNC)HandleEntry;
425 }
426
427 for (i = OS_SYS_VECTOR_CNT; i < (LOSCFG_PLATFORM_HWI_LIMIT + OS_SYS_VECTOR_CNT); i++) {
428 hwiForm[i] = (HWI_PROC_FUNC)IrqEntry;
429 }
430 HalHwiHandleReInit((UINT32)hwiForm);
431
432 HalSetVbr((UINT32)hwiForm);
433 for (i = 0; i < BYTES_OF_128_INT; i++) {
434 VIC_REG->IABR[i] = 0x0;
435 VIC_REG->ICPR[i] = MASK_32_BITS;
436 }
437 return;
438 }
439
440