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