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