?? intalib.s
字號(hào):
/* intALib.s - assembly language interrupt handling routines *//* Copyright 1984-2003 Wind River Systems, Inc. */ .data .globl copyright_wind_river .long copyright_wind_river/*modification history--------------------02h,09jun03,mil Merged from CP1 to e500.02g,30jan03,jtp Comment intCrtEnt regarding need to flush critical save data before reenabling MMU02f,20nov02,mil Updated support for PPC85XX.02e,03oct02,dtr Adding save/restore of spefscr for 85XX.02d,03aug02,pcs Add support for PPC85XX and make it the same as PPC603 for the present.02c,13jun02,jtp disable MMU during context restore for 4XX (SPR #78396)02b,17may02,pch SPR 77035: fix WindView calculation of vector address02a,17apr02,jtp support PPC440 cache & mmu01z,15oct01,kab Fix SPR #71240: Enable PPC604 MMU IR,DR rather than cache lock.01z,25sep01,yvp Fix SPR62760: Use _WRS_TEXT_SEG_START macro instead of .align01y,18sep01,tcr fix WindView instrumentation for interrupts01x,16aug01,pch Add PPC440 support; change test for CPU==PPC4xx to ifdef _PPC_MSR_CE_U where appropriate01w,20jun01,pch Export intCrtEnt & intCrtExit for PPC40501v,08may01,pch Add assembler abstractions (FUNC_EXPORT, FUNC_BEGIN, etc.)01u,17apr01,dtr FUNC doesn't work relpacing with function type. This should enable intLock etc to be seen as function in symbol table.01y,25oct00,s_m renamed PPC405 cpu types01x,18oct00,s_m restore MMU state in intExit for PPC40501w,18oct00,s_m enable MMU in interrupt wrapper01v,13oct00,sm fpfix and fpCrtfix are externs only for PPC405F01u,06oct00,sm Include fix for PPC405F errata01t,24aug98,cjtc Windview 2.0 event logging now handled in int controller code. Avoids problem with out-of-sequence timestamps in event log (SPR 21868)01q,18aug98,tpr added PowerPC EC 603 support.01s,16apr98,pr commenting out triggering code. Modified evtAction into int3201r,23jan98,pr modified WV code accordingly to the changes made in eventP.h01q,13dec97,pr started changes of WindView code for WV2.0. STILL IN PROGRESS01p,06aug97,tam fixed problem with CE interrupt (SPR #8964)01o,22jul97,tpr added sync instruction arround HID0 modification (SPR #8976)01n,27mar97,tam set FP & RI bits before calling the rescheduler (SPR #8286)01m,18mar97,tam modified interrupt masks for PPC403; added intCrtEnt() and intCrtExit() (SPR #8192).01l,12dec96,tpr added sync before HID0 changing to lock data cache (SPR #7605)01k,15jul96,tpr replace cahce flushing by cache locking in intEnt().01j,11jul96,pr cleanup for windview instrumentation01i,08jul96,pr added windview instrumentation - conditionally compiled01h,24jun96,tpr added PowerPC 860 support.01g,23may96,tpr fixed SPR 6593.01f,06mar96,tpr removed bug intExit() for PPC603.01e,23feb96,tpr added intEnt() and intExit().01d,23sep95,tpr changed intUnlock code to unlock interrupt only.01c,03feb95,caf cleanup.01b,05dec94,caf changed 'bcr' to 'bclr'.*//*DESCRIPTIONThis library contains various functions associated with interrupt managementfor the PowerPC family. The intEnt() entry point is used to save the currentcontext prior to call the C or assembly interrupt handler. intExit() is usedto leave interrupt processing and restart the current task or interrupt handler,or call the rescheduler if a higher priority task has been made ready by theinterrupt handler.The routines intLock() and intUnlock() are used to lock and unlock externalinterrupts and the internal decrementer (PPC440, PPC601, PPC603, PPC604) ortimer (PPC403, PPC405) during critical code sections.Architecture: intExit() | __________|____________ / \ | in Kernel | not in Kernel and v or Nested v not Nested | ______________|__________________ intRet / \ | current task = | current task not v highest ready task v highest ready task | _________________|______________ intRet / \ | preempt disabled | v or task not ready saveIntContext | | intRet reschedule() | windLoadContext()SEE ALSO: intLib, windALib, excALib, sigCtxLib*/#define _ASMLANGUAGE#include "vxWorks.h"#include "asm.h"#include "esf.h"#include "private/eventP.h"#include "private/taskLibP.h"#include "excLib.h"/* Certain versions of PPC405F need a fix for Errata # 18 (lfd) instruction * Note: This errata is numbered 18 for the 405GF and numbered 20 for the * D8405 */#define PPC405F_ERRATA_18 /* define this to include fix */ /* globals */ FUNC_EXPORT(intEnt) /* Interrupt Entry routine */ FUNC_EXPORT(intExit) /* Interrupt Exit routine */#ifdef _PPC_MSR_CE_U FUNC_EXPORT(intCrtEnt) /* Critical Interrupt Entry routine */ FUNC_EXPORT(intCrtExit) /* Critical Interrupt Exit routine */#endif /* _PPC_MSR_CE_U */ FUNC_EXPORT(intLock) /* Interrupt Lock routine */ FUNC_EXPORT(intUnlock) /* Interrupt Unlock routine */ /* externs */ FUNC_IMPORT(reschedule) /* rescheduler */#if (CPU == PPC405F) FUNC_EXPORT(fpfix) /* PPC405F errata fix */ FUNC_EXPORT(fpCrtfix) /* PPC405F errata fix for crt.intrp */#endif /* CPU == PPC405F */ DATA_IMPORT(readyQHead) /* ready queue head */ DATA_IMPORT(kernelState) /* kernel state */ DATA_IMPORT(taskIdCurrent) /* current task identifier */ DATA_IMPORT(intCnt) /* interrupt counter */ DATA_IMPORT(errno) /* error number */ _WRS_TEXT_SEG_START/********************************************************************************* intEnt - catch and dispatch external interrupts** This is the interrupt dispatcher that is pointed by the PowerPC exception.* It saves the context when interrupt happens and return to the stub.** NOMANUAL* void excIntStub()*/FUNC_BEGIN(intEnt) /* At the entry of this function, the following is done */ /* mtspr SPRG3, p0 /@ save P0 to SPRG3 */ /* mfspr p0, LR /@ load LR to P0 */ /* bla intEnt /@ save vector in LR, jump to handler */ mtspr SPRG2, p0 /* save LR to SPRG2 */ mtspr SPRG0, p1 /* save P1 to SPRG0 */ /* * On the PowerPC 60X, when an external interrupt is taken, the * processor turns the MMU off. At this moment the cache is no * longer controlled by the WIMG bits of the MMU. If the data cache * is on, the value of the SP, CR, PC and MSR register are written in * the cache and not in the memory. * The interrupt handler should be executed with the MMU in the * same state as the non-interrupt code. This stub should * re-enable the data or/and instruction MMU if they were enabled * before the interrupt. * By re-enabling the MMU, the cache restarts to be controlled via the * WIMG bits. If the memory pages which handle the interrupt stack are * in not cacheables state, the cache is turn off for all memory acces * in this area. * In intExit() the SP, CR, PC, and MSR register values should be * restored. Because the MMU is on, the processor go to read the memory * to get the register values. But the true value is save in the cache. * In this case the restored value is corrupted and can crash VxWorks. * To avoid memory this coherency problem, the data cache should be * locked. */ /* * Note that the PPC604 has HW support for TLB-miss. * PPC603 &c cannot enable the TLB until ready to handle nested * interrupts from a TLB-miss. This is not an issue for the PPC604, * so enable the MMU I/D immediately, get the cache state back, and * don't go through any cache-lock gyrations. * This is a critical performance issue if HID0[ABE] (propagate * sync to bus) is set: The PPC7400/7410 cannot turn it off. */#if (CPU == PPC604) mfspr p1, SRR1 /* load P1 w/ SRR1(MSR) */ rlwinm p1, p1, 0, 26, 27 /* get IR and DR bit values */ /* before the interrupt */ mfmsr p0 /* get the current MSR value */ or p0, p0, p1 /* set MMU bits if previously */ mtmsr p0 /* set & restore MSR value */ isync /* instruction sync. */#endif /* (CPU == PPC604) */ mfcr p1 /* save CR to P1 before it is changed */ /* * The special purpose register SPRG1 contains the real interrupt * nesting count. It is initialzed in wintIntStackSet() in windALib.s. * Because intCnt is faked in windTickAnnounce(), intCnt cannot be * used for checking of nested interrupts to switch stack. */ mfspr p0, SPRG1 /* get nested count */ addi p0, p0, 1 /* increment nested count */ mtspr SPRG1, p0 /* update nested count */ /* * The PowerPC Familly doesn't support the notion of interrupt * stack. To avoid to add the size of interrupt stack in each task * stack this stub switch from the task stack to the interrupt stack * by changing the value of the SP(R1). * This switch should be performed only if the interrupt is not * a nested interrupt. */ cmpwi p0, 1 /* test for nested interrput */ beq intStackSwitch /* no, switch to interrupt stack */#if ((CPU == PPC603) || (CPU == PPCEC603)) mfspr p0, HID0 /* get HID0 value */ mtcr p0 /* save temporily HID0 */ ori p0, p0, _PPC_HID0_DLOCK /* set the DLOCK bit */ sync mtspr HID0, p0 /* LOCK the Data Cache */#endif /* ((CPU == PPC603) || (CPU == PPCEC603) */ stwu sp, -_PPC_ESF_STK_SIZE(sp) /* we already use int. stack */ b intSaveCritical /* save old stack pointer */intStackSwitch:#if ((CPU == PPC603) || (CPU == PPCEC603)) mfspr p0, HID0 /* get HID0 value */ mtcr p0 /* save temporily HID0 */ ori p0, p0, _PPC_HID0_DLOCK /* set the DLOCK bit */ sync mtspr HID0, p0 /* LOCK the Data Cache */#endif /* ((CPU == PPC603) || (CPU == PPCEC603)) */ addi p0, sp, 0 /* save current SP to P0 */ lis sp, HIADJ(vxIntStackBase) /* load int. stack base addr. */ lwz sp, LO(vxIntStackBase)(sp) /* in SP */ stwu p0, -_PPC_ESF_STK_SIZE(sp) /* carve stack */intSaveCritical: stw p1, _PPC_ESF_CR(sp) /* save CR */ mfspr p0, SRR0 /* load P0 with SRR0(PC) */ stw p0, _PPC_ESF_PC(sp) /* save SRR0(PC) */ mfspr p1, SRR1 /* load P1 with SRR1(MSR) */ stw p1, _PPC_ESF_MSR(sp) /* save SRR1(MSR) */#if (CPU == PPC405F) /* * we need the following fix for certain versions of PPC405F */# ifdef PPC405F_ERRATA_18 mfspr p0, LR /* save current LR */ stw p0, _PPC_ESF_LR(sp) bl fpfix /* handle fix */ lwz p0, _PPC_ESF_LR(sp) mtspr LR, p0 /* restore current LR */# endif /* PPC405F_ERRATA_18 */#endif /* (CPU == PPC405F) */#if ((CPU == PPC405) || (CPU == PPC405F) || (CPU == PPC440) || \ (CPU == PPC85XX)) /* * Before we reenable the MMU, we need to ensure that the values * we pushed on the stack above are flushed out of cache. */ dcbf 0, sp /* push SP value in memory */ li p0, _PPC_ESF_CR dcbf p0, sp /* push CR value in memory */ li p0, _PPC_ESF_PC dcbf p0, sp /* push PC value in memory */ li p0, _PPC_ESF_MSR dcbf p0, sp /* push MSR value in memory */ sync#endif /* CPU == PPC405 || CPU == PPC405F || CPU == PPC440 */#if ((CPU == PPC603) || (CPU == PPCEC603)) mfcr p0 /* load temporily saved HID0 */ mtspr HID0, p0 /* UNLOCK the Data Cache */#endif /* ((CPU == PPC603) || (CPU == PPCEC603)) */ /* PPC604 enabled MMU IR/DR above */#ifdef _WRS_TLB_MISS_CLASS_SW /* * 604 MMU (Hardware miss handling) was reenabled above; this case * will reenable all other MMUs (software miss handlers) */ rlwinm p1, p1, 0, 26, 27 /* get IR and DR bit values */ /* before the interrupt */ mfmsr p0 /* get the current MSR value */ or p0, p0, p1 /* set MMU bits if previously */ mtmsr p0 /* set & restore MSR value */ isync /* instruction sync. */#endif /* _WRS_TLB_MISS_CLASS_SW */ mfspr p0, SPRG2 /* load saved LR to P0 */ stw p0, _PPC_ESF_LR(sp) /* save LR */ mfspr p0, SPRG3 /* reload saved P0 */ stw p0, _PPC_ESF_P0(sp) /* save P0 to the stack */ mfspr p1, SPRG0 /* reload saved P1 */ stw p1, _PPC_ESF_P1(sp) /* save P1 to the stack */ lis p0, HIADJ(errno) lwz p0, LO(errno)(p0) /* load ERRNO to P0 and */ stw p0, _PPC_ESF_ERRNO(sp) /* save ERRNO to the stack */ lis p1, HIADJ(intCnt) lwz p0, LO(intCnt)(p1) /* load intCnt value */ addi p0, p0, 1 /* increment intCnt value */ stw p0, LO(intCnt)(p1) /* save new intCnt value */ /* * The critical status are saved at this stage. The interrupt should * be enabled as soon as possible to reduce the interrupt latency. * However, there is only one mask bit on PowerPC. It is at the * interrupt controller level to set mask for each individual * interrupt. * Thus, we save task's register first, then call interrupt controller * routine to decide if the interrupt should be re-enabled or not. */ mfspr p0, XER /* load XER to P0 */ stw p0, _PPC_ESF_XER(sp) /* save XER to the stack */ mfspr p0, CTR /* load CTR to P0 */ stw p0, _PPC_ESF_CTR(sp) /* save CTR to the stack */#if (CPU==PPC601) mfspr p0, MQ /* load MQ to P0 */ stw p0, _PPC_ESF_MQ(sp) /* save MQ to the stack */#endif /* (CPU==PPC601) */#if (CPU==PPC85XX) mfspr p0, SPEFSCR /* load SPEFSCR to P0 */ stw p0, _PPC_ESF_SPEFSCR(sp) /* save SPEFSCR to the stack */#endif /* (CPU==PPC85XX) */#if FALSE lwz p0, 0(sp) stw p0, _PPC_ESF_SP(sp)#endif stw r0, _PPC_ESF_R0(sp) /* save general register 0 */ stw r2, _PPC_ESF_R2(sp) /* save general register 2 */ stw p2, _PPC_ESF_P2(sp) /* save general register 5 */ stw p3, _PPC_ESF_P3(sp) /* save general register 6 */ stw p4, _PPC_ESF_P4(sp) /* save general register 7 */ stw p5, _PPC_ESF_P5(sp) /* save general register 8 */ stw p6, _PPC_ESF_P6(sp) /* save general register 9 */ stw p7, _PPC_ESF_P7(sp) /* save general register 10 */ stw r11, _PPC_ESF_R11(sp) /* save general register 11 */ stw r12, _PPC_ESF_R12(sp) /* save general register 12 */ stw r13, _PPC_ESF_R13(sp) /* save general register 13 */ /* * The callee should save the non volatile registers, thus they are * not saved here. An assembly routine should not use these registers * or follow the calling convention by saving them before using. */ /* * Instrumentation for external interrupts is done in the interrupt * controller code. The timestamp is no longer taken here. This avoids * the problem with out-of-sequence timestamps appearing in the event * log if a tickAnnounce occurs between here and when the interrupt * controller code is taken (SPR 21358) */#ifdef WV_INSTRUMENTATION /* windview instrumentation - BEGIN * enter an interrupt handler. */ lis p6, HIADJ(evtAction) /* WindView or triggering on? */ lwz p0, LO(evtAction)(p6) cmpwi p0, 0 bne actionIntEnt /* if so, more tests */noActionIntEnt:#endif /* WV_INSTRUMENTATION */ blr /* return */#ifdef WV_INSTRUMENTATIONactionIntEnt: /* * The external interrupt is instrumented elsewhere, so the only one we * do here is decrementer (or PIT for PPC40x). */ mfspr p0, LR /* save exception number to P0*//*
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -