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