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 */ 48UINT32 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 */ 60VOID 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 */ 69UINT32 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 */ 82STATIC 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 */ 95STATIC UINT32 HwiPending(HWI_HANDLE_T hwiNum) 96{ 97 __asm__ __volatile__("wsr %0, intset; rsync" : : "a"(0x1U << hwiNum)); 98 return LOS_OK; 99} 100 101STATIC 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 111STATIC 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 **************************************************************************** */ 128STATIC 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 */ 146STATIC UINT32 HwiClear(HWI_HANDLE_T hwiNum) 147{ 148 __asm__ __volatile__("wsr %0, intclear; rsync" : : "a"(0x1U << hwiNum)); 149 150 return LOS_OK; 151} 152 153STATIC UINT32 HwiCreate(HWI_HANDLE_T hwiNum, HWI_PRIOR_T hwiPrio) 154{ 155 (VOID)hwiPrio; 156 HwiUnmask(hwiNum); 157 return LOS_OK; 158} 159 160STATIC HwiControllerOps g_archHwiOps = { 161 .triggerIrq = HwiPending, 162 .enableIrq = HwiUnmask, 163 .disableIrq = HwiMask, 164 .getCurIrqNum = HwiNumGet, 165 .clearIrq = HwiClear, 166 .createIrq = HwiCreate, 167}; 168 169HwiControllerOps *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 **************************************************************************** */ 181VOID 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 217ExcInfo g_excInfo = {0}; 218 219#if (LOSCFG_KERNEL_PRINTF != 0) 220 221STATIC 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 231STATIC 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 248STATIC 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) 266STATIC 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 284STATIC 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 325STATIC 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 340VOID 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 */ 367WEAK UINT32 __stack_chk_guard = 0xd00a0dff; 368 369WEAK 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 **************************************************************************** */ 383VOID 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