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 #include "los_interrupt.h"
32 #include <stdarg.h>
33 #include "securec.h"
34 #include "los_context.h"
35 #include "los_arch_interrupt.h"
36 #include "los_debug.h"
37 #include "los_hook.h"
38 #include "los_task.h"
39 #include "los_sched.h"
40 #include "los_memory.h"
41 #include "los_membox.h"
42 #include "los_reg.h"
43
44 #define OS_INT_IRQ_ENABLE (1U << 0)
45 #define OS_INT_FIQ_ENABLE (1U << 1)
46 #define OS_INT_REG_BASE 0x00802040UL
47 #define OS_INT_GLOBAL_ENABLE_ADDR (OS_INT_REG_BASE + 4)
48 #define OS_INT_ENABLE_ADDR (OS_INT_REG_BASE)
49 #define OS_INT_STATUS_ADDR (OS_INT_REG_BASE + 12)
50
51 #define OS_INSTR_SET_MASK 0x01000020U
52 #define OS_ARM_INSTR_LEN 4
53 #define OS_THUMB_INSTR_LEN 2
54
55 UINT32 g_intCount = 0;
56 ExcInfo g_excInfo = {0};
57
58 /* *
59 * @ingroup los_hwi
60 * hardware interrupt form mapping handling function array.
61 */
62 STATIC HWI_PROC_FUNC g_hwiForm[OS_VECTOR_CNT] = {0};
63
64 #if (LOSCFG_PLATFORM_HWI_WITH_ARG == 1)
65
66 typedef struct {
67 HWI_PROC_FUNC pfnHandler;
68 VOID *pParm;
69 } HWI_HANDLER_FUNC;
70
71 /* *
72 * @ingroup los_hwi
73 * hardware interrupt handler form mapping handling function array.
74 */
75 STATIC HWI_HANDLER_FUNC g_hwiHandlerForm[OS_VECTOR_CNT] = {{ (HWI_PROC_FUNC)0, (HWI_ARG_T)0 }};
76
77 /* *
78 * @ingroup los_hwi
79 * Set interrupt vector table.
80 */
OsSetVector(UINT32 num,HWI_PROC_FUNC vector,VOID * arg)81 VOID OsSetVector(UINT32 num, HWI_PROC_FUNC vector, VOID *arg)
82 {
83 if ((num + OS_SYS_VECTOR_CNT) < OS_VECTOR_CNT) {
84 g_hwiForm[num + OS_SYS_VECTOR_CNT] = (HWI_PROC_FUNC)HalInterrupt;
85 g_hwiHandlerForm[num + OS_SYS_VECTOR_CNT].pfnHandler = vector;
86 g_hwiHandlerForm[num + OS_SYS_VECTOR_CNT].pParm = arg;
87 }
88 }
89
90 #else
91 /* *
92 * @ingroup los_hwi
93 * hardware interrupt handler form mapping handling function array.
94 */
95 STATIC HWI_PROC_FUNC g_hwiHandlerForm[OS_VECTOR_CNT] = {0};
96
97 /* *
98 * @ingroup los_hwi
99 * Set interrupt vector table.
100 */
OsSetVector(UINT32 num,HWI_PROC_FUNC vector)101 VOID OsSetVector(UINT32 num, HWI_PROC_FUNC vector)
102 {
103 if ((num + OS_SYS_VECTOR_CNT) < OS_VECTOR_CNT) {
104 g_hwiForm[num + OS_SYS_VECTOR_CNT] = HalInterrupt;
105 g_hwiHandlerForm[num + OS_SYS_VECTOR_CNT] = vector;
106 }
107 }
108 #endif
109
110
111 /* ****************************************************************************
112 Function : HwiNumGet
113 Description : Get an interrupt number
114 Input : None
115 Output : None
116 Return : Interrupt Indexes number
117 **************************************************************************** */
HwiNumGet(VOID)118 STATIC UINT32 HwiNumGet(VOID)
119 {
120 UINT32 status;
121
122 READ_UINT32(status, OS_INT_STATUS_ADDR);
123
124 return (31 - CLZ(status));
125 }
126
HwiUnmask(HWI_HANDLE_T hwiNum)127 STATIC UINT32 HwiUnmask(HWI_HANDLE_T hwiNum)
128 {
129 if (hwiNum >= OS_HWI_MAX_NUM) {
130 return OS_ERRNO_HWI_NUM_INVALID;
131 }
132
133 *((volatile UINT32 *)OS_INT_ENABLE_ADDR) |= (1U << (hwiNum));
134
135 return LOS_OK;
136 }
137
HwiMask(HWI_HANDLE_T hwiNum)138 STATIC UINT32 HwiMask(HWI_HANDLE_T hwiNum)
139 {
140 if (hwiNum >= OS_HWI_MAX_NUM) {
141 return OS_ERRNO_HWI_NUM_INVALID;
142 }
143
144 *((volatile UINT32 *)OS_INT_ENABLE_ADDR) &= ~(1U << (hwiNum));
145
146 return LOS_OK;
147 }
148
149 HwiControllerOps g_archHwiOps = {
150 .enableIrq = HwiUnmask,
151 .disableIrq = HwiMask,
152 .getCurIrqNum = HwiNumGet,
153 };
154
ArchIsIntActive(VOID)155 inline UINT32 ArchIsIntActive(VOID)
156 {
157 return (g_intCount > 0);
158 }
159 /* ****************************************************************************
160 Function : HalHwiDefaultHandler
161 Description : default handler of the hardware interrupt
162 Input : None
163 Output : None
164 Return : None
165 **************************************************************************** */
HalHwiDefaultHandler(VOID)166 LITE_OS_SEC_TEXT_MINOR VOID HalHwiDefaultHandler(VOID)
167 {
168 PRINT_ERR("%s irqnum:%u\n", __FUNCTION__, HwiNumGet());
169 while (1) {}
170 }
171
HalPreInterruptHandler(UINT32 arg)172 WEAK VOID HalPreInterruptHandler(UINT32 arg)
173 {
174 (VOID)arg;
175 return;
176 }
177
HalAftInterruptHandler(UINT32 arg)178 WEAK VOID HalAftInterruptHandler(UINT32 arg)
179 {
180 (VOID)arg;
181 return;
182 }
183
184 /* ****************************************************************************
185 Function : HalInterrupt
186 Description : Hardware interrupt entry function
187 Input : None
188 Output : None
189 Return : None
190 **************************************************************************** */
HalInterrupt(VOID)191 LITE_OS_SEC_TEXT VOID HalInterrupt(VOID)
192 {
193 UINT32 intSave;
194 UINT32 hwiIndex;
195
196 intSave = LOS_IntLock();
197 g_intCount++;
198 LOS_IntRestore(intSave);
199
200 #if (LOSCFG_BASE_CORE_SCHED_SLEEP == 1)
201 OsSchedUpdateSleepTime();
202 #endif
203
204 hwiIndex = HwiNumGet();
205
206 OsHookCall(LOS_HOOK_TYPE_ISR_ENTER, hwiIndex);
207
208 HalPreInterruptHandler(hwiIndex);
209
210 #if (LOSCFG_PLATFORM_HWI_WITH_ARG == 1)
211 if (g_hwiHandlerForm[hwiIndex].pfnHandler != 0) {
212 g_hwiHandlerForm[hwiIndex].pfnHandler((VOID *)g_hwiHandlerForm[hwiIndex].pParm);
213 }
214 #else
215 if (g_hwiHandlerForm[hwiIndex] != 0) {
216 g_hwiHandlerForm[hwiIndex]();
217 }
218 #endif
219
220 HalAftInterruptHandler(hwiIndex);
221
222 OsHookCall(LOS_HOOK_TYPE_ISR_EXIT, hwiIndex);
223
224 intSave = LOS_IntLock();
225 g_intCount--;
226 LOS_IntRestore(intSave);
227 }
228
229 /* ****************************************************************************
230 Function : ArchHwiCreate
231 Description : create hardware interrupt
232 Input : hwiNum --- hwi num to create
233 hwiPrio --- priority of the hwi
234 hwiMode --- unused
235 hwiHandler --- hwi handler
236 irqParam --- param of the hwi handler
237 Output : None
238 Return : LOS_OK on success or error code on failure
239 **************************************************************************** */
ArchHwiCreate(HWI_HANDLE_T hwiNum,HWI_PRIOR_T hwiPrio,HWI_MODE_T hwiMode,HWI_PROC_FUNC hwiHandler,HwiIrqParam * irqParam)240 LITE_OS_SEC_TEXT_INIT UINT32 ArchHwiCreate(HWI_HANDLE_T hwiNum,
241 HWI_PRIOR_T hwiPrio,
242 HWI_MODE_T hwiMode,
243 HWI_PROC_FUNC hwiHandler,
244 HwiIrqParam *irqParam)
245 {
246 (VOID)hwiMode;
247 UINT32 intSave;
248
249 if (hwiHandler == NULL) {
250 return OS_ERRNO_HWI_PROC_FUNC_NULL;
251 }
252
253 if (hwiNum >= OS_HWI_MAX_NUM) {
254 return OS_ERRNO_HWI_NUM_INVALID;
255 }
256
257 if (g_hwiForm[hwiNum + OS_SYS_VECTOR_CNT] != (HWI_PROC_FUNC)HalHwiDefaultHandler) {
258 return OS_ERRNO_HWI_ALREADY_CREATED;
259 }
260
261 intSave = LOS_IntLock();
262 #if (LOSCFG_PLATFORM_HWI_WITH_ARG == 1)
263 if (irqParam != NULL) {
264 OsSetVector(hwiNum, hwiHandler, irqParam->pDevId);
265 } else {
266 OsSetVector(hwiNum, hwiHandler, NULL);
267 }
268 #else
269 (VOID)irqParam;
270 OsSetVector(hwiNum, hwiHandler);
271 #endif
272 HwiUnmask(hwiNum);
273 LOS_IntRestore(intSave);
274
275 return LOS_OK;
276 }
277
278 /* ****************************************************************************
279 Function : ArchHwiDelete
280 Description : Delete hardware interrupt
281 Input : hwiNum --- hwi num to delete
282 irqParam --- param of the hwi handler
283 Output : None
284 Return : LOS_OK on success or error code on failure
285 **************************************************************************** */
ArchHwiDelete(HWI_HANDLE_T hwiNum,HwiIrqParam * irqParam)286 LITE_OS_SEC_TEXT_INIT UINT32 ArchHwiDelete(HWI_HANDLE_T hwiNum, HwiIrqParam *irqParam)
287 {
288 (VOID)irqParam;
289 UINT32 intSave;
290
291 if (hwiNum >= OS_HWI_MAX_NUM) {
292 return OS_ERRNO_HWI_NUM_INVALID;
293 }
294
295 HwiMask(hwiNum);
296
297 intSave = LOS_IntLock();
298 g_hwiForm[hwiNum + OS_SYS_VECTOR_CNT] = (HWI_PROC_FUNC)HalHwiDefaultHandler;
299 LOS_IntRestore(intSave);
300
301 return LOS_OK;
302 }
303
304 #if (LOSCFG_KERNEL_PRINTF != 0)
OsExcTypeInfo(const ExcInfo * excInfo)305 STATIC VOID OsExcTypeInfo(const ExcInfo *excInfo)
306 {
307 CHAR *phaseStr[] = {"exc in init", "exc in task", "exc in hwi"};
308
309 PRINTK("Type = %d\n", excInfo->type);
310 PRINTK("ThrdPid = %d\n", excInfo->thrdPid);
311 PRINTK("Phase = %s\n", phaseStr[excInfo->phase]);
312 PRINTK("FaultAddr = 0x%x\n", excInfo->faultAddr);
313 }
314
OsExcCurTaskInfo(const ExcInfo * excInfo)315 STATIC VOID OsExcCurTaskInfo(const ExcInfo *excInfo)
316 {
317 PRINTK("Current task info:\n");
318 if (excInfo->phase == OS_EXC_IN_TASK) {
319 LosTaskCB *taskCB = OS_TCB_FROM_TID(LOS_CurTaskIDGet());
320 PRINTK("Task name = %s\n", taskCB->taskName);
321 PRINTK("Task ID = %d\n", taskCB->taskID);
322 PRINTK("Task SP = 0x%x\n", taskCB->stackPointer);
323 PRINTK("Task ST = 0x%x\n", taskCB->topOfStack);
324 PRINTK("Task SS = 0x%x\n", taskCB->stackSize);
325 } else if (excInfo->phase == OS_EXC_IN_HWI) {
326 PRINTK("Exception occur in interrupt phase!\n");
327 } else {
328 PRINTK("Exception occur in system init phase!\n");
329 }
330 }
331
OsExcRegInfo(const ExcInfo * excInfo)332 STATIC VOID OsExcRegInfo(const ExcInfo *excInfo)
333 {
334 PRINTK("Exception reg dump:\n");
335 PRINTK("PC = 0x%x\n", excInfo->context->pc);
336 PRINTK("LR = 0x%x\n", excInfo->context->lr);
337 PRINTK("R0 = 0x%x\n", excInfo->context->r0);
338 PRINTK("R1 = 0x%x\n", excInfo->context->r1);
339 PRINTK("R2 = 0x%x\n", excInfo->context->r2);
340 PRINTK("R3 = 0x%x\n", excInfo->context->r3);
341 PRINTK("R4 = 0x%x\n", excInfo->context->r4);
342 PRINTK("R5 = 0x%x\n", excInfo->context->r5);
343 PRINTK("R6 = 0x%x\n", excInfo->context->r6);
344 PRINTK("R7 = 0x%x\n", excInfo->context->r7);
345 PRINTK("R8 = 0x%x\n", excInfo->context->r8);
346 PRINTK("R9 = 0x%x\n", excInfo->context->r9);
347 PRINTK("R10 = 0x%x\n", excInfo->context->r10);
348 PRINTK("R11 = 0x%x\n", excInfo->context->r11);
349 PRINTK("R12 = 0x%x\n", excInfo->context->r12);
350 PRINTK("xPSR = 0x%x\n", excInfo->context->spsr);
351 }
352
353 #if (LOSCFG_KERNEL_BACKTRACE == 1)
OsExcBackTraceInfo(const ExcInfo * excInfo)354 STATIC VOID OsExcBackTraceInfo(const ExcInfo *excInfo)
355 {
356 UINTPTR LR[LOSCFG_BACKTRACE_DEPTH] = {0};
357 UINT32 index;
358
359 OsBackTraceHookCall(LR, LOSCFG_BACKTRACE_DEPTH, 0, excInfo->context->sp);
360
361 PRINTK("----- backtrace start -----\n");
362 for (index = 0; index < LOSCFG_BACKTRACE_DEPTH; index++) {
363 if (LR[index] == 0) {
364 break;
365 }
366 PRINTK("backtrace %d -- lr = 0x%x\n", index, LR[index]);
367 }
368 PRINTK("----- backtrace end -----\n");
369 }
370 #endif
371
OsExcMemPoolCheckInfo(VOID)372 STATIC VOID OsExcMemPoolCheckInfo(VOID)
373 {
374 PRINTK("\r\nmemory pools check:\n");
375 #if (LOSCFG_PLATFORM_EXC == 1)
376 MemInfoCB memExcInfo[OS_SYS_MEM_NUM];
377 UINT32 errCnt;
378 UINT32 i;
379
380 (VOID)memset_s(memExcInfo, sizeof(memExcInfo), 0, sizeof(memExcInfo));
381
382 errCnt = OsMemExcInfoGet(OS_SYS_MEM_NUM, memExcInfo);
383 if (errCnt < OS_SYS_MEM_NUM) {
384 errCnt += OsMemboxExcInfoGet(OS_SYS_MEM_NUM - errCnt, memExcInfo + errCnt);
385 }
386
387 if (errCnt == 0) {
388 PRINTK("all memory pool check passed!\n");
389 return;
390 }
391
392 for (i = 0; i < errCnt; i++) {
393 PRINTK("pool num = %d\n", i);
394 PRINTK("pool type = %d\n", memExcInfo[i].type);
395 PRINTK("pool addr = 0x%x\n", memExcInfo[i].startAddr);
396 PRINTK("pool size = 0x%x\n", memExcInfo[i].size);
397 PRINTK("pool free = 0x%x\n", memExcInfo[i].free);
398 PRINTK("pool blkNum = %d\n", memExcInfo[i].blockSize);
399 PRINTK("pool error node addr = 0x%x\n", memExcInfo[i].errorAddr);
400 PRINTK("pool error node len = 0x%x\n", memExcInfo[i].errorLen);
401 PRINTK("pool error node owner = %d\n", memExcInfo[i].errorOwner);
402 }
403 #endif
404 UINT32 ret = LOS_MemIntegrityCheck(LOSCFG_SYS_HEAP_ADDR);
405 if (ret == LOS_OK) {
406 PRINTK("system heap memcheck over, all passed!\n");
407 }
408
409 PRINTK("memory pool check end!\n");
410 }
411 #endif
412
OsExcInfoDisplay(const ExcInfo * excInfo)413 STATIC VOID OsExcInfoDisplay(const ExcInfo *excInfo)
414 {
415 #if (LOSCFG_KERNEL_PRINTF != 0)
416 PRINTK("*************Exception Information**************\n");
417 OsExcTypeInfo(excInfo);
418 OsExcCurTaskInfo(excInfo);
419 OsExcRegInfo(excInfo);
420 #if (LOSCFG_KERNEL_BACKTRACE == 1)
421 OsExcBackTraceInfo(excInfo);
422 #endif
423 OsGetAllTskInfo();
424 OsExcMemPoolCheckInfo();
425 #endif
426 }
427
HalExcHandleEntry(UINT32 excType,UINT32 faultAddr,UINT32 pid,EXC_CONTEXT_S * excBufAddr)428 LITE_OS_SEC_TEXT_INIT VOID HalExcHandleEntry(UINT32 excType, UINT32 faultAddr, UINT32 pid, EXC_CONTEXT_S *excBufAddr)
429 {
430 g_intCount++;
431 g_excInfo.nestCnt++;
432
433 g_excInfo.type = excType;
434
435 if ((excType == OS_EXCEPT_UNDEF_INSTR) || (excType == OS_EXCEPT_SWI)) {
436 if ((excBufAddr->spsr & OS_INSTR_SET_MASK) == 0) { /* Work status: ARM */
437 excBufAddr->pc -= OS_ARM_INSTR_LEN;
438 } else if ((excBufAddr->spsr & OS_INSTR_SET_MASK) == 0x20) { /* Work status: Thumb */
439 excBufAddr->pc -= OS_THUMB_INSTR_LEN;
440 }
441 }
442 g_excInfo.faultAddr = OS_EXC_IMPRECISE_ACCESS_ADDR;
443
444 if (g_losTask.runTask != NULL) {
445 g_excInfo.phase = OS_EXC_IN_TASK;
446 g_excInfo.thrdPid = g_losTask.runTask->taskID;
447 } else {
448 g_excInfo.phase = OS_EXC_IN_INIT;
449 g_excInfo.thrdPid = OS_NULL_INT;
450 }
451 g_excInfo.context = excBufAddr;
452
453 OsDoExcHook(EXC_INTERRUPT);
454 OsExcInfoDisplay(&g_excInfo);
455 ArchSysExit();
456 }
457
458 /* ****************************************************************************
459 Function : HalHwiInit
460 Description : initialization of the hardware interrupt
461 Input : None
462 Output : None
463 Return : None
464 **************************************************************************** */
HalHwiInit(VOID)465 LITE_OS_SEC_TEXT_INIT VOID HalHwiInit(VOID)
466 {
467 #if (LOSCFG_USE_SYSTEM_DEFINED_INTERRUPT == 1)
468 UINT32 reg;
469 UINT32 val;
470
471 for (val = OS_SYS_VECTOR_CNT; val < OS_VECTOR_CNT; val++) {
472 #if (LOSCFG_PLATFORM_HWI_WITH_ARG == 1)
473 g_hwiForm[val].pfnHook = HalHwiDefaultHandler;
474 g_hwiForm[val].uwParam = 0;
475 #else
476 g_hwiForm[val] = (HWI_PROC_FUNC)HalHwiDefaultHandler;
477 #endif
478 }
479
480 val = OS_INT_IRQ_ENABLE | OS_INT_FIQ_ENABLE;
481 READ_UINT32(reg, OS_INT_GLOBAL_ENABLE_ADDR);
482 reg |= val;
483 WRITE_UINT32(reg, OS_INT_GLOBAL_ENABLE_ADDR);
484 #endif
485 return;
486 }
487
ArchIntLock(VOID)488 UINT32 ArchIntLock(VOID)
489 {
490 UINT32 ret;
491 UINT32 temp;
492
493 __asm__ __volatile__("MRS %0, CPSR\n"
494 "ORR %1, %0, #0xC0\n"
495 "MSR CPSR_c, %1"
496 : "=r"(ret), "=r"(temp)
497 :
498 : "memory");
499 return ret;
500 }
501
ArchIntRestore(UINT32 intSave)502 VOID ArchIntRestore(UINT32 intSave)
503 {
504 __asm__ __volatile__("MSR CPSR_c, %0" : : "r"(intSave));
505 }
506
ArchIntUnLock(VOID)507 UINT32 ArchIntUnLock(VOID)
508 {
509 UINT32 intSave;
510
511 __asm__ __volatile__("MRS %0, CPSR\n"
512 "BIC %0, %0, #0xC0\n"
513 "MSR CPSR_c, %0"
514 : "=r"(intSave)
515 :
516 : "memory");
517 return intSave;
518 }
519
520