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