📄 excarchlib.c
字号:
* excCrtConnect(), or excRelocCrtConnect()* excIntCrtConnect(), or excRelocIntCrtConnect()* excMchkConnect(), or excRelocMchkConnect()* excIntConnectTimer() (phasing out)** NOMANUAL*/LOCAL STATUS excConnectVector ( INSTR * newVector, /* calculated exc vector */ int vecType, /* norm/crit/mchk? */ VOIDFUNCPTR entry, /* handler entry */ VOIDFUNCPTR routine, /* routine to be called */ VOIDFUNCPTR exit /* handler exit */ ) { INSTR entBranch, routineBranch, exitBranch, scratch; int entOff, isrOff, exitOff; int vecSize; /* Set offsets into handler */ if ((vecType == VEC_TYPE_CRT) || (vecType == VEC_TYPE_MCHK)) {#ifdef _EXC_OFF_CRTL entOff = entCrtOffset; isrOff = isrCrtOffset; exitOff = exitCrtOffset;#else return ERROR; /* no critical exception handler for either crt or mchk class */#endif /* _EXC_OFF_CRTL */ } else if (vecType == VEC_TYPE_NORM) { entOff = entOffset; isrOff = isrOffset; exitOff = exitOffset; } else /* vecType == VEC_TYPE_UNDEF or undef */ { return ERROR; /* check only once in excConnectVector */ } if (excExtendedVectors == TRUE) { /* copy the vector template code into the vector and save the size */ if ((vecType == VEC_TYPE_CRT) || (vecType == VEC_TYPE_MCHK)) {#ifdef _EXC_OFF_CRTL /* VEC_TYPE_MCHK requireds _EXC_OFF_CRTL defined */ vecSize = sizeof(excExtCrtConnectCode); bcopy ((char *) excExtCrtConnectCode, (char *) newVector, vecSize);#ifdef _PPC_MSR_MCE if (vecType == VEC_TYPE_MCHK) { /* use SPRG4 for mchk */ scratch = *newVector; *newVector = (scratch & 0xffe007ff) | SPR_SET(SPRG4_W); }#endif /* _PPC_MSR_MCE */#else /* _EXC_OFF_CRTL */ return ERROR;#endif /* _EXC_OFF_CRTL */ } else /* vecType == VEC_TYPE_NORM */ { vecSize = sizeof(excExtConnectCode); bcopy ((char *) excExtConnectCode, (char *) newVector, vecSize); } /* fill in the two halves of the 32-bit function addresses */ newVector[entOff] = (INSTR) (0x3c600000 | MSW((int)entry)); newVector[entOff+1] = (INSTR) (0x60630000 | LSW((int)entry)); newVector[isrOff] = (INSTR) (0x3c600000 | MSW((int)routine)); newVector[isrOff+1] = (INSTR) (0x60630000 | LSW((int)routine)); newVector[exitOff] = (INSTR) (0x3c600000 | MSW((int)exit)); newVector[exitOff+1] = (INSTR) (0x60630000 | LSW((int)exit)); } else /* excExtendedVectors == TRUE */ { /* Compute branch instructions for short stub, or 0. */ entBranch = blCompute (entry, &newVector[entOff]); routineBranch = blCompute (routine, &newVector[isrOff]); exitBranch = blCompute (exit, &newVector[exitOff]); /* * If any branch was out of range, return ERROR */ if ( (entBranch == (INSTR) 0) || (routineBranch == (INSTR) 0) || (exitBranch == (INSTR) 0) ) return ERROR; /* copy the vector template code into the vector and save the size */ if ((vecType == VEC_TYPE_CRT) || (vecType == VEC_TYPE_MCHK)) {#ifdef _EXC_OFF_CRTL /* VEC_TYPE_MCHK requireds _EXC_OFF_CRTL defined */ vecSize = sizeof(excCrtConnectCode); bcopy ((char *) excCrtConnectCode, (char *) newVector, vecSize);#ifdef _PPC_MSR_MCE if (vecType == VEC_TYPE_MCHK) { /* use SPRG4 for mchk */ scratch = *newVector; *newVector = (scratch & 0xffe007ff) | SPR_SET(SPRG4_W); }#endif /* _PPC_MSR_MCE */#else /* _EXC_OFF_CRTL */ return ERROR;#endif /* _EXC_OFF_CRTL */ } else /* vecType == VEC_TYPE_NORM */ { vecSize = sizeof(excConnectCode); bcopy ((char *) excConnectCode, (char *) newVector, vecSize); } /* fill in the branch instructions */ newVector[entOff] = entBranch; newVector[isrOff] = routineBranch; newVector[exitOff] = exitBranch; } /* excExtendedVectors == TRUE */ CACHE_TEXT_UPDATE((void *) newVector, vecSize); /* synchronize cache */ return (OK); }#ifdef _PPC_MSR_CE# ifdef _EXC_OFF_CRTL /* if not, excCrtConnectCode does not exist *//********************************************************************************* excCrtConnect - connect a C routine to a critical exception vector (PPC4xx)** This routine connects a specified C routine to a specified critical 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 excCrtConnect ( VOIDFUNCPTR * vector, /* exception vector to attach to */ VOIDFUNCPTR routine /* routine to be called */ ) { return ( excRelocCrtConnect (vector, routine, (VOIDFUNCPTR *) 0) ); }/********************************************************************************* excRelocCrtConnect - connect a C routine to an exception vector with* possible relocation** This routine is same as excCrtConnect 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 excRelocCrtConnect ( 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_CRT, excCrtEnt, routine, excCrtExit); 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); }/********************************************************************************* excIntCrtConnect - connect a C routine to a critical interrupt vector (PPC4xx)** This routine connects a specified C routine to a specified asynchronous * critical exception vector such as the critical external interrupt vector * (0x100), or the watchdog timer vector (0x1020). An interrupt stub is created * and placed at <vector> in the exception table. The address of <routine> is * stored in the interrupt stub code. When the asynchronous exception occurs,* the processor jumps to the interrupt stub code, saves only the requested * registers, and calls the C routines.** When the C routine is invoked, interrupts are still locked. It is the* C routine's responsibility to re-enable interrupts.** The routine can be any normal C routine, except that it must not* invoke certain operating system functions that may block or perform* I/O operations.** Before the requested registers are saved, the interrupt stub switches from the* current task stack to the interrupt stack. In the case of nested interrupts,* no stack switching is performed, because the interrupt stack is already set.** RETURNS: OK if the routine connected successfully, or* ERROR if the routine was too far away for a 26-bit offset.* * SEE ALSO: excConnect(), excCrtConnect, excVecSet()*/STATUS excIntCrtConnect ( VOIDFUNCPTR * vector, /* exception vector to attach to */ VOIDFUNCPTR routine /* routine to be called */ ) { return ( excRelocIntCrtConnect (vector, routine, (VOIDFUNCPTR *) 0) ); }/********************************************************************************* excRelocIntCrtConnect - connect a C routine to an exception vector with* possible relocation** This routine is same as excIntCrtConnect 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 excRelocIntCrtConnect ( 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_CRT, intCrtEnt, routine, intCrtExit); 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));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -