• 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 #include <stdarg.h>
32 #include "securec.h"
33 #include "los_context.h"
34 #include "los_arch_interrupt.h"
35 #include "los_hook.h"
36 #include "los_task.h"
37 #include "los_sched.h"
38 #include "los_memory.h"
39 #include "los_membox.h"
40 #if (LOSCFG_CPUP_INCLUDE_IRQ == 1)
41 #include "los_cpup.h"
42 #endif
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 ExcInfo g_excInfo = {0};
56 
57 /* ****************************************************************************
58  Function    : HwiNumGet
59  Description : Get an interrupt number
60  Input       : None
61  Output      : None
62  Return      : Interrupt Indexes number
63  **************************************************************************** */
HwiNumGet(VOID)64 STATIC UINT32 HwiNumGet(VOID)
65 {
66     UINT32 status;
67 
68     READ_UINT32(status, OS_INT_STATUS_ADDR);
69 
70     return (31 - CLZ(status));
71 }
72 
HwiUnmask(HWI_HANDLE_T hwiNum)73 STATIC UINT32 HwiUnmask(HWI_HANDLE_T hwiNum)
74 {
75     *((volatile UINT32 *)OS_INT_ENABLE_ADDR) |= (1U << (hwiNum));
76 
77     return LOS_OK;
78 }
79 
HwiMask(HWI_HANDLE_T hwiNum)80 STATIC UINT32 HwiMask(HWI_HANDLE_T hwiNum)
81 {
82     *((volatile UINT32 *)OS_INT_ENABLE_ADDR) &= ~(1U << (hwiNum));
83 
84     return LOS_OK;
85 }
86 
HwiCreate(HWI_HANDLE_T hwiNum,HWI_PRIOR_T hwiPrio)87 STATIC UINT32 HwiCreate(HWI_HANDLE_T hwiNum, HWI_PRIOR_T hwiPrio)
88 {
89     (VOID)hwiPrio;
90     HwiUnmask(hwiNum);
91     return LOS_OK;
92 }
93 
94 STATIC HwiControllerOps g_archHwiOps = {
95     .enableIrq      = HwiUnmask,
96     .disableIrq     = HwiMask,
97     .getCurIrqNum   = HwiNumGet,
98     .createIrq      = HwiCreate,
99 };
100 
ArchIntOpsGet(VOID)101 HwiControllerOps *ArchIntOpsGet(VOID)
102 {
103     return &g_archHwiOps;
104 }
105 
106 /* ****************************************************************************
107  Function    : HalInterrupt
108  Description : Hardware interrupt entry function
109  Input       : None
110  Output      : None
111  Return      : None
112  **************************************************************************** */
HalInterrupt(VOID)113 LITE_OS_SEC_TEXT VOID HalInterrupt(VOID)
114 {
115     UINT32 intSave;
116     UINT32 hwiIndex;
117 
118     intSave = LOS_IntLock();
119     g_intCount++;
120     LOS_IntRestore(intSave);
121 
122 #if (LOSCFG_BASE_CORE_SCHED_SLEEP == 1)
123     OsSchedUpdateSleepTime();
124 #endif
125 
126     hwiIndex = HwiNumGet();
127 
128     OsHookCall(LOS_HOOK_TYPE_ISR_ENTER, hwiIndex);
129 #if (LOSCFG_CPUP_INCLUDE_IRQ == 1)
130     OsCpupIrqStart(hwiIndex);
131 #endif
132 
133     HalPreInterruptHandler(hwiIndex);
134 
135 #if (LOSCFG_PLATFORM_HWI_WITH_ARG == 1)
136     if (g_hwiHandlerForm[hwiIndex].pfnHandler != 0) {
137         g_hwiHandlerForm[hwiIndex].pfnHandler((VOID *)g_hwiHandlerForm[hwiIndex].pParm);
138     }
139 #else
140     if (g_hwiHandlerForm[hwiIndex] != 0) {
141         g_hwiHandlerForm[hwiIndex]();
142     }
143 #endif
144 
145 #if (LOSCFG_DEBUG_TOOLS == 1)
146     ++g_hwiFormCnt[hwiIndex];
147 #endif
148 
149     HalAftInterruptHandler(hwiIndex);
150 
151 #if (LOSCFG_CPUP_INCLUDE_IRQ == 1)
152     OsCpupIrqEnd(hwiIndex);
153 #endif
154 
155     OsHookCall(LOS_HOOK_TYPE_ISR_EXIT, hwiIndex);
156 
157     intSave = LOS_IntLock();
158     g_intCount--;
159     LOS_IntRestore(intSave);
160 }
161 
162 #if (LOSCFG_KERNEL_PRINTF != 0)
OsExcTypeInfo(const ExcInfo * excInfo)163 STATIC VOID OsExcTypeInfo(const ExcInfo *excInfo)
164 {
165     CHAR *phaseStr[] = {"exc in init", "exc in task", "exc in hwi"};
166 
167     PRINTK("Type      = %d\n", excInfo->type);
168     PRINTK("ThrdPid   = %d\n", excInfo->thrdPid);
169     PRINTK("Phase     = %s\n", phaseStr[excInfo->phase]);
170     PRINTK("FaultAddr = 0x%x\n", excInfo->faultAddr);
171 }
172 
OsExcCurTaskInfo(const ExcInfo * excInfo)173 STATIC VOID OsExcCurTaskInfo(const ExcInfo *excInfo)
174 {
175     PRINTK("Current task info:\n");
176     if (excInfo->phase == OS_EXC_IN_TASK) {
177         LosTaskCB *taskCB = OS_TCB_FROM_TID(LOS_CurTaskIDGet());
178         PRINTK("Task name = %s\n", taskCB->taskName);
179         PRINTK("Task ID   = %d\n", taskCB->taskID);
180         PRINTK("Task SP   = 0x%x\n", taskCB->stackPointer);
181         PRINTK("Task ST   = 0x%x\n", taskCB->topOfStack);
182         PRINTK("Task SS   = 0x%x\n", taskCB->stackSize);
183     } else if (excInfo->phase == OS_EXC_IN_HWI) {
184         PRINTK("Exception occur in interrupt phase!\n");
185     } else {
186         PRINTK("Exception occur in system init phase!\n");
187     }
188 }
189 
OsExcRegInfo(const ExcInfo * excInfo)190 STATIC VOID OsExcRegInfo(const ExcInfo *excInfo)
191 {
192     PRINTK("Exception reg dump:\n");
193     PRINTK("PC        = 0x%x\n", excInfo->context->pc);
194     PRINTK("LR        = 0x%x\n", excInfo->context->lr);
195     PRINTK("R0        = 0x%x\n", excInfo->context->r0);
196     PRINTK("R1        = 0x%x\n", excInfo->context->r1);
197     PRINTK("R2        = 0x%x\n", excInfo->context->r2);
198     PRINTK("R3        = 0x%x\n", excInfo->context->r3);
199     PRINTK("R4        = 0x%x\n", excInfo->context->r4);
200     PRINTK("R5        = 0x%x\n", excInfo->context->r5);
201     PRINTK("R6        = 0x%x\n", excInfo->context->r6);
202     PRINTK("R7        = 0x%x\n", excInfo->context->r7);
203     PRINTK("R8        = 0x%x\n", excInfo->context->r8);
204     PRINTK("R9        = 0x%x\n", excInfo->context->r9);
205     PRINTK("R10       = 0x%x\n", excInfo->context->r10);
206     PRINTK("R11       = 0x%x\n", excInfo->context->r11);
207     PRINTK("R12       = 0x%x\n", excInfo->context->r12);
208     PRINTK("xPSR      = 0x%x\n", excInfo->context->spsr);
209 }
210 
211 #if (LOSCFG_KERNEL_BACKTRACE == 1)
OsExcBackTraceInfo(const ExcInfo * excInfo)212 STATIC VOID OsExcBackTraceInfo(const ExcInfo *excInfo)
213 {
214     UINTPTR LR[LOSCFG_BACKTRACE_DEPTH] = {0};
215     UINT32 index;
216 
217     OsBackTraceHookCall(LR, LOSCFG_BACKTRACE_DEPTH, 0, excInfo->context->sp);
218 
219     PRINTK("----- backtrace start -----\n");
220     for (index = 0; index < LOSCFG_BACKTRACE_DEPTH; index++) {
221         if (LR[index] == 0) {
222             break;
223         }
224         PRINTK("backtrace %d -- lr = 0x%x\n", index, LR[index]);
225     }
226     PRINTK("----- backtrace end -----\n");
227 }
228 #endif
229 
OsExcMemPoolCheckInfo(VOID)230 STATIC VOID OsExcMemPoolCheckInfo(VOID)
231 {
232     PRINTK("\r\nmemory pools check:\n");
233 #if (LOSCFG_PLATFORM_EXC == 1)
234     MemInfoCB memExcInfo[OS_SYS_MEM_NUM];
235     UINT32 errCnt;
236     UINT32 i;
237 
238     (VOID)memset_s(memExcInfo, sizeof(memExcInfo), 0, sizeof(memExcInfo));
239 
240     errCnt = OsMemExcInfoGet(OS_SYS_MEM_NUM, memExcInfo);
241     if (errCnt < OS_SYS_MEM_NUM) {
242         errCnt += OsMemboxExcInfoGet(OS_SYS_MEM_NUM - errCnt, memExcInfo + errCnt);
243     }
244 
245     if (errCnt == 0) {
246         PRINTK("all memory pool check passed!\n");
247         return;
248     }
249 
250     for (i = 0; i < errCnt; i++) {
251         PRINTK("pool num    = %d\n", i);
252         PRINTK("pool type   = %d\n", memExcInfo[i].type);
253         PRINTK("pool addr   = 0x%x\n", memExcInfo[i].startAddr);
254         PRINTK("pool size   = 0x%x\n", memExcInfo[i].size);
255         PRINTK("pool free   = 0x%x\n", memExcInfo[i].free);
256         PRINTK("pool blkNum = %d\n", memExcInfo[i].blockSize);
257         PRINTK("pool error node addr  = 0x%x\n", memExcInfo[i].errorAddr);
258         PRINTK("pool error node len   = 0x%x\n", memExcInfo[i].errorLen);
259         PRINTK("pool error node owner = %d\n", memExcInfo[i].errorOwner);
260     }
261 #endif
262     UINT32 ret = LOS_MemIntegrityCheck(LOSCFG_SYS_HEAP_ADDR);
263     if (ret == LOS_OK) {
264         PRINTK("system heap memcheck over, all passed!\n");
265     }
266 
267     PRINTK("memory pool check end!\n");
268 }
269 #endif
270 
OsExcInfoDisplay(const ExcInfo * excInfo)271 STATIC VOID OsExcInfoDisplay(const ExcInfo *excInfo)
272 {
273 #if (LOSCFG_KERNEL_PRINTF != 0)
274     PRINTK("*************Exception Information**************\n");
275     OsExcTypeInfo(excInfo);
276     OsExcCurTaskInfo(excInfo);
277     OsExcRegInfo(excInfo);
278 #if (LOSCFG_KERNEL_BACKTRACE == 1)
279     OsExcBackTraceInfo(excInfo);
280 #endif
281     OsGetAllTskInfo();
282     OsExcMemPoolCheckInfo();
283 #endif
284 }
285 
HalExcHandleEntry(UINT32 excType,UINT32 faultAddr,UINT32 pid,EXC_CONTEXT_S * excBufAddr)286 LITE_OS_SEC_TEXT_INIT VOID HalExcHandleEntry(UINT32 excType, UINT32 faultAddr, UINT32 pid, EXC_CONTEXT_S *excBufAddr)
287 {
288     g_intCount++;
289     g_excInfo.nestCnt++;
290 
291     g_excInfo.type = excType;
292 
293     if ((excType == OS_EXCEPT_UNDEF_INSTR) || (excType == OS_EXCEPT_SWI)) {
294         if ((excBufAddr->spsr & OS_INSTR_SET_MASK) == 0) { /* Work status: ARM */
295             excBufAddr->pc -= OS_ARM_INSTR_LEN;
296         } else if ((excBufAddr->spsr & OS_INSTR_SET_MASK) == 0x20) { /* Work status: Thumb */
297             excBufAddr->pc -= OS_THUMB_INSTR_LEN;
298         }
299     }
300     g_excInfo.faultAddr = OS_EXC_IMPRECISE_ACCESS_ADDR;
301 
302     if (g_losTask.runTask != NULL) {
303         g_excInfo.phase = OS_EXC_IN_TASK;
304         g_excInfo.thrdPid = g_losTask.runTask->taskID;
305     } else {
306         g_excInfo.phase = OS_EXC_IN_INIT;
307         g_excInfo.thrdPid = OS_NULL_INT;
308     }
309     g_excInfo.context = excBufAddr;
310 
311     OsDoExcHook(EXC_INTERRUPT);
312     OsExcInfoDisplay(&g_excInfo);
313     ArchSysExit();
314 }
315 
316 /* ****************************************************************************
317  Function    : HalHwiInit
318  Description : initialization of the hardware interrupt
319  Input       : None
320  Output      : None
321  Return      : None
322  **************************************************************************** */
HalHwiInit(VOID)323 LITE_OS_SEC_TEXT_INIT VOID HalHwiInit(VOID)
324 {
325 #if (LOSCFG_USE_SYSTEM_DEFINED_INTERRUPT == 1)
326     UINT32 reg;
327     UINT32 val;
328     HWI_PROC_FUNC *hwiForm = (HWI_PROC_FUNC *)ArchGetHwiFrom();
329 
330     for (val = OS_SYS_VECTOR_CNT; val < OS_VECTOR_CNT; val++) {
331 #if (LOSCFG_PLATFORM_HWI_WITH_ARG == 1)
332         hwiForm[val].pfnHook = HalHwiDefaultHandler;
333         hwiForm[val].uwParam = 0;
334 #else
335         hwiForm[val] = (HWI_PROC_FUNC)HalHwiDefaultHandler;
336 #endif
337     }
338 
339     val = OS_INT_IRQ_ENABLE | OS_INT_FIQ_ENABLE;
340     READ_UINT32(reg, OS_INT_GLOBAL_ENABLE_ADDR);
341     reg |= val;
342     WRITE_UINT32(reg, OS_INT_GLOBAL_ENABLE_ADDR);
343 #endif
344     return;
345 }
346 
ArchIntLock(VOID)347 UINT32 ArchIntLock(VOID)
348 {
349     UINT32 ret;
350     UINT32 temp;
351 
352     __asm__ __volatile__("MRS %0, CPSR\n"
353                          "ORR %1, %0, #0xC0\n"
354                          "MSR CPSR_c, %1"
355                          : "=r"(ret), "=r"(temp)
356                          :
357                          : "memory");
358     return ret;
359 }
360 
ArchIntRestore(UINT32 intSave)361 VOID ArchIntRestore(UINT32 intSave)
362 {
363     __asm__ __volatile__("MSR CPSR_c, %0" : : "r"(intSave));
364 }
365 
ArchIntUnLock(VOID)366 UINT32 ArchIntUnLock(VOID)
367 {
368     UINT32 intSave;
369 
370     __asm__ __volatile__("MRS %0, CPSR\n"
371                          "BIC %0, %0, #0xC0\n"
372                          "MSR CPSR_c, %0"
373                          : "=r"(intSave)
374                          :
375                          : "memory");
376     return intSave;
377 }
378