更新日期: 2022/06/01 来源: https://gitee.com/weharmony/kernel_liteos_a_note
los_exc.c
浏览该文件的文档.
1/*!
2 * @file los_exc.c
3 * @brief 异常接管主文件
4 * @link
5 * @verbatim
6 基本概念
7 异常接管是操作系统对运行期间发生的异常情况(芯片硬件异常)进行处理的一系列动作,
8 例如打印异常发生时当前函数的调用栈信息、CPU现场信息、任务的堆栈情况等。
9
10 异常接管作为一种调测手段,可以在系统发生异常时给用户提供有用的异常信息,譬如异常类型、
11 发生异常时的系统状态等,方便用户定位分析问题。
12
13 异常接管,在系统发生异常时的处理动作为:显示异常发生时正在运行的任务信息
14 (包括任务名、任务号、堆栈大小等),以及CPU现场等信息。
15
16 运作机制
17 每个函数都有自己的栈空间,称为栈帧。调用函数时,会创建子函数的栈帧,
18 同时将函数入参、局部变量、寄存器入栈。栈帧从高地址向低地址生长。
19
20 以ARM32 CPU架构为例,每个栈帧中都会保存PC、LR、SP和FP寄存器的历史值。
21 ARM处理器中的R13被用作SP
22
23 堆栈分析
24 LR寄存器(Link Register),链接寄存器,指向函数的返回地址。
25 R11:可以用作通用寄存器,在开启特定编译选项时可以用作帧指针寄存器FP,用来实现栈回溯功能。
26 GNU编译器(gcc)默认将R11作为存储变量的通用寄存器,因而默认情况下无法使用FP的栈回溯功能。
27 为支持调用栈解析功能,需要在编译参数中添加-fno-omit-frame-pointer选项,提示编译器将R11作为FP使用。
28 FP寄存器(Frame Point),帧指针寄存器,指向当前函数的父函数的栈帧起始地址。利用该寄存器可以得到父函数的栈帧,
29 从栈帧中获取父函数的FP,就可以得到祖父函数的栈帧,以此类推,可以追溯程序调用栈,得到函数间的调用关系。
30 当系统发生异常时,系统打印异常函数的栈帧中保存的寄存器内容,以及父函数、祖父函数的
31 栈帧中的LR、FP寄存器内容,用户就可以据此追溯函数间的调用关系,定位异常原因。
32 异常接管对系统运行期间发生的芯片硬件异常进行处理,不同芯片的异常类型存在差异,具体异常类型可以查看芯片手册。
33
34 异常接管一般的定位步骤如下:
35 打开编译后生成的镜像反汇编(asm)文件。
36 搜索PC指针(指向当前正在执行的指令)在asm中的位置,找到发生异常的函数。
37 根据LR值查找异常函数的父函数。
38 重复步骤3,得到函数间的调用关系,找到异常原因。
39
40 注意事项
41 要查看调用栈信息,必须添加编译选项宏-fno-omit-frame-pointer支持stack frame,否则编译时FP寄存器是关闭的。
42
43 参考
44 http://weharmonyos.com/openharmony/zh-cn/device-dev/kernel/%E7%94%A8%E6%88%B7%E6%80%81%E5%BC%82%E5%B8%B8%E4%BF%A1%E6%81%AF%E8%AF%B4%E6%98%8E.html
45 @endverbatim
46
47 * @version
48 * @author weharmonyos.com | 鸿蒙研究站 | 每天死磕一点点
49 * @date 2021-11-20
50 */
51/*
52 * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
53 * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
54 *
55 * Redistribution and use in source and binary forms, with or without modification,
56 * are permitted provided that the following conditions are met:
57 *
58 * 1. Redistributions of source code must retain the above copyright notice, this list of
59 * conditions and the following disclaimer.
60 *
61 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
62 * of conditions and the following disclaimer in the documentation and/or other materials
63 * provided with the distribution.
64 *
65 * 3. Neither the name of the copyright holder nor the names of its contributors may be used
66 * to endorse or promote products derived from this software without specific prior written
67 * permission.
68 *
69 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
70 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
71 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
72 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
73 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
74 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
75 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
76 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
77 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
78 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
79 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
80 */
81
82#include "los_exc.h"
83#include "los_memory_pri.h"
84#include "los_printf_pri.h"
85#include "los_task_pri.h"
86#include "los_percpu_pri.h"
87#include "los_hw_pri.h"
88#ifdef LOSCFG_SAVE_EXCINFO
89#include "los_excinfo_pri.h"
90#endif
91#include "los_sys_stack_pri.h"
92#ifdef LOSCFG_COREDUMP
93#include "los_coredump.h"
94#endif
95#ifdef LOSCFG_GDB
96#include "gdb_int.h"
97#endif
98#include "los_mp.h"
99#include "los_vm_map.h"
100#include "los_vm_dump.h"
101#include "los_arch_mmu.h"
102#include "los_vm_phys.h"
103#include "los_vm_fault.h"
104#include "los_vm_common.h"
105#ifdef LOSCFG_KERNEL_DYNLOAD
106#include "los_load_elf.h"
107#endif
108#include "arm.h"
109#include "los_bitmap.h"
110#include "los_process_pri.h"
111#include "los_exc_pri.h"
112#include "los_sched_pri.h"
113#ifdef LOSCFG_FS_VFS
114#include "console.h"
115#endif
116#ifdef LOSCFG_BLACKBOX
117#include "los_blackbox.h"
118#endif
119
120#define INVALID_CPUID 0xFFFF
121#define OS_EXC_VMM_NO_REGION 0x0U
122#define OS_EXC_VMM_ALL_REGION 0x1U
123
126STATIC UINT32 g_currHandleExcCpuid = INVALID_CPUID;
127VOID OsExcHook(UINT32 excType, ExcContext *excBufAddr, UINT32 far, UINT32 fsr);
128UINT32 g_curNestCount[LOSCFG_KERNEL_CORE_NUM] = {0}; ///< 记录当前嵌套异常的数量
129BOOL g_excFromUserMode[LOSCFG_KERNEL_CORE_NUM]; ///< 记录CPU core 异常来自用户态还是内核态 TRUE为用户态,默认为内核态
130STATIC EXC_PROC_FUNC g_excHook = (EXC_PROC_FUNC)OsExcHook; ///< 全局异常处理钩子
131#ifdef LOSCFG_KERNEL_SMP
132STATIC SPIN_LOCK_INIT(g_excSerializerSpin); //初始化异常系列化自旋锁
133STATIC UINT32 g_currHandleExcPID = OS_INVALID_VALUE;
134STATIC UINT32 g_nextExcWaitCpu = INVALID_CPUID;
135#endif
136
137#define OS_MAX_BACKTRACE 15U //打印栈内容的数目
138#define DUMPSIZE 128U
139#define DUMPREGS 12U
140#define COM_REGS 4U
141#define INSTR_SET_MASK 0x01000020U
142#define THUMB_INSTR_LEN 2U
143#define ARM_INSTR_LEN 4U
144#define POINTER_SIZE 4U
145#define WNR_BIT 11U
146#define FSR_FLAG_OFFSET_BIT 10U
147#define FSR_BITS_BEGIN_BIT 3U
148
149#define GET_FS(fsr) (((fsr)&0xFU) | (((fsr) & (1U << 10)) >> 6))
150#define GET_WNR(dfsr) ((dfsr) & (1U << 11))
151
152#define IS_VALID_ADDR(ptr) (((ptr) >= g_minAddr) && \
153 ((ptr) <= g_maxAddr) && \
154 (IS_ALIGNED((ptr), sizeof(CHAR *))))
155
156/**
157 * @brief
158 * @verbatim
159 6种异常情况下对应的栈,每一种异常模式都有其独立的堆栈,用不同的堆栈指针来索引,
160 这样当ARM进入异常模式的时候,程序就可以把一般通用寄存器压入堆栈,返回时再出栈,
161 保证了各种模式下程序的状态的完整性
162
163 用户模式,运行应用程序的普通模式。限制你的内存访问并且不能直接读取硬件设备。
164 超级用户模式(SVC 模式),主要用于 SWI(软件中断)和 OS(操作系统)。这个模式有额外的特权,
165 允许你进一步控制计算机。例如,你必须进入超级用户模式来读取一个插件(podule)。
166 这不能在用户模式下完成。
167 中断模式(IRQ 模式),用来处理发起中断的外设。这个模式也是有特权的。导致 IRQ 的设备有
168 键盘、 VSync (在发生屏幕刷新的时候)、IOC 定时器、串行口、硬盘、软盘、等等...
169 快速中断模式(FIQ 模式),用来处理发起快速中断的外设。这个模式是有特权的。导致 FIQ 的设备有
170 处理数据的软盘,串行端口。
171
172 IRQ 和 FIQ 之间的区别是对于 FIQ 你必须尽快处理你事情并离开这个模式。
173 IRQ 可以被 FIQ 所中断但 IRQ 不能中断 FIQ
174 * @endverbatim
175 */
176STATIC const StackInfo g_excStack[] = {
177 {&__svc_stack, OS_EXC_SVC_STACK_SIZE, "svc_stack"}, //8K 主管模式堆栈.有些指令只能在SVC模式下运行
178 {&__exc_stack, OS_EXC_STACK_SIZE, "exc_stack"} //4K 异常处理堆栈
179};
180/// 获取系统状态
182{
183 UINT32 flag;
184 UINT32 cpuid = g_currHandleExcCpuid; //全局变量 当前执行CPU ID
185
186 if (cpuid == INVALID_CPUID) { //当前CPU处于空闲状态的情况
187 flag = OS_SYSTEM_NORMAL;
188 } else if (cpuid == ArchCurrCpuid()) { //碰到了正在执行此处代码的CPU core
189 flag = OS_SYSTEM_EXC_CURR_CPU; //当前CPU
190 } else {
191 flag = OS_SYSTEM_EXC_OTHER_CPU; //其他CPU
192 }
193
194 return flag;
195}
196
197STATIC INT32 OsDecodeFS(UINT32 bitsFS)
198{
199 switch (bitsFS) {
200 case 0x05: /* 0b00101 */
201 case 0x07: /* 0b00111 */
202 PrintExcInfo("Translation fault, %s\n", (bitsFS & 0x2) ? "page" : "section");
203 break;
204 case 0x09: /* 0b01001 */
205 case 0x0b: /* 0b01011 */
206 PrintExcInfo("Domain fault, %s\n", (bitsFS & 0x2) ? "page" : "section");
207 break;
208 case 0x0d: /* 0b01101 */
209 case 0x0f: /* 0b01111 */
210 PrintExcInfo("Permission fault, %s\n", (bitsFS & 0x2) ? "page" : "section");
211 break;
212 default:
213 PrintExcInfo("Unknown fault! FS:0x%x. "
214 "Check IFSR and DFSR in ARM Architecture Reference Manual.\n",
215 bitsFS);
216 break;
217 }
218
219 return LOS_OK;
220}
221
223{
224 INT32 ret;
225 UINT32 bitsFS = GET_FS(regIFSR); /* FS bits[4]+[3:0] */
226
227 ret = OsDecodeFS(bitsFS);
228 return ret;
229}
230
232{
233 INT32 ret = 0;
234 UINT32 bitWnR = GET_WNR(regDFSR); /* WnR bit[11] */
235 UINT32 bitsFS = GET_FS(regDFSR); /* FS bits[4]+[3:0] */
236
237 if (bitWnR) {
238 PrintExcInfo("Abort caused by a write instruction. ");
239 } else {
240 PrintExcInfo("Abort caused by a read instruction. ");
241 }
242
243 if (bitsFS == 0x01) { /* 0b00001 */
244 PrintExcInfo("Alignment fault.\n");
245 return ret;
246 }
247 ret = OsDecodeFS(bitsFS);
248 return ret;
249}
250
251#ifdef LOSCFG_KERNEL_VM
252
253/**
254 * @brief 共享页缺失异常
255 * @param excType
256 * @param frame
257 * @param far 异常状态寄存器(Fault Status Register -FAR)
258 * @param fsr 异常地址寄存器(Fault Address Register -FSR)
259 * @return UINT32
260 */
262{
263 BOOL instructionFault = FALSE;
264 UINT32 pfFlags = 0;
265 UINT32 fsrFlag;
266 BOOL write = FALSE;
267 UINT32 ret;
268
269 PRINT_INFO("page fault entry!!!\n");
270 if (OsGetSystemStatus() == OS_SYSTEM_EXC_CURR_CPU) {
271 return LOS_ERRNO_VM_NOT_FOUND;
272 }
273#if defined(LOSCFG_KERNEL_SMP) && defined(LOSCFG_DEBUG_VERSION)
274 BOOL irqEnable = !(LOS_SpinHeld(&g_taskSpin) && OsSchedIsLock());
275 if (irqEnable) {
277 } else {
278 PrintExcInfo("[ERR][%s] may be held scheduler lock when entering [%s] on cpu [%u]\n",
279 OsCurrTaskGet()->taskName, __FUNCTION__, ArchCurrCpuid());
280 }
281#else
283#endif
284 if (excType == OS_EXCEPT_PREFETCH_ABORT) {
285 instructionFault = TRUE;
286 } else {
287 write = !!BIT_GET(fsr, WNR_BIT);
288 }
289
290 fsrFlag = ((BIT_GET(fsr, FSR_FLAG_OFFSET_BIT) ? 0b10000 : 0) | BITS_GET(fsr, FSR_BITS_BEGIN_BIT, 0));
291 switch (fsrFlag) {
292 case 0b00101:
293 /* translation fault */
294 case 0b00111:
295 /* translation fault */
296 case 0b01101:
297 /* permission fault */
298 case 0b01111: {
299 /* permission fault */
300 BOOL user = (frame->regCPSR & CPSR_MODE_MASK) == CPSR_MODE_USR;
301 pfFlags |= write ? VM_MAP_PF_FLAG_WRITE : 0;
302 pfFlags |= user ? VM_MAP_PF_FLAG_USER : 0;
303 pfFlags |= instructionFault ? VM_MAP_PF_FLAG_INSTRUCTION : 0;
304 pfFlags |= VM_MAP_PF_FLAG_NOT_PRESENT;
305 OsSigIntLock();
306 ret = OsVmPageFaultHandler(far, pfFlags, frame);
308 break;
309 }
310 default:
311 OsArmWriteTlbimvaais(ROUNDDOWN(far, PAGE_SIZE));
312 ret = LOS_OK;
313 break;
314 }
315#if defined(LOSCFG_KERNEL_SMP) && defined(LOSCFG_DEBUG_VERSION)
316 if (irqEnable) {
318 }
319#else
321#endif
322 return ret;
323}
324#endif
325/// 异常类型
326STATIC VOID OsExcType(UINT32 excType, ExcContext *excBufAddr, UINT32 far, UINT32 fsr)
327{
328 /* undefinited exception handling or software interrupt | 未定义的异常处理或软件中断 */
329 if ((excType == OS_EXCEPT_UNDEF_INSTR) || (excType == OS_EXCEPT_SWI)) {
330 if ((excBufAddr->regCPSR & INSTR_SET_MASK) == 0) { /* work status: ARM */
331 excBufAddr->PC = excBufAddr->PC - ARM_INSTR_LEN;
332 } else if ((excBufAddr->regCPSR & INSTR_SET_MASK) == 0x20) { /* work status: Thumb */
333 excBufAddr->PC = excBufAddr->PC - THUMB_INSTR_LEN;
334 }
335 }
336
337 if (excType == OS_EXCEPT_PREFETCH_ABORT) { //取指异常
338 PrintExcInfo("prefetch_abort fault fsr:0x%x, far:0x%0+8x\n", fsr, far);
339 (VOID) OsDecodeInstructionFSR(fsr);
340 } else if (excType == OS_EXCEPT_DATA_ABORT) { // 数据异常
341 PrintExcInfo("data_abort fsr:0x%x, far:0x%0+8x\n", fsr, far);
342 (VOID) OsDecodeDataFSR(fsr);
343 }
344}
345
346STATIC const CHAR *g_excTypeString[] = {
347 ///< 异常类型的字符说明,在鸿蒙内核中什么才算是异常? 看这里
348 "reset", //复位异常源 - SVC模式(Supervisor保护模式)
349 "undefined instruction", //未定义指令异常源- und模式
350 "software interrupt", //软中断异常源 - SVC模式
351 "prefetch abort", //取指异常源 - abort模式
352 "data abort", //数据异常源 - abort模式
353 "fiq", //快中断异常源 - FIQ模式
354 "address abort", //地址异常源 - abort模式
355 "irq" //中断异常源 - IRQ模式
356};
357
358#ifdef LOSCFG_KERNEL_VM
360{
361 struct Vnode *curVnode = NULL;
362 struct Vnode *lastVnode = NULL;
363 LosVmMapRegion *curRegion = NULL;
364 LosVmMapRegion *lastRegion = NULL;
365
366 if ((region == NULL) || (runProcess == NULL)) {
367 return 0;
368 }
369
370 if (!LOS_IsRegionFileValid(region)) {
371 return region->range.base;
372 }
373
374 lastRegion = region;
375 do {
376 curRegion = lastRegion;
377 lastRegion = LOS_RegionFind(runProcess->vmSpace, curRegion->range.base - 1);
378 if ((lastRegion == NULL) || !LOS_IsRegionFileValid(lastRegion)) {
379 goto DONE;
380 }
381 curVnode = curRegion->unTypeData.rf.vnode;
382 lastVnode = lastRegion->unTypeData.rf.vnode;
383 } while (curVnode == lastVnode);
384
385DONE:
386#ifdef LOSCFG_KERNEL_DYNLOAD
387 if (curRegion->range.base == EXEC_MMAP_BASE) {
388 return 0;
389 }
390#endif
391 return curRegion->range.base;
392}
393#endif
394/**
395 * @brief 打印异常系统信息
396 *
397 * @param excType
398 * @param excBufAddr
399 * @return STATIC
400 */
401STATIC VOID OsExcSysInfo(UINT32 excType, const ExcContext *excBufAddr)
402{
403 LosTaskCB *runTask = OsCurrTaskGet(); //获取当前任务
404 LosProcessCB *runProcess = OsCurrProcessGet(); //获取当前进程
405
406 PrintExcInfo("excType: %s\n"
407 "processName = %s\n"
408 "processID = %u\n"
409#ifdef LOSCFG_KERNEL_VM
410 "process aspace = 0x%08x -> 0x%08x\n"
411#endif
412 "taskName = %s\n"
413 "taskID = %u\n",
414 g_excTypeString[excType],
415 runProcess->processName,
416 runProcess->processID,
417#ifdef LOSCFG_KERNEL_VM
418 runProcess->vmSpace->base,
419 runProcess->vmSpace->base + runProcess->vmSpace->size,
420#endif
421 runTask->taskName,
422 runTask->taskID);
423 //这里可以看出一个任务有两个运行栈空间
424#ifdef LOSCFG_KERNEL_VM
425 if (OsProcessIsUserMode(runProcess)) { //用户态栈空间,对于栈而言,栈底的地址要小于栈顶的地址
426 PrintExcInfo("task user stack = 0x%08x -> 0x%08x\n", //用户态栈空间由用户空间提供
427 runTask->userMapBase, runTask->userMapBase + runTask->userMapSize);
428 } else
429#endif
430 {
431 PrintExcInfo("task kernel stack = 0x%08x -> 0x%08x\n", //
432 runTask->topOfStack, runTask->topOfStack + runTask->stackSize);
433 }
434
435 PrintExcInfo("pc = 0x%x ", excBufAddr->PC);
436#ifdef LOSCFG_KERNEL_VM
437 LosVmMapRegion *region = NULL;
438 if (g_excFromUserMode[ArchCurrCpuid()] == TRUE) { //当前CPU处于用户模式
439 if (LOS_IsUserAddress((vaddr_t)excBufAddr->PC)) { //pc寄存器处于用户空间
440 region = LOS_RegionFind(runProcess->vmSpace, (VADDR_T)excBufAddr->PC); //找到所在线性区
441 if (region != NULL) {
442 PrintExcInfo("in %s ---> 0x%x", OsGetRegionNameOrFilePath(region),
443 (VADDR_T)excBufAddr->PC - OsGetTextRegionBase(region, runProcess));
444 }
445 }
446
447 PrintExcInfo("\nulr = 0x%x ", excBufAddr->ULR); //打印用户模式下程序的返回地址
448 region = LOS_RegionFind(runProcess->vmSpace, (VADDR_T)excBufAddr->ULR); //通过返回地址找到线性区
449 if (region != NULL) {
450 PrintExcInfo("in %s ---> 0x%x", OsGetRegionNameOrFilePath(region),
451 (VADDR_T)excBufAddr->ULR - OsGetTextRegionBase(region, runProcess));
452 }
453 PrintExcInfo("\nusp = 0x%x", excBufAddr->USP); //打印用户模式下栈指针
454 } else
455#endif
456 {
457 PrintExcInfo("\nklr = 0x%x\n" //注意:只有一个内核空间和内核堆空间,而每个用户进程就有自己独立的用户空间。
458 "ksp = 0x%x\n", //用户空间的虚拟地址范围是一样的,只是映射到不同的物理内存页。
459 excBufAddr->LR, //直接打印程序的返回地址
460 excBufAddr->SP); //直接打印栈指针
461 }
462
463 PrintExcInfo("\nfp = 0x%x\n", excBufAddr->R11);
464}
465/**
466 * @brief 异常情况下打印各寄存器的信息
467 *
468 * @param excBufAddr
469 * @return STATIC
470 */
471STATIC VOID OsExcRegsInfo(const ExcContext *excBufAddr)
472{
473 /*
474 * Split register information into two parts:
475 * Ensure printing does not rely on memory modules.
476 */
477 //将寄存器信息分为两部分:确保打印不依赖内存模块。
478 PrintExcInfo("R0 = 0x%x\n"
479 "R1 = 0x%x\n"
480 "R2 = 0x%x\n"
481 "R3 = 0x%x\n"
482 "R4 = 0x%x\n"
483 "R5 = 0x%x\n"
484 "R6 = 0x%x\n",
485 excBufAddr->R0, excBufAddr->R1, excBufAddr->R2, excBufAddr->R3,
486 excBufAddr->R4, excBufAddr->R5, excBufAddr->R6);
487 PrintExcInfo("R7 = 0x%x\n"
488 "R8 = 0x%x\n"
489 "R9 = 0x%x\n"
490 "R10 = 0x%x\n"
491 "R11 = 0x%x\n"
492 "R12 = 0x%x\n"
493 "CPSR = 0x%x\n",
494 excBufAddr->R7, excBufAddr->R8, excBufAddr->R9, excBufAddr->R10,
495 excBufAddr->R11, excBufAddr->R12, excBufAddr->regCPSR);
496}
497///注册异常处理钩子
498LITE_OS_SEC_TEXT_INIT UINT32 LOS_ExcRegHook(EXC_PROC_FUNC excHook)
499{
500 UINT32 intSave;
501
502 intSave = LOS_IntLock();
503 g_excHook = excHook;
504 LOS_IntRestore(intSave);
505
506 return LOS_OK;
507}
508///获取hook函数
510{
511 return g_excHook;
512}
513///dump 虚拟空间下异常虚拟地址线性区
514#ifdef LOSCFG_KERNEL_VM
516{
517 INT32 i, numPages, pageCount;
518 paddr_t addr, oldAddr, startVaddr, startPaddr;
519 vaddr_t pageBase;
520 BOOL mmuFlag = FALSE;
521
522 numPages = region->range.size >> PAGE_SHIFT;
523 mmuFlag = TRUE;
524 for (pageCount = 0, startPaddr = 0, startVaddr = 0, i = 0; i < numPages; i++) {
525 pageBase = region->range.base + i * PAGE_SIZE;
526 addr = 0;
527 if (LOS_ArchMmuQuery(&space->archMmu, pageBase, &addr, NULL) != LOS_OK) {
528 if (startPaddr == 0) {
529 continue;
530 }
531 } else if (startPaddr == 0) {
532 startVaddr = pageBase;
533 startPaddr = addr;
534 oldAddr = addr;
535 pageCount++;
536 if (numPages > 1) {
537 continue;
538 }
539 } else if (addr == (oldAddr + PAGE_SIZE)) {
540 pageCount++;
541 oldAddr = addr;
542 if (i < (numPages - 1)) {
543 continue;
544 }
545 }
546 if (mmuFlag == TRUE) {
547 PrintExcInfo(" uvaddr kvaddr mapped size\n");
548 mmuFlag = FALSE;
549 }
550 PrintExcInfo(" 0x%08x 0x%08x 0x%08x\n",
551 startVaddr, LOS_PaddrToKVaddr(startPaddr), (UINT32)pageCount << PAGE_SHIFT);
552 pageCount = 0;
553 startPaddr = 0;
554 }
555}
556///dump 进程使用的内存线性区
557STATIC VOID OsDumpProcessUsedMemRegion(LosProcessCB *runProcess, LosVmSpace *runspace, UINT16 vmmFlags)
558{
559 LosVmMapRegion *region = NULL;
560 LosRbNode *pstRbNodeTemp = NULL;
561 LosRbNode *pstRbNodeNext = NULL;
562 UINT32 count = 0;
563
564 /* search the region list */
565 RB_SCAN_SAFE(&runspace->regionRbTree, pstRbNodeTemp, pstRbNodeNext)
566 region = (LosVmMapRegion *)pstRbNodeTemp;
567 PrintExcInfo("%3u -> regionBase: 0x%08x regionSize: 0x%08x\n", count, region->range.base, region->range.size);
568 if (vmmFlags == OS_EXC_VMM_ALL_REGION) {
569 OsDumpExcVaddrRegion(runspace, region);
570 }
571 count++;
572 (VOID) OsRegionOverlapCheckUnlock(runspace, region);
573 RB_SCAN_SAFE_END(&space->regionRbTree, pstRbNodeTemp, pstRbNodeNext)
574}
575///dump 进程使用的内存节点
576STATIC VOID OsDumpProcessUsedMemNode(UINT16 vmmFlags)
577{
578 LosProcessCB *runProcess = NULL;
579 LosVmSpace *runspace = NULL;
580
581 runProcess = OsCurrProcessGet();
582 if (runProcess == NULL) {
583 return;
584 }
585
586 if (!OsProcessIsUserMode(runProcess)) {
587 return;
588 }
589
590 PrintExcInfo("\n ******Current process %u vmm regions: ******\n", runProcess->processID);
591
592 runspace = runProcess->vmSpace;
593 if (!runspace) {
594 return;
595 }
596
597 OsDumpProcessUsedMemRegion(runProcess, runspace, vmmFlags);
598 return;
599}
600#endif
601
602/** 打印异常上下文
603 * @brief dump 上下文内存,注意内核异常不能简单的映射理解为应用的异常,异常对内核来说是一个很常见操作,
604 \n 比如任务的切换对内核来说就是一个异常处理
605 * @param excBufAddr
606 * @return VOID
607 */
608VOID OsDumpContextMem(const ExcContext *excBufAddr)
609{
610 UINT32 count = 0;
611 const UINT32 *excReg = NULL;
612 if (g_excFromUserMode[ArchCurrCpuid()] == TRUE) {
613 return;
614 }
615
616 for (excReg = &(excBufAddr->R0); count < COM_REGS; excReg++, count++) {
617 if (IS_VALID_ADDR(*excReg)) {
618 PrintExcInfo("\ndump mem around R%u:%p", count, (*excReg));
619 OsDumpMemByte(DUMPSIZE, ((*excReg) - (DUMPSIZE >> 1)));
620 }
621 }
622 for (excReg = &(excBufAddr->R4); count < DUMPREGS; excReg++, count++) {
623 if (IS_VALID_ADDR(*excReg)) {
624 PrintExcInfo("\ndump mem around R%u:%p", count, (*excReg));
625 OsDumpMemByte(DUMPSIZE, ((*excReg) - (DUMPSIZE >> 1)));
626 }
627 }
628 if (IS_VALID_ADDR(excBufAddr->R12)) {
629 PrintExcInfo("\ndump mem around R12:%p", excBufAddr->R12);
630 OsDumpMemByte(DUMPSIZE, (excBufAddr->R12 - (DUMPSIZE >> 1)));
631 }
632 if (IS_VALID_ADDR(excBufAddr->SP)) {
633 PrintExcInfo("\ndump mem around SP:%p", excBufAddr->SP);
634 OsDumpMemByte(DUMPSIZE, (excBufAddr->SP - (DUMPSIZE >> 1)));
635 }
636}
637///异常恢复,继续执行
638STATIC VOID OsExcRestore(VOID)
639{
640 UINT32 currCpuid = ArchCurrCpuid();
641
642 g_excFromUserMode[currCpuid] = FALSE;
643 g_intCount[currCpuid] = 0;
644 g_curNestCount[currCpuid] = 0;
645#ifdef LOSCFG_KERNEL_SMP
647#endif
649}
650///用户态异常处理函数
651STATIC VOID OsUserExcHandle(ExcContext *excBufAddr)
652{
653 UINT32 intSave;
654 UINT32 currCpu = ArchCurrCpuid();
655 LosTaskCB *runTask = OsCurrTaskGet();
656 LosProcessCB *runProcess = OsCurrProcessGet();
657
658 if (g_excFromUserMode[ArchCurrCpuid()] == FALSE) { //内核态直接退出,不处理了.
659 return;
660 }
661
662#ifdef LOSCFG_KERNEL_SMP
663 LOS_SpinLock(&g_excSerializerSpin);
664 if (g_nextExcWaitCpu != INVALID_CPUID) {
666 g_nextExcWaitCpu = INVALID_CPUID;
667 } else {
668 g_currHandleExcCpuid = INVALID_CPUID;
669 }
670 g_currHandleExcPID = OS_INVALID_VALUE;
671 LOS_SpinUnlock(&g_excSerializerSpin);
672#else
673 g_currHandleExcCpuid = INVALID_CPUID;
674#endif
675
676#ifdef LOSCFG_KERNEL_SMP
677#ifdef LOSCFG_FS_VFS
679#endif
680#endif
681
682#ifdef LOSCFG_BLACKBOX
683 BBoxNotifyError("USER_CRASH", MODULE_SYSTEM, "Crash in user", 0);
684#endif
685 SCHEDULER_LOCK(intSave);
686#ifdef LOSCFG_SAVE_EXCINFO
688#endif
689 OsProcessExitCodeSignalSet(runProcess, SIGUSR2);
690
691 /* An exception was raised by a task that is not the current main thread during the exit process of
692 * the current process.
693 */
694 if (runProcess->processStatus & OS_PROCESS_FLAG_EXIT) {
695 SCHEDULER_UNLOCK(intSave);
696 /* Exception handling All operations should be kept prior to that operation */
697 OsExcRestore();
698 OsRunningTaskToExit(runTask, OS_PRO_EXIT_OK);
699 } else {
700 SCHEDULER_UNLOCK(intSave);
701
702 /* Exception handling All operations should be kept prior to that operation */
703 OsExcRestore();
704 /* kill user exc process */
705 LOS_Exit(OS_PRO_EXIT_OK); //进程退出
706 }
707
708 /* User mode exception handling failed , which normally does not exist */ //用户态的异常处理失败,通常情况下不会发生
709 g_curNestCount[currCpu]++;
710 g_intCount[currCpu]++;
711 PrintExcInfo("User mode exception ends unscheduled!\n");
712}
713///此函数用于验证fp或验证检查开始和结束范围
714//sp是上级函数即调用者的堆栈首地址,fp是上级函数的堆栈结束地址
715/* this function is used to validate fp or validate the checking range start and end. */
716STATIC INLINE BOOL IsValidFP(UINTPTR regFP, UINTPTR start, UINTPTR end, vaddr_t *vaddr)
717{
718 VADDR_T kvaddr = regFP;
719
720 if (!((regFP > start) && (regFP < end) && IS_ALIGNED(regFP, sizeof(CHAR *)))) {
721 return FALSE;
722 }
723
724#ifdef LOSCFG_KERNEL_VM
725 PADDR_T paddr;
726 if (g_excFromUserMode[ArchCurrCpuid()] == TRUE) {
727 LosProcessCB *runProcess = OsCurrProcessGet();
728 LosVmSpace *runspace = runProcess->vmSpace;
729 if (runspace == NULL) {
730 return FALSE;
731 }
732
733 if (LOS_ArchMmuQuery(&runspace->archMmu, regFP, &paddr, NULL) != LOS_OK) {
734 return FALSE;
735 }
736
737 kvaddr = (PADDR_T)(UINTPTR)LOS_PaddrToKVaddr(paddr);
738 }
739#endif
740 if (vaddr != NULL) {
741 *vaddr = kvaddr;
742 }
743
744 return TRUE;
745}
746///找到一个合适的栈
747STATIC INLINE BOOL FindSuitableStack(UINTPTR regFP, UINTPTR *start, UINTPTR *end, vaddr_t *vaddr)
748{
749 UINT32 index, stackStart, stackEnd;
750 BOOL found = FALSE;
751 LosTaskCB *taskCB = NULL;
752 const StackInfo *stack = NULL;
753 vaddr_t kvaddr;
754
755#ifdef LOSCFG_KERNEL_VM
756 if (g_excFromUserMode[ArchCurrCpuid()] == TRUE) {//当前CPU在用户态执行发生异常
757 taskCB = OsCurrTaskGet();
758 stackStart = taskCB->userMapBase; //用户态栈基地址,即用户态栈顶
759 stackEnd = taskCB->userMapBase + taskCB->userMapSize; //用户态栈结束地址
760 if (IsValidFP(regFP, stackStart, stackEnd, &kvaddr) == TRUE) {
761 found = TRUE;
762 goto FOUND;
763 }
764 return found;
765 }
766#endif
767
768 /* Search in the task stacks | 找任务的内核态栈*/
769 for (index = 0; index < g_taskMaxNum; index++) {
770 taskCB = &g_taskCBArray[index];
771 if (OsTaskIsUnused(taskCB)) {
772 continue;
773 }
774
775 stackStart = taskCB->topOfStack; //内核态栈顶
776 stackEnd = taskCB->topOfStack + taskCB->stackSize; //内核态栈底
777 if (IsValidFP(regFP, stackStart, stackEnd, &kvaddr) == TRUE) {
778 found = TRUE;
779 goto FOUND;
780 }
781 }
782
783 /* Search in the exc stacks */ //从异常栈中找
784 for (index = 0; index < sizeof(g_excStack) / sizeof(StackInfo); index++) {
785 stack = &g_excStack[index];
786 stackStart = (UINTPTR)stack->stackTop;
787 stackEnd = stackStart + LOSCFG_KERNEL_CORE_NUM * stack->stackSize;
788 if (IsValidFP(regFP, stackStart, stackEnd, &kvaddr) == TRUE) {
789 found = TRUE;
790 goto FOUND;
791 }
792 }
793
794FOUND:
795 if (found == TRUE) {
796 *start = stackStart;
797 *end = stackEnd;
798 *vaddr = kvaddr;
799 }
800
801 return found;
802}
803
805{
806 if (info == NULL) {
807 return FALSE;
808 }
809#ifdef LOSCFG_KERNEL_VM
810 BOOL ret = FALSE;
811 const CHAR *name = NULL;
812 LosVmMapRegion *region = NULL;
813 LosProcessCB *runProcess = OsCurrProcessGet();
814
815 if (LOS_IsUserAddress((VADDR_T)ip) == FALSE) {
816 info->ip = ip;
817 name = "kernel";
818 ret = FALSE;
819 goto END;
820 }
821
822 region = LOS_RegionFind(runProcess->vmSpace, (VADDR_T)ip);
823 if (region == NULL) {
824 info->ip = ip;
825 name = "invalid";
826 ret = FALSE;
827 goto END;
828 }
829
830 info->ip = ip - OsGetTextRegionBase(region, runProcess);
831 name = OsGetRegionNameOrFilePath(region);
832 ret = TRUE;
833 if (strcmp(name, "/lib/libc.so") != 0) {
834 PRINT_ERR("ip = 0x%x, %s\n", info->ip, name);
835 }
836END:
837 info->len = strlen(name);
838 if (strncpy_s(info->f_path, REGION_PATH_MAX, name, REGION_PATH_MAX - 1) != EOK) {
839 info->f_path[0] = '\0';
840 info->len = 0;
841 PRINT_ERR("copy f_path failed, %s\n", name);
842 }
843 return ret;
844#else
845 info->ip = ip;
846 return FALSE;
847#endif
848}
849
850UINT32 BackTraceGet(UINTPTR regFP, IpInfo *callChain, UINT32 maxDepth)
851{
852 UINTPTR tmpFP, backLR;
853 UINTPTR stackStart, stackEnd;
854 UINTPTR backFP = regFP;
855 UINT32 count = 0;
856 BOOL ret;
857 VADDR_T kvaddr;
858
859 if (FindSuitableStack(regFP, &stackStart, &stackEnd, &kvaddr) == FALSE) {
860 if (callChain == NULL) {
861 PrintExcInfo("traceback error fp = 0x%x\n", regFP);
862 }
863 return 0;
864 }
865
866 /*
867 * Check whether it is the leaf function.
868 * Generally, the frame pointer points to the address of link register, while in the leaf function,
869 * there's no function call, and compiler will not store the link register, but the frame pointer
870 * will still be stored and updated. In that case we needs to find the right position of frame pointer.
871 */
872 tmpFP = *(UINTPTR *)(UINTPTR)kvaddr;
873 if (IsValidFP(tmpFP, stackStart, stackEnd, NULL) == TRUE) {
874 backFP = tmpFP;
875 if (callChain == NULL) {
876 PrintExcInfo("traceback fp fixed, trace using fp = 0x%x\n", backFP);
877 }
878 }
879
880 while (IsValidFP(backFP, stackStart, stackEnd, &kvaddr) == TRUE) {
881 tmpFP = backFP;
882#ifdef LOSCFG_COMPILER_CLANG_LLVM
883 backFP = *(UINTPTR *)(UINTPTR)kvaddr;
884 if (IsValidFP(tmpFP + POINTER_SIZE, stackStart, stackEnd, &kvaddr) == FALSE) {
885 if (callChain == NULL) {
886 PrintExcInfo("traceback backLR check failed, backLP: 0x%x\n", tmpFP + POINTER_SIZE);
887 }
888 return 0;
889 }
890 backLR = *(UINTPTR *)(UINTPTR)kvaddr;
891#else
892 backLR = *(UINTPTR *)(UINTPTR)kvaddr;
893 if (IsValidFP(tmpFP - POINTER_SIZE, stackStart, stackEnd, &kvaddr) == FALSE) {
894 if (callChain == NULL) {
895 PrintExcInfo("traceback backFP check failed, backFP: 0x%x\n", tmpFP - POINTER_SIZE);
896 }
897 return 0;
898 }
899 backFP = *(UINTPTR *)(UINTPTR)kvaddr;
900#endif
901 IpInfo info = {0};
902 ret = OsGetUsrIpInfo((VADDR_T)backLR, &info);
903 if (callChain == NULL) {
904 PrintExcInfo("traceback %u -- lr = 0x%x fp = 0x%x ", count, backLR, backFP);
905 if (ret) {
906#ifdef LOSCFG_KERNEL_VM
907 PrintExcInfo("lr in %s --> 0x%x\n", info.f_path, info.ip);
908#else
909 PrintExcInfo("\n");
910#endif
911 } else {
912 PrintExcInfo("\n");
913 }
914 } else {
915 (VOID)memcpy_s(&callChain[count], sizeof(IpInfo), &info, sizeof(IpInfo));
916 }
917 count++;
918 if ((count == maxDepth) || (backFP == tmpFP)) {
919 break;
920 }
921 }
922 return count;
923}
924
926{
927 (VOID) BackTraceGet(regFP, NULL, OS_MAX_BACKTRACE);
928}
929///打印调用栈信息
930VOID BackTrace(UINT32 regFP) //fp:R11寄存器
931{
932 PrintExcInfo("*******backtrace begin*******\n");
933
934 BackTraceSub(regFP);
935}
936///异常接管模块的初始化
937VOID OsExcInit(VOID)
938{
939 OsExcStackInfoReg(g_excStack, sizeof(g_excStack) / sizeof(g_excStack[0])); //异常模式下注册内核栈信息
940}
941///由注册后回调,发送异常情况下会回调这里执行,见于 OsUndefIncExcHandleEntry, OsExcHandleEntry ==函数
942VOID OsExcHook(UINT32 excType, ExcContext *excBufAddr, UINT32 far, UINT32 fsr)
943{ //参考文档 https://gitee.com/openharmony/docs/blob/master/kernel/%E7%94%A8%E6%88%B7%E6%80%81%E5%BC%82%E5%B8%B8%E4%BF%A1%E6%81%AF%E8%AF%B4%E6%98%8E.md
944 OsExcType(excType, excBufAddr, far, fsr); //1.打印异常的类型
945 OsExcSysInfo(excType, excBufAddr); //2.打印异常的基本信息
946 OsExcRegsInfo(excBufAddr); //3.打印异常的寄存器信息
947
948 BackTrace(excBufAddr->R11); //4.打印调用栈信息,
949
950 (VOID) OsShellCmdTskInfoGet(OS_ALL_TASK_MASK, NULL, OS_PROCESS_INFO_ALL); //打印进程线程基本信息 相当于执行下 shell task -a 命令
951
952#ifndef LOSCFG_DEBUG_VERSION //打开debug开关
953 if (g_excFromUserMode[ArchCurrCpuid()] != TRUE) {
954#endif
955#ifdef LOSCFG_KERNEL_VM
956 OsDumpProcessUsedMemNode(OS_EXC_VMM_NO_REGION);
957#endif
958 OsExcStackInfo(); // 打印任务栈的信息
959#ifndef LOSCFG_DEBUG_VERSION
960 }
961#endif
962
963 OsDumpContextMem(excBufAddr); // 打印上下文
964
965 (VOID) OsShellCmdMemCheck(0, NULL); //检查内存,相当于执行 shell memcheck 命令
966
967#ifdef LOSCFG_COREDUMP
968 LOS_CoreDumpV2(excType, excBufAddr);
969#endif
970
971 OsUserExcHandle(excBufAddr); //用户态下异常的处理
972}
973///打印调用栈信息
975{
976 UINT32 count = 0;
977 LosTaskCB *runTask = OsCurrTaskGet();
978 UINTPTR stackBottom = runTask->topOfStack + runTask->stackSize; //内核态的 栈底 = 栈顶 + 大小
979 UINT32 *stackPointer = (UINT32 *)stackBottom;
980
981 PrintExcInfo("runTask->stackPointer = 0x%x\n"
982 "runTask->topOfStack = 0x%x\n"
983 "text_start:0x%x,text_end:0x%x\n",
984 stackPointer, runTask->topOfStack, &__text_start, &__text_end);
985 //打印OS_MAX_BACKTRACE多一条栈信息,注意stack中存放的是函数调用地址和指令的地址
986 while ((stackPointer > (UINT32 *)runTask->topOfStack) && (count < OS_MAX_BACKTRACE)) {
987 if ((*stackPointer > (UINTPTR)(&__text_start)) && //正常情况下 sp的内容都是文本段的内容
988 (*stackPointer < (UINTPTR)(&__text_end)) &&
989 IS_ALIGNED((*stackPointer), POINTER_SIZE)) { //sp的内容是否对齐, sp指向指令的地址
990 if ((*(stackPointer - 1) > (UINT32)runTask->topOfStack) &&
991 (*(stackPointer - 1) < stackBottom) && //@note_why 这里为什么要对 stackPointer - 1 进行判断
992 IS_ALIGNED((*(stackPointer - 1)), POINTER_SIZE)) {
993 count++;
994 PrintExcInfo("traceback %u -- lr = 0x%x\n", count, *stackPointer);
995 }
996 }
997 stackPointer--;
998 }
999 PRINTK("\n");
1000}
1001/***********************************************
1002R11寄存器(frame pointer)
1003在程序执行过程中(通常是发生了某种意外情况而需要进行调试),通过SP和FP所限定的stack frame,
1004就可以得到母函数的SP和FP,从而得到母函数的stack frame(PC,LR,SP,FP会在函数调用的第一时间压栈),
1005以此追溯,即可得到所有函数的调用顺序。
1006***********************************************/
1007VOID OsTaskBackTrace(UINT32 taskID) //任务栈信息追溯
1008{
1009 LosTaskCB *taskCB = NULL;
1010
1011 if (OS_TID_CHECK_INVALID(taskID)) {
1012 PRINT_ERR("\r\nTask ID is invalid!\n");
1013 return;
1014 }
1015 taskCB = OS_TCB_FROM_TID(taskID);
1016 if (OsTaskIsUnused(taskCB) || (taskCB->taskEntry == NULL)) {
1017 PRINT_ERR("\r\nThe task is not created!\n");
1018 return;
1019 }
1020 PRINTK("TaskName = %s\n", taskCB->taskName);
1021 PRINTK("TaskID = 0x%x\n", taskCB->taskID);
1022 BackTrace(((TaskContext *)(taskCB->stackPointer))->R11); /* R11 : FP */
1023}
1024
1025VOID OsBackTrace(VOID)
1026{
1027 UINT32 regFP = Get_Fp();
1028 LosTaskCB *runTask = OsCurrTaskGet();
1029 PrintExcInfo("OsBackTrace fp = 0x%x\n", regFP);
1030 PrintExcInfo("runTask->taskName = %s\n", runTask->taskName);
1031 PrintExcInfo("runTask->taskID = %u\n", runTask->taskID);
1032 BackTrace(regFP);
1033}
1034///未定义的异常处理函数,由汇编调用 见于 los_hw_exc.s
1035#ifdef LOSCFG_GDB
1037{
1038 excBufAddr->PC -= 4; /* lr in undef is pc + 4 */
1039
1040 if (gdb_undef_hook(excBufAddr, OS_EXCEPT_UNDEF_INSTR)) {
1041 return;
1042 }
1043
1044 if (g_excHook != NULL) {//是否注册异常打印函数
1045 /* far, fsr are unused in exc type of OS_EXCEPT_UNDEF_INSTR */
1046 g_excHook(OS_EXCEPT_UNDEF_INSTR, excBufAddr, 0, 0); //回调函数,详见: OsExcHook
1047 }
1048 while (1) {}
1049}
1050
1051///预取指令异常处理函数,由汇编调用 见于 los_hw_exc.s
1052#if __LINUX_ARM_ARCH__ >= 7
1054{
1055 UINT32 far;
1056 UINT32 fsr;
1057
1058 excBufAddr->PC -= 4; /* lr in prefetch abort is pc + 4 */
1059
1060 if (gdbhw_hook(excBufAddr, OS_EXCEPT_PREFETCH_ABORT)) {
1061 return;
1062 }
1063
1064 if (g_excHook != NULL) {
1065 far = OsArmReadIfar(); //far 为CP15的 C6寄存器 详见:https://blog.csdn.net/kuangyufei/article/details/108994081
1066 fsr = OsArmReadIfsr(); //fsr 为CP15的 C5寄存器
1067 g_excHook(OS_EXCEPT_PREFETCH_ABORT, excBufAddr, far, fsr); //回调函数,详见: OsExcHook
1068 }
1069 while (1) {}
1070}
1071
1072///数据中止异常处理函数,由汇编调用 见于 los_hw_exc.s
1074{
1075 UINT32 far;
1076 UINT32 fsr;
1077
1078 excBufAddr->PC -= 8; /* lr in data abort is pc + 8 */
1079
1080 if (gdbhw_hook(excBufAddr, OS_EXCEPT_DATA_ABORT)) {
1081 return;
1082 }
1083
1084 if (g_excHook != NULL) {
1085 far = OsArmReadDfar();
1086 fsr = OsArmReadDfsr();
1087 g_excHook(OS_EXCEPT_DATA_ABORT, excBufAddr, far, fsr); ////回调函数,详见: OsExcHook
1088 }
1089 while (1) {}
1090}
1091#endif /* __LINUX_ARM_ARCH__ */
1092#endif /* LOSCFG_GDB */
1093
1094#ifdef LOSCFG_KERNEL_SMP
1095#define EXC_WAIT_INTER 50U //异常等待间隔时间
1096#define EXC_WAIT_TIME 2000U //异常等待时间
1097
1098///等待所有CPU停止
1099STATIC VOID WaitAllCpuStop(UINT32 cpuid)
1100{
1101 UINT32 i;
1102 UINT32 time = 0;
1103
1104 while (time < EXC_WAIT_TIME) {
1105 for (i = 0; i < LOSCFG_KERNEL_CORE_NUM; i++) {
1106 if ((i != cpuid) && !OsCpuStatusIsHalt(i)) {
1107 LOS_Mdelay(EXC_WAIT_INTER);
1108 time += EXC_WAIT_INTER;
1109 break;
1110 }
1111 }
1112 /* Other CPUs are all haletd or in the exc. */
1113 if (i == LOSCFG_KERNEL_CORE_NUM) {
1114 break;
1115 }
1116 }
1117 return;
1118}
1119
1121{
1122 while (1) {
1123 LOS_SpinLock(&g_excSerializerSpin);
1124 if ((g_currHandleExcCpuid == INVALID_CPUID) || (g_currHandleExcCpuid == currCpuid)) {
1125 g_currHandleExcCpuid = currCpuid;
1127 LOS_SpinUnlock(&g_excSerializerSpin);
1128 break;
1129 }
1130
1131 if (g_nextExcWaitCpu == INVALID_CPUID) {
1132 g_nextExcWaitCpu = currCpuid;
1133 }
1134 LOS_SpinUnlock(&g_excSerializerSpin);
1135 LOS_Mdelay(EXC_WAIT_INTER);
1136 }
1137}
1138///检查所有CPU的状态
1139STATIC VOID OsCheckAllCpuStatus(VOID)
1140{
1141 UINT32 currCpuid = ArchCurrCpuid();
1142 UINT32 ret, target;
1143
1145 LOCKDEP_CLEAR_LOCKS();
1146
1147 LOS_SpinLock(&g_excSerializerSpin);
1148 /* Only the current CPU anomaly */
1149 if (g_currHandleExcCpuid == INVALID_CPUID) {
1150 g_currHandleExcCpuid = currCpuid;
1152 LOS_SpinUnlock(&g_excSerializerSpin);
1153#ifndef LOSCFG_SAVE_EXCINFO
1154 if (g_excFromUserMode[currCpuid] == FALSE) {
1155 target = (UINT32)(OS_MP_CPU_ALL & ~CPUID_TO_AFFI_MASK(currCpuid));
1157 }
1158#endif
1159 } else if (g_excFromUserMode[currCpuid] == TRUE) {
1160 /* Both cores raise exceptions, and the current core is a user-mode exception.
1161 * Both cores are abnormal and come from the same process
1162 */
1163 if (OsCurrProcessGet()->processID == g_currHandleExcPID) {
1164 LOS_SpinUnlock(&g_excSerializerSpin);
1165 OsExcRestore();
1166 ret = LOS_TaskDelete(OsCurrTaskGet()->taskID);
1167 LOS_Panic("%s supend task :%u failed: 0x%x\n", __FUNCTION__, OsCurrTaskGet()->taskID, ret);
1168 }
1169 LOS_SpinUnlock(&g_excSerializerSpin);
1170
1172 } else {
1173 if ((g_currHandleExcCpuid < LOSCFG_KERNEL_CORE_NUM) && (g_excFromUserMode[g_currHandleExcCpuid] == TRUE)) {
1174 g_currHandleExcCpuid = currCpuid;
1175 LOS_SpinUnlock(&g_excSerializerSpin);
1176 target = (UINT32)(OS_MP_CPU_ALL & ~CPUID_TO_AFFI_MASK(currCpuid));
1178 } else {
1179 LOS_SpinUnlock(&g_excSerializerSpin);
1180 while (1) {}
1181 }
1182 }
1183#ifndef LOSCFG_SAVE_EXCINFO
1184 /* use halt ipi to stop other active cores */
1185 if (g_excFromUserMode[ArchCurrCpuid()] == FALSE) {
1186 WaitAllCpuStop(currCpuid);
1187 }
1188#endif
1189}
1190#endif
1191
1192STATIC VOID OsCheckCpuStatus(VOID)
1193{
1194#ifdef LOSCFG_KERNEL_SMP
1196#else
1198#endif
1199}
1200///执行期间的优先处理 excBufAddr为CPU异常上下文,
1201LITE_OS_SEC_TEXT VOID STATIC OsExcPriorDisposal(ExcContext *excBufAddr)
1202{
1203 if ((excBufAddr->regCPSR & CPSR_MASK_MODE) == CPSR_USER_MODE) { //用户模式下,访问地址不能出用户空间
1204 g_minAddr = USER_ASPACE_BASE; //可访问地址范围的开始地址,
1205 g_maxAddr = USER_ASPACE_BASE + USER_ASPACE_SIZE; //地址范围的结束地址,就是用户空间
1206 g_excFromUserMode[ArchCurrCpuid()] = TRUE; //当前CPU执行切到用户态
1207 } else {
1208 g_minAddr = KERNEL_ASPACE_BASE; //可访问地址范围的开始地址
1209 g_maxAddr = KERNEL_ASPACE_BASE + KERNEL_ASPACE_SIZE; //可访问地址范围的结束地址
1210 g_excFromUserMode[ArchCurrCpuid()] = FALSE; //当前CPU执行切到内核态
1211 }
1212
1214
1215#ifdef LOSCFG_KERNEL_SMP
1216#ifdef LOSCFG_FS_VFS
1217 /* Wait for the end of the Console task to avoid multicore printing code */
1218 OsWaitConsoleSendTaskPend(OsCurrTaskGet()->taskID); //等待控制台任务结束,以避免多核打印代码
1219#endif
1220#endif
1221}
1222///异常信息头部打印
1223LITE_OS_SEC_TEXT_INIT STATIC VOID OsPrintExcHead(UINT32 far)
1224{
1225#ifdef LOSCFG_BLACKBOX
1226#ifdef LOSCFG_SAVE_EXCINFO
1227 SetExcInfoIndex(0);
1228#endif
1229#endif
1230#ifdef LOSCFG_KERNEL_VM
1231 /* You are not allowed to add any other print information before this exception information */
1232 if (g_excFromUserMode[ArchCurrCpuid()] == TRUE) {
1233#ifdef LOSCFG_DEBUG_VERSION
1234 VADDR_T vaddr = ROUNDDOWN(far, PAGE_SIZE);
1235 LosVmSpace *space = LOS_SpaceGet(vaddr);
1236 if (space != NULL) {
1237 LOS_DumpMemRegion(vaddr);
1238 }
1239#endif
1240 PrintExcInfo("##################excFrom: User!####################\n"); //用户态异常信息说明
1241 } else
1242#endif
1243 {
1244 PrintExcInfo("##################excFrom: kernel!###################\n"); //内核态异常信息说明
1245 }
1246}
1247
1248#ifdef LOSCFG_SAVE_EXCINFO
1249STATIC VOID OsSysStateSave(UINT32 *intCount, UINT32 *lockCount)
1250{
1251 *intCount = g_intCount[ArchCurrCpuid()];
1252 *lockCount = OsSchedLockCountGet();
1254 OsSchedLockSet(0);
1255}
1256
1257STATIC VOID OsSysStateRestore(UINT32 intCount, UINT32 lockCount)
1258{
1259 g_intCount[ArchCurrCpuid()] = intCount;
1260 OsSchedLockSet(lockCount);
1261}
1262#endif
1263
1264/*
1265 * Description : EXC handler entry
1266 * Input : excType --- exc type
1267 * excBufAddr --- address of EXC buf
1268 */
1269LITE_OS_SEC_TEXT_INIT VOID OsExcHandleEntry(UINT32 excType, ExcContext *excBufAddr, UINT32 far, UINT32 fsr)
1270{ //异常信息处理入口
1271#ifdef LOSCFG_SAVE_EXCINFO
1272 UINT32 intCount;
1273 UINT32 lockCount;
1274#endif
1275 /* Task scheduling is not allowed during exception handling */
1276 OsSchedLock();
1277
1279
1280 OsExcPriorDisposal(excBufAddr);
1281
1282 OsPrintExcHead(far); //打印异常信息头部信息 ##################excFrom: User!####################
1283
1284#ifdef LOSCFG_KERNEL_SMP
1285 OsAllCpuStatusOutput(); //打印各CPU core的状态
1286#endif
1287
1288#ifdef LOSCFG_SAVE_EXCINFO
1289 log_read_write_fn func = GetExcInfoRW(); //获取异常信息读写函数,用于打印异常信息栈
1290#endif
1291
1292 if (g_excHook != NULL) {//全局异常钩子函数
1293 if (g_curNestCount[ArchCurrCpuid()] == 1) {//说明只有一个异常
1294#ifdef LOSCFG_SAVE_EXCINFO
1295 if (func != NULL) {
1296#ifndef LOSCFG_BLACKBOX
1297 SetExcInfoIndex(0);
1298#endif
1299 OsSysStateSave(&intCount, &lockCount);
1301 OsSysStateRestore(intCount, lockCount);
1302 }
1303#endif
1304 g_excHook(excType, excBufAddr, far, fsr);
1305 } else { //说明出现了异常嵌套的情况
1306 OsCallStackInfo(); //打印栈内容
1307 }
1308
1309#ifdef LOSCFG_SAVE_EXCINFO
1310 if (func != NULL) {
1311 PrintExcInfo("Be sure flash space bigger than GetExcInfoIndex():0x%x\n", GetExcInfoIndex());
1312 OsSysStateSave(&intCount, &lockCount);
1314 OsSysStateRestore(intCount, lockCount);
1315 }
1316#endif
1317 }
1318
1319#ifdef LOSCFG_SHELL_CMD_DEBUG
1320 SystemRebootFunc rebootHook = OsGetRebootHook();
1321 if ((OsSystemExcIsReset() == TRUE) && (rebootHook != NULL)) {
1322 LOS_Mdelay(3000); /* 3000: System dead, delay 3 seconds after system restart */
1323 rebootHook();
1324 }
1325#endif
1326
1327#ifdef LOSCFG_BLACKBOX
1328 BBoxNotifyError(EVENT_PANIC, MODULE_SYSTEM, "Crash in kernel", 1);
1329#endif
1330 while (1) {}
1331}
1332
1333__attribute__((noinline)) VOID LOS_Panic(const CHAR *fmt, ...)
1334{
1335 va_list ap;
1336 va_start(ap, fmt);
1337 OsVprintf(fmt, ap, EXC_OUTPUT);
1338 va_end(ap);
1339 __asm__ __volatile__("swi 0"); //触发断异常
1340 while (1) {}
1341}
1342
1343/* stack protector */
1344USED UINT32 __stack_chk_guard = 0xd00a0dff;
1345
1347{
1348 /* __builtin_return_address is a builtin function, building in gcc */
1349 LOS_Panic("stack-protector: Kernel stack is corrupted in: %p\n",
1350 __builtin_return_address(0));
1351}
1352
1353VOID LOS_RecordLR(UINTPTR *LR, UINT32 LRSize, UINT32 recordCount, UINT32 jumpCount)
1354{
1355 UINT32 count = 0;
1356 UINT32 index = 0;
1357 UINT32 stackStart, stackEnd;
1358 LosTaskCB *taskCB = NULL;
1359 UINTPTR framePtr, tmpFramePtr, linkReg;
1360
1361 if (LR == NULL) {
1362 return;
1363 }
1364 /* if LR array is not enough,just record LRSize. */
1365 if (LRSize < recordCount) {
1366 recordCount = LRSize;
1367 }
1368
1369 taskCB = OsCurrTaskGet();
1370 stackStart = taskCB->topOfStack;
1371 stackEnd = stackStart + taskCB->stackSize;
1372
1373 framePtr = Get_Fp();
1374 while ((framePtr > stackStart) && (framePtr < stackEnd) && IS_ALIGNED(framePtr, sizeof(CHAR *))) {
1375 tmpFramePtr = framePtr;
1376#ifdef LOSCFG_COMPILER_CLANG_LLVM
1377 linkReg = *(UINTPTR *)(tmpFramePtr + sizeof(UINTPTR));
1378#else
1379 linkReg = *(UINTPTR *)framePtr;
1380#endif
1381 if (index >= jumpCount) {
1382 LR[count++] = linkReg;
1383 if (count == recordCount) {
1384 break;
1385 }
1386 }
1387 index++;
1388#ifdef LOSCFG_COMPILER_CLANG_LLVM
1389 framePtr = *(UINTPTR *)framePtr;
1390#else
1391 framePtr = *(UINTPTR *)(tmpFramePtr - sizeof(UINTPTR));
1392#endif
1393 }
1394
1395 /* if linkReg is not enough,clean up the last of the effective LR as the end. */
1396 if (count < recordCount) {
1397 LR[count] = 0;
1398 }
1399}
STATIC INLINE UINT32 OsArmReadDfar(VOID)
Definition: arm.h:169
STATIC INLINE UINT32 OsArmReadIfsr(VOID)
Definition: arm.h:156
STATIC INLINE UINT32 OsArmReadIfar(VOID)
Definition: arm.h:195
STATIC INLINE UINT32 OsArmReadDfsr(VOID)
Definition: arm.h:143
STATIC INLINE VOID OsArmWriteTlbimvaais(UINT32 val)
Definition: arm.h:527
macro EXC_SP_SET stackBottom
Definition: asm.h:50
VOID OsWakeConsoleSendTask(VOID)
唤醒控制台发送任务
Definition: console.c:1658
VOID OsWaitConsoleSendTaskPend(UINT32 taskID)
Definition: console.c:1633
VOID HalIrqSendIpi(UINT32 target, UINT32 ipi)
Definition: gic_v2.c:58
VOID(* log_read_write_fn)(UINT32 startAddr, UINT32 space, UINT32 rwFlag, CHAR *buf)
define the type of functions for reading or writing exception information.
Definition: los_config.h:435
LITE_OS_SEC_TEXT_INIT UINT32 LOS_ExcRegHook(EXC_PROC_FUNC excHook)
注册异常处理钩子
Definition: los_exc.c:498
VOID LOS_RecordLR(UINTPTR *LR, UINT32 LRSize, UINT32 recordCount, UINT32 jumpCount)
record LR function.
Definition: los_exc.c:1353
VOID OsTaskBackTrace(UINT32 taskID)
Kernel task backtrace function.
Definition: los_exc.c:1007
VOID(* EXC_PROC_FUNC)(UINT32, ExcContext *, UINT32, UINT32)
Define an exception handling function hook.
Definition: los_exc.h:153
STATIC INLINE UINTPTR Get_Fp(VOID)
Kernel FP Register address obtain function.
Definition: los_exc.h:123
NORETURN VOID LOS_Panic(const CHAR *fmt,...)
Kernel panic function.
VOID OsBackTrace(VOID)
Kernel backtrace function.
Definition: los_exc.c:1025
size_t g_intCount[LOSCFG_KERNEL_CORE_NUM]
记录每个CPUcore的中断数量
Definition: los_hwi.c:153
STATIC INLINE VOID LOS_IntRestore(UINT32 intSave)
Restore interrupts. | 恢复到使用LOS_IntLock关闭所有中断之前的状态
Definition: los_hwi.h:337
STATIC INLINE UINT32 LOS_IntLock(VOID)
Disable all interrupts. | 关闭当前处理器所有中断响应
Definition: los_hwi.h:286
LITE_OS_SEC_BSS UINT32 g_taskMaxNum
任务最大数量 默认128个
Definition: los_task.c:150
LITE_OS_SEC_TEXT_INIT UINT32 LOS_TaskDelete(UINT32 taskID)
Delete a task.
Definition: los_task.c:968
LITE_OS_SEC_BSS LosTaskCB * g_taskCBArray
外部变量 任务池 默认128个
Definition: los_task.c:147
LITE_OS_SEC_TEXT_MINOR VOID LOS_Mdelay(UINT32 msecs)
以ms为单位的忙等,但可以被优先级更高的任务抢占
Definition: los_hw_tick.c:73
https://blog.csdn.net/qq_38410730/article/details/81036768
STATUS_T LOS_ArchMmuQuery(const LosArchMmu *archMmu, VADDR_T vaddr, PADDR_T *paddr, UINT32 *flags)
LOS_ArchMmuQuery 获取进程空间虚拟地址对应的物理地址以及映射属性。 本函数是内核高频函数,通过MMU查询虚拟地址是否映射过,带走映射的物理地址和权限
Definition: los_arch_mmu.c:569
int BBoxNotifyError(const char event[EVENT_MAX_LEN], const char module[MODULE_MAX_LEN], const char errorDesc[ERROR_DESC_MAX_LEN], int needSysReset)
SystemRebootFunc OsGetRebootHook(VOID)
获取系统重启钩子函数
Definition: los_config.c:63
CHAR __text_end
代码区结束地址
VOID(* SystemRebootFunc)(VOID)
Definition: los_config.h:475
CHAR __text_start
代码区开始地址
STATIC UINT32 g_currHandleExcCpuid
Definition: los_exc.c:126
STATIC VOID WaitAllCpuStop(UINT32 cpuid)
等待所有CPU停止
Definition: los_exc.c:1099
STATIC VOID OsDumpProcessUsedMemRegion(LosProcessCB *runProcess, LosVmSpace *runspace, UINT16 vmmFlags)
dump 进程使用的内存线性区
Definition: los_exc.c:557
STATIC UINTPTR g_maxAddr
Definition: los_exc.c:125
STATIC VOID OsUserExcHandle(ExcContext *excBufAddr)
用户态异常处理函数
Definition: los_exc.c:651
STATIC UINTPTR g_minAddr
Definition: los_exc.c:124
VOID OsCallStackInfo(VOID)
打印调用栈信息
Definition: los_exc.c:974
STATIC INT32 OsDecodeDataFSR(UINT32 regDFSR)
Definition: los_exc.c:231
STATIC VOID OsCheckAllCpuStatus(VOID)
检查所有CPU的状态
Definition: los_exc.c:1139
BOOL g_excFromUserMode[LOSCFG_KERNEL_CORE_NUM]
记录CPU core 异常来自用户态还是内核态 TRUE为用户态,默认为内核态
Definition: los_exc.c:129
VOID OsDumpContextMem(const ExcContext *excBufAddr)
dump 上下文内存,注意内核异常不能简单的映射理解为应用的异常,异常对内核来说是一个很常见操作, 比如任务的切换对内核来说就是一个异常处理
Definition: los_exc.c:608
STATIC const StackInfo g_excStack[]
Definition: los_exc.c:176
VOID BackTrace(UINT32 regFP)
打印调用栈信息
Definition: los_exc.c:930
STATIC VOID OsSysStateRestore(UINT32 intCount, UINT32 lockCount)
Definition: los_exc.c:1257
UINT32 OsGetSystemStatus(VOID)
获取系统状态
Definition: los_exc.c:181
STATIC const CHAR * g_excTypeString[]
Definition: los_exc.c:346
LITE_OS_SEC_TEXT VOID STATIC OsExcPriorDisposal(ExcContext *excBufAddr)
执行期间的优先处理 excBufAddr为CPU异常上下文,
Definition: los_exc.c:1201
UINT32 OsArmSharedPageFault(UINT32 excType, ExcContext *frame, UINT32 far, UINT32 fsr)
共享页缺失异常
Definition: los_exc.c:261
STATIC VOID OsExcType(UINT32 excType, ExcContext *excBufAddr, UINT32 far, UINT32 fsr)
异常类型
Definition: los_exc.c:326
STATIC VOID OsCheckCpuStatus(VOID)
Definition: los_exc.c:1192
STATIC VOID OsDumpExcVaddrRegion(LosVmSpace *space, LosVmMapRegion *region)
dump 虚拟空间下异常虚拟地址线性区
Definition: los_exc.c:515
STATIC INT32 OsDecodeFS(UINT32 bitsFS)
Definition: los_exc.c:197
STATIC VOID OsSysStateSave(UINT32 *intCount, UINT32 *lockCount)
Definition: los_exc.c:1249
BOOL OsGetUsrIpInfo(UINTPTR ip, IpInfo *info)
Definition: los_exc.c:804
UINT32 g_curNestCount[LOSCFG_KERNEL_CORE_NUM]
记录当前嵌套异常的数量
Definition: los_exc.c:128
STATIC INLINE BOOL IsValidFP(UINTPTR regFP, UINTPTR start, UINTPTR end, vaddr_t *vaddr)
此函数用于验证fp或验证检查开始和结束范围
Definition: los_exc.c:716
STATIC EXC_PROC_FUNC g_excHook
全局异常处理钩子
Definition: los_exc.c:130
STATIC VOID OsExcRestore(VOID)
异常恢复,继续执行
Definition: los_exc.c:638
VOID OsPrefetchAbortExcHandleEntry(ExcContext *excBufAddr)
预取指令异常处理函数,由汇编调用 见于 los_hw_exc.s
Definition: los_exc.c:1053
STATIC INT32 OsDecodeInstructionFSR(UINT32 regIFSR)
Definition: los_exc.c:222
VOID BackTraceSub(UINTPTR regFP)
Definition: los_exc.c:925
STATIC VADDR_T OsGetTextRegionBase(LosVmMapRegion *region, LosProcessCB *runProcess)
Definition: los_exc.c:359
VOID OsExcHook(UINT32 excType, ExcContext *excBufAddr, UINT32 far, UINT32 fsr)
由注册后回调,发送异常情况下会回调这里执行,见于 OsUndefIncExcHandleEntry, OsExcHandleEntry ==函数
Definition: los_exc.c:942
VOID __stack_chk_fail(VOID)
Definition: los_exc.c:1346
STATIC VOID OsDumpProcessUsedMemNode(UINT16 vmmFlags)
dump 进程使用的内存节点
Definition: los_exc.c:576
VOID OsUndefIncExcHandleEntry(ExcContext *excBufAddr)
未定义的异常处理函数,由汇编调用 见于 los_hw_exc.s
Definition: los_exc.c:1036
STATIC VOID OsExcSysInfo(UINT32 excType, const ExcContext *excBufAddr)
打印异常系统信息
Definition: los_exc.c:401
LITE_OS_SEC_TEXT_INIT STATIC VOID OsPrintExcHead(UINT32 far)
异常信息头部打印
Definition: los_exc.c:1223
VOID OsExcInit(VOID)
异常接管模块的初始化
Definition: los_exc.c:937
STATIC VOID OsWaitOtherCoresHandleExcEnd(UINT32 currCpuid)
Definition: los_exc.c:1120
VOID OsDataAbortExcHandleEntry(ExcContext *excBufAddr)
数据中止异常处理函数,由汇编调用 见于 los_hw_exc.s
Definition: los_exc.c:1073
UINT32 BackTraceGet(UINTPTR regFP, IpInfo *callChain, UINT32 maxDepth)
Definition: los_exc.c:850
EXC_PROC_FUNC OsExcRegHookGet(VOID)
获取hook函数
Definition: los_exc.c:509
USED UINT32 __stack_chk_guard
Definition: los_exc.c:1344
STATIC INLINE BOOL FindSuitableStack(UINTPTR regFP, UINTPTR *start, UINTPTR *end, vaddr_t *vaddr)
找到一个合适的栈
Definition: los_exc.c:747
STATIC UINT32 g_currHandleExcPID
Definition: los_exc.c:133
STATIC UINT32 g_nextExcWaitCpu
Definition: los_exc.c:134
__attribute__((noinline))
可变参数,输出到控制台
Definition: los_exc.c:1333
STATIC VOID OsExcRegsInfo(const ExcContext *excBufAddr)
异常情况下打印各寄存器的信息
Definition: los_exc.c:471
STATIC SPIN_LOCK_INIT(g_excSerializerSpin)
LITE_OS_SEC_TEXT_INIT VOID OsExcHandleEntry(UINT32 excType, ExcContext *excBufAddr, UINT32 far, UINT32 fsr)
Definition: los_exc.c:1269
BOOL OsSystemExcIsReset(VOID)
UINT32 GetExcInfoIndex(VOID)
获取异常信息索引位
Definition: los_excinfo.c:74
CHAR * GetExcInfoBuf(VOID)
获取异常信息的缓存
Definition: los_excinfo.c:64
UINT32 GetRecordAddr(VOID)
Definition: los_excinfo.c:84
UINT32 GetRecordSpace(VOID)
Definition: los_excinfo.c:94
log_read_write_fn GetExcInfoRW(VOID)
获取异常信息读写函数
Definition: los_excinfo.c:54
VOID OsRecordExcInfoTime(VOID)
记录异常信息产生的时间
Definition: los_excinfo.c:149
VOID SetExcInfoIndex(UINT32 index)
设置异常信息索引位
Definition: los_excinfo.c:69
STATIC INLINE VOID ArchIrqDisable(VOID)
Definition: los_hw_cpu.h:214
STATIC INLINE UINT32 ArchCurrCpuid(VOID)
Definition: los_hw_cpu.h:168
STATIC INLINE VOID ArchIrqEnable(VOID)
Definition: los_hw_cpu.h:223
UINT32 OsShellCmdMemCheck(INT32 argc, const CHAR *argv[])
VOID OsDumpMemByte(size_t length, UINTPTR addr)
@ LOS_MP_IPI_HALT
!< 调度CPU
Definition: los_mp.h:52
STATIC INLINE UINT32 OsCpuStatusIsHalt(UINT16 cpuid)
@ CPU_EXC
cpu in the exc | CPU处于异常状态
@ CPU_RUNNING
cpu is running | CPU正在运行状态
VOID OsAllCpuStatusOutput(VOID)
Definition: los_percpu.c:38
STATIC INLINE VOID OsCpuStatusSet(ExcFlag flag)
VOID OsVprintf(const CHAR *fmt, va_list ap, OutputType type)
printf由 print 和 format 两个单词构成,格式化输出函数, 一般用于向标准输出设备按规定格式输出信息
Definition: los_printf.c:138
@ EXC_OUTPUT
Definition: los_printf.h:108
VOID PrintExcInfo(const CHAR *fmt,...)
打印异常信息
Definition: los_printf.c:263
LITE_OS_SEC_TEXT VOID LOS_Exit(INT32 status)
LOS_Exit 进程退出
Definition: los_process.c:2086
STATIC INLINE BOOL OsProcessIsUserMode(const LosProcessCB *processCB)
STATIC INLINE VOID OsProcessExitCodeSignalSet(LosProcessCB *processCB, UINT32 signal)
设置进程退出信号(0 ~ 7)
STATIC INLINE LosProcessCB * OsCurrProcessGet(VOID)
STATIC INLINE VOID OsProcessExitCodeCoreDumpSet(LosProcessCB *processCB)
置进程退出码第七位为1
STATIC INLINE LosTaskCB * OsCurrTaskGet(VOID)
STATIC INLINE UINT32 OsSchedLockCountGet(VOID)
STATIC INLINE VOID OsSchedLockSet(UINT32 count)
STATIC INLINE VOID OsSchedLock(VOID)
STATIC INLINE BOOL OsSchedIsLock(VOID)
VOID OsSigIntUnlock(VOID)
Definition: los_signal.c:712
VOID OsSigIntLock(VOID)
Definition: los_signal.c:704
BOOL LOS_SpinHeld(const SPIN_LOCK_S *lock)
Definition: los_spinlock.c:45
VOID LOS_SpinLock(SPIN_LOCK_S *lock)
Definition: los_spinlock.c:50
VOID LOS_SpinUnlock(SPIN_LOCK_S *lock)
Definition: los_spinlock.c:84
VOID OsExcStackInfoReg(const StackInfo *stackInfo, UINT32 stackNum)
注册栈信息
VOID OsExcStackInfo(VOID)
打印栈的信息 把每个CPU的栈信息打印出来
UINTPTR __exc_stack
UINTPTR __svc_stack
LITE_OS_SEC_TEXT VOID OsRunningTaskToExit(LosTaskCB *runTask, UINT32 status)
Definition: los_task.c:908
SPIN_LOCK_S g_taskSpin
UINT32 OsShellCmdTskInfoGet(UINT32 taskID, VOID *seqfile, UINT16 flag)
STATIC INLINE BOOL OsTaskIsUnused(const LosTaskCB *taskCB)
任务是否在使用
Definition: los_task_pri.h:255
unsigned short UINT16
Definition: los_typedef.h:56
unsigned long PADDR_T
Definition: los_typedef.h:207
signed int INT32
Definition: los_typedef.h:60
unsigned long paddr_t
Definition: los_typedef.h:209
unsigned long vaddr_t
Definition: los_typedef.h:206
unsigned long VADDR_T
Definition: los_typedef.h:208
unsigned long UINTPTR
Definition: los_typedef.h:68
unsigned int UINT32
Definition: los_typedef.h:57
char CHAR
Definition: los_typedef.h:63
size_t BOOL
Definition: los_typedef.h:88
const CHAR * OsGetRegionNameOrFilePath(LosVmMapRegion *region)
Definition: los_vm_dump.c:57
INT32 OsRegionOverlapCheckUnlock(LosVmSpace *space, LosVmMapRegion *region)
Definition: los_vm_dump.c:85
STATUS_T OsVmPageFaultHandler(VADDR_T vaddr, UINT32 flags, ExcContext *frame)
Definition: los_vm_fault.c:352
BOOL LOS_IsRegionFileValid(LosVmMapRegion *region)
映射类型为文件的线性区是否有效
Definition: los_vm_map.c:512
LosVmSpace * LOS_SpaceGet(VADDR_T vaddr)
获取虚拟地址对应的进程空间结构体指针
Definition: los_vm_map.c:117
STATIC INLINE BOOL LOS_IsUserAddress(VADDR_T vaddr)
虚拟地址是否在用户空间
Definition: los_vm_map.h:275
LosVmMapRegion * LOS_RegionFind(LosVmSpace *vmSpace, VADDR_T addr)
查找线性区 根据起始地址在进程空间内查找是否存在
Definition: los_vm_map.c:414
VADDR_T * LOS_PaddrToKVaddr(PADDR_T paddr)
通过物理地址获取内核虚拟地址
Definition: los_vm_phys.c:688
VOID LOS_DumpMemRegion(VADDR_T vaddr)
输出内存线性区
UINT32 R1
Definition: los_exc.h:82
UINT32 ULR
Definition: los_exc.h:80
UINT32 R9
Definition: los_exc.h:73
UINT32 R3
Definition: los_exc.h:84
UINT32 R7
Definition: los_exc.h:71
UINT64 LR
Definition: los_exc.h:61
UINT64 SP
Definition: los_exc.h:62
UINT32 R10
Definition: los_exc.h:74
UINT32 R5
Definition: los_exc.h:69
UINT32 PC
Definition: los_exc.h:87
UINT32 regCPSR
Definition: los_exc.h:88
UINT32 R8
Definition: los_exc.h:72
UINT32 USP
Definition: los_exc.h:79
UINT32 R4
Definition: los_exc.h:68
UINT32 R11
Definition: los_exc.h:75
UINT32 R6
Definition: los_exc.h:70
UINT32 R0
Definition: los_exc.h:81
UINT32 R12
Definition: los_exc.h:85
UINT32 R2
Definition: los_exc.h:83
UINTPTR ip
Definition: los_exc_pri.h:51
UINT32 len
Definition: los_exc_pri.h:52
CHAR f_path[REGION_PATH_MAX]
Definition: los_exc_pri.h:53
UINT32 processID
UINT16 processStatus
CHAR processName[OS_PCB_NAME_LEN]
LosVmSpace * vmSpace
UINT32 stackSize
栈大小
VOID * stackTop
栈顶
TSK_ENTRY_FUNC taskEntry
UINT32 taskID
UINT32 stackSize
UINTPTR userMapBase
用户空间的栈顶位置,内存来自用户空间,和topOfStack有本质的区别.
CHAR taskName[OS_TCB_NAME_LEN]
UINTPTR topOfStack
VOID * stackPointer
UINT32 userMapSize
UINT32 size
Definition: los_vm_map.h:85
VADDR_T base
Definition: los_vm_map.h:84
struct VmMapRegion::@4::VmRegionFile rf
union VmMapRegion::@4 unTypeData
LosVmMapRange range
Definition: los_vm_map.h:123
虚拟空间,每个进程都有一个属于自己的虚拟内存地址空间
Definition: los_vm_map.h:146
VADDR_T base
Definition: los_vm_map.h:150
LosRbTree regionRbTree
Definition: los_vm_map.h:148
LosArchMmu archMmu
Definition: los_vm_map.h:157
UINT32 size
Definition: los_vm_map.h:151
vnode并不包含文件名,因为 vnode和文件名是 1:N 的关系
Definition: vnode.h:164
if(tv==NULL)
Definition: time.c:430
time_t time(time_t *t)
Definition: time.c:1224