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