void do_dispatch_general()

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);
}