static VOID _KernelSecondaryCoreStartup (PLW_CLASS_CPU pcpuCur) { PLW_CLASS_TCB ptcbOrg; KN_SMP_MB(); while (KN_PRIMARY_IS_GO() == LW_FALSE) { /* 等待主核运行 */ LW_SPINLOCK_DELAY(); /* 短延迟并释放总线 */ } LW_SPIN_KERN_LOCK_IGNIRQ(); LW_TCB_GET_CUR(ptcbOrg); _CpuActive(pcpuCur); /* CPU 激活 */ LW_SPIN_KERN_UNLOCK_SCHED(ptcbOrg); pcpuCur->CPU_iKernelCounter = 0; /* 允许调度 */ KN_SMP_MB(); _DebugHandle(__LOGMESSAGE_LEVEL, "secondary cpu multi-task start...\r\n"); #if LW_CFG_CPU_FPU_EN > 0 _ThreadFpuSwith(LW_FALSE); /* 初始化将要运行任务 FPU 环境 */ #endif errno = ERROR_NONE; /* 清除错误 */ archTaskCtxStart(pcpuCur); /* 当前 CPU 进入任务状态 */ }
/********************************************************************************************************* ** 函数名称: _KernelPrimaryCoreStartup ** 功能描述: 系统的主核 (负责初始化的核) 进入多任务状态, 进入多任务状态后, 所有核均对等不分主从 ** 输 入 : pcpuCur 当前 CPU ** 输 出 : ** 全局变量: ** 调用模块: *********************************************************************************************************/ static VOID _KernelPrimaryCoreStartup (PLW_CLASS_CPU pcpuCur) { PLW_CLASS_TCB ptcbOrg; LW_SPIN_KERN_LOCK_IGNIRQ(); LW_TCB_GET_CUR(ptcbOrg); _CpuActive(pcpuCur); /* CPU 激活 */ LW_SPIN_KERN_UNLOCK_SCHED(ptcbOrg); #if LW_CFG_SMP_EN > 0 KN_SMP_MB(); /* 内存屏障, 确保之前操作已处理*/ KN_PRIMARY_GO(); /* 通知从核可以进入多任务模式 */ LW_SPINLOCK_NOTIFY(); #endif /* LW_CFG_SMP_EN */ pcpuCur->CPU_iKernelCounter = 0; /* 允许调度 */ KN_SMP_MB(); _DebugHandle(__LOGMESSAGE_LEVEL, "primary cpu multi-task start...\r\n"); #if LW_CFG_CPU_FPU_EN > 0 _ThreadFpuSwith(LW_FALSE); /* 初始化将要运行任务 FPU 环境 */ #endif errno = ERROR_NONE; /* 清除错误 */ archTaskCtxStart(pcpuCur); /* 当前 CPU 进入任务状态 */ }
/********************************************************************************************************* ** 函数名称: archDataStorageExceptionHandle ** 功能描述: 数据存储异常处理 ** 输 入 : NONE ** 输 出 : NONE ** 全局变量: ** 调用模块: ** 注 意 : 此函数退出时必须为中断关闭状态. *********************************************************************************************************/ VOID archDataStorageExceptionHandle (addr_t ulRetAddr) { PLW_CLASS_TCB ptcbCur; addr_t ulAbortAddr; LW_VMM_ABORT abtInfo; ulAbortAddr = ppcGetDAR(); abtInfo.VMABT_uiType = LW_VMM_ABORT_TYPE_TERMINAL; LW_TCB_GET_CUR(ptcbCur); #if LW_CFG_VMM_EN > 0 UINT32 uiDSISR = ppcMmuGetDSISR(); /* * See << programming_environment_manual >> Figure 7-16 */ if (uiDSISR & (0x1 << (31 - 1))) { /* * Page fault (no PTE found) */ abtInfo.VMABT_uiType = ppcMmuPteMissHandle(ulAbortAddr); abtInfo.VMABT_uiMethod = LW_VMM_ABORT_METHOD_READ; } else if (uiDSISR & (0x1 << (31 - 4))) { /* * Page protection violation */ if (uiDSISR & (0x1 << (31 - 6))) { /* * If the access is a store */ abtInfo.VMABT_uiType = LW_VMM_ABORT_TYPE_PERM; abtInfo.VMABT_uiMethod = LW_VMM_ABORT_METHOD_WRITE; } else { /* * 不允许读 */ abtInfo.VMABT_uiType = LW_VMM_ABORT_TYPE_PERM; abtInfo.VMABT_uiMethod = LW_VMM_ABORT_METHOD_READ; } } else { /* * dcbt/dcbtst Instruction */ abtInfo.VMABT_uiType = LW_VMM_ABORT_TYPE_TERMINAL; } #endif if (abtInfo.VMABT_uiType) { API_VmmAbortIsr(ulRetAddr, ulAbortAddr, &abtInfo, ptcbCur); } }
/********************************************************************************************************* ** 函数名称: archTraceHandle ** 功能描述: Trace 处理 ** 输 入 : NONE ** 输 出 : NONE ** 全局变量: ** 调用模块: ** 注 意 : 此函数退出时必须为中断关闭状态. *********************************************************************************************************/ VOID archTraceHandle (addr_t ulRetAddr) { PLW_CLASS_TCB ptcbCur; LW_VMM_ABORT abtInfo; LW_TCB_GET_CUR(ptcbCur); abtInfo.VMABT_uiType = LW_VMM_ABORT_TYPE_TERMINAL; API_VmmAbortIsr(ulRetAddr, ulRetAddr, &abtInfo, ptcbCur); }
/********************************************************************************************************* ** 函数名称: archSystemCallHandle ** 功能描述: 系统调用处理 ** 输 入 : NONE ** 输 出 : NONE ** 全局变量: ** 调用模块: ** 注 意 : 此函数退出时必须为中断关闭状态. *********************************************************************************************************/ VOID archSystemCallHandle (addr_t ulRetAddr) { PLW_CLASS_TCB ptcbCur; LW_VMM_ABORT abtInfo; LW_TCB_GET_CUR(ptcbCur); abtInfo.VMABT_uiType = LW_VMM_ABORT_TYPE_SYS; API_VmmAbortIsr(ulRetAddr, ulRetAddr, &abtInfo, ptcbCur); }
/********************************************************************************************************* ** 函数名称: archInstructionStorageExceptionHandle ** 功能描述: 指令访问异常处理 ** 输 入 : NONE ** 输 出 : NONE ** 全局变量: ** 调用模块: ** 注 意 : 此函数退出时必须为中断关闭状态. *********************************************************************************************************/ VOID archInstructionStorageExceptionHandle (addr_t ulRetAddr) { PLW_CLASS_TCB ptcbCur; addr_t ulAbortAddr; LW_VMM_ABORT abtInfo; ulAbortAddr = ppcGetDAR(); abtInfo.VMABT_uiType = LW_VMM_ABORT_TYPE_TERMINAL; LW_TCB_GET_CUR(ptcbCur); #if LW_CFG_VMM_EN > 0 /* * See << programming_environment_manual >> Figure 7-16 */ UINT32 uiSRR1 = ppcMmuGetSRR1(); if (uiSRR1 & (0x1 << (31 - 1))) { /* * Page fault (no PTE found) */ abtInfo.VMABT_uiType = ppcMmuPteMissHandle(ulAbortAddr); abtInfo.VMABT_uiMethod = LW_VMM_ABORT_METHOD_READ; } else if (uiSRR1 & (0x1 << (31 - 4))) { /* * Page protection violation * 不允许预取 */ abtInfo.VMABT_uiType = LW_VMM_ABORT_TYPE_PERM; abtInfo.VMABT_uiMethod = LW_VMM_ABORT_METHOD_READ; } else if (uiSRR1 & (0x1 << (31 - 3))) { /* * If the segment is designated as no-execute */ abtInfo.VMABT_uiType = LW_VMM_ABORT_TYPE_PERM; abtInfo.VMABT_uiMethod = LW_VMM_ABORT_METHOD_EXEC; } else { /* * dcbt/dcbtst Instruction */ abtInfo.VMABT_uiType = LW_VMM_ABORT_TYPE_TERMINAL; } #endif if (abtInfo.VMABT_uiType) { API_VmmAbortIsr(ulRetAddr, ulAbortAddr, &abtInfo, ptcbCur); } }
/********************************************************************************************************* ** 函数名称: archAlignmentExceptionHandle ** 功能描述: 非对齐异常处理 ** 输 入 : NONE ** 输 出 : NONE ** 全局变量: ** 调用模块: ** 注 意 : 此函数退出时必须为中断关闭状态. *********************************************************************************************************/ VOID archAlignmentExceptionHandle (addr_t ulRetAddr) { PLW_CLASS_TCB ptcbCur; addr_t ulAbortAddr; LW_VMM_ABORT abtInfo; ulAbortAddr = ppcGetDAR(); abtInfo.VMABT_uiType = LW_VMM_ABORT_TYPE_BUS; LW_TCB_GET_CUR(ptcbCur); API_VmmAbortIsr(ulRetAddr, ulAbortAddr, &abtInfo, ptcbCur); }
/********************************************************************************************************* ** 函数名称: archFpuUnavailableExceptionHandle ** 功能描述: FPU 不可用异常处理 ** 输 入 : NONE ** 输 出 : NONE ** 全局变量: ** 调用模块: ** 注 意 : 此函数退出时必须为中断关闭状态. *********************************************************************************************************/ VOID archFpuUnavailableExceptionHandle (addr_t ulRetAddr) { PLW_CLASS_TCB ptcbCur; LW_VMM_ABORT abtInfo; LW_TCB_GET_CUR(ptcbCur); #if LW_CFG_CPU_FPU_EN > 0 if (archFpuUndHandle(ptcbCur) == ERROR_NONE) { /* 进行 FPU 指令探测 */ return; } #endif /* LW_CFG_CPU_FPU_EN > 0 */ abtInfo.VMABT_uiType = LW_VMM_ABORT_TYPE_FPE; API_VmmAbortIsr(ulRetAddr, ulRetAddr, &abtInfo, ptcbCur); }
/********************************************************************************************************* ** 函数名称: archProgramExceptionHandle ** 功能描述: 程序异常处理 ** 输 入 : NONE ** 输 出 : NONE ** 全局变量: ** 调用模块: ** 注 意 : 此函数退出时必须为中断关闭状态. *********************************************************************************************************/ VOID archProgramExceptionHandle (addr_t ulRetAddr) { PLW_CLASS_TCB ptcbCur; LW_VMM_ABORT abtInfo; #if LW_CFG_GDB_EN > 0 UINT uiBpType = archDbgTrapType(ulRetAddr, (PVOID)LW_NULL); /* 断点指令探测 */ if (uiBpType) { if (API_DtraceBreakTrap(ulRetAddr, uiBpType) == ERROR_NONE) { /* 进入调试接口断点处理 */ return; } } #endif /* LW_CFG_GDB_EN > 0 */ LW_TCB_GET_CUR(ptcbCur); abtInfo.VMABT_uiType = LW_VMM_ABORT_TYPE_UNDEF; abtInfo.VMABT_uiMethod = LW_VMM_ABORT_METHOD_EXEC; API_VmmAbortIsr(ulRetAddr, ulRetAddr, &abtInfo, ptcbCur); }
/********************************************************************************************************* ** 函数名称: archAbtHandle ** 功能描述: 系统发生 data abort 或者 prefetch_abort 异常时会调用此函数 ** 输 入 : ulRetAddr 异常返回地址. ** uiArmExcType ARM 异常类型 ** 输 出 : NONE ** 全局变量: ** 调用模块: *********************************************************************************************************/ VOID archAbtHandle (addr_t ulRetAddr, UINT32 uiArmExcType) { #define ARM_EXC_TYPE_ABT 8 #define ARM_EXC_TYPE_PRE 4 PLW_CLASS_TCB ptcbCur; addr_t ulAbortAddr; ULONG ulAbortType; if (uiArmExcType == ARM_EXC_TYPE_ABT) { ulAbortAddr = armGetAbtAddr(); ulAbortType = armGetAbtType(); } else { ulAbortAddr = armGetPreAddr(ulRetAddr); ulAbortType = armGetPreType(); } LW_TCB_GET_CUR(ptcbCur); API_VmmAbortIsr(ulRetAddr, ulAbortAddr, ulAbortType, ptcbCur); }
/********************************************************************************************************* ** 函数名称: archUndHandle ** 功能描述: archUndEntry 需要调用此函数处理未定义指令 ** 输 入 : ulAddr 对应的地址 ** uiCpsr 产生异常时的 CPSR ** 输 出 : NONE ** 全局变量: ** 调用模块: *********************************************************************************************************/ VOID archUndHandle (addr_t ulAddr, UINT32 uiCpsr) { PLW_CLASS_TCB ptcbCur; #if LW_CFG_GDB_EN > 0 UINT uiBpType = archDbgTrapType(ulAddr, (PVOID)uiCpsr); /* 断点指令探测 */ if (uiBpType) { if (API_DtraceBreakTrap(ulAddr, uiBpType) == ERROR_NONE) { /* 进入调试接口断点处理 */ return; } } #endif /* LW_CFG_GDB_EN > 0 */ LW_TCB_GET_CUR(ptcbCur); #if LW_CFG_CPU_FPU_EN > 0 if (archFpuUndHandle(ptcbCur) == ERROR_NONE) { /* 进行 FPU 指令探测 */ return; } #endif /* LW_CFG_CPU_FPU_EN > 0 */ API_VmmAbortIsr(ulAddr, ulAddr, LW_VMM_ABORT_TYPE_UNDEF, ptcbCur); }
VOID _ThreadFpuSwith (BOOL bIntSwitch) { PLW_CLASS_TCB ptcbCur; PLW_CLASS_TCB ptcbHigh; LW_TCB_GET_CUR(ptcbCur); LW_TCB_GET_HIGH(ptcbHigh); if (LW_KERN_FPU_EN_GET()) { /* 中断状态支持 FPU */ /* * 由于内核支持 FPU 所以, 中断函数会保存当前任务的 FPU 上下文 * 所以如果是中断环境的调度函数, 则不需要保存当前任务 FPU 上下文 */ if (bIntSwitch == LW_FALSE) { if (ptcbCur->TCB_ulOption & LW_OPTION_THREAD_USED_FP) { __ARCH_FPU_SAVE(ptcbCur->TCB_pvStackFP); /* 需要保存当前 FPU CTX */ } } } else { /* * 由于中断状态不支持 FPU 所以, 中断函数中不会对 FPU 上下文有任何操作 * 这里不管是 _Sched() 还是 _SchedInt() 都需要保存当前任务的 FPU 上下文 */ if (ptcbCur->TCB_ulOption & LW_OPTION_THREAD_USED_FP) { __ARCH_FPU_SAVE(ptcbCur->TCB_pvStackFP); /* 需要保存当前 FPU CTX */ } } if (ptcbHigh->TCB_ulOption & LW_OPTION_THREAD_USED_FP) { __ARCH_FPU_RESTORE(ptcbHigh->TCB_pvStackFP); /* 需要恢复新任务 FPU CTX */ } else { __ARCH_FPU_DISABLE(); /* 新任务不需要 FPU 支持 */ } }
/********************************************************************************************************* ** 函数名称: _ThreadStatusChange ** 功能描述: 改变线程状态 (进入内核状态被调用) ** 输 入 : ptcb 线程控制块 ** uiStatusReq 状态 (LW_TCB_REQ_SUSPEND / LW_TCB_REQ_WDEATH / LW_TCB_REQ_STOP) ** 输 出 : ERROR ** 全局变量: ** 调用模块: ** 注 意 : 此函数已经预置的阻塞点, 最后一次退出内核时, 将阻塞等待目标线程状态改变完毕. *********************************************************************************************************/ ULONG _ThreadStatusChange (PLW_CLASS_TCB ptcb, UINT uiStatusReq) { INTREG iregInterLevel; PLW_CLASS_PCB ppcb; PLW_CLASS_TCB ptcbCur; iregInterLevel = KN_INT_DISABLE(); /* 关闭中断 */ LW_TCB_GET_CUR(ptcbCur); #if LW_CFG_SMP_EN > 0 if (ptcb == ptcbCur) { /* 改变自己的状态 */ goto __change1; } else if (!__LW_THREAD_IS_READY(ptcb)) { /* 任务没有就绪 */ goto __change2; } else { /* 目标任务处于就绪状态 */ if (LW_CPU_GET_CUR_NESTING()) { KN_INT_ENABLE(iregInterLevel); /* 打开中断 */ return (ERROR_KERNEL_IN_ISR); /* 中断状态下无法完成此工作 */ } if (!__LW_THREAD_IS_RUNNING(ptcb)) { /* 目标任务不是正在执行 */ ppcb = _GetPcb(ptcb); __DEL_FROM_READY_RING(ptcb, ppcb); /* 从就绪表中删除 */ goto __change2; } else { /* 目标任务正在执行 */ _SmpUpdateIpi(LW_CPU_GET(ptcb->TCB_ulCPUId)); /* 发送核间中断通知改变状态 */ _ThreadWaitStatus(ptcbCur, ptcb, uiStatusReq); /* 设置等待对方完成状态 */ } KN_INT_ENABLE(iregInterLevel); /* 打开中断 */ return (ERROR_NONE); /* 退出内核时开始等待 */ } __change1: #endif /* LW_CFG_SMP_EN */ if (__LW_THREAD_IS_READY(ptcb)) { ppcb = _GetPcb(ptcb); __DEL_FROM_READY_RING(ptcb, ppcb); /* 从就绪表中删除 */ } #if LW_CFG_SMP_EN > 0 __change2: #endif /* LW_CFG_SMP_EN */ ptcbCur->TCB_uiStatusChangeReq = 0; /* 状态修改操作执行成功 */ switch (uiStatusReq) { case LW_TCB_REQ_SUSPEND: ptcb->TCB_ulSuspendNesting++; ptcb->TCB_usStatus |= LW_THREAD_STATUS_SUSPEND; break; case LW_TCB_REQ_STOP: ptcb->TCB_ulStopNesting++; ptcb->TCB_usStatus |= LW_THREAD_STATUS_STOP; break; case LW_TCB_REQ_WDEATH: ptcb->TCB_usStatus |= LW_THREAD_STATUS_WDEATH; break; } KN_INT_ENABLE(iregInterLevel); return (ERROR_NONE); }