From d73503d22bcb2bf79944abe3e4b1e6897ce982e3 Mon Sep 17 00:00:00 2001 From: wupeifeng Date: Thu, 26 Jun 2025 11:10:57 +0000 Subject: [PATCH] script: Add ARMv7-R exception handle MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit description: 参考LiteOs移植适配Armv7-r架构的异常处理 Signed-off-by: wupeifeng --- demos/d9_secure/src/start.S | 12 +- .../cpu/armv7-r/common/exc/CMakeLists.txt | 1 + src/arch/cpu/armv7-r/common/exc/exception.S | 112 +++++- src/arch/cpu/armv7-r/common/exc/prt_exc.c | 325 +++++++++++------- .../cpu/armv7-r/common/exc/prt_exc_init.c | 168 +++++++++ .../cpu/armv7-r/common/exc/prt_exc_internal.h | 4 + 6 files changed, 486 insertions(+), 136 deletions(-) create mode 100755 src/arch/cpu/armv7-r/common/exc/prt_exc_init.c diff --git a/demos/d9_secure/src/start.S b/demos/d9_secure/src/start.S index b0c71047..c54bdd75 100755 --- a/demos/d9_secure/src/start.S +++ b/demos/d9_secure/src/start.S @@ -18,13 +18,13 @@ _start: B arm_reset - B _osUnHandleed - B _osUnHandleed - B _osUnHandleed - B _osUnHandleed - B _osUnHandleed + B _osExceptUndefInstrHdl + B _osExceptSwiHdl + B _osExceptPrefetchAbortHdl + B _osExceptDataAbortHdl + B _osExceptAddrAbortHdl B OsHwiDispatcher - B _osUnHandleed + B _osExceptFiqHdl FUNCTION(arm_reset) OsStackBssInit: diff --git a/src/arch/cpu/armv7-r/common/exc/CMakeLists.txt b/src/arch/cpu/armv7-r/common/exc/CMakeLists.txt index 905ff5df..9e3a7bd4 100755 --- a/src/arch/cpu/armv7-r/common/exc/CMakeLists.txt +++ b/src/arch/cpu/armv7-r/common/exc/CMakeLists.txt @@ -1,2 +1,3 @@ add_library_ex(prt_exc.c) +add_library_ex(prt_exc_init.c) add_library_ex(exception.S) \ No newline at end of file diff --git a/src/arch/cpu/armv7-r/common/exc/exception.S b/src/arch/cpu/armv7-r/common/exc/exception.S index aae22637..66891f10 100755 --- a/src/arch/cpu/armv7-r/common/exc/exception.S +++ b/src/arch/cpu/armv7-r/common/exc/exception.S @@ -28,16 +28,32 @@ #include "prt_exc_internal.h" + .extern g_intCount + .extern g_curNestCount .extern OsExcHandleEntry - .global _osUnHandleed + .global _osExceptFiqHdl + .global _osExceptAddrAbortHdl + .global _osExceptDataAbortHdl + .global _osExceptPrefetchAbortHdl + .global _osExceptSwiHdl + .global _osExceptUndefInstrHdl + .global OsGdbHandleException .fpu vfpv4 +@ Description: Undefined instruction exception handler +_osExceptUndefInstrHdl: + @ LR offset to return from this exception: 0. + STMFD SP, {R0-R7} @ Push working registers, but don`t change SP. + + MOV R0, #OS_EXCEPT_UNDEF_INSTR @ Set exception ID to OS_EXCEPT_UNDEF_INSTR. + + B _osExceptDispatch @ Branch to global exception handler. @ Description: Software interrupt exception handler -_osUnHandleed: +_osExceptSwiHdl: STMFD SP!, {LR} @ Store PC STMFD SP!, {LR} STMFD SP!, {SP} @@ -46,9 +62,97 @@ _osUnHandleed: MRS R1, SPSR @ Save exception`s CPSR. STMFD SP!, {R1} @ Push task`s CPSR (i.e. exception SPSR). - MOV R0, #0 @ Set exception ID to OS_EXCEPT_SWI. + MOV R0, #OS_EXCEPT_SWI @ Set exception ID to OS_EXCEPT_SWI. MOV R5, SP - B OsExcHandleEntry @ Branch to global exception handler. + B _osExceptionSwi @ Branch to global exception handler. + +@ Description: Prefectch abort exception handler +_osExceptPrefetchAbortHdl: + SUB LR, LR, #4 @ LR offset to return from this exception: -4. + STMFD SP, {R0-R7} @ Push working registers, but don`t change SP. + + MOV R0, #OS_EXCEPT_PREFETCH_ABORT @ Set exception ID to OS_EXCEPT_PREFETCH_ABORT. + + B _osExceptDispatch @ Branch to global exception handler. + + +@ Description: Data abort exception handler +_osExceptDataAbortHdl: + SUB LR, LR, #8 @ LR offset to return from this exception: -8. + STMFD SP, {R0-R7} @ Push working registers, but don`t change SP. + + MOV R0, #OS_EXCEPT_DATA_ABORT @ Set exception ID to OS_EXCEPT_DATA_ABORT. + + B _osExceptDispatch @ Branch to global exception handler. + +@ Description: Address abort exception handler +_osExceptAddrAbortHdl: + SUB LR, LR, #8 @ LR offset to return from this exception: -8. + STMFD SP, {R0-R7} @ Push working registers, but don`t change SP. + + MOV R0, #OS_EXCEPT_ADDR_ABORT @ Set exception ID to OS_EXCEPT_ADDR_ABORT. + + B _osExceptDispatch @ Branch to global exception handler. + +@ Description: Fast interrupt request exception handler +_osExceptFiqHdl: + SUB LR, LR, #4 @ LR offset to return from this exception: -4. + STMFD SP, {R0-R7} @ Push working registers. + + MOV R0, #OS_EXCEPT_FIQ @ Set exception ID to OS_EXCEPT_FIQ. + + B _osExceptDispatch @ Branch to global exception handler. + +@ Description: Exception handler +@ Parameter : R0 Exception Type +@ Regs Hold : R3 Exception`s CPSR +_osExceptDispatch: + MRS R1, SPSR @ Save CPSR before exception. + MOV R2, LR @ Save PC before exception. + SUB R3, SP, #(8 * 4) @ Save the start address of working registers. + + MSR CPSR_c, #(PSR_INT_DISABLE | PSR_SVC_MODE) @ Switch to SVC mode, and disable all interrupts + MOV R5, SP + + EXC_SP_SET __exc_stack_top, OS_ARCH_SYS_STACK_SIZE, R6, R7 + + STMFD SP!, {R2} @ Push Exception PC + STMFD SP!, {LR} + STMFD SP!, {R5} @ Push original SP, + STMFD SP!, {R8-R12} @ Push original R12-R8, + LDMFD R3!, {R4-R11} @ Move original R7-R0 from exception stack to original stack. + STMFD SP!, {R4-R11} + STMFD SP!, {R1} @ Push task`s CPSR (i.e. exception SPSR). + +_osExceptionSwi: + MOV R1, SP + + LDR R2, =g_curNestCount @ if(g_curNestCount > 0) dump to _osExceptionGetSP + LDR R4, [R2] + + CMP R4, #0 + BNE _osExceptionGetSP + + MRC P15, 0, R4, C0, C0, 5 + AND R4, R4, #MPIDR_CPUID_MASK @ Get Current cpu id + LSL R2, R4, #2 + LDR R3, =g_intCount @ Judge the exception is occur in task stack or system stack + ADD R3, R3, R2 + LDR R2, [R3] + + CMP R2, #0 @ if (g_intCount[ArchCurrCpuid()] > 0) + BNE _osExceptionGetSP @ can not switch svc stack + + EXC_SP_SET __svc_stack_top, OS_ARCH_SVC_STACK_SIZE, R6, R7 @ Switch to unified exception stack. + + ADD R2, R2, #1 + STR R2, [R3] + +_osExceptionGetSP: + LDR R2, =OsExcHandleEntry @ OsExcHandleEntry(UINT32 excType, ExcRegInfo * excBufAddr) + + MOV LR, PC + BX R2 .end diff --git a/src/arch/cpu/armv7-r/common/exc/prt_exc.c b/src/arch/cpu/armv7-r/common/exc/prt_exc.c index d8b1a428..3d93190e 100755 --- a/src/arch/cpu/armv7-r/common/exc/prt_exc.c +++ b/src/arch/cpu/armv7-r/common/exc/prt_exc.c @@ -1,160 +1,233 @@ -/* - * Copyright (c) 2022-2022 Huawei Technologies Co., Ltd. All rights reserved. - * - * UniProton is licensed under Mulan PSL v2. - * You can use this software according to the terms and conditions of the Mulan PSL v2. - * You may obtain a copy of Mulan PSL v2 at: - * http://license.coscl.org.cn/MulanPSL2 - * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, - * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, - * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. - * See the Mulan PSL v2 for more details. - * Create: 2022-11-22 - * Description: 异常处理。 - */ +/* ---------------------------------------------------------------------------- + * Copyright (c) Huawei Technologies Co., Ltd. 2013-2020. All rights reserved. + * Description: ARMv7 Exc Implementation + * Author: Huawei LiteOS Team + * Create: 2013-01-01 + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior written + * permission. + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * --------------------------------------------------------------------------- */ + /* ---------------------------------------------------------------------------- + * Modifications Copyright (c) 2024, Greater Bay Area National Center of Technology Innovation + * Change Logs: 更改文件名,适配UniProton并删除多余函数 + * --------------------------------------------------------------------------- */ #include "prt_exc_internal.h" -OS_SEC_BSS ExcTaskInfoFunc g_excTaskInfoGet; +#define IS_ALIGNED(val, align) (((U32)(val) & ((U32)(align) - 1)) == 0) + +#define OS_MAX_BACKTRACE 15U +#define INSTR_SET_MASK 0x01000020U +#define THUMB_INSTR_LEN 2U +#define ARM_INSTR_LEN 4U +#define POINTER_SIZE 4U +#define STATIC + +#define GET_FS(fsr) (((fsr) & 0xFU) | (((fsr) & (1U << 10)) >> 6)) +#define GET_WNR(dfsr) ((dfsr) & (1U << 11)) + extern uintptr_t __exc_stack_top; +// 异常时获取当前任务的信息 -/* - * 描述: EXC钩子处理函数 - */ -INIT_SEC_L4_TEXT void OsExcHookHandle(void) -{ - struct ExcInfo *excInfo = OS_EXC_INFO_ADDR; - if (g_excModInfo.excepHook != NULL) { - (void)g_excModInfo.excepHook(excInfo); // 目前不支持异常返回 - } - PRT_SysReboot(); -} -/* - * 描述: FIQ异常处理 - */ -OS_SEC_ALW_INLINE INLINE void OsExcFiqProc(U32 excType) +STATIC INLINE U32 OsGetDFSR(void) { - struct ExcInfo excInfo = {0}; - excInfo.excCause = excType; - - if (g_excModInfo.excepHook != NULL) { - (void)g_excModInfo.excepHook(&excInfo); - } + U32 regDFSR; + __asm__ __volatile__("mrc p15, 0, %0, c5, c0, 0" + : "=r"(regDFSR)); + return regDFSR; +} - PRT_SysReboot(); +STATIC INLINE U32 OsGetIFSR(void) +{ + U32 regIFSR; + __asm__ __volatile__("mrc p15, 0, %0, c5, c0, 1" + : "=r"(regIFSR)); + return regIFSR; } -/* - * 描述: 获取异常前的线程信息 - */ -OS_SEC_ALW_INLINE INLINE void OsExcSetThreadInfo(struct ExcInfo *excInfo) +STATIC INLINE U32 OsGetDFAR(void) { - U32 threadId = INVALIDPID; - struct TskInfo taskInfo = {0}; + U32 regDFAR; + __asm__ __volatile__("mrc p15, 0, %0, c6, c0, 0" + : "=r"(regDFAR)); + return regDFAR; +} - if (g_excTaskInfoGet != NULL) { - g_excTaskInfoGet(&threadId, &taskInfo); - } +STATIC INLINE U32 OsGetIFAR(void) +{ + U32 regIFAR; + __asm__ __volatile__("mrc p15, 0, %0, c6, c0, 2" + : "=r"(regIFAR)); + return regIFAR; +} - /* 记录发生异常时的线程ID,发生在任务和软中断中,此项具有意义,其他线程中,此项无意义 */ - excInfo->threadId = INVALIDPID; - - /* 设置异常前的线程类型 */ - if (OS_INT_COUNT > 0) { - excInfo->threadType = EXC_IN_HWI; - } else if ((UNI_FLAG & OS_FLG_TICK_ACTIVE) != 0) { - excInfo->threadType = EXC_IN_TICK; - } else if ((UNI_FLAG & OS_FLG_SYS_ACTIVE) != 0) { - excInfo->threadType = EXC_IN_SYS; - } else if ((UNI_FLAG & OS_FLG_BGD_ACTIVE) != 0) { - excInfo->threadType = EXC_IN_TASK; - if (OsTskMaxNumGet() > 0) { /* 任务存在时 */ - excInfo->threadId = threadId; +void OsCallStackInfo(void) +{ + U32 count = 0; + struct TagTskCb *runTask = RUNNING_TASK;//LosTaskCB *runTask = OsCurrTaskGet(); + U32 stackBottom = RUNNING_TASK->topOfStack + RUNNING_TASK->stackSize; + U32 *stackPointer = (U32 *)stackBottom; + + printf("runTask->stackPointer = 0x%x\n", stackPointer); + printf("runTask->topOfStack = 0x%x\n", runTask->topOfStack); + printf("text_start:0x%x,text_end:0x%x\n", &__text_start, &__text_end); + + while ((stackPointer > (U32 *)runTask->topOfStack) && (count < OS_MAX_BACKTRACE)) { + if ((*stackPointer > (U32)(&__text_start)) && + (*stackPointer < (U32)(&__text_end)) && + IS_ALIGNED((*stackPointer), POINTER_SIZE)) { + if ((*(stackPointer - 1) > (U32)runTask->topOfStack) && + (*(stackPointer - 1) < stackBottom) && + IS_ALIGNED((*(stackPointer - 1)), POINTER_SIZE)) { + count++; + printf("traceback %u -- lr = 0x%x\n", count, *stackPointer); + } } - } else { /* OS_FLG_BGD_ACTIVE没有置位,代表此时还在系统进程中,没有进入业务线程 */ - excInfo->threadType = EXC_IN_SYS_BOOT; - } - - /* 任务栈栈底 */ - if (excInfo->threadType == EXC_IN_TASK) { - excInfo->stackBottom = TRUNCATE((taskInfo.topOfStack + taskInfo.stackSize), OS_EXC_STACK_ALIGN); + stackPointer--; } + printf("\n"); } -/* - * 描述: 记录异常信息 - */ -INIT_SEC_L4_TEXT void OsExcSaveInfo(struct ExcInfo *excInfo, struct ExcRegInfo *regs) -{ - U64 cycle; - - /* 记录异常嵌套计数 */ - excInfo->nestCnt = CUR_NEST_COUNT; - /* 记录os版本号 */ - if (strncpy_s(excInfo->osVer, sizeof(excInfo->osVer), PRT_SysGetOsVersion(), (sizeof(excInfo->osVer) - 1)) != EOK) { - OS_GOTO_SYS_ERROR(); +STATIC S32 OsDecodeFS(U32 bitsFS) +{ + switch (bitsFS) { + case 0x05: /* 0b00101 */ + case 0x07: /* 0b00111 */ + printf("Translation fault, %s\n", (bitsFS & 0x2) ? "page" : "section"); + break; + case 0x09: /* 0b01001 */ + case 0x0b: /* 0b01011 */ + printf("Domain fault, %s\n", (bitsFS & 0x2) ? "page" : "section"); + break; + case 0x0d: /* 0b01101 */ + case 0x0f: /* 0b01111 */ + printf("Permission fault, %s\n", (bitsFS & 0x2) ? "page" : "section"); + break; + default: + printf("Unknown fault! FS:0x%x. " + "Check IFSR and DFSR in ARM Architecture Reference Manual.\n", + bitsFS); + break; } - excInfo->osVer[OS_SYS_OS_VER_LEN - 1] = '\0'; - - /* 记录CPU ID */ - excInfo->coreId = 0x0U; - - /* 设置字节序 */ - /* 魔术字 */ - excInfo->byteOrder = OS_BYTE_ORDER; - - /* 记录CPU类型 */ - excInfo->cpuType = OsGetCpuType(); - - /* 记录CPU TICK值 */ - cycle = OsCurCycleGet64(); - excInfo->cpuTick.cntHi = OS_GET_64BIT_HIGH_32BIT(cycle); - excInfo->cpuTick.cntLo = (U32)cycle; - /* 记录寄存器信息 */ - excInfo->regInfo = *regs; - - /* 记录异常前栈指针 */ - excInfo->sp = regs->SP; + return OS_OK; +} - /* 记录异常前栈底,系统栈栈底 */ - excInfo->stackBottom = (uintptr_t)&__exc_stack_top; +STATIC S32 OsDecodeInstructionFSR(U32 regIFSR) +{ + S32 ret; + U32 bitsFS = GET_FS(regIFSR); /* FS bits[4]+[3:0] */ - OsExcSetThreadInfo(excInfo); + ret = OsDecodeFS(bitsFS); + return ret; } -/* - * 描述: EXC模块的处理分发函数 - */ -INIT_SEC_L4_TEXT void OsExcHandleEntry(U32 excType, struct ExcRegInfo *excRegs) +STATIC S32 OsDecodeDataFSR(U32 regDFSR) { - struct ExcInfo *excInfo = OS_EXC_INFO_ADDR; - - UNI_FLAG |= (OS_FLG_HWI_ACTIVE | OS_FLG_EXC_ACTIVE); - if (excType == OS_EXCEPT_FIQ) { - OsExcFiqProc(excType); - return; + S32 ret = 0; + U32 bitWnR = GET_WNR(regDFSR); /* WnR bit[11] */ + U32 bitsFS = GET_FS(regDFSR); /* FS bits[4]+[3:0] */ + + if (bitWnR) { + printf("Abort caused by a write instruction. "); + } else { + printf("Abort caused by a read instruction. "); } - /* 记录异常类型 */ - excInfo->excCause = excType; - excInfo->fatalErrNo = OsFatalErrClr(); + if (bitsFS == 0x01) { /* 0b00001 */ + printf("Alignment fault.\n"); + return ret; + } + ret = OsDecodeFS(bitsFS); + return ret; +} - CUR_NEST_COUNT++; +void OsExcType(U32 excType, struct ExcRegInfo *excRegs) +{ + /* undefinited exception handling or software interrupt */ + if ((excType == OS_EXCEPT_UNDEF_INSTR) || (excType == OS_EXCEPT_SWI)) { + if ((excRegs->regCPSR & INSTR_SET_MASK) == 0) { /* work status: ARM */ + excRegs->PC = excRegs->PC - ARM_INSTR_LEN; + } else if ((excRegs->regCPSR & INSTR_SET_MASK) == 0x20) { /* work status: Thumb */ + excRegs->PC = excRegs->PC - THUMB_INSTR_LEN; + } + } - /* 记录异常信息 */ - OsExcSaveInfo(excInfo, excRegs); + if (excType == OS_EXCEPT_PREFETCH_ABORT) { + printf("prefetch_abort fault fsr:0x%x, far:0x%0+8x\n", OsGetIFSR(), OsGetIFAR()); + (void)OsDecodeInstructionFSR(OsGetIFSR()); + } else if (excType == OS_EXCEPT_DATA_ABORT) { + printf("data_abort fsr:0x%x, far:0x%0+8x\n", OsGetDFSR(), OsGetDFAR()); + (void)OsDecodeDataFSR(OsGetDFSR()); + } +} - /* 回调异常钩子函数 */ - OsExcHookHandle(); +STATIC const char *g_excTypeString[] = { + "reset", + "undefined instruction", + "software interrupt", + "prefetch abort", + "data abort", + "fiq", + "address abort", + "irq" +}; + +void OsExcSysInfo(U32 excType, const struct ExcRegInfo *excRegs) +{ + struct TagTskCb *runTask = RUNNING_TASK; + + printf("excType:%s\n", g_excTypeString[excType]); +#if (defined(OS_OPTION_TASK_INFO)) + printf("taskName = %s\n", runTask->name); +#endif + printf("taskId = %u\n", runTask->taskPid); + printf("task topStack = 0x%x\n", runTask->topOfStack); + printf("task stackSize = 0x%x\n", runTask->stackSize); + printf("excRegs pc = 0x%x\n", excRegs->PC); + printf("excRegs lr = 0x%x\n", excRegs->LR); + printf("excRegs sp = 0x%x\n", excRegs->SP); + printf("excRegs fp = 0x%x\n", excRegs->R11); } -/* - * 描述: EXC模块的初始化 - */ -OS_SEC_L4_TEXT U32 OsExcConfigInit(void) +void OsExcRegsInfo(struct ExcRegInfo *excBufAddr) { - return OS_OK; + /* + * Split register information into two parts: + * Ensure printing does not rely on memory modules. + */ + printf("R0 = 0x%x\n", excBufAddr->R0); + printf("R1 = 0x%x\n", excBufAddr->R1); + printf("R2 = 0x%x\n", excBufAddr->R2); + printf("R3 = 0x%x\n", excBufAddr->R3); + printf("R4 = 0x%x\n", excBufAddr->R4); + printf("R5 = 0x%x\n", excBufAddr->R5); + printf("R6 = 0x%x\n", excBufAddr->R6); + printf("R7 = 0x%x\n", excBufAddr->R7); + printf("R8 = 0x%x\n", excBufAddr->R8); + printf("R9 = 0x%x\n", excBufAddr->R9); + printf("R10 = 0x%x\n", excBufAddr->R10); + printf("R11 = 0x%x\n", excBufAddr->R11); + printf("R12 = 0x%x\n", excBufAddr->R12); + printf("CPSR = 0x%x\n", excBufAddr->regCPSR); } diff --git a/src/arch/cpu/armv7-r/common/exc/prt_exc_init.c b/src/arch/cpu/armv7-r/common/exc/prt_exc_init.c new file mode 100755 index 00000000..155ff054 --- /dev/null +++ b/src/arch/cpu/armv7-r/common/exc/prt_exc_init.c @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2022-2022 Huawei Technologies Co., Ltd. All rights reserved. + * + * UniProton is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * Create: 2022-11-22 + * Description: 异常处理(初始化相关)。 + */ + +#include "prt_exc_internal.h" + +OS_SEC_BSS ExcTaskInfoFunc g_excTaskInfoGet; +extern uintptr_t __exc_stack_top; + +/* + * 描述: EXC钩子处理函数 + */ +INIT_SEC_L4_TEXT void OsExcHookHandle(void) +{ + struct ExcInfo *excInfo = OS_EXC_INFO_ADDR; + + if (g_excModInfo.excepHook != NULL) { + (void)g_excModInfo.excepHook(excInfo); // 目前不支持异常返回 + } + + PRT_SysReboot(); +} +/* + * 描述: FIQ异常处理 + */ +OS_SEC_ALW_INLINE INLINE void OsExcFiqProc(U32 excType) +{ + struct ExcInfo excInfo = {0}; + excInfo.excCause = excType; + + if (g_excModInfo.excepHook != NULL) { + (void)g_excModInfo.excepHook(&excInfo); + } + + PRT_SysReboot(); +} + +/* + * 描述: 获取异常前的线程信息 + */ +OS_SEC_ALW_INLINE INLINE void OsExcSetThreadInfo(struct ExcInfo *excInfo) +{ + U32 threadId = INVALIDPID; + struct TskInfo taskInfo = {0}; + + if (g_excTaskInfoGet != NULL) { + g_excTaskInfoGet(&threadId, &taskInfo); + } + + /* 记录发生异常时的线程ID,发生在任务和软中断中,此项具有意义,其他线程中,此项无意义 */ + excInfo->threadId = INVALIDPID; + + /* 设置异常前的线程类型 */ + if (OS_INT_COUNT > 0) { + excInfo->threadType = EXC_IN_HWI; + } else if ((UNI_FLAG & OS_FLG_TICK_ACTIVE) != 0) { + excInfo->threadType = EXC_IN_TICK; + } else if ((UNI_FLAG & OS_FLG_SYS_ACTIVE) != 0) { + excInfo->threadType = EXC_IN_SYS; + } else if ((UNI_FLAG & OS_FLG_BGD_ACTIVE) != 0) { + excInfo->threadType = EXC_IN_TASK; + if (OsTskMaxNumGet() > 0) { /* 任务存在时 */ + excInfo->threadId = threadId; + } + } else { /* OS_FLG_BGD_ACTIVE没有置位,代表此时还在系统进程中,没有进入业务线程 */ + excInfo->threadType = EXC_IN_SYS_BOOT; + } + + /* 任务栈栈底 */ + if (excInfo->threadType == EXC_IN_TASK) { + excInfo->stackBottom = TRUNCATE((taskInfo.topOfStack + taskInfo.stackSize), OS_EXC_STACK_ALIGN); + } +} +/* + * 描述: 记录异常信息 + */ +INIT_SEC_L4_TEXT void OsExcSaveInfo(struct ExcInfo *excInfo, struct ExcRegInfo *regs) +{ + U64 cycle; + + /* 记录异常嵌套计数 */ + excInfo->nestCnt = CUR_NEST_COUNT; + + /* 记录os版本号 */ + if (strncpy_s(excInfo->osVer, sizeof(excInfo->osVer), PRT_SysGetOsVersion(), (sizeof(excInfo->osVer) - 1)) != EOK) { + OS_GOTO_SYS_ERROR(); + } + excInfo->osVer[OS_SYS_OS_VER_LEN - 1] = '\0'; + + /* 记录CPU ID */ + excInfo->coreId = 0x0U; + + /* 设置字节序 */ + /* 魔术字 */ + excInfo->byteOrder = OS_BYTE_ORDER; + + /* 记录CPU类型 */ + excInfo->cpuType = OsGetCpuType(); + + /* 记录CPU TICK值 */ + cycle = OsCurCycleGet64(); + excInfo->cpuTick.cntHi = OS_GET_64BIT_HIGH_32BIT(cycle); + excInfo->cpuTick.cntLo = (U32)cycle; + + /* 记录寄存器信息 */ + excInfo->regInfo = *regs; + + /* 记录异常前栈指针 */ + excInfo->sp = regs->SP; + + /* 记录异常前栈底,系统栈栈底 */ + excInfo->stackBottom = (uintptr_t)&__exc_stack_top; + + OsExcSetThreadInfo(excInfo); +} + +/* + * 描述: EXC模块的处理分发函数 + */ +INIT_SEC_L4_TEXT void OsExcHandleEntry(U32 excType, struct ExcRegInfo *excRegs) +{ + struct ExcInfo *excInfo = OS_EXC_INFO_ADDR; + + UNI_FLAG |= (OS_FLG_HWI_ACTIVE | OS_FLG_EXC_ACTIVE); + if (excType == OS_EXCEPT_FIQ) { + OsExcFiqProc(excType); + return; + } + + /* 记录异常类型 */ + excInfo->excCause = excType; + excInfo->fatalErrNo = OsFatalErrClr(); + + CUR_NEST_COUNT++; + + if (g_curNestCount == 1) { + OsExcType(excType, excRegs); + OsExcSysInfo(excType, excRegs); + OsExcRegsInfo(excRegs); + } else { + OsCallStackInfo(); + } + + /* 记录异常信息 */ + OsExcSaveInfo(excInfo, excRegs); + + /* 回调异常钩子函数 */ + OsExcHookHandle(); +} + +/* + * 描述: EXC模块的初始化 + */ +OS_SEC_L4_TEXT U32 OsExcConfigInit(void) +{ + return OS_OK; +} diff --git a/src/arch/cpu/armv7-r/common/exc/prt_exc_internal.h b/src/arch/cpu/armv7-r/common/exc/prt_exc_internal.h index 6653d9b7..a9da0281 100755 --- a/src/arch/cpu/armv7-r/common/exc/prt_exc_internal.h +++ b/src/arch/cpu/armv7-r/common/exc/prt_exc_internal.h @@ -66,6 +66,10 @@ extern char __heap_start; extern char __init_array_start__; extern char __init_array_end__; +void OsExcType(U32 excType, struct ExcRegInfo *excRegs); +void OsExcSysInfo(U32 excType, const struct ExcRegInfo *excRegs); +void OsExcRegsInfo(struct ExcRegInfo *excBufAddr); +void OsCallStackInfo(void); #else #include #endif -- Gitee