in kernel/traps.c [289:354]
void do_dispatch_general(unsigned long entry, unsigned long addr,
unsigned long itype, struct pt_regs *regs,
unsigned long oipc)
{
unsigned int swid = itype >> ITYPE_offSWID;
unsigned long type = itype & (ITYPE_mskINST | ITYPE_mskETYPE);
if (type == ETYPE_ALIGNMENT_CHECK) {
#ifdef CONFIG_ALIGNMENT_TRAP
/* Alignment check */
if (user_mode(regs) && unalign_access_mode) {
int ret;
ret = do_unaligned_access(addr, regs);
if (ret == 0)
return;
if (ret == -EFAULT)
pr_emerg
("Unhandled unaligned access exception\n");
}
#endif
do_page_fault(entry, addr, type, regs);
} else if (type == ETYPE_RESERVED_INSTRUCTION) {
/* Reserved instruction */
do_revinsn(regs);
} else if (type == ETYPE_COPROCESSOR) {
/* Coprocessor */
#if IS_ENABLED(CONFIG_FPU)
unsigned int fucop_exist = __nds32__mfsr(NDS32_SR_FUCOP_EXIST);
unsigned int cpid = ((itype & ITYPE_mskCPID) >> ITYPE_offCPID);
if ((cpid == FPU_CPID) &&
(fucop_exist & FUCOP_EXIST_mskCP0ISFPU)) {
unsigned int subtype = (itype & ITYPE_mskSTYPE);
if (true == do_fpu_exception(subtype, regs))
return;
}
#endif
unhandled_exceptions(entry, addr, type, regs);
} else if (type == ETYPE_TRAP && swid == SWID_RAISE_INTERRUPT_LEVEL) {
/* trap, used on v3 EDM target debugging workaround */
/*
* DIPC(OIPC) is passed as parameter before
* interrupt is enabled, so the DIPC will not be corrupted
* even though interrupts are coming in
*/
/*
* 1. update ipc
* 2. update pt_regs ipc with oipc
* 3. update pt_regs ipsw (clear DEX)
*/
__asm__ volatile ("mtsr %0, $IPC\n\t"::"r" (oipc));
regs->ipc = oipc;
if (regs->pipsw & PSW_mskDEX) {
pr_emerg
("Nested Debug exception is possibly happened\n");
pr_emerg("ipc:%08x pipc:%08x\n",
(unsigned int)regs->ipc,
(unsigned int)regs->pipc);
}
do_debug_trap(entry, addr, itype, regs);
regs->ipsw &= ~PSW_mskDEX;
} else
unhandled_exceptions(entry, addr, type, regs);
}