• 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_interrupt.h"
33 #include <stdarg.h>
34 #include "securec.h"
35 #include "los_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 #include "los_arch_regs.h"
44 
45 UINT32 g_intCount = 0;
46 
47 /* *
48  * @ingroup los_hwi
49  * Hardware interrupt form mapping handling function array.
50  */
51 STATIC HWI_PROC_FUNC __attribute__((aligned(LOSCFG_ARCH_HWI_VECTOR_ALIGN))) g_hwiForm[OS_VECTOR_CNT] = {0};
52 
53 #if (LOSCFG_PLATFORM_HWI_WITH_ARG == 1)
54 
55 typedef struct {
56     HWI_PROC_FUNC pfnHandler;
57     VOID *pParm;
58 } HWI_HANDLER_FUNC;
59 
60 /* *
61  * @ingroup los_hwi
62  * Hardware interrupt handler form mapping handling function array.
63  */
64 STATIC HWI_HANDLER_FUNC g_hwiHandlerForm[OS_VECTOR_CNT] = {{ (HWI_PROC_FUNC)0, (HWI_ARG_T)0 }};
65 
66 /* *
67  * @ingroup los_hwi
68  * Set interrupt vector table.
69  */
OsSetVector(UINT32 num,HWI_PROC_FUNC vector,VOID * arg)70 VOID OsSetVector(UINT32 num, HWI_PROC_FUNC vector, VOID *arg)
71 {
72     if ((num + OS_SYS_VECTOR_CNT) < OS_VECTOR_CNT) {
73         g_hwiForm[num + OS_SYS_VECTOR_CNT] = (HWI_PROC_FUNC)HalInterrupt;
74         g_hwiHandlerForm[num + OS_SYS_VECTOR_CNT].pfnHandler = vector;
75         g_hwiHandlerForm[num + OS_SYS_VECTOR_CNT].pParm = arg;
76     }
77 }
78 
79 #else
80 /* *
81  * @ingroup los_hwi
82  * Hardware interrupt handler form mapping handling function array.
83  */
84 STATIC HWI_PROC_FUNC g_hwiHandlerForm[OS_VECTOR_CNT] = {0};
85 
86 /* *
87  * @ingroup los_hwi
88  * Set interrupt vector table.
89  */
OsSetVector(UINT32 num,HWI_PROC_FUNC vector)90 VOID OsSetVector(UINT32 num, HWI_PROC_FUNC vector)
91 {
92     if ((num + OS_SYS_VECTOR_CNT) < OS_VECTOR_CNT) {
93         g_hwiForm[num + OS_SYS_VECTOR_CNT] = HalInterrupt;
94         g_hwiHandlerForm[num + OS_SYS_VECTOR_CNT] = vector;
95     }
96 }
97 #endif
98 
HwiNumValid(UINT32 num)99 UINT32 HwiNumValid(UINT32 num)
100 {
101     return (num >= OS_SYS_VECTOR_CNT) && (num <= OS_VECTOR_CNT);
102 }
103 
104 /* *
105  * @ingroup los_hwi
106  * Lock all interrupt.
107  */
ArchIntLock(VOID)108 UINT32 ArchIntLock(VOID)
109 {
110     UINT32 ret;
111 
112     __asm__ volatile("rsil %0, %1" : "=r"(ret) : "i"(INT_MASK) : "memory");
113     return ret;
114 }
115 
116 /* *
117  * @ingroup los_hwi
118  * Restore interrupt status.
119  */
ArchIntRestore(UINT32 intSave)120 VOID ArchIntRestore(UINT32 intSave)
121 {
122     __asm__ volatile("wsr.ps %0; rsync" : : "r"(intSave) : "memory");
123 }
124 
125 /* *
126  * @ingroup los_hwi
127  * Unlock interrupt.
128  */
ArchIntUnLock(VOID)129 UINT32 ArchIntUnLock(VOID)
130 {
131     UINT32 intSave;
132 
133     __asm__ volatile("rsil %0, %1" : "=r"(intSave) : "i"(0) : "memory");
134 
135     return intSave;
136 }
137 
138 /* *
139  * @ingroup los_hwi
140  * Determine if the interrupt is locked
141  */
ArchIntLocked(VOID)142 STATIC INLINE UINT32 ArchIntLocked(VOID)
143 {
144     UINT32 intSave;
145 
146     __asm__ volatile("rsr %0, ps " : "=r"(intSave) : : "memory");
147 
148     return (intSave & SPREG_PS_DI_MASK);
149 }
150 
151 /* *
152  * @ingroup los_hwi
153  * Trigger the interrupt
154  */
HwiPending(HWI_HANDLE_T hwiNum)155 STATIC UINT32 HwiPending(HWI_HANDLE_T hwiNum)
156 {
157     if (!HwiNumValid(hwiNum)) {
158         return OS_ERRNO_HWI_NUM_INVALID;
159     }
160 
161     __asm__ __volatile__("wsr   %0, intset; rsync" : : "a"(0x1U << hwiNum));
162 
163     return LOS_OK;
164 }
165 
HwiUnmask(HWI_HANDLE_T hwiNum)166 UINT32 HwiUnmask(HWI_HANDLE_T hwiNum)
167 {
168     UINT32 ier;
169 
170     if (!HwiNumValid(hwiNum)) {
171         return OS_ERRNO_HWI_NUM_INVALID;
172     }
173 
174     __asm__ __volatile__("rsr %0, intenable" : "=a"(ier) : : "memory");
175     __asm__ __volatile__("wsr %0, intenable; rsync" : : "a"(ier | ((UINT32)0x1U << hwiNum)));
176 
177     return LOS_OK;
178 }
179 
HwiMask(HWI_HANDLE_T hwiNum)180 UINT32 HwiMask(HWI_HANDLE_T hwiNum)
181 {
182     UINT32 ier;
183 
184     if (!HwiNumValid(hwiNum)) {
185         return OS_ERRNO_HWI_NUM_INVALID;
186     }
187 
188     __asm__ __volatile__("rsr %0, intenable" : "=a"(ier) : : "memory");
189     __asm__ __volatile__("wsr %0, intenable; rsync" : : "a"(ier & ~((UINT32)0x1U << hwiNum)));
190 
191     return LOS_OK;
192 }
193 
194 /* ****************************************************************************
195  Function    : HwiNumGet
196  Description : Get an interrupt number
197  Input       : None
198  Output      : None
199  Return      : Interrupt Indexes number
200  **************************************************************************** */
HwiNumGet(VOID)201 STATIC UINT32 HwiNumGet(VOID)
202 {
203     UINT32 ier;
204     UINT32 intenable;
205     UINT32 intSave;
206 
207     __asm__ __volatile__("rsr %0, interrupt" : "=a"(ier) : : "memory");
208     __asm__ __volatile__("rsr %0, intenable" : "=a"(intenable) : : "memory");
209 
210     intSave = ier & intenable;
211 
212     return  __builtin_ffs(intSave) - 1;
213 }
214 
215 /* *
216  * @ingroup los_hwi
217  * Clear the interrupt
218  */
HwiClear(HWI_HANDLE_T vector)219 STATIC UINT32 HwiClear(HWI_HANDLE_T vector)
220 {
221     if (!HwiNumValid(vector)) {
222         return OS_ERRNO_HWI_NUM_INVALID;
223     }
224 
225     __asm__ __volatile__("wsr   %0, intclear; rsync" : : "a"(0x1U << vector));
226 
227     return LOS_OK;
228 }
229 
230 HwiControllerOps g_archHwiOps = {
231     .triggerIrq     = HwiPending,
232     .enableIrq      = HwiUnmask,
233     .disableIrq     = HwiMask,
234     .getCurIrqNum   = HwiNumGet,
235     .clearIrq       = HwiClear,
236 };
237 
ArchIsIntActive(VOID)238 INLINE UINT32 ArchIsIntActive(VOID)
239 {
240     return (g_intCount > 0);
241 }
242 
243 /* ****************************************************************************
244  Function    : HalHwiDefaultHandler
245  Description : default handler of the hardware interrupt
246  Input       : None
247  Output      : None
248  Return      : None
249  **************************************************************************** */
HalHwiDefaultHandler(VOID)250 VOID HalHwiDefaultHandler(VOID)
251 {
252     PRINT_ERR("%s irqnum:%u\n", __FUNCTION__, HwiNumGet());
253     while (1) {}
254 }
255 
HalPreInterruptHandler(UINT32 arg)256 WEAK VOID HalPreInterruptHandler(UINT32 arg)
257 {
258     (VOID)arg;
259     return;
260 }
261 
HalAftInterruptHandler(UINT32 arg)262 WEAK VOID HalAftInterruptHandler(UINT32 arg)
263 {
264     (VOID)arg;
265     return;
266 }
267 
268 /* ****************************************************************************
269  Function    : HalInterrupt
270  Description : Hardware interrupt entry function
271  Input       : None
272  Output      : None
273  Return      : None
274  **************************************************************************** */
HalInterrupt(VOID)275 VOID HalInterrupt(VOID)
276 {
277     UINT32 hwiIndex;
278     UINT32 intSave;
279 
280     intSave = LOS_IntLock();
281     g_intCount++;
282     LOS_IntRestore(intSave);
283 
284     hwiIndex = HwiNumGet();
285     HwiClear(hwiIndex);
286 
287     OsHookCall(LOS_HOOK_TYPE_ISR_ENTER, hwiIndex);
288 
289     HalPreInterruptHandler(hwiIndex);
290 
291 #if (LOSCFG_PLATFORM_HWI_WITH_ARG == 1)
292     if (g_hwiHandlerForm[hwiIndex].pfnHandler != 0) {
293         g_hwiHandlerForm[hwiIndex].pfnHandler((VOID *)g_hwiHandlerForm[hwiIndex].pParm);
294     }
295 #else
296     if (g_hwiHandlerForm[hwiIndex] != 0) {
297         g_hwiHandlerForm[hwiIndex]();
298     }
299 #endif
300 
301     HalAftInterruptHandler(hwiIndex);
302 
303     OsHookCall(LOS_HOOK_TYPE_ISR_EXIT, hwiIndex);
304 
305     intSave = LOS_IntLock();
306     g_intCount--;
307     LOS_IntRestore(intSave);
308     HalIrqEndCheckNeedSched();
309 }
310 
311 /* ****************************************************************************
312  Function    : ArchHwiCreate
313  Description : create hardware interrupt
314  Input       : hwiNum   --- hwi num to create
315                hwiPrio  --- priority of the hwi
316                hwiMode  --- unused
317                hwiHandler --- hwi handler
318                irqParam --- param of the hwi handler
319  Output      : None
320  Return      : LOS_OK on success or error code on failure
321  **************************************************************************** */
ArchHwiCreate(HWI_HANDLE_T hwiNum,HWI_PRIOR_T hwiPrio,HWI_MODE_T hwiMode,HWI_PROC_FUNC hwiHandler,HwiIrqParam * irqParam)322 UINT32 ArchHwiCreate(HWI_HANDLE_T hwiNum,
323                      HWI_PRIOR_T hwiPrio,
324                      HWI_MODE_T hwiMode,
325                      HWI_PROC_FUNC hwiHandler,
326                      HwiIrqParam *irqParam)
327 {
328     (VOID)hwiMode;
329     UINT32 intSave;
330 
331     if (hwiHandler == NULL) {
332         return OS_ERRNO_HWI_PROC_FUNC_NULL;
333     }
334 
335     if (hwiNum >= OS_HWI_MAX_NUM) {
336         return OS_ERRNO_HWI_NUM_INVALID;
337     }
338 
339     if (g_hwiForm[hwiNum + OS_SYS_VECTOR_CNT] != (HWI_PROC_FUNC)HalHwiDefaultHandler) {
340         return OS_ERRNO_HWI_ALREADY_CREATED;
341     }
342 
343     if (hwiPrio > OS_HWI_PRIO_LOWEST) {
344         return OS_ERRNO_HWI_PRIO_INVALID;
345     }
346 
347     intSave = LOS_IntLock();
348 #if (LOSCFG_PLATFORM_HWI_WITH_ARG == 1)
349     if (irqParam != NULL) {
350         OsSetVector(hwiNum, hwiHandler, irqParam->pDevId);
351     } else {
352         OsSetVector(hwiNum, hwiHandler, NULL);
353     }
354 #else
355     (VOID)irqParam;
356     OsSetVector(hwiNum, hwiHandler);
357 #endif
358     HwiUnmask(hwiNum);
359 
360     LOS_IntRestore(intSave);
361 
362     return LOS_OK;
363 }
364 
365 /* ****************************************************************************
366  Function    : ArchHwiDelete
367  Description : Delete hardware interrupt
368  Input       : hwiNum   --- hwi num to delete
369                irqParam --- param of the hwi handler
370  Output      : None
371  Return      : LOS_OK on success or error code on failure
372  **************************************************************************** */
ArchHwiDelete(HWI_HANDLE_T hwiNum,HwiIrqParam * irqParam)373 LITE_OS_SEC_TEXT_INIT UINT32 ArchHwiDelete(HWI_HANDLE_T hwiNum, HwiIrqParam *irqParam)
374 {
375     (VOID)irqParam;
376     UINT32 intSave;
377 
378     if (hwiNum >= OS_HWI_MAX_NUM) {
379         return OS_ERRNO_HWI_NUM_INVALID;
380     }
381 
382     HwiMask(hwiNum);
383 
384     intSave = LOS_IntLock();
385 
386     g_hwiForm[hwiNum + OS_SYS_VECTOR_CNT] = (HWI_PROC_FUNC)HalHwiDefaultHandler;
387 
388     LOS_IntRestore(intSave);
389 
390     return LOS_OK;
391 }
392 
393 ExcInfo g_excInfo = {0};
394 
395 #if (LOSCFG_KERNEL_PRINTF != 0)
396 
OsExcTypeInfo(const ExcInfo * excInfo)397 STATIC VOID OsExcTypeInfo(const ExcInfo *excInfo)
398 {
399     CHAR *phaseStr[] = {"exc in init", "exc in task", "exc in hwi"};
400 
401     PRINTK("Type      = %d\n", excInfo->type);
402     PRINTK("ThrdPid   = %d\n", excInfo->thrdPid);
403     PRINTK("Phase     = %s\n", phaseStr[excInfo->phase]);
404     PRINTK("FaultAddr = 0x%x\n", excInfo->faultAddr);
405 }
406 
OsExcCurTaskInfo(const ExcInfo * excInfo)407 STATIC VOID OsExcCurTaskInfo(const ExcInfo *excInfo)
408 {
409     PRINTK("Current task info:\n");
410     if (excInfo->phase == OS_EXC_IN_TASK) {
411         LosTaskCB *taskCB = OS_TCB_FROM_TID(LOS_CurTaskIDGet());
412         PRINTK("Task name = %s\n", taskCB->taskName);
413         PRINTK("Task ID   = %d\n", taskCB->taskID);
414         PRINTK("Task SP   = 0x%x\n", (UINTPTR)taskCB->stackPointer);
415         PRINTK("Task ST   = 0x%x\n", taskCB->topOfStack);
416         PRINTK("Task SS   = 0x%x\n", taskCB->stackSize);
417     } else if (excInfo->phase == OS_EXC_IN_HWI) {
418         PRINTK("Exception occur in interrupt phase!\n");
419     } else {
420         PRINTK("Exception occur in system init phase!\n");
421     }
422 }
423 
OsExcRegInfo(const ExcInfo * excInfo)424 STATIC VOID OsExcRegInfo(const ExcInfo *excInfo)
425 {
426     INT32 index;
427     PRINTK("Exception reg dump:\n");
428     PRINTK("sar          = 0x%x\n", excInfo->context->sar);
429     PRINTK("excCause     = 0x%x\n", excInfo->context->excCause);
430     PRINTK("excVaddr     = 0x%x\n", excInfo->context->excVaddr);
431     PRINTK("lbeg         = 0x%x\n", excInfo->context->lbeg);
432     PRINTK("lend         = 0x%x\n", excInfo->context->lend);
433     PRINTK("lcount       = 0x%x\n", excInfo->context->lcount);
434     PRINTK("pc           = 0x%x\n", excInfo->context->pc);
435     PRINTK("ps           = 0x%x\n", excInfo->context->ps);
436     for (index = 0; index < XTENSA_LOGREG_NUM; index++) {
437         PRINTK("regA%d        = 0x%x\n", index, excInfo->context->regA[index]);
438     }
439 }
440 
441 #if (LOSCFG_KERNEL_BACKTRACE == 1)
OsExcBackTraceInfo(const ExcInfo * excInfo)442 STATIC VOID OsExcBackTraceInfo(const ExcInfo *excInfo)
443 {
444     UINTPTR LR[LOSCFG_BACKTRACE_DEPTH] = {0};
445     UINT32 index;
446 
447     OsBackTraceHookCall(LR, LOSCFG_BACKTRACE_DEPTH, 0, excInfo->context->regA[1]);
448 
449     PRINTK("----- backtrace start -----\n");
450     for (index = 0; index < LOSCFG_BACKTRACE_DEPTH; index++) {
451         if (LR[index] == 0) {
452             break;
453         }
454         PRINTK("backtrace %d -- lr = 0x%x\n", index, LR[index]);
455     }
456     PRINTK("----- backtrace end -----\n");
457 }
458 #endif
459 
OsExcMemPoolCheckInfo(VOID)460 STATIC VOID OsExcMemPoolCheckInfo(VOID)
461 {
462     PRINTK("\r\nmemory pools check:\n");
463 #if (LOSCFG_PLATFORM_EXC == 1)
464     MemInfoCB memExcInfo[OS_SYS_MEM_NUM];
465     UINT32 errCnt;
466     UINT32 i;
467 
468     (VOID)memset_s(memExcInfo, sizeof(memExcInfo), 0, sizeof(memExcInfo));
469 
470     errCnt = OsMemExcInfoGet(OS_SYS_MEM_NUM, memExcInfo);
471     if (errCnt < OS_SYS_MEM_NUM) {
472         errCnt += OsMemboxExcInfoGet(OS_SYS_MEM_NUM - errCnt, memExcInfo + errCnt);
473     }
474 
475     if (errCnt == 0) {
476         PRINTK("all memory pool check passed!\n");
477         return;
478     }
479 
480     for (i = 0; i < errCnt; i++) {
481         PRINTK("pool num    = %d\n", i);
482         PRINTK("pool type   = %d\n", memExcInfo[i].type);
483         PRINTK("pool addr   = 0x%x\n", memExcInfo[i].startAddr);
484         PRINTK("pool size   = 0x%x\n", memExcInfo[i].size);
485         PRINTK("pool free   = 0x%x\n", memExcInfo[i].free);
486         PRINTK("pool blkNum = %d\n", memExcInfo[i].blockSize);
487         PRINTK("pool error node addr  = 0x%x\n", memExcInfo[i].errorAddr);
488         PRINTK("pool error node len   = 0x%x\n", memExcInfo[i].errorLen);
489         PRINTK("pool error node owner = %d\n", memExcInfo[i].errorOwner);
490     }
491 #endif
492     UINT32 ret = LOS_MemIntegrityCheck(LOSCFG_SYS_HEAP_ADDR);
493     if (ret == LOS_OK) {
494         PRINTK("system heap memcheck over, all passed!\n");
495     }
496 
497     PRINTK("memory pool check end!\n");
498 }
499 #endif
500 
OsExcInfoDisplay(const ExcInfo * excInfo)501 STATIC VOID OsExcInfoDisplay(const ExcInfo *excInfo)
502 {
503 #if (LOSCFG_KERNEL_PRINTF != 0)
504     PRINTK("*************Exception Information**************\n");
505     OsExcTypeInfo(excInfo);
506     OsExcCurTaskInfo(excInfo);
507     OsExcRegInfo(excInfo);
508 #if (LOSCFG_KERNEL_BACKTRACE == 1)
509     OsExcBackTraceInfo(excInfo);
510 #endif
511     OsGetAllTskInfo();
512     OsExcMemPoolCheckInfo();
513 #endif
514 }
515 
HalExcHandleEntry(UINTPTR faultAddr,EXC_CONTEXT_S * excBufAddr,UINT32 type)516 VOID HalExcHandleEntry(UINTPTR faultAddr, EXC_CONTEXT_S *excBufAddr, UINT32 type)
517 {
518     g_excInfo.nestCnt++;
519     g_excInfo.faultAddr = faultAddr;
520     g_excInfo.type = type;
521 
522     LosTaskCB *taskCB = g_losTask.runTask;
523 
524     if ((taskCB == NULL) || (taskCB == OS_TCB_FROM_TID(g_taskMaxNum))) {
525         g_excInfo.phase = OS_EXC_IN_INIT;
526         g_excInfo.thrdPid = OS_NULL_INT;
527     } else if (HwiNumGet() != OS_NULL_INT) {
528         g_excInfo.phase = OS_EXC_IN_HWI;
529         g_excInfo.thrdPid = HwiNumGet();
530     } else {
531         g_excInfo.phase = OS_EXC_IN_TASK;
532         g_excInfo.thrdPid = g_losTask.runTask->taskID;
533     }
534 
535     g_excInfo.context = excBufAddr;
536 
537     OsDoExcHook(EXC_INTERRUPT);
538     OsExcInfoDisplay(&g_excInfo);
539     ArchSysExit();
540 }
541 
542 /* Stack protector */
543 WEAK UINT32 __stack_chk_guard = 0xd00a0dff;
544 
__stack_chk_fail(VOID)545 WEAK VOID __stack_chk_fail(VOID)
546 {
547     /* __builtin_return_address is a builtin function, building in gcc */
548     LOS_Panic("stack-protector: Kernel stack is corrupted in: 0x%x\n",
549               __builtin_return_address(0));
550 }
551 
552 /* ****************************************************************************
553  Function    : HalHwiInit
554  Description : initialization of the hardware interrupt
555  Input       : None
556  Output      : None
557  Return      : None
558  **************************************************************************** */
HalHwiInit(VOID)559 VOID HalHwiInit(VOID)
560 {
561     EnableExceptionInterface();
562     for (UINT32 i = 0; i < OS_HWI_MAX_NUM; i++) {
563         g_hwiForm[i + OS_SYS_VECTOR_CNT] = HalHwiDefaultHandler;
564         HwiMask(i);
565     }
566     asm volatile ("wsr %0, vecbase" : : "r"(INIT_VECTOR_START));
567     return;
568 }
569