📄 excarchlib.c
字号:
/******************************************************************************** excBErrVecInit - initialize the bus error interrupt vector** This routine sets the specified bus error interrupt vector to point to* a special bridge-routine to emulate a bus error exception. The SH* architecture does not have a bus error exception, but some boards could* detect a VME bus timeout error and report it to CPU using interrupt* mechanism. To treat this type of interrupt as an exception, BSP should call* this routine to specify the bus error interrupt vector. Also the interrupt* acknowledge function pointer _func_excBErrIntAck must be initialized by BSP.* Then the interrupt is treated as an exception, and the handler run in the* context of offending task.** WHEN TO CALL* This routine may be called from sysHwInit2() in BSP, if necessary.** RETURNS: OK if specified vector is valid, ERROR otherwise.*/STATUS excBErrVecInit ( int inum ) { STATUS status = ERROR; /* set global variable to specify bus error interrupt vector number */ excBErrVecNum = inum; /* set bus error emulation vector */#if (CPU==SH7750 || CPU==SH7700) if ((inum >= INUM_INTR_LOW && inum <= INUM_INTR_HIGH) || inum == INUM_NMI) { UINT vecAddr = (UINT)intVecBaseGet () + SH7700_EXC_BERR_STUB_OFFSET; intVecSet ((FUNCPTR *)INUM_TO_IVEC (inum), (FUNCPTR)vecAddr); status = OK; }#elif (CPU==SH7600 || CPU==SH7000) if ((inum > INUM_USER_BREAK && inum <= HIGH_VEC) || inum == INUM_NMI) { intVecSet ((FUNCPTR *)INUM_TO_IVEC (inum), (FUNCPTR)excBsrTblBErr); status = OK; }#endif /* CPU==SH7600 || CPU==SH7000 */ return status; }/******************************************************************************** excExcHandle - interrupt level handling of exceptions** This routine handles exception traps. It is never to be called except* from the special assembly language interrupt stub routine.** It prints out a bunch of pertinent information about the trap that* occurred via excTask.** Note that this routine runs in the context of the task that got the exception.** NOMANUAL*/void excExcHandle ( int vecNum, /* exception vector number */ ESFSH * pEsf, /* pointer to exception stack frame */ REG_SET * pRegs /* pointer to register info on stack */ ) { EXC_INFO excInfo;#if (CPU==SH7750) /* see if denormalized number exception */ if ((vecNum == INUM_FPU_EXCEPTION) && (fppExcHandle (pEsf, pRegs) == OK)) return;#endif excGetInfoFromESF (vecNum, pEsf, pRegs, &excInfo); /* fill excInfo/pRegs */ if ((_func_excBaseHook != NULL) && /* user hook around? */ ((* _func_excBaseHook) (vecNum, pEsf, pRegs, &excInfo))) return; /* user hook fixed it */ if ((excBErrVecNum != NONE) && (vecNum == excBErrVecNum) && excTasRetry (vecNum, pEsf, pRegs)) return; /* retry the TAS */#ifdef WV_INSTRUMENTATION /* windview - level 3 event logging */#if (CPU==SH7750 || CPU==SH7700) EVT_CTX_1(EVENT_EXCEPTION, INUM_TO_IEVT (vecNum));#elif (CPU==SH7600 || CPU==SH7000) EVT_CTX_1(EVENT_EXCEPTION, vecNum);#endif#endif /* if exception occured in an isr or before multi tasking then reboot */ if ((INT_CONTEXT ()) || (Q_FIRST (&activeQHead) == NULL)) { if (_func_excPanicHook != NULL) /* panic hook? */ (*_func_excPanicHook) (vecNum, pEsf, pRegs, &excInfo); reboot (BOOT_WARM_AUTOBOOT); return; /* reboot returns?! */ } /* task caused exception */ taskIdCurrent->pExcRegSet = pRegs; /* for taskRegs[GS]et */ taskIdDefault ((int)taskIdCurrent); /* update default tid */ bcopy ((char *) &excInfo, (char *) &(taskIdCurrent->excInfo), sizeof (EXC_INFO)); /* copy in exc info */ /* CAUTION: pRegs is invalid after calling _func_sigExcKill. */ if (_func_sigExcKill != NULL) /* signals installed? */ (*_func_sigExcKill) (vecNum, INUM_TO_IVEC(vecNum), pRegs); if (_func_excInfoShow != NULL) /* default show rtn? */ (*_func_excInfoShow) (&excInfo, TRUE); if (excExcepHook != NULL) /* 5.0.2 hook? */ (* excExcepHook) (taskIdCurrent, vecNum, pEsf); taskSuspend (0); /* whoa partner... */ taskIdCurrent->pExcRegSet = (REG_SET *) NULL; /* invalid after rts */ }/******************************************************************************** excIntHandle - interrupt level handling of interrupts** This routine handles interrupts. It is never to be called except* from the special assembly language interrupt stub routine.** It prints out a bunch of pertinent information about the trap that* occurred via excTask().** NOMANUAL*/void excIntHandle ( int vecNum, /* exception vector number */ ESFSH * pEsf, /* pointer to exception stack frame */ REG_SET * pRegs /* pointer to register info on stack */ ) { EXC_INFO excInfo; excGetInfoFromESF (vecNum, pEsf, pRegs, &excInfo); /* fill excInfo/pRegs */#ifdef WV_INSTRUMENTATION /* windview - level 3 event logging */#if (CPU==SH7750 || CPU==SH7700) EVT_CTX_1(EVENT_EXCEPTION, INUM_TO_IEVT (vecNum));#elif (CPU==SH7600 || CPU==SH7000) EVT_CTX_1(EVENT_EXCEPTION, vecNum);#endif#endif if (_func_excIntHook != NULL) (*_func_excIntHook) (vecNum, pEsf, pRegs, &excInfo); if (Q_FIRST (&activeQHead) == NULL) /* pre kernel */ reboot (BOOT_WARM_AUTOBOOT); /* better reboot */ }/******************************************************************************** excGetInfoFromESF - get relevent info from exception stack frame** NOMANUAL** <SH7700 exception case, it differs if interrupt>** |_____________| _______* |TRA/TEA/FPSCR| 96 +12 ESFSH.info (JUNK if interrupt)* | EXPEVT | 92 +8 _____ ESFSH.event (not saved, use vecNum)* | ssr | 88 +4 ^ ESFSH.sr* pEsf --> | spc | 84 +0 | ___ ESFSH.pc* | r15 | 80 |* | r14 | 76 |* | r13 | 72 |* | r12 | 68 |* | r11 | 64 |* | r10 | 60 |* | r9 | 56 |* | r8 | 52 |* | macl | 48 |* | mach | 44 REG_SET* | r7 | 40 |* | r6 | 36 |* | r5 | 32 |* | r4 | 28 |* | r3 | 24 |* | r2 | 20 | _________________* | r1 | 16 | |_____pad_______|* | r0 | 12 | |_____info______|* | pr | 8 | |______sr_______|* | gbr | 4 | |______pc_______| * pRegs -> |____ vbr ____| 0 _____v__ pExcInfo ---> |_valid_|_vecNum|* | |*/LOCAL void excGetInfoFromESF ( FAST int vecNum, /* vector number */ FAST ESFSH *pEsf, /* pointer to exception stack frame */ REG_SET * pRegs, /* pointer to register info on stack */ EXC_INFO * pExcInfo /* where to fill in exception info */ ) {#if (CPU==SH7750 || CPU==SH7700) pExcInfo->valid = EXC_VEC_NUM | EXC_PC | EXC_STATUS_REG; pExcInfo->vecNum = vecNum; pExcInfo->pc = ((ESFSH *)pEsf)->pc; pExcInfo->sr = ((ESFSH *)pEsf)->sr; pExcInfo->info = ((ESFSH *)pEsf)->info; if (((ESFSH *)pEsf)->event == (INUM_TO_IEVT (INUM_TRAPA_INSTRUCTION))) { pExcInfo->valid |= EXC_TRAP; } else if ((vecNum>=INUM_TLB_READ_MISS) && (vecNum<=INUM_WRITE_ADDRESS_ERROR)) { pExcInfo->valid |= EXC_ACCESS_ADDR; }#ifdef _WRS_HW_FP_SUPPORT else if (vecNum == INUM_FPU_EXCEPTION) { pExcInfo->valid |= EXC_FPSCR; if (pTaskLastFpTcb != NULL) fppSave (pTaskLastFpTcb->pFpContext); }#endif#if (CPU==SH7750) else if (vecNum==INUM_TLB_MULTIPLE_HIT) { pExcInfo->valid |= EXC_ACCESS_ADDR; }#endif /* CPU==SH7750 */#elif (CPU==SH7600 || CPU==SH7000) int size = sizeof (ESFSH); pExcInfo->valid = EXC_VEC_NUM | EXC_PC | EXC_STATUS_REG; pExcInfo->vecNum = vecNum; pExcInfo->pc = ((ESFSH *)pEsf)->pc; pExcInfo->sr = ((ESFSH *)pEsf)->sr; pRegs->spReg = (ULONG)((char *) pEsf + size); /* bump up stack ptr */#endif /* CPU==SH7600 || CPU==SH7000 */ }/******************************************************************************** excTasRetry - retry a TAS instruction** If this was a bus error involving a RMW cycle (TAS instruction) we* return to the handler to retry it. Such is the case in a vme* bus deadlock cycle, where the local CPU initiates a TAS instuction* (or RMW cycle) at the same time it's dual port arbiter grants the local bus* to an external access. The cpu backs off by signaling a bus error and* setting the RM bit in the special status word of the bus error exception* frame. The solution is simply to retry the instruction hoping that the* external access has been resolved. Even if a card such as a disk controller* has grabed the bus for DMA accesses for a long time, the worst that will* happen is we'll end up back here again, and we can keep trying until we get* through.** RETURNS: TRUE if retry desired, FALSE if not TAS cycle.* NOMANUAL*/LOCAL BOOL excTasRetry ( int vecNum, /* exception vector number */ ESFSH * pEsf, /* pointer to exception stack frame */ REG_SET * pRegs /* pointer to register info on stack */ ) { if (_func_excBErrIntAck != NULL) (* _func_excBErrIntAck) (); if (0) /* XXX how to identify the TAS cycle with SH??? */ { ++excTasErrors; /* keep count of TAS errors */ return (TRUE); /* retry the instruction */ } return (FALSE); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -