• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_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_arch_regs.h"
43 
44 /* *
45  * @ingroup los_hwi
46  * Lock all interrupt.
47  */
ArchIntLock(VOID)48 UINT32 ArchIntLock(VOID)
49 {
50     UINT32 ret;
51 
52     __asm__ volatile("rsil %0, %1" : "=r"(ret) : "i"(INT_MASK) : "memory");
53     return ret;
54 }
55 
56 /* *
57  * @ingroup los_hwi
58  * Restore interrupt status.
59  */
ArchIntRestore(UINT32 intSave)60 VOID ArchIntRestore(UINT32 intSave)
61 {
62     __asm__ volatile("wsr.ps %0; rsync" : : "r"(intSave) : "memory");
63 }
64 
65 /* *
66  * @ingroup los_hwi
67  * Unlock interrupt.
68  */
ArchIntUnLock(VOID)69 UINT32 ArchIntUnLock(VOID)
70 {
71     UINT32 intSave;
72 
73     __asm__ volatile("rsil %0, %1" : "=r"(intSave) : "i"(0) : "memory");
74 
75     return intSave;
76 }
77 
78 /* *
79  * @ingroup los_hwi
80  * Determine if the interrupt is locked
81  */
ArchIntLocked(VOID)82 STATIC INLINE UINT32 ArchIntLocked(VOID)
83 {
84     UINT32 intSave;
85 
86     __asm__ volatile("rsr %0, ps " : "=r"(intSave) : : "memory");
87 
88     return (intSave & SPREG_PS_DI_MASK);
89 }
90 
91 /* *
92  * @ingroup los_hwi
93  * Trigger the interrupt
94  */
HwiPending(HWI_HANDLE_T hwiNum)95 STATIC UINT32 HwiPending(HWI_HANDLE_T hwiNum)
96 {
97     __asm__ __volatile__("wsr   %0, intset; rsync" : : "a"(0x1U << hwiNum));
98     return LOS_OK;
99 }
100 
HwiUnmask(HWI_HANDLE_T hwiNum)101 STATIC UINT32 HwiUnmask(HWI_HANDLE_T hwiNum)
102 {
103     UINT32 ier;
104 
105     __asm__ __volatile__("rsr %0, intenable" : "=a"(ier) : : "memory");
106     __asm__ __volatile__("wsr %0, intenable; rsync" : : "a"(ier | ((UINT32)0x1U << hwiNum)));
107 
108     return LOS_OK;
109 }
110 
HwiMask(HWI_HANDLE_T hwiNum)111 STATIC UINT32 HwiMask(HWI_HANDLE_T hwiNum)
112 {
113     UINT32 ier;
114 
115     __asm__ __volatile__("rsr %0, intenable" : "=a"(ier) : : "memory");
116     __asm__ __volatile__("wsr %0, intenable; rsync" : : "a"(ier & ~((UINT32)0x1U << hwiNum)));
117 
118     return LOS_OK;
119 }
120 
121 /* ****************************************************************************
122  Function    : HwiNumGet
123  Description : Get an interrupt number
124  Input       : None
125  Output      : None
126  Return      : Interrupt Indexes number
127  **************************************************************************** */
HwiNumGet(VOID)128 STATIC UINT32 HwiNumGet(VOID)
129 {
130     UINT32 ier;
131     UINT32 intenable;
132     UINT32 intSave;
133 
134     __asm__ __volatile__("rsr %0, interrupt" : "=a"(ier) : : "memory");
135     __asm__ __volatile__("rsr %0, intenable" : "=a"(intenable) : : "memory");
136 
137     intSave = ier & intenable;
138 
139     return  __builtin_ffs(intSave) - 1;
140 }
141 
142 /* *
143  * @ingroup los_hwi
144  * Clear the interrupt
145  */
HwiClear(HWI_HANDLE_T hwiNum)146 STATIC UINT32 HwiClear(HWI_HANDLE_T hwiNum)
147 {
148     __asm__ __volatile__("wsr   %0, intclear; rsync" : : "a"(0x1U << hwiNum));
149 
150     return LOS_OK;
151 }
152 
HwiCreate(HWI_HANDLE_T hwiNum,HWI_PRIOR_T hwiPrio)153 STATIC UINT32 HwiCreate(HWI_HANDLE_T hwiNum, HWI_PRIOR_T hwiPrio)
154 {
155     (VOID)hwiPrio;
156     HwiUnmask(hwiNum);
157     return LOS_OK;
158 }
159 
160 STATIC HwiControllerOps g_archHwiOps = {
161     .triggerIrq     = HwiPending,
162     .enableIrq      = HwiUnmask,
163     .disableIrq     = HwiMask,
164     .getCurIrqNum   = HwiNumGet,
165     .clearIrq       = HwiClear,
166     .createIrq      = HwiCreate,
167 };
168 
ArchIntOpsGet(VOID)169 HwiControllerOps *ArchIntOpsGet(VOID)
170 {
171     return &g_archHwiOps;
172 }
173 
174 /* ****************************************************************************
175  Function    : HalInterrupt
176  Description : Hardware interrupt entry function
177  Input       : None
178  Output      : None
179  Return      : None
180  **************************************************************************** */
HalInterrupt(VOID)181 VOID HalInterrupt(VOID)
182 {
183     UINT32 hwiIndex;
184     UINT32 intSave;
185 
186     intSave = LOS_IntLock();
187     g_intCount++;
188     LOS_IntRestore(intSave);
189 
190     hwiIndex = HwiNumGet();
191     HwiClear(hwiIndex);
192 
193     OsHookCall(LOS_HOOK_TYPE_ISR_ENTER, hwiIndex);
194 
195     HalPreInterruptHandler(hwiIndex);
196 
197 #if (LOSCFG_PLATFORM_HWI_WITH_ARG == 1)
198     if (g_hwiHandlerForm[hwiIndex].pfnHandler != 0) {
199         g_hwiHandlerForm[hwiIndex].pfnHandler((VOID *)g_hwiHandlerForm[hwiIndex].pParm);
200     }
201 #else
202     if (g_hwiHandlerForm[hwiIndex] != 0) {
203         g_hwiHandlerForm[hwiIndex]();
204     }
205 #endif
206 
207     HalAftInterruptHandler(hwiIndex);
208 
209     OsHookCall(LOS_HOOK_TYPE_ISR_EXIT, hwiIndex);
210 
211     intSave = LOS_IntLock();
212     g_intCount--;
213     LOS_IntRestore(intSave);
214     HalIrqEndCheckNeedSched();
215 }
216 
217 ExcInfo g_excInfo = {0};
218 
219 #if (LOSCFG_KERNEL_PRINTF != 0)
220 
OsExcTypeInfo(const ExcInfo * excInfo)221 STATIC VOID OsExcTypeInfo(const ExcInfo *excInfo)
222 {
223     CHAR *phaseStr[] = {"exc in init", "exc in task", "exc in hwi"};
224 
225     PRINTK("Type      = %d\n", excInfo->type);
226     PRINTK("ThrdPid   = %d\n", excInfo->thrdPid);
227     PRINTK("Phase     = %s\n", phaseStr[excInfo->phase]);
228     PRINTK("FaultAddr = 0x%x\n", excInfo->faultAddr);
229 }
230 
OsExcCurTaskInfo(const ExcInfo * excInfo)231 STATIC VOID OsExcCurTaskInfo(const ExcInfo *excInfo)
232 {
233     PRINTK("Current task info:\n");
234     if (excInfo->phase == OS_EXC_IN_TASK) {
235         LosTaskCB *taskCB = OS_TCB_FROM_TID(LOS_CurTaskIDGet());
236         PRINTK("Task name = %s\n", taskCB->taskName);
237         PRINTK("Task ID   = %d\n", taskCB->taskID);
238         PRINTK("Task SP   = 0x%x\n", (UINTPTR)taskCB->stackPointer);
239         PRINTK("Task ST   = 0x%x\n", taskCB->topOfStack);
240         PRINTK("Task SS   = 0x%x\n", taskCB->stackSize);
241     } else if (excInfo->phase == OS_EXC_IN_HWI) {
242         PRINTK("Exception occur in interrupt phase!\n");
243     } else {
244         PRINTK("Exception occur in system init phase!\n");
245     }
246 }
247 
OsExcRegInfo(const ExcInfo * excInfo)248 STATIC VOID OsExcRegInfo(const ExcInfo *excInfo)
249 {
250     INT32 index;
251     PRINTK("Exception reg dump:\n");
252     PRINTK("sar          = 0x%x\n", excInfo->context->sar);
253     PRINTK("excCause     = 0x%x\n", excInfo->context->excCause);
254     PRINTK("excVaddr     = 0x%x\n", excInfo->context->excVaddr);
255     PRINTK("lbeg         = 0x%x\n", excInfo->context->lbeg);
256     PRINTK("lend         = 0x%x\n", excInfo->context->lend);
257     PRINTK("lcount       = 0x%x\n", excInfo->context->lcount);
258     PRINTK("pc           = 0x%x\n", excInfo->context->pc);
259     PRINTK("ps           = 0x%x\n", excInfo->context->ps);
260     for (index = 0; index < XTENSA_LOGREG_NUM; index++) {
261         PRINTK("regA%d        = 0x%x\n", index, excInfo->context->regA[index]);
262     }
263 }
264 
265 #if (LOSCFG_KERNEL_BACKTRACE == 1)
OsExcBackTraceInfo(const ExcInfo * excInfo)266 STATIC VOID OsExcBackTraceInfo(const ExcInfo *excInfo)
267 {
268     UINTPTR LR[LOSCFG_BACKTRACE_DEPTH] = {0};
269     UINT32 index;
270 
271     OsBackTraceHookCall(LR, LOSCFG_BACKTRACE_DEPTH, 0, excInfo->context->regA[1]);
272 
273     PRINTK("----- backtrace start -----\n");
274     for (index = 0; index < LOSCFG_BACKTRACE_DEPTH; index++) {
275         if (LR[index] == 0) {
276             break;
277         }
278         PRINTK("backtrace %d -- lr = 0x%x\n", index, LR[index]);
279     }
280     PRINTK("----- backtrace end -----\n");
281 }
282 #endif
283 
OsExcMemPoolCheckInfo(VOID)284 STATIC VOID OsExcMemPoolCheckInfo(VOID)
285 {
286     PRINTK("\r\nmemory pools check:\n");
287 #if (LOSCFG_PLATFORM_EXC == 1)
288     MemInfoCB memExcInfo[OS_SYS_MEM_NUM];
289     UINT32 errCnt;
290     UINT32 i;
291 
292     (VOID)memset_s(memExcInfo, sizeof(memExcInfo), 0, sizeof(memExcInfo));
293 
294     errCnt = OsMemExcInfoGet(OS_SYS_MEM_NUM, memExcInfo);
295     if (errCnt < OS_SYS_MEM_NUM) {
296         errCnt += OsMemboxExcInfoGet(OS_SYS_MEM_NUM - errCnt, memExcInfo + errCnt);
297     }
298 
299     if (errCnt == 0) {
300         PRINTK("all memory pool check passed!\n");
301         return;
302     }
303 
304     for (i = 0; i < errCnt; i++) {
305         PRINTK("pool num    = %d\n", i);
306         PRINTK("pool type   = %d\n", memExcInfo[i].type);
307         PRINTK("pool addr   = 0x%x\n", memExcInfo[i].startAddr);
308         PRINTK("pool size   = 0x%x\n", memExcInfo[i].size);
309         PRINTK("pool free   = 0x%x\n", memExcInfo[i].free);
310         PRINTK("pool blkNum = %d\n", memExcInfo[i].blockSize);
311         PRINTK("pool error node addr  = 0x%x\n", memExcInfo[i].errorAddr);
312         PRINTK("pool error node len   = 0x%x\n", memExcInfo[i].errorLen);
313         PRINTK("pool error node owner = %d\n", memExcInfo[i].errorOwner);
314     }
315 #endif
316     UINT32 ret = LOS_MemIntegrityCheck(LOSCFG_SYS_HEAP_ADDR);
317     if (ret == LOS_OK) {
318         PRINTK("system heap memcheck over, all passed!\n");
319     }
320 
321     PRINTK("memory pool check end!\n");
322 }
323 #endif
324 
OsExcInfoDisplay(const ExcInfo * excInfo)325 STATIC VOID OsExcInfoDisplay(const ExcInfo *excInfo)
326 {
327 #if (LOSCFG_KERNEL_PRINTF != 0)
328     PRINTK("*************Exception Information**************\n");
329     OsExcTypeInfo(excInfo);
330     OsExcCurTaskInfo(excInfo);
331     OsExcRegInfo(excInfo);
332 #if (LOSCFG_KERNEL_BACKTRACE == 1)
333     OsExcBackTraceInfo(excInfo);
334 #endif
335     OsGetAllTskInfo();
336     OsExcMemPoolCheckInfo();
337 #endif
338 }
339 
HalExcHandleEntry(UINTPTR faultAddr,EXC_CONTEXT_S * excBufAddr,UINT32 type)340 VOID HalExcHandleEntry(UINTPTR faultAddr, EXC_CONTEXT_S *excBufAddr, UINT32 type)
341 {
342     g_excInfo.nestCnt++;
343     g_excInfo.faultAddr = faultAddr;
344     g_excInfo.type = type;
345 
346     LosTaskCB *taskCB = g_losTask.runTask;
347 
348     if ((taskCB == NULL) || (taskCB == OS_TCB_FROM_TID(g_taskMaxNum))) {
349         g_excInfo.phase = OS_EXC_IN_INIT;
350         g_excInfo.thrdPid = OS_NULL_INT;
351     } else if (HwiNumGet() != OS_NULL_INT) {
352         g_excInfo.phase = OS_EXC_IN_HWI;
353         g_excInfo.thrdPid = HwiNumGet();
354     } else {
355         g_excInfo.phase = OS_EXC_IN_TASK;
356         g_excInfo.thrdPid = g_losTask.runTask->taskID;
357     }
358 
359     g_excInfo.context = excBufAddr;
360 
361     OsDoExcHook(EXC_INTERRUPT);
362     OsExcInfoDisplay(&g_excInfo);
363     ArchSysExit();
364 }
365 
366 /* Stack protector */
367 WEAK UINT32 __stack_chk_guard = 0xd00a0dff;
368 
__stack_chk_fail(VOID)369 WEAK VOID __stack_chk_fail(VOID)
370 {
371     /* __builtin_return_address is a builtin function, building in gcc */
372     LOS_Panic("stack-protector: Kernel stack is corrupted in: 0x%x\n",
373               __builtin_return_address(0));
374 }
375 
376 /* ****************************************************************************
377  Function    : HalHwiInit
378  Description : initialization of the hardware interrupt
379  Input       : None
380  Output      : None
381  Return      : None
382  **************************************************************************** */
HalHwiInit(VOID)383 VOID HalHwiInit(VOID)
384 {
385     EnableExceptionInterface();
386     HWI_PROC_FUNC *hwiForm = (HWI_PROC_FUNC *)ArchGetHwiFrom();
387     for (UINT32 i = 0; i < OS_HWI_MAX_NUM; i++) {
388         hwiForm[i + OS_SYS_VECTOR_CNT] = HalHwiDefaultHandler;
389         HwiMask(i);
390     }
391     asm volatile ("wsr %0, vecbase" : : "r"(INIT_VECTOR_START));
392     return;
393 }
394