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