void up_assert(const uint8_t *filename, int lineno) { #if CONFIG_TASK_NAME_SIZE > 0 && defined(CONFIG_DEBUG_ALERT) struct tcb_s *rtcb = this_task(); #endif board_autoled_on(LED_ASSERTION); #if CONFIG_TASK_NAME_SIZE > 0 _alert("Assertion failed at file:%s line: %d task: %s\n", filename, lineno, rtcb->name); #else _alert("Assertion failed at file:%s line: %d\n", filename, lineno); #endif up_dumpstate(); #ifdef CONFIG_BOARD_CRASHDUMP board_crashdump(up_getsp(), this_task(), filename, lineno); #endif #ifdef CONFIG_ARCH_USBDUMP /* Dump USB trace data */ (void)usbtrace_enumerate(assert_tracecallback, NULL); #endif _up_assert(EXIT_FAILURE); }
static void z80_registerdump(void) { if (g_current_regs) { _alert("AF: %04x I: %04x\n", g_current_regs[XCPT_AF], g_current_regs[XCPT_I]); _alert("BC: %04x DE: %04x HL: %04x\n", g_current_regs[XCPT_BC], g_current_regs[XCPT_DE], g_current_regs[XCPT_HL]); _alert("IX: %04x IY: %04x\n", g_current_regs[XCPT_IX], g_current_regs[XCPT_IY]); _alert("SP: %04x PC: %04x\n" g_current_regs[XCPT_SP], g_current_regs[XCPT_PC]); } }
uint32_t *arm_undefinedinsn(uint32_t *regs) { _alert("Undefined instruction at 0x%x\n", regs[REG_PC]); CURRENT_REGS = regs; PANIC(); return regs; /* To keep the compiler happy */ }
int callfunc(struct rule *r,struct function *f,void *dp,int type){ int i=0; int fid=f->fid; for(i=0;i<10;i++){ if(!fid) break; switch (fid) { case 1: _addself(r,f->pt); break; case 2: _delself(r,f->pt); break; case 3: _greater(r,f->pt); break; case 4: _less(r,f->pt); break; case 5: _equal(r,f->pt); break; case 6: _unequal(r,f->pt); break; case FUNC_LOG: _log(r,f->pt); case FUNC_ALERT: _alert(r,f->pt); } } }
int up_memfault(int irq, FAR void *context, FAR void *arg) { /* Dump some memory management fault info */ (void)up_irq_save(); _alert("PANIC!!! Memory Management Fault:\n"); mfinfo(" IRQ: %d context: %p\n", irq, regs); _alert(" CFAULTS: %08x MMFAR: %08x\n", getreg32(NVIC_CFAULTS), getreg32(NVIC_MEMMANAGE_ADDR)); mfinfo(" BASEPRI: %08x PRIMASK: %08x IPSR: %08x CONTROL: %08x\n", getbasepri(), getprimask(), getipsr(), getcontrol()); mfinfo(" R0: %08x %08x %08x %08x %08x %08x %08x %08x\n", regs[REG_R0], regs[REG_R1], regs[REG_R2], regs[REG_R3], regs[REG_R4], regs[REG_R5], regs[REG_R6], regs[REG_R7]); mfinfo(" R8: %08x %08x %08x %08x %08x %08x %08x %08x\n", regs[REG_R8], regs[REG_R9], regs[REG_R10], regs[REG_R11], regs[REG_R12], regs[REG_R13], regs[REG_R14], regs[REG_R15]); #ifdef CONFIG_ARMV7M_USEBASEPRI # ifdef REG_EXC_RETURN mfinfo(" xPSR: %08x BASEPRI: %08x EXC_RETURN: %08x (saved)\n", CURRENT_REGS[REG_XPSR], CURRENT_REGS[REG_BASEPRI], CURRENT_REGS[REG_EXC_RETURN]); # else mfinfo(" xPSR: %08x BASEPRI: %08x (saved)\n", CURRENT_REGS[REG_XPSR], CURRENT_REGS[REG_BASEPRI]); # endif #else # ifdef REG_EXC_RETURN mfinfo(" xPSR: %08x PRIMASK: %08x EXC_RETURN: %08x (saved)\n", CURRENT_REGS[REG_XPSR], CURRENT_REGS[REG_PRIMASK], CURRENT_REGS[REG_EXC_RETURN]); # else mfinfo(" xPSR: %08x PRIMASK: %08x (saved)\n", CURRENT_REGS[REG_XPSR], CURRENT_REGS[REG_PRIMASK]); # endif #endif PANIC(); return OK; /* Won't get here */ }
uint32_t *arm_dataabort(uint32_t *regs, uint32_t dfar, uint32_t dfsr) { /* Save the saved processor context in CURRENT_REGS where it can be accessed * for register dumps and possibly context switching. */ CURRENT_REGS = regs; /* Crash -- possibly showing diagnostic debug information. */ _alert("Data abort. PC: %08x DFAR: %08x DFSR: %08x\n", regs[REG_PC], dfar, dfsr); PANIC(); return regs; /* To keep the compiler happy */ }
uint32_t *arm_syscall(uint32_t *regs) { _alert("SYSCALL from 0x%x\n", regs[REG_PC]); CURRENT_REGS = regs; PANIC(); }
uint32_t *arm_dataabort(uint32_t *regs, uint32_t dfar, uint32_t dfsr) { struct tcb_s *tcb = this_task(); uint32_t *savestate; /* Save the saved processor context in CURRENT_REGS where it can be accessed * for register dumps and possibly context switching. */ savestate = (uint32_t *)CURRENT_REGS; CURRENT_REGS = regs; /* In the NuttX on-demand paging implementation, only the read-only, .text * section is paged. However, the ARM compiler generated PC-relative data * fetches from within the .text sections. Also, it is customary to locate * read-only data (.rodata) within the same section as .text so that it * does not require copying to RAM. Misses in either of these case should * cause a data abort. * * We are only interested in data aborts due to page translations faults. * Sections should already be in place and permissions should already be * be set correctly (to read-only) so any other data abort reason is a * fatal error. */ pginfo("DFSR: %08x DFAR: %08x\n", dfsr, dfar); if ((dfsr & FSR_MASK) != FSR_PAGE) { goto segfault; } /* Check the (virtual) address of data that caused the data abort. When * the exception occurred, this address was provided in the DFAR register. * (It has not yet been saved in the register context save area). */ pginfo("VBASE: %08x VEND: %08x\n", PG_PAGED_VBASE, PG_PAGED_VEND); if (dfar < PG_PAGED_VBASE || dfar >= PG_PAGED_VEND) { goto segfault; } /* Save the offending data address as the fault address in the TCB of * the currently task. This fault address is also used by the prefetch * abort handling; this will allow common paging logic for both * prefetch and data aborts. */ tcb->xcp.dfar = regs[REG_R15]; /* Call pg_miss() to schedule the page fill. A consequences of this * call are: * * (1) The currently executing task will be blocked and saved on * on the g_waitingforfill task list. * (2) An interrupt-level context switch will occur so that when * this function returns, it will return to a different task, * most likely the page fill worker thread. * (3) The page fill worker task has been signalled and should * execute immediately when we return from this exception. */ pg_miss(); /* Restore the previous value of CURRENT_REGS. NULL would indicate that * we are no longer in an interrupt handler. It will be non-NULL if we * are returning from a nested interrupt. */ CURRENT_REGS = savestate; return regs; segfault: _alert("Data abort. PC: %08x DFAR: %08x DFSR: %08x\n", regs[REG_PC], dfar, dfsr); PANIC(); return regs; /* To keep the compiler happy */ }
void up_prefetchabort(uint32_t *regs) { #ifdef CONFIG_PAGING uint32_t *savestate; /* Save the saved processor context in CURRENT_REGS where it can be accessed * for register dumps and possibly context switching. */ savestate = (uint32_t *)CURRENT_REGS; #endif CURRENT_REGS = regs; #ifdef CONFIG_PAGING /* Get the (virtual) address of instruction that caused the prefetch abort. * When the exception occurred, this address was provided in the lr register * and this value was saved in the context save area as the PC at the * REG_R15 index. * * Check to see if this miss address is within the configured range of * virtual addresses. */ pginfo("VADDR: %08x VBASE: %08x VEND: %08x\n", regs[REG_PC], PG_PAGED_VBASE, PG_PAGED_VEND); if (regs[REG_R15] >= PG_PAGED_VBASE && regs[REG_R15] < PG_PAGED_VEND) { /* Save the offending PC as the fault address in the TCB of the currently * executing task. This value is, of course, already known in regs[REG_R15], * but saving it in this location will allow common paging logic for both * prefetch and data aborts. */ struct tcb_s *tcb = this_task(); tcb->xcp.far = regs[REG_R15]; /* Call pg_miss() to schedule the page fill. A consequences of this * call are: * * (1) The currently executing task will be blocked and saved on * on the g_waitingforfill task list. * (2) An interrupt-level context switch will occur so that when * this function returns, it will return to a different task, * most likely the page fill worker thread. * (3) The page fill worker task has been signalled and should * execute immediately when we return from this exception. */ pg_miss(); /* Restore the previous value of CURRENT_REGS. NULL would indicate that * we are no longer in an interrupt handler. It will be non-NULL if we * are returning from a nested interrupt. */ CURRENT_REGS = savestate; } else #endif { _alert("Prefetch abort. PC: %08x\n", regs[REG_PC]); PANIC(); } }