📄 excarchlib.c
字号:
} return (rc); }# endif /* _EXC_OFF_CRTL */#endif /* _PPC_MSR_CE */#ifdef _PPC_MSR_MCE# ifdef _EXC_OFF_CRTL /* also need excCrtConnectCode like critical int *//********************************************************************************* excMchkConnect - connect a C routine to a machine chk exception vector** This routine connects a specified C routine to a specified mcheck exception* vector. An exception stub is created and in placed at <vector> in the* exception table. The address of <routine> is stored in the exception stub* code. When an exception occurs, the processor jumps to the exception stub* code, saves the registers, and call the C routines.** The routine can be any normal C code, except that it must not* invoke certain operating system functions that may block or perform* I/O operations.** The registers are saved to an Exception Stack Frame (ESF) which is placed* on the stack of the task that has produced the exception. The ESF structure* is defined in h/arch/ppc/esfPpc.h.** The only argument passed by the exception stub to the C routine is a pointer* to the ESF containing the register values. The prototype of this C routine* is as follows:* .CS* void excHandler (ESFPPC *);* .CE** When the C routine returns, the exception stub restores the registers saved* in the ESF and continues execution of the current task.** RETURNS: OK if the routine connected successfully, or* ERROR if the routine was too far away for a 26-bit offset.* * SEE ALSO: excIntConnect(), excIntCrtConnect, excVecSet()*/STATUS excMchkConnect ( VOIDFUNCPTR * vector, /* exception vector to attach to */ VOIDFUNCPTR routine /* routine to be called */ ) { return ( excRelocMchkConnect (vector, routine, (VOIDFUNCPTR *) 0) ); }/********************************************************************************* excRelocMchkConnect - connect a C routine to an exception vector with* possible relocation** This routine is same as excMchkConnect with an added parameter, which is* the relocation offset of the vector to be installed. If the extra* parameter is non-zero, the vector is installed at this offset instead* of the standard offset specified in the first parameter. A branch* instruction is then written to the original offset to reach the* relocated vector. A relative branch will be used, unless out of the* 26-bit offset range where it will attempt an absolute branch. The* caller should take care of the branch instruction clobbering useful* data specified by vector, including the stub being installed should* the original offset overlaps the stub of the relocated vector.** RETURNS: OK if the routine connected successfully, or* ERROR if the routine was too far away for one branch instr.**/STATUS excRelocMchkConnect ( VOIDFUNCPTR * vector, /* exception vector to attach to */ VOIDFUNCPTR routine, /* routine to be called */ VOIDFUNCPTR * vectorReloc /* relocated exception vector */ ) { FAST STATUS rc; FAST INSTR branch; FAST INSTR * newVector; FAST int base = (int) excVecBaseGet (); if ((int) vectorReloc == 0) { newVector = (INSTR *) ( base | (int) vector ); } else { vector = (VOIDFUNCPTR *) ( base | (int) vector ); newVector = (INSTR *) ( base | (int) vectorReloc ); } rc = excConnectVector(newVector, VEC_TYPE_MCHK, excMchkEnt, routine, excMchkExit); if ( ((int) vectorReloc != 0) && (rc == OK) ) { /* if relocated vector, write branch (with link bit cleared) */ branch = blCompute ( (VOIDFUNCPTR) newVector, (INSTR *) vector ); if (branch == 0) return ERROR; *vector = (VOIDFUNCPTR) (branch & 0xfffffffe); CACHE_TEXT_UPDATE ((void *) vector, sizeof(INSTR)); } return (rc); }# endif /* _EXC_OFF_CRTL */#endif /* _PPC_MSR_CE */#if defined(_EXC_NEW_OFF_PIT) || defined(_EXC_NEW_OFF_FIT)/********************************************************************************* excIntConnectTimer - connect a C routine to the FIT or PIT interrupt vector** NOTE: phasing out, should use excRelocIntConnect(), currently still* used by BSPs (evb403, walnut, and wrSbc405gp)**/STATUS excIntConnectTimer ( VOIDFUNCPTR * vector, /* exception vector to attach to */ VOIDFUNCPTR routine /* routine to be called */ ) { VOIDFUNCPTR * newVector; newVector = (VOIDFUNCPTR *) vecOffRelocMatch ((UINT32) vector); /* * not in other exc*Connect, but to preserve original behavior of * excIntConnectTimer(), NULL is checked here. */ if ((INSTR *) newVector == NULL) return ERROR; return ( excRelocIntConnect(vector, routine, newVector) ); }#endif /* _EXC_NEW_OFF_PIT || _EXC_NEW_OFF_FIT *//********************************************************************************* excVecSet - set a CPU exception vector** This routine set the C routine that will be called when the exception* corresponding to <vector> will occur. This function doesn't create the* exception stub. Just replace the C routine to call in the exception * stub. ** SEE ALSO: excVecGet(), excConnect(), excIntConnect()*/void excVecSet ( FUNCPTR * vector, /* vector offset */ FUNCPTR function /* address to place in vector */ ) { INSTR * newVector; /* * SPR #77145: See Exception Vector Table comment near top of file. * Relocated vectors saves wrong vector offset in ESF, thus need to * be patched to get right. Note also that pEsf->vecOffset (or * _PPC_ESF_VEC_OFF) is supposed to contain the offset only, but * excEnt and intEnt save the full address in current implementation. * They are same now because vector base is at 0x0, but will need work * when flexible vecotr positioning is supported, like using IVPR and * IVORn on the 440 and e500 book E compliant cores. */#if TRUE vector = (FUNCPTR *) vecOffRelocMatch ((UINT32) vector);#else /* TRUE */ /* * function call to vecOffRelocMatch() is cleaner but more expensive * can use following code instead (register compare/branch/set, * instead of table walk each entry compare/branch/memset) */#if ( (CPU == PPC403) || (CPU==PPC405) || (CPU==PPC405F) )# ifdef _EXC_NEW_OFF_PIT if ((UINT32) vector == _EXC_OFF_PIT) { vector = (FUNCPTR *) _EXC_NEW_OFF_PIT; } else# endif /* _EXC_NEW_OFF_PIT */ {# ifdef _EXC_NEW_OFF_FIT if ((UINT32) vector == _EXC_OFF_FIT) { vector = (FUNCPTR *) _EXC_NEW_OFF_FIT; }# endif /* _EXC_NEW_OFF_FIT */ }#endif /* ( (CPU == PPC403) || (CPU==PPC405) || (CPU==PPC405F) ) */#if (CPU == PPC604)# ifdef _EXC_NEW_OFF_PERF if ((UINT32) vector == _EXC_OFF_PERF) { vector = (FUNCPTR *) _EXC_NEW_OFF_PERF; }# endif /* _EXC_NEW_OFF_PERF */#endif /* (CPU == PPC604) */#endif /* TRUE */ /* vector is offset by the vector base address */ newVector = (INSTR *) ((int) vector | (int) excVecBaseGet ()); /* * One of the connect functions (excConnect, excIntConnect, excCrtConnect, * or excIntCrtConnect) has previously copied the appropriate stub code * (excConnectCode[] or excCrtConnectCode[] or their extended versions to * the vector location. We now need to change an instruction in the stub * to jump to the new handler function. * * If the processor supports "critical" exceptions, there are two * different stubs and the offset of the jump instruction within * the stub depends on whether it is the "critical" or the "normal" * stub. To distinguish between them, we examine the first word of * the stub. */ if (excExtendedVectors == TRUE) {#ifdef ISR_CRT_OFF if (excExtCrtConnectCode[0] == newVector[0]) { newVector[isrCrtOffset] = (INSTR) (0x3c600000 | MSW((int)function)); newVector[isrCrtOffset+1] = (INSTR) (0x60630000 | LSW((int)function)); CACHE_TEXT_UPDATE((void *) &newVector[isrCrtOffset], 2*sizeof(INSTR *)); } else#endif /* ISR_CRT_OFF */ { newVector[isrOffset] = (INSTR) (0x3c600000 | MSW((int)function)); newVector[isrOffset+1] = (INSTR) (0x60630000 | LSW((int)function)); CACHE_TEXT_UPDATE((void *) &newVector[isrOffset], 2 * sizeof(INSTR *)); } } else /* non-extended vectors */ {#ifdef ISR_CRT_OFF if (excCrtConnectCode[0] == newVector[0]) { INSTR routineBranch = blCompute ( (VOIDFUNCPTR) function, &newVector[isrCrtOffset] ); /* * if the function is too far for a 26-bit offset, blCompute will * return 0. Could set an errno in that case. */ if (routineBranch == 0) { if (_func_logMsg != NULL) _func_logMsg ("Target %08lx for vector %x out of range\n", function, &newVector[isrCrtOffset], 0,0,0,0); } else { newVector[isrCrtOffset] = routineBranch; CACHE_TEXT_UPDATE((void *) &newVector[isrCrtOffset], sizeof(INSTR *)); } } else#endif /* ISR_CRT_OFF */ { INSTR routineBranch = blCompute ( (VOIDFUNCPTR) function, &newVector[isrOffset] ); /* * if the function is too far for a 26-bit offset, blCompute will * return 0. Could set an errno in that case. */ if (routineBranch == 0) { if (_func_logMsg != NULL) _func_logMsg ("Target %08lx for vector %x out of range\n", function, &newVector[isrOffset], 0,0,0,0); } else { newVector[isrOffset] = routineBranch; CACHE_TEXT_UPDATE((void *) &newVector[isrOffset], sizeof(INSTR *)); } } } }/********************************************************************************* excVecGet - get a CPU exception vector** This routine returns the address of the current C routine connected to* the <vector>.** RETURNS: the address of the C routine.** SEE ALSO: excVecSet()*/FUNCPTR excVecGet ( FUNCPTR * vector /* vector offset */ ) { INSTR * vec; INSTR routine; /* * SPR #77145: See Exception Vector Table comment near top of file. * Relocated vectors saves wrong vector offset in ESF, thus need to * be patched to get right. Note also that pEsf->vecOffset (or * _PPC_ESF_VEC_OFF) is supposed to c
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -