⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 intalib.s

📁 VxWorks BSP框架源代码包含头文件和驱动
💻 S
📖 第 1 页 / 共 4 页
字号:
/* 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*//*

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -