• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
3  * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without modification,
6  * are permitted provided that the following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright notice, this list of
9  *    conditions and the following disclaimer.
10  *
11  * 2. Redistributions in binary form must reproduce the above copyright notice, this list
12  *    of conditions and the following disclaimer in the documentation and/or other materials
13  *    provided with the distribution.
14  *
15  * 3. Neither the name of the copyright holder nor the names of its contributors may be used
16  *    to endorse or promote products derived from this software without specific prior written
17  *    permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
23  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
26  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
28  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
29  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 #include "los_exc.h"
33 #include "los_memory_pri.h"
34 #include "los_printf_pri.h"
35 #include "los_task_pri.h"
36 #include "los_percpu_pri.h"
37 #include "los_hw_pri.h"
38 #ifdef LOSCFG_SAVE_EXCINFO
39 #include "los_excinfo_pri.h"
40 #endif
41 #include "los_sys_stack_pri.h"
42 #ifdef LOSCFG_COREDUMP
43 #include "los_coredump.h"
44 #endif
45 #ifdef LOSCFG_GDB
46 #include "gdb_int.h"
47 #endif
48 #include "los_mp.h"
49 #include "los_vm_map.h"
50 #include "los_vm_dump.h"
51 #include "los_arch_mmu.h"
52 #include "los_vm_phys.h"
53 #include "los_vm_fault.h"
54 #include "los_vm_common.h"
55 #ifdef LOSCFG_KERNEL_DYNLOAD
56 #include "los_load_elf.h"
57 #endif
58 #include "arm.h"
59 #include "los_bitmap.h"
60 #include "los_process_pri.h"
61 #include "los_exc_pri.h"
62 #include "los_sched_pri.h"
63 #ifdef LOSCFG_FS_VFS
64 #include "console.h"
65 #endif
66 #ifdef LOSCFG_BLACKBOX
67 #include "los_blackbox.h"
68 #endif
69 
70 
71 #define INVALID_CPUID  0xFFFF
72 #define OS_EXC_VMM_NO_REGION  0x0U
73 #define OS_EXC_VMM_ALL_REGION 0x1U
74 
75 STATIC UINTPTR g_minAddr;
76 STATIC UINTPTR g_maxAddr;
77 STATIC UINT32 g_currHandleExcCpuID = INVALID_CPUID;
78 VOID OsExcHook(UINT32 excType, ExcContext *excBufAddr, UINT32 far, UINT32 fsr);
79 UINT32 g_curNestCount[LOSCFG_KERNEL_CORE_NUM] = { 0 };
80 BOOL g_excFromUserMode[LOSCFG_KERNEL_CORE_NUM];
81 STATIC EXC_PROC_FUNC g_excHook = (EXC_PROC_FUNC)OsExcHook;
82 #ifdef LOSCFG_KERNEL_SMP
83 STATIC SPIN_LOCK_INIT(g_excSerializerSpin);
84 STATIC UINT32 g_currHandleExcPID = OS_INVALID_VALUE;
85 STATIC UINT32 g_nextExcWaitCpu = INVALID_CPUID;
86 #endif
87 
88 #define OS_MAX_BACKTRACE    15U
89 #define DUMPSIZE            128U
90 #define DUMPREGS            12U
91 #define INSTR_SET_MASK      0x01000020U
92 #define THUMB_INSTR_LEN     2U
93 #define ARM_INSTR_LEN       4U
94 #define POINTER_SIZE        4U
95 #define WNR_BIT             11U
96 #define FSR_FLAG_OFFSET_BIT 10U
97 #define FSR_BITS_BEGIN_BIT  3U
98 
99 
100 #define GET_FS(fsr) (((fsr) & 0xFU) | (((fsr) & (1U << 10)) >> 6))
101 #define GET_WNR(dfsr) ((dfsr) & (1U << 11))
102 
103 #define IS_VALID_ADDR(ptr) (((ptr) >= g_minAddr) &&       \
104                             ((ptr) <= g_maxAddr) && \
105                             (IS_ALIGNED((ptr), sizeof(CHAR *))))
106 
107 STATIC const StackInfo g_excStack[] = {
108     { &__svc_stack,   OS_EXC_SVC_STACK_SIZE,   "svc_stack" },
109     { &__exc_stack,   OS_EXC_STACK_SIZE,       "exc_stack" }
110 };
111 
OsGetSystemStatus(VOID)112 UINT32 OsGetSystemStatus(VOID)
113 {
114     UINT32 flag;
115     UINT32 cpuID = g_currHandleExcCpuID;
116 
117     if (cpuID == INVALID_CPUID) {
118         flag = OS_SYSTEM_NORMAL;
119     } else if (cpuID == ArchCurrCpuid()) {
120         flag = OS_SYSTEM_EXC_CURR_CPU;
121     } else {
122         flag = OS_SYSTEM_EXC_OTHER_CPU;
123     }
124 
125     return flag;
126 }
127 
OsDecodeFS(UINT32 bitsFS)128 STATIC INT32 OsDecodeFS(UINT32 bitsFS)
129 {
130     switch (bitsFS) {
131         case 0x05:  /* 0b00101 */
132         case 0x07:  /* 0b00111 */
133             PrintExcInfo("Translation fault, %s\n", (bitsFS & 0x2) ? "page" : "section");
134             break;
135         case 0x09:  /* 0b01001 */
136         case 0x0b:  /* 0b01011 */
137             PrintExcInfo("Domain fault, %s\n", (bitsFS & 0x2) ? "page" : "section");
138             break;
139         case 0x0d:  /* 0b01101 */
140         case 0x0f:  /* 0b01111 */
141             PrintExcInfo("Permission fault, %s\n", (bitsFS & 0x2) ? "page" : "section");
142             break;
143         default:
144             PrintExcInfo("Unknown fault! FS:0x%x. "
145                          "Check IFSR and DFSR in ARM Architecture Reference Manual.\n",
146                          bitsFS);
147             break;
148     }
149 
150     return LOS_OK;
151 }
152 
OsDecodeInstructionFSR(UINT32 regIFSR)153 STATIC INT32 OsDecodeInstructionFSR(UINT32 regIFSR)
154 {
155     INT32 ret;
156     UINT32 bitsFS = GET_FS(regIFSR); /* FS bits[4]+[3:0] */
157 
158     ret = OsDecodeFS(bitsFS);
159     return ret;
160 }
161 
OsDecodeDataFSR(UINT32 regDFSR)162 STATIC INT32 OsDecodeDataFSR(UINT32 regDFSR)
163 {
164     INT32 ret = 0;
165     UINT32 bitWnR = GET_WNR(regDFSR); /* WnR bit[11] */
166     UINT32 bitsFS = GET_FS(regDFSR);  /* FS bits[4]+[3:0] */
167 
168     if (bitWnR) {
169         PrintExcInfo("Abort caused by a write instruction. ");
170     } else {
171         PrintExcInfo("Abort caused by a read instruction. ");
172     }
173 
174     if (bitsFS == 0x01) { /* 0b00001 */
175         PrintExcInfo("Alignment fault.\n");
176         return ret;
177     }
178     ret = OsDecodeFS(bitsFS);
179     return ret;
180 }
181 
182 #ifdef LOSCFG_KERNEL_VM
OsArmSharedPageFault(UINT32 excType,ExcContext * frame,UINT32 far,UINT32 fsr)183 UINT32 OsArmSharedPageFault(UINT32 excType, ExcContext *frame, UINT32 far, UINT32 fsr)
184 {
185     BOOL instructionFault = FALSE;
186     UINT32 pfFlags = 0;
187     UINT32 fsrFlag;
188     BOOL write = FALSE;
189     UINT32 ret;
190 
191     PRINT_INFO("page fault entry!!!\n");
192     if (OsGetSystemStatus() == OS_SYSTEM_EXC_CURR_CPU) {
193         return LOS_ERRNO_VM_NOT_FOUND;
194     }
195 #if defined(LOSCFG_KERNEL_SMP) && defined(LOSCFG_DEBUG_VERSION)
196     BOOL irqEnable = !(LOS_SpinHeld(&g_taskSpin) && OsSchedIsLock());
197     if (irqEnable) {
198         ArchIrqEnable();
199     } else {
200         PrintExcInfo("[ERR][%s] may be held scheduler lock when entering [%s] on cpu [%u]\n",
201                      OsCurrTaskGet()->taskName, __FUNCTION__, ArchCurrCpuid());
202     }
203 #else
204     ArchIrqEnable();
205 #endif
206     if (excType == OS_EXCEPT_PREFETCH_ABORT) {
207         instructionFault = TRUE;
208     } else {
209         write = !!BIT_GET(fsr, WNR_BIT);
210     }
211 
212     fsrFlag = ((BIT_GET(fsr, FSR_FLAG_OFFSET_BIT) ? 0b10000 : 0) | BITS_GET(fsr, FSR_BITS_BEGIN_BIT, 0));
213     switch (fsrFlag) {
214         case 0b00101:
215         /* translation fault */
216         case 0b00111:
217         /* translation fault */
218         case 0b01101:
219         /* permission fault */
220         case 0b01111: {
221         /* permission fault */
222             BOOL user = (frame->regCPSR & CPSR_MODE_MASK) == CPSR_MODE_USR;
223             pfFlags |= write ? VM_MAP_PF_FLAG_WRITE : 0;
224             pfFlags |= user ? VM_MAP_PF_FLAG_USER : 0;
225             pfFlags |= instructionFault ? VM_MAP_PF_FLAG_INSTRUCTION : 0;
226             pfFlags |= VM_MAP_PF_FLAG_NOT_PRESENT;
227             OsSigIntLock();
228             ret = OsVmPageFaultHandler(far, pfFlags, frame);
229             OsSigIntUnlock();
230             break;
231         }
232         default:
233             OsArmWriteTlbimvaais(ROUNDDOWN(far, PAGE_SIZE));
234             ret = LOS_OK;
235             break;
236     }
237 #if defined(LOSCFG_KERNEL_SMP) && defined(LOSCFG_DEBUG_VERSION)
238     if (irqEnable) {
239         ArchIrqDisable();
240     }
241 #else
242     ArchIrqDisable();
243 #endif
244     return ret;
245 }
246 #endif
247 
OsExcType(UINT32 excType,ExcContext * excBufAddr,UINT32 far,UINT32 fsr)248 STATIC VOID OsExcType(UINT32 excType, ExcContext *excBufAddr, UINT32 far, UINT32 fsr)
249 {
250     /* undefined exception handling or software interrupt */
251     if ((excType == OS_EXCEPT_UNDEF_INSTR) || (excType == OS_EXCEPT_SWI)) {
252         if ((excBufAddr->regCPSR & INSTR_SET_MASK) == 0) { /* work status: ARM */
253             excBufAddr->PC = excBufAddr->PC - ARM_INSTR_LEN;
254         } else if ((excBufAddr->regCPSR & INSTR_SET_MASK) == 0x20) { /* work status: Thumb */
255             excBufAddr->PC = excBufAddr->PC - THUMB_INSTR_LEN;
256         }
257     }
258 
259     if (excType == OS_EXCEPT_PREFETCH_ABORT) {
260         PrintExcInfo("prefetch_abort fault fsr:0x%x, far:0x%0+8x\n", fsr, far);
261         (VOID)OsDecodeInstructionFSR(fsr);
262     } else if (excType == OS_EXCEPT_DATA_ABORT) {
263         PrintExcInfo("data_abort fsr:0x%x, far:0x%0+8x\n", fsr, far);
264         (VOID)OsDecodeDataFSR(fsr);
265     }
266 }
267 
268 STATIC const CHAR *g_excTypeString[] = {
269     "reset",
270     "undefined instruction",
271     "software interrupt",
272     "prefetch abort",
273     "data abort",
274     "fiq",
275     "address abort",
276     "irq"
277 };
278 
279 #ifdef LOSCFG_KERNEL_VM
OsGetTextRegionBase(LosVmMapRegion * region,LosProcessCB * runProcess)280 STATIC VADDR_T OsGetTextRegionBase(LosVmMapRegion *region, LosProcessCB *runProcess)
281 {
282     struct Vnode *curVnode = NULL;
283     struct Vnode *lastVnode = NULL;
284     LosVmMapRegion *curRegion = NULL;
285     LosVmMapRegion *lastRegion = NULL;
286 
287     if ((region == NULL) || (runProcess == NULL)) {
288         return 0;
289     }
290 
291     if (!LOS_IsRegionFileValid(region)) {
292         return region->range.base;
293     }
294 
295     lastRegion = region;
296     do {
297         curRegion = lastRegion;
298         lastRegion = LOS_RegionFind(runProcess->vmSpace, curRegion->range.base - 1);
299         if ((lastRegion == NULL) || !LOS_IsRegionFileValid(lastRegion)) {
300             goto DONE;
301         }
302         curVnode = curRegion->unTypeData.rf.vnode;
303         lastVnode = lastRegion->unTypeData.rf.vnode;
304     } while (curVnode == lastVnode);
305 
306 DONE:
307 #ifdef LOSCFG_KERNEL_DYNLOAD
308     if (curRegion->range.base == EXEC_MMAP_BASE) {
309         return 0;
310     }
311 #endif
312     return curRegion->range.base;
313 }
314 #endif
315 
OsExcSysInfo(UINT32 excType,const ExcContext * excBufAddr)316 STATIC VOID OsExcSysInfo(UINT32 excType, const ExcContext *excBufAddr)
317 {
318     LosTaskCB *runTask = OsCurrTaskGet();
319     LosProcessCB *runProcess = OsCurrProcessGet();
320 
321     PrintExcInfo("excType: %s\n"
322                  "processName       = %s\n"
323                  "processID         = %u\n"
324 #ifdef LOSCFG_KERNEL_VM
325                  "process aspace    = 0x%08x -> 0x%08x\n"
326 #endif
327                  "taskName          = %s\n"
328                  "taskID            = %u\n",
329                  g_excTypeString[excType],
330                  runProcess->processName,
331                  runProcess->processID,
332 #ifdef LOSCFG_KERNEL_VM
333                  runProcess->vmSpace->base,
334                  runProcess->vmSpace->base + runProcess->vmSpace->size,
335 #endif
336                  runTask->taskName,
337                  runTask->taskID);
338 
339 #ifdef LOSCFG_KERNEL_VM
340     if (OsProcessIsUserMode(runProcess)) {
341         PrintExcInfo("task user stack   = 0x%08x -> 0x%08x\n",
342                      runTask->userMapBase, runTask->userMapBase + runTask->userMapSize);
343     } else
344 #endif
345     {
346         PrintExcInfo("task kernel stack = 0x%08x -> 0x%08x\n",
347                      runTask->topOfStack, runTask->topOfStack + runTask->stackSize);
348     }
349 
350     PrintExcInfo("pc    = 0x%x ", excBufAddr->PC);
351 #ifdef LOSCFG_KERNEL_VM
352     LosVmMapRegion *region = NULL;
353     if (g_excFromUserMode[ArchCurrCpuid()] == TRUE) {
354         if (LOS_IsUserAddress((vaddr_t)excBufAddr->PC)) {
355             region = LOS_RegionFind(runProcess->vmSpace, (VADDR_T)excBufAddr->PC);
356             if (region != NULL) {
357                 PrintExcInfo("in %s ---> 0x%x", OsGetRegionNameOrFilePath(region),
358                              (VADDR_T)excBufAddr->PC - OsGetTextRegionBase(region, runProcess));
359             }
360         }
361 
362         PrintExcInfo("\nulr   = 0x%x ", excBufAddr->ULR);
363         region = LOS_RegionFind(runProcess->vmSpace, (VADDR_T)excBufAddr->ULR);
364         if (region != NULL) {
365             PrintExcInfo("in %s ---> 0x%x", OsGetRegionNameOrFilePath(region),
366                          (VADDR_T)excBufAddr->ULR - OsGetTextRegionBase(region, runProcess));
367         }
368         PrintExcInfo("\nusp   = 0x%x", excBufAddr->USP);
369     } else
370 #endif
371     {
372         PrintExcInfo("\nklr   = 0x%x\n"
373                      "ksp   = 0x%x\n",
374                      excBufAddr->LR,
375                      excBufAddr->SP);
376     }
377 
378     PrintExcInfo("\nfp    = 0x%x\n", excBufAddr->R11);
379 }
380 
OsExcRegsInfo(const ExcContext * excBufAddr)381 STATIC VOID OsExcRegsInfo(const ExcContext *excBufAddr)
382 {
383     /*
384      * Split register information into two parts:
385      * Ensure printing does not rely on memory modules.
386      */
387     PrintExcInfo("R0    = 0x%x\n"
388                  "R1    = 0x%x\n"
389                  "R2    = 0x%x\n"
390                  "R3    = 0x%x\n"
391                  "R4    = 0x%x\n"
392                  "R5    = 0x%x\n"
393                  "R6    = 0x%x\n",
394                  excBufAddr->R0, excBufAddr->R1, excBufAddr->R2, excBufAddr->R3,
395                  excBufAddr->R4, excBufAddr->R5, excBufAddr->R6);
396     PrintExcInfo("R7    = 0x%x\n"
397                  "R8    = 0x%x\n"
398                  "R9    = 0x%x\n"
399                  "R10   = 0x%x\n"
400                  "R11   = 0x%x\n"
401                  "R12   = 0x%x\n"
402                  "CPSR  = 0x%x\n",
403                  excBufAddr->R7, excBufAddr->R8, excBufAddr->R9, excBufAddr->R10,
404                  excBufAddr->R11, excBufAddr->R12, excBufAddr->regCPSR);
405 }
406 
LOS_ExcRegHook(EXC_PROC_FUNC excHook)407 LITE_OS_SEC_TEXT_INIT UINT32 LOS_ExcRegHook(EXC_PROC_FUNC excHook)
408 {
409     UINT32 intSave;
410 
411     intSave = LOS_IntLock();
412     g_excHook = excHook;
413     LOS_IntRestore(intSave);
414 
415     return LOS_OK;
416 }
417 
OsExcRegHookGet(VOID)418 EXC_PROC_FUNC OsExcRegHookGet(VOID)
419 {
420     return g_excHook;
421 }
422 
423 #ifdef LOSCFG_KERNEL_VM
OsDumpExcVaddrRegion(LosVmSpace * space,LosVmMapRegion * region)424 STATIC VOID OsDumpExcVaddrRegion(LosVmSpace *space, LosVmMapRegion *region)
425 {
426     INT32 i, numPages, pageCount;
427     paddr_t addr, oldAddr, startVaddr, startPaddr;
428     vaddr_t pageBase;
429     BOOL mmuFlag = FALSE;
430 
431     numPages = region->range.size >> PAGE_SHIFT;
432     mmuFlag = TRUE;
433     for (pageCount = 0, startPaddr = 0, startVaddr = 0, i = 0; i < numPages; i++) {
434         pageBase = region->range.base + i * PAGE_SIZE;
435         addr = 0;
436         if (LOS_ArchMmuQuery(&space->archMmu, pageBase, &addr, NULL) != LOS_OK) {
437             if (startPaddr == 0) {
438                 continue;
439             }
440         } else if (startPaddr == 0) {
441             startVaddr = pageBase;
442             startPaddr = addr;
443             oldAddr = addr;
444             pageCount++;
445             if (numPages > 1) {
446                 continue;
447             }
448         } else if (addr == (oldAddr + PAGE_SIZE)) {
449             pageCount++;
450             oldAddr = addr;
451             if (i < (numPages - 1)) {
452                 continue;
453             }
454         }
455         if (mmuFlag == TRUE) {
456             PrintExcInfo("       uvaddr       kvaddr       mapped size\n");
457             mmuFlag = FALSE;
458         }
459         PrintExcInfo("       0x%08x   0x%08x   0x%08x\n",
460                      startVaddr, LOS_PaddrToKVaddr(startPaddr), (UINT32)pageCount << PAGE_SHIFT);
461         pageCount = 0;
462         startPaddr = 0;
463     }
464 }
465 
OsDumpProcessUsedMemRegion(LosProcessCB * runProcess,LosVmSpace * runspace,UINT16 vmmFlags)466 STATIC VOID OsDumpProcessUsedMemRegion(LosProcessCB *runProcess, LosVmSpace *runspace, UINT16 vmmFlags)
467 {
468     LosVmMapRegion *region = NULL;
469     LosRbNode *pstRbNodeTemp = NULL;
470     LosRbNode *pstRbNodeNext = NULL;
471     UINT32 count = 0;
472 
473     /* search the region list */
474     RB_SCAN_SAFE(&runspace->regionRbTree, pstRbNodeTemp, pstRbNodeNext)
475         region = (LosVmMapRegion *)pstRbNodeTemp;
476         PrintExcInfo("%3u -> regionBase: 0x%08x regionSize: 0x%08x\n", count, region->range.base, region->range.size);
477         if (vmmFlags == OS_EXC_VMM_ALL_REGION) {
478             OsDumpExcVaddrRegion(runspace, region);
479         }
480         count++;
481         (VOID)OsRegionOverlapCheckUnlock(runspace, region);
482     RB_SCAN_SAFE_END(&space->regionRbTree, pstRbNodeTemp, pstRbNodeNext)
483 }
484 
OsDumpProcessUsedMemNode(UINT16 vmmFlags)485 STATIC VOID OsDumpProcessUsedMemNode(UINT16 vmmFlags)
486 {
487     LosProcessCB *runProcess = NULL;
488     LosVmSpace *runspace = NULL;
489 
490     runProcess = OsCurrProcessGet();
491     if (runProcess == NULL) {
492         return;
493     }
494 
495     if (!OsProcessIsUserMode(runProcess)) {
496         return;
497     }
498 
499     PrintExcInfo("\n   ******Current process %u vmm regions: ******\n", runProcess->processID);
500 
501     runspace = runProcess->vmSpace;
502     if (!runspace) {
503         return;
504     }
505 
506     OsDumpProcessUsedMemRegion(runProcess, runspace, vmmFlags);
507     return;
508 }
509 #endif
510 
OsDumpContextMem(const ExcContext * excBufAddr)511 VOID OsDumpContextMem(const ExcContext *excBufAddr)
512 {
513     UINT32 count = 0;
514     const UINT32 *excReg = NULL;
515     if (g_excFromUserMode[ArchCurrCpuid()] == TRUE) {
516         return;
517     }
518 
519     for (excReg = &(excBufAddr->R0); count <= DUMPREGS; excReg++, count++) {
520         if (IS_VALID_ADDR(*excReg)) {
521             PrintExcInfo("\ndump mem around R%u:%p", count, (*excReg));
522             OsDumpMemByte(DUMPSIZE, ((*excReg) - (DUMPSIZE >> 1)));
523         }
524     }
525 
526     if (IS_VALID_ADDR(excBufAddr->SP)) {
527         PrintExcInfo("\ndump mem around SP:%p", excBufAddr->SP);
528         OsDumpMemByte(DUMPSIZE, (excBufAddr->SP - (DUMPSIZE >> 1)));
529     }
530 }
531 
OsExcRestore(VOID)532 STATIC VOID OsExcRestore(VOID)
533 {
534     UINT32 currCpuID = ArchCurrCpuid();
535 
536     g_excFromUserMode[currCpuID] = FALSE;
537     g_intCount[currCpuID] = 0;
538     g_curNestCount[currCpuID] = 0;
539 #ifdef LOSCFG_KERNEL_SMP
540     OsCpuStatusSet(CPU_RUNNING);
541 #endif
542     OsSchedLockSet(0);
543 }
544 
OsUserExcHandle(ExcContext * excBufAddr)545 STATIC VOID OsUserExcHandle(ExcContext *excBufAddr)
546 {
547     UINT32 intSave;
548     UINT32 currCpu = ArchCurrCpuid();
549     LosTaskCB *runTask = OsCurrTaskGet();
550     LosProcessCB *runProcess = OsCurrProcessGet();
551 
552     if (g_excFromUserMode[ArchCurrCpuid()] == FALSE) {
553         return;
554     }
555 
556 #ifdef LOSCFG_KERNEL_SMP
557     LOS_SpinLock(&g_excSerializerSpin);
558     if (g_nextExcWaitCpu != INVALID_CPUID) {
559         g_currHandleExcCpuID = g_nextExcWaitCpu;
560         g_nextExcWaitCpu = INVALID_CPUID;
561     } else {
562         g_currHandleExcCpuID = INVALID_CPUID;
563     }
564     g_currHandleExcPID = OS_INVALID_VALUE;
565     LOS_SpinUnlock(&g_excSerializerSpin);
566 #else
567     g_currHandleExcCpuID = INVALID_CPUID;
568 #endif
569 
570 #ifdef LOSCFG_KERNEL_SMP
571 #ifdef LOSCFG_FS_VFS
572     OsWakeConsoleSendTask();
573 #endif
574 #endif
575 
576 #ifdef LOSCFG_BLACKBOX
577     BBoxNotifyError("USER_CRASH", MODULE_SYSTEM, "Crash in user", 0);
578 #endif
579     SCHEDULER_LOCK(intSave);
580 #ifdef LOSCFG_SAVE_EXCINFO
581     OsProcessExitCodeCoreDumpSet(runProcess);
582 #endif
583     OsProcessExitCodeSignalSet(runProcess, SIGUSR2);
584 
585     /* An exception was raised by a task during the exit process of
586      * the current process.
587      */
588     if (runProcess->processStatus & OS_PROCESS_FLAG_EXIT) {
589         SCHEDULER_UNLOCK(intSave);
590         /* Exception handling All operations should be kept prior to that operation */
591         OsExcRestore();
592         OsRunningTaskToExit(runTask, OS_PRO_EXIT_OK);
593     } else {
594         SCHEDULER_UNLOCK(intSave);
595 
596         /* Exception handling All operations should be kept prior to that operation */
597         OsExcRestore();
598         /* kill user exc process */
599         LOS_Exit(OS_PRO_EXIT_OK);
600     }
601 
602     /* User mode exception handling failed , which normally does not exist */
603     g_curNestCount[currCpu]++;
604     g_intCount[currCpu]++;
605     PrintExcInfo("User mode exception ends unscheduled!\n");
606 }
607 
608 /* this function is used to validate fp or validate the checking range start and end. */
IsValidFP(UINTPTR regFP,UINTPTR start,UINTPTR end,vaddr_t * vaddr)609 STATIC INLINE BOOL IsValidFP(UINTPTR regFP, UINTPTR start, UINTPTR end, vaddr_t *vaddr)
610 {
611     VADDR_T kvaddr = regFP;
612 
613     if (!((regFP > start) && (regFP < end) && IS_ALIGNED(regFP, sizeof(CHAR *)))) {
614         return FALSE;
615     }
616 
617 #ifdef LOSCFG_KERNEL_VM
618     PADDR_T paddr;
619     if (g_excFromUserMode[ArchCurrCpuid()] == TRUE) {
620         LosProcessCB *runProcess = OsCurrProcessGet();
621         LosVmSpace *runspace = runProcess->vmSpace;
622         if (runspace == NULL) {
623             return FALSE;
624         }
625 
626         if (LOS_ArchMmuQuery(&runspace->archMmu, regFP, &paddr, NULL) != LOS_OK) {
627             return FALSE;
628         }
629 
630         kvaddr = (PADDR_T)(UINTPTR)LOS_PaddrToKVaddr(paddr);
631     }
632 #endif
633     if (vaddr != NULL) {
634         *vaddr = kvaddr;
635     }
636 
637     return TRUE;
638 }
639 
FindSuitableStack(UINTPTR regFP,UINTPTR * start,UINTPTR * end,vaddr_t * vaddr)640 STATIC INLINE BOOL FindSuitableStack(UINTPTR regFP, UINTPTR *start, UINTPTR *end, vaddr_t *vaddr)
641 {
642     UINT32 index, stackStart, stackEnd;
643     BOOL found = FALSE;
644     LosTaskCB *taskCB = NULL;
645     const StackInfo *stack = NULL;
646     vaddr_t kvaddr;
647 
648     if (g_excFromUserMode[ArchCurrCpuid()] == TRUE) {
649         taskCB = OsCurrTaskGet();
650         stackStart = taskCB->userMapBase;
651         stackEnd = taskCB->userMapBase + taskCB->userMapSize;
652         if (IsValidFP(regFP, stackStart, stackEnd, &kvaddr) == TRUE) {
653             found = TRUE;
654             goto FOUND;
655         }
656         return found;
657     }
658 
659     /* Search in the task stacks */
660     for (index = 0; index < g_taskMaxNum; index++) {
661         taskCB = &g_taskCBArray[index];
662         if (OsTaskIsUnused(taskCB)) {
663             continue;
664         }
665 
666         stackStart = taskCB->topOfStack;
667         stackEnd = taskCB->topOfStack + taskCB->stackSize;
668         if (IsValidFP(regFP, stackStart, stackEnd, &kvaddr) == TRUE) {
669             found = TRUE;
670             goto FOUND;
671         }
672     }
673 
674     /* Search in the exc stacks */
675     for (index = 0; index < sizeof(g_excStack) / sizeof(StackInfo); index++) {
676         stack = &g_excStack[index];
677         stackStart = (UINTPTR)stack->stackTop;
678         stackEnd = stackStart + LOSCFG_KERNEL_CORE_NUM * stack->stackSize;
679         if (IsValidFP(regFP, stackStart, stackEnd, &kvaddr) == TRUE) {
680             found = TRUE;
681             goto FOUND;
682         }
683     }
684 
685 FOUND:
686     if (found == TRUE) {
687         *start = stackStart;
688         *end = stackEnd;
689         *vaddr = kvaddr;
690     }
691 
692     return found;
693 }
694 
OsGetUsrIpInfo(UINTPTR ip,IpInfo * info)695 BOOL OsGetUsrIpInfo(UINTPTR ip, IpInfo *info)
696 {
697     if (info == NULL) {
698         return FALSE;
699     }
700 #ifdef LOSCFG_KERNEL_VM
701     BOOL ret = FALSE;
702     const CHAR *name = NULL;
703     LosVmMapRegion *region = NULL;
704     LosProcessCB *runProcess = OsCurrProcessGet();
705 
706     if (LOS_IsUserAddress((VADDR_T)ip) == FALSE) {
707         info->ip = ip;
708         name = "kernel";
709         ret = FALSE;
710         goto END;
711     }
712 
713     region = LOS_RegionFind(runProcess->vmSpace, (VADDR_T)ip);
714     if (region == NULL) {
715         info->ip = ip;
716         name = "invalid";
717         ret = FALSE;
718         goto END;
719     }
720 
721     info->ip = ip - OsGetTextRegionBase(region, runProcess);
722     name = OsGetRegionNameOrFilePath(region);
723     ret = TRUE;
724     if (strcmp(name, "/lib/libc.so") != 0) {
725         PRINT_ERR("ip = 0x%x, %s\n", info->ip, name);
726     }
727 END:
728     info->len = strlen(name);
729     if (strncpy_s(info->f_path, REGION_PATH_MAX, name, REGION_PATH_MAX - 1) != EOK) {
730         info->f_path[0] = '\0';
731         info->len = 0;
732         PRINT_ERR("copy f_path failed, %s\n", name);
733     }
734     return ret;
735 #else
736     info->ip = ip;
737     return FALSE;
738 #endif
739 }
740 
BackTraceGet(UINTPTR regFP,IpInfo * callChain,UINT32 maxDepth)741 UINT32 BackTraceGet(UINTPTR regFP, IpInfo *callChain, UINT32 maxDepth)
742 {
743     UINTPTR tmpFP, backLR;
744     UINTPTR stackStart, stackEnd;
745     UINTPTR backFP = regFP;
746     UINT32 count = 0;
747     BOOL ret;
748     VADDR_T kvaddr;
749 
750     if (FindSuitableStack(regFP, &stackStart, &stackEnd, &kvaddr) == FALSE) {
751         if (callChain == NULL) {
752             PrintExcInfo("traceback error fp = 0x%x\n", regFP);
753         }
754         return 0;
755     }
756 
757     /*
758      * Check whether it is the leaf function.
759      * Generally, the frame pointer points to the address of link register, while in the leaf function,
760      * there's no function call, and compiler will not store the link register, but the frame pointer
761      * will still be stored and updated. In that case we needs to find the right position of frame pointer.
762      */
763     tmpFP = *(UINTPTR *)(UINTPTR)kvaddr;
764     if (IsValidFP(tmpFP, stackStart, stackEnd, NULL) == TRUE) {
765         backFP = tmpFP;
766         if (callChain == NULL) {
767             PrintExcInfo("traceback fp fixed, trace using   fp = 0x%x\n", backFP);
768         }
769     }
770 
771     while (IsValidFP(backFP, stackStart, stackEnd, &kvaddr) == TRUE) {
772         tmpFP = backFP;
773 #ifdef LOSCFG_COMPILER_CLANG_LLVM
774         backFP = *(UINTPTR *)(UINTPTR)kvaddr;
775         if (IsValidFP(tmpFP + POINTER_SIZE, stackStart, stackEnd, &kvaddr) == FALSE) {
776             if (callChain == NULL) {
777                 PrintExcInfo("traceback backLR check failed, backLP: 0x%x\n", tmpFP + POINTER_SIZE);
778             }
779             return 0;
780         }
781         backLR = *(UINTPTR *)(UINTPTR)kvaddr;
782 #else
783         backLR = *(UINTPTR *)(UINTPTR)kvaddr;
784         if (IsValidFP(tmpFP - POINTER_SIZE, stackStart, stackEnd, &kvaddr) == FALSE) {
785             if (callChain == NULL) {
786                 PrintExcInfo("traceback backFP check failed, backFP: 0x%x\n", tmpFP - POINTER_SIZE);
787             }
788             return 0;
789         }
790         backFP = *(UINTPTR *)(UINTPTR)kvaddr;
791 #endif
792         IpInfo info = {0};
793         ret = OsGetUsrIpInfo((VADDR_T)backLR, &info);
794         if (callChain == NULL) {
795             PrintExcInfo("traceback %u -- lr = 0x%x    fp = 0x%x ", count, backLR, backFP);
796             if (ret) {
797 #ifdef LOSCFG_KERNEL_VM
798                 PrintExcInfo("lr in %s --> 0x%x\n", info.f_path, info.ip);
799 #else
800                 PrintExcInfo("\n");
801 #endif
802             } else {
803                 PrintExcInfo("\n");
804             }
805         } else {
806             (VOID)memcpy_s(&callChain[count], sizeof(IpInfo), &info, sizeof(IpInfo));
807         }
808         count++;
809         if ((count == maxDepth) || (backFP == tmpFP)) {
810             break;
811         }
812     }
813     return count;
814 }
815 
BackTraceSub(UINTPTR regFP)816 VOID BackTraceSub(UINTPTR regFP)
817 {
818     (VOID)BackTraceGet(regFP, NULL, OS_MAX_BACKTRACE);
819 }
820 
BackTrace(UINT32 regFP)821 VOID BackTrace(UINT32 regFP)
822 {
823     PrintExcInfo("*******backtrace begin*******\n");
824 
825     BackTraceSub(regFP);
826 }
827 
OsExcInit(VOID)828 VOID OsExcInit(VOID)
829 {
830     OsExcStackInfoReg(g_excStack, sizeof(g_excStack) / sizeof(g_excStack[0]));
831 }
832 
OsExcHook(UINT32 excType,ExcContext * excBufAddr,UINT32 far,UINT32 fsr)833 VOID OsExcHook(UINT32 excType, ExcContext *excBufAddr, UINT32 far, UINT32 fsr)
834 {
835     OsExcType(excType, excBufAddr, far, fsr);
836     OsExcSysInfo(excType, excBufAddr);
837     OsExcRegsInfo(excBufAddr);
838 
839     BackTrace(excBufAddr->R11);
840 
841     (VOID)OsShellCmdTskInfoGet(OS_ALL_TASK_MASK, NULL, OS_PROCESS_INFO_ALL);
842 
843 #ifndef LOSCFG_DEBUG_VERSION
844     if (g_excFromUserMode[ArchCurrCpuid()] != TRUE) {
845 #endif
846 #ifdef LOSCFG_KERNEL_VM
847         OsDumpProcessUsedMemNode(OS_EXC_VMM_NO_REGION);
848 #endif
849         OsExcStackInfo();
850 #ifndef LOSCFG_DEBUG_VERSION
851     }
852 #endif
853 
854     OsDumpContextMem(excBufAddr);
855 
856     (VOID)OsShellCmdMemCheck(0, NULL);
857 
858 #ifdef LOSCFG_COREDUMP
859     LOS_CoreDumpV2(excType, excBufAddr);
860 #endif
861 
862     OsUserExcHandle(excBufAddr);
863 }
864 
OsCallStackInfo(VOID)865 VOID OsCallStackInfo(VOID)
866 {
867     UINT32 count = 0;
868     LosTaskCB *runTask = OsCurrTaskGet();
869     UINTPTR stackBottom = runTask->topOfStack + runTask->stackSize;
870     UINT32 *stackPointer = (UINT32 *)stackBottom;
871 
872     PrintExcInfo("runTask->stackPointer = 0x%x\n"
873                  "runTask->topOfStack = 0x%x\n"
874                  "text_start:0x%x,text_end:0x%x\n",
875                  stackPointer, runTask->topOfStack, &__text_start, &__text_end);
876 
877     while ((stackPointer > (UINT32 *)runTask->topOfStack) && (count < OS_MAX_BACKTRACE)) {
878         if ((*stackPointer > (UINTPTR)(&__text_start)) &&
879             (*stackPointer < (UINTPTR)(&__text_end)) &&
880             IS_ALIGNED((*stackPointer), POINTER_SIZE)) {
881             if ((*(stackPointer - 1) > (UINT32)runTask->topOfStack) &&
882                 (*(stackPointer - 1) < stackBottom) &&
883                 IS_ALIGNED((*(stackPointer - 1)), POINTER_SIZE)) {
884                 count++;
885                 PrintExcInfo("traceback %u -- lr = 0x%x\n", count, *stackPointer);
886             }
887         }
888         stackPointer--;
889     }
890     PRINTK("\n");
891 }
892 
OsTaskBackTrace(UINT32 taskID)893 VOID OsTaskBackTrace(UINT32 taskID)
894 {
895     LosTaskCB *taskCB = NULL;
896 
897     if (OS_TID_CHECK_INVALID(taskID)) {
898         PRINT_ERR("\r\nTask ID is invalid!\n");
899         return;
900     }
901     taskCB = OS_TCB_FROM_TID(taskID);
902     if (OsTaskIsUnused(taskCB) || (taskCB->taskEntry == NULL)) {
903         PRINT_ERR("\r\nThe task is not created!\n");
904         return;
905     }
906     PRINTK("TaskName = %s\n", taskCB->taskName);
907     PRINTK("TaskID = 0x%x\n", taskCB->taskID);
908     BackTrace(((TaskContext *)(taskCB->stackPointer))->R11); /* R11 : FP */
909 }
910 
OsBackTrace(VOID)911 VOID OsBackTrace(VOID)
912 {
913     UINT32 regFP = Get_Fp();
914     LosTaskCB *runTask = OsCurrTaskGet();
915     PrintExcInfo("OsBackTrace fp = 0x%x\n", regFP);
916     PrintExcInfo("runTask->taskName = %s\n", runTask->taskName);
917     PrintExcInfo("runTask->taskID = %u\n", runTask->taskID);
918     BackTrace(regFP);
919 }
920 
921 #ifdef LOSCFG_GDB
OsUndefIncExcHandleEntry(ExcContext * excBufAddr)922 VOID OsUndefIncExcHandleEntry(ExcContext *excBufAddr)
923 {
924     excBufAddr->PC -= 4;  /* lr in undef is pc + 4 */
925 
926     if (gdb_undef_hook(excBufAddr, OS_EXCEPT_UNDEF_INSTR)) {
927         return;
928     }
929 
930     if (g_excHook != NULL) {
931         /* far, fsr are unused in exc type of OS_EXCEPT_UNDEF_INSTR */
932         g_excHook(OS_EXCEPT_UNDEF_INSTR, excBufAddr, 0, 0);
933     }
934     while (1) {}
935 }
936 
937 #if __LINUX_ARM_ARCH__ >= 7
OsPrefetchAbortExcHandleEntry(ExcContext * excBufAddr)938 VOID OsPrefetchAbortExcHandleEntry(ExcContext *excBufAddr)
939 {
940     UINT32 far;
941     UINT32 fsr;
942 
943     excBufAddr->PC -= 4;  /* lr in prefetch abort is pc + 4 */
944 
945     if (gdbhw_hook(excBufAddr, OS_EXCEPT_PREFETCH_ABORT)) {
946         return;
947     }
948 
949     if (g_excHook != NULL) {
950         far = OsArmReadIfar();
951         fsr = OsArmReadIfsr();
952         g_excHook(OS_EXCEPT_PREFETCH_ABORT, excBufAddr, far, fsr);
953     }
954     while (1) {}
955 }
956 
OsDataAbortExcHandleEntry(ExcContext * excBufAddr)957 VOID OsDataAbortExcHandleEntry(ExcContext *excBufAddr)
958 {
959     UINT32 far;
960     UINT32 fsr;
961 
962     excBufAddr->PC -= 8;  /* lr in data abort is pc + 8 */
963 
964     if (gdbhw_hook(excBufAddr, OS_EXCEPT_DATA_ABORT)) {
965         return;
966     }
967 
968     if (g_excHook != NULL) {
969         far = OsArmReadDfar();
970         fsr = OsArmReadDfsr();
971         g_excHook(OS_EXCEPT_DATA_ABORT, excBufAddr, far, fsr);
972     }
973     while (1) {}
974 }
975 #endif /* __LINUX_ARM_ARCH__ */
976 #endif /* LOSCFG_GDB */
977 
978 #ifdef LOSCFG_KERNEL_SMP
979 #define EXC_WAIT_INTER 50U
980 #define EXC_WAIT_TIME  2000U
981 
WaitAllCpuStop(UINT32 cpuID)982 STATIC VOID WaitAllCpuStop(UINT32 cpuID)
983 {
984     UINT32 i;
985     UINT32 time = 0;
986 
987     while (time < EXC_WAIT_TIME) {
988         for (i = 0; i < LOSCFG_KERNEL_CORE_NUM; i++) {
989             if ((i != cpuID) && !OsCpuStatusIsHalt(i)) {
990                 LOS_Mdelay(EXC_WAIT_INTER);
991                 time += EXC_WAIT_INTER;
992                 break;
993             }
994         }
995         /* Other CPUs are all haletd or in the exc. */
996         if (i == LOSCFG_KERNEL_CORE_NUM) {
997             break;
998         }
999     }
1000     return;
1001 }
1002 
OsWaitOtherCoresHandleExcEnd(UINT32 currCpuID)1003 STATIC VOID OsWaitOtherCoresHandleExcEnd(UINT32 currCpuID)
1004 {
1005     while (1) {
1006         LOS_SpinLock(&g_excSerializerSpin);
1007         if ((g_currHandleExcCpuID == INVALID_CPUID) || (g_currHandleExcCpuID == currCpuID)) {
1008             g_currHandleExcCpuID = currCpuID;
1009             g_currHandleExcPID = OsCurrProcessGet()->processID;
1010             LOS_SpinUnlock(&g_excSerializerSpin);
1011             break;
1012         }
1013 
1014         if (g_nextExcWaitCpu == INVALID_CPUID) {
1015             g_nextExcWaitCpu = currCpuID;
1016         }
1017         LOS_SpinUnlock(&g_excSerializerSpin);
1018         LOS_Mdelay(EXC_WAIT_INTER);
1019     }
1020 }
1021 
OsCheckAllCpuStatus(VOID)1022 STATIC VOID OsCheckAllCpuStatus(VOID)
1023 {
1024     UINT32 currCpuID = ArchCurrCpuid();
1025     UINT32 ret, target;
1026 
1027     OsCpuStatusSet(CPU_EXC);
1028     LOCKDEP_CLEAR_LOCKS();
1029 
1030     LOS_SpinLock(&g_excSerializerSpin);
1031     /* Only the current CPU anomaly */
1032     if (g_currHandleExcCpuID == INVALID_CPUID) {
1033         g_currHandleExcCpuID = currCpuID;
1034         g_currHandleExcPID = OsCurrProcessGet()->processID;
1035         LOS_SpinUnlock(&g_excSerializerSpin);
1036 #ifndef LOSCFG_SAVE_EXCINFO
1037         if (g_excFromUserMode[currCpuID] == FALSE) {
1038             target = (UINT32)(OS_MP_CPU_ALL & ~CPUID_TO_AFFI_MASK(currCpuID));
1039             HalIrqSendIpi(target, LOS_MP_IPI_HALT);
1040         }
1041 #endif
1042     } else if (g_excFromUserMode[currCpuID] == TRUE) {
1043         /* Both cores raise exceptions, and the current core is a user-mode exception.
1044          * Both cores are abnormal and come from the same process
1045          */
1046         if (OsCurrProcessGet()->processID == g_currHandleExcPID) {
1047             LOS_SpinUnlock(&g_excSerializerSpin);
1048             OsExcRestore();
1049             ret = LOS_TaskDelete(OsCurrTaskGet()->taskID);
1050             LOS_Panic("%s supend task :%u failed: 0x%x\n", __FUNCTION__, OsCurrTaskGet()->taskID, ret);
1051         }
1052         LOS_SpinUnlock(&g_excSerializerSpin);
1053 
1054         OsWaitOtherCoresHandleExcEnd(currCpuID);
1055     } else {
1056         if ((g_currHandleExcCpuID < LOSCFG_KERNEL_CORE_NUM) && (g_excFromUserMode[g_currHandleExcCpuID] == TRUE)) {
1057             g_currHandleExcCpuID = currCpuID;
1058             LOS_SpinUnlock(&g_excSerializerSpin);
1059             target = (UINT32)(OS_MP_CPU_ALL & ~CPUID_TO_AFFI_MASK(currCpuID));
1060             HalIrqSendIpi(target, LOS_MP_IPI_HALT);
1061         } else {
1062             LOS_SpinUnlock(&g_excSerializerSpin);
1063             while (1) {}
1064         }
1065     }
1066 #ifndef LOSCFG_SAVE_EXCINFO
1067     /* use halt ipi to stop other active cores */
1068     if (g_excFromUserMode[ArchCurrCpuid()] == FALSE) {
1069         WaitAllCpuStop(currCpuID);
1070     }
1071 #endif
1072 }
1073 #endif
1074 
OsCheckCpuStatus(VOID)1075 STATIC VOID OsCheckCpuStatus(VOID)
1076 {
1077 #ifdef LOSCFG_KERNEL_SMP
1078     OsCheckAllCpuStatus();
1079 #else
1080     g_currHandleExcCpuID = ArchCurrCpuid();
1081 #endif
1082 }
1083 
OsExcPriorDisposal(ExcContext * excBufAddr)1084 LITE_OS_SEC_TEXT VOID STATIC OsExcPriorDisposal(ExcContext *excBufAddr)
1085 {
1086     if ((excBufAddr->regCPSR & CPSR_MASK_MODE) == CPSR_USER_MODE) {
1087         g_minAddr = USER_ASPACE_BASE;
1088         g_maxAddr = USER_ASPACE_BASE + USER_ASPACE_SIZE;
1089         g_excFromUserMode[ArchCurrCpuid()] = TRUE;
1090     } else {
1091         g_minAddr = KERNEL_ASPACE_BASE;
1092         g_maxAddr = KERNEL_ASPACE_BASE + KERNEL_ASPACE_SIZE;
1093         g_excFromUserMode[ArchCurrCpuid()] = FALSE;
1094     }
1095 
1096     OsCheckCpuStatus();
1097 
1098 #ifdef LOSCFG_KERNEL_SMP
1099 #ifdef LOSCFG_FS_VFS
1100     /* Wait for the end of the Console task to avoid multicore printing code */
1101     OsWaitConsoleSendTaskPend(OsCurrTaskGet()->taskID);
1102 #endif
1103 #endif
1104 }
1105 
OsPrintExcHead(UINT32 far)1106 LITE_OS_SEC_TEXT_INIT STATIC VOID OsPrintExcHead(UINT32 far)
1107 {
1108 #ifdef LOSCFG_BLACKBOX
1109 #ifdef LOSCFG_SAVE_EXCINFO
1110     SetExcInfoIndex(0);
1111 #endif
1112 #endif
1113 #ifdef LOSCFG_KERNEL_VM
1114     /* You are not allowed to add any other print information before this exception information */
1115     if (g_excFromUserMode[ArchCurrCpuid()] == TRUE) {
1116 #ifdef LOSCFG_DEBUG_VERSION
1117         VADDR_T vaddr = ROUNDDOWN(far, PAGE_SIZE);
1118         LosVmSpace *space = LOS_SpaceGet(vaddr);
1119         if (space != NULL) {
1120             LOS_DumpMemRegion(vaddr);
1121         }
1122 #endif
1123         PrintExcInfo("##################excFrom: User!####################\n");
1124     } else
1125 #endif
1126     {
1127         PrintExcInfo("##################excFrom: kernel!###################\n");
1128     }
1129 }
1130 
1131 #ifdef LOSCFG_SAVE_EXCINFO
OsSysStateSave(UINT32 * intCount,UINT32 * lockCount)1132 STATIC VOID OsSysStateSave(UINT32 *intCount, UINT32 *lockCount)
1133 {
1134     *intCount = g_intCount[ArchCurrCpuid()];
1135     *lockCount = OsSchedLockCountGet();
1136     g_intCount[ArchCurrCpuid()] = 0;
1137     OsSchedLockSet(0);
1138 }
1139 
OsSysStateRestore(UINT32 intCount,UINT32 lockCount)1140 STATIC VOID OsSysStateRestore(UINT32 intCount, UINT32 lockCount)
1141 {
1142     g_intCount[ArchCurrCpuid()] = intCount;
1143     OsSchedLockSet(lockCount);
1144 }
1145 #endif
1146 
1147 /*
1148  * Description : EXC handler entry
1149  * Input       : excType    --- exc type
1150  *               excBufAddr --- address of EXC buf
1151  */
OsExcHandleEntry(UINT32 excType,ExcContext * excBufAddr,UINT32 far,UINT32 fsr)1152 LITE_OS_SEC_TEXT_INIT VOID OsExcHandleEntry(UINT32 excType, ExcContext *excBufAddr, UINT32 far, UINT32 fsr)
1153 {
1154 #ifdef LOSCFG_SAVE_EXCINFO
1155     UINT32 intCount;
1156     UINT32 lockCount;
1157 #endif
1158 
1159     /* Task scheduling is not allowed during exception handling */
1160     OsSchedLock();
1161 
1162     g_curNestCount[ArchCurrCpuid()]++;
1163 
1164     OsExcPriorDisposal(excBufAddr);
1165 
1166     OsPrintExcHead(far);
1167 
1168 #ifdef LOSCFG_KERNEL_SMP
1169     OsAllCpuStatusOutput();
1170 #endif
1171 
1172 #ifdef LOSCFG_SAVE_EXCINFO
1173     log_read_write_fn func = GetExcInfoRW();
1174 #endif
1175 
1176     if (g_excHook != NULL) {
1177         if (g_curNestCount[ArchCurrCpuid()] == 1) {
1178 #ifdef LOSCFG_SAVE_EXCINFO
1179             if (func != NULL) {
1180 #ifndef LOSCFG_BLACKBOX
1181                 SetExcInfoIndex(0);
1182 #endif
1183                 OsSysStateSave(&intCount, &lockCount);
1184                 OsRecordExcInfoTime();
1185                 OsSysStateRestore(intCount, lockCount);
1186             }
1187 #endif
1188             g_excHook(excType, excBufAddr, far, fsr);
1189         } else {
1190             OsCallStackInfo();
1191         }
1192 
1193 #ifdef LOSCFG_SAVE_EXCINFO
1194         if (func != NULL) {
1195             PrintExcInfo("Be sure flash space bigger than GetExcInfoIndex():0x%x\n", GetExcInfoIndex());
1196             OsSysStateSave(&intCount, &lockCount);
1197             func(GetRecordAddr(), GetRecordSpace(), 0, GetExcInfoBuf());
1198             OsSysStateRestore(intCount, lockCount);
1199         }
1200 #endif
1201     }
1202 
1203 #ifdef LOSCFG_SHELL_CMD_DEBUG
1204     SystemRebootFunc rebootHook = OsGetRebootHook();
1205     if ((OsSystemExcIsReset() == TRUE) && (rebootHook != NULL)) {
1206         LOS_Mdelay(3000); /* 3000: System dead, delay 3 seconds after system restart */
1207         rebootHook();
1208     }
1209 #endif
1210 
1211 #ifdef LOSCFG_BLACKBOX
1212     BBoxNotifyError(EVENT_PANIC, MODULE_SYSTEM, "Crash in kernel", 1);
1213 #endif
1214     while (1) {}
1215 }
1216 
LOS_Panic(const CHAR * fmt,...)1217 __attribute__((noinline)) VOID LOS_Panic(const CHAR *fmt, ...)
1218 {
1219     va_list ap;
1220     va_start(ap, fmt);
1221     OsVprintf(fmt, ap, EXC_OUTPUT);
1222     va_end(ap);
1223     __asm__ __volatile__("swi 0");
1224     while (1) {}
1225 }
1226 
1227 /* stack protector */
1228 USED UINT32 __stack_chk_guard = 0xd00a0dff;
1229 
__stack_chk_fail(VOID)1230 VOID __stack_chk_fail(VOID)
1231 {
1232     /* __builtin_return_address is a builtin function, building in gcc */
1233     LOS_Panic("stack-protector: Kernel stack is corrupted in: %p\n",
1234               __builtin_return_address(0));
1235 }
1236 
LOS_RecordLR(UINTPTR * LR,UINT32 LRSize,UINT32 recordCount,UINT32 jumpCount)1237 VOID LOS_RecordLR(UINTPTR *LR, UINT32 LRSize, UINT32 recordCount, UINT32 jumpCount)
1238 {
1239     UINT32 count = 0;
1240     UINT32 index = 0;
1241     UINT32 stackStart, stackEnd;
1242     LosTaskCB *taskCB = NULL;
1243     UINTPTR framePtr, tmpFramePtr, linkReg;
1244 
1245     if (LR == NULL) {
1246         return;
1247     }
1248     /* if LR array is not enough,just record LRSize. */
1249     if (LRSize < recordCount) {
1250         recordCount = LRSize;
1251     }
1252 
1253     taskCB = OsCurrTaskGet();
1254     stackStart = taskCB->topOfStack;
1255     stackEnd = stackStart + taskCB->stackSize;
1256 
1257     framePtr = Get_Fp();
1258     while ((framePtr > stackStart) && (framePtr < stackEnd) && IS_ALIGNED(framePtr, sizeof(CHAR *))) {
1259         tmpFramePtr = framePtr;
1260 #ifdef LOSCFG_COMPILER_CLANG_LLVM
1261         linkReg = *(UINTPTR *)(tmpFramePtr + sizeof(UINTPTR));
1262 #else
1263         linkReg = *(UINTPTR *)framePtr;
1264 #endif
1265         if (index >= jumpCount) {
1266             LR[count++] = linkReg;
1267             if (count == recordCount) {
1268                 break;
1269             }
1270         }
1271         index++;
1272 #ifdef LOSCFG_COMPILER_CLANG_LLVM
1273         framePtr = *(UINTPTR *)framePtr;
1274 #else
1275         framePtr = *(UINTPTR *)(tmpFramePtr - sizeof(UINTPTR));
1276 #endif
1277     }
1278 
1279     /* if linkReg is not enough,clean up the last of the effective LR as the end. */
1280     if (count < recordCount) {
1281         LR[count] = 0;
1282     }
1283 }
1284 
1285