📄 cachealib.s
字号:
/* cacheALib.s - PowerPC cache management assembly routines *//* Copyright 1995-2003 Wind River Systems, Inc. */ .data .globl copyright_wind_river .long copyright_wind_river/*modification history--------------------02d,24jul03,dtr Formal inspection fixes, remove some CPU==PPC85XX defines and fix bug introduced with CP1 merge.02c,09jun03,dtr CP1 merge02c,31jan03,jtp SPR 82770 handle multiple icbi needed for PPC440 virtual-tagged I-Cache02b,13jan03,pch SPR 79170: check for MMU enabled before en/disabling cache02b,20dec02,mil Fixed build error.02a,04dec02,dtr Adding support for E500.02a,03dec02,pch 604 seems to need sync instead of isync after changing HID0[ICE]01z,12sep02,pch SPR 80642: fix 40x/60x/7xx/74xx handling in cachePpcDisable01z,03aug02,pcs Add support for PPC85XX and make it the same as PPC603 for the present.01y,21may02,pch SPR 77727: fix 405 preprocessor expressions SPR 77736: workaround for PPC405GP errata #1501x,17apr02,jtp support PPC440 cache01w,29oct01,dtr SPR 63012 - use of non-volatile conditional field.01v,22oct01,gls changed to flush 64K cache for 604/7xx (SPR #67431/#28800)01u,25sep01,yvp Fix SPR62760: Use _WRS_TEXT_SEG_START macro instead of .align01t,08may01,pch Add assembler abstractions (FUNC_EXPORT, FUNC_BEGIN, etc.)01s,03nov00,s_m added check in cachePpcDisable for PPC405 - if MMU is on return error01r,25oct00,s_m renamed PPC405 cpu types01q,16oct00,sm In cachePpcEnable, used ppc405DccrVall to initialize the cache, since this is configurable by bsp.01p,11oct00,sm fixed problems in cachePpcEnable for PPC40501o,06oct00,sm added support for PPC40501n,24feb99,tpr added cacheArchPipeFlush.01m,18aug98,tpr added PowerPC EC 603 support.01l,22jul97,tpr added sync instruction arround HID0 modification (SPR #8976)01k,21feb97,tam added support for the PPC403GCX processor.01j,03sep96,tam added PPC403 support.01i,29jul96,tpr changed MPC_IMP_DCACHE_SIZE value.01h,15apr96,tam fixed typo error in cachePpcEnable (SPR #6334 ).01g,23feb96,tpr clean up the code.01f,06jan96,tpr replace %hi and %lo by HI and LO.01e,27sep95,tpr removed MMU disable in cacheEnable() and cacheDisable().01d,01aug95,kvk Fixed cacheEnable added cacheDisable to support PPC604.01c,22jun95,caf added ifdef for PPC403, cleanup.01b,27mar95,caf added cacheEnable() support.01a,30jan95,caf created.*//*DESCRIPTIONThis library contains routines to manipulate the PowerPC family caches.INCLUDE FILES: cacheLib.hSEE ALSO: cacheLib*/#define _ASMLANGUAGE#include "vxWorks.h"#include "asm.h"#include "cacheLib.h" /* defines */#if ((CPU == PPC603) || (CPU == PPCEC603) || (CPU == PPC604))/* sizes used in cachePpcDisable(), only for the 60x cases */#define MPC_IMP_BLOCK_SIZE _CACHE_ALIGN_SIZE# if (CPU == PPC604)# define MPC_IMP_DCACHE_SIZE 32768# else /* CPU == PPC604 */# define MPC_IMP_DCACHE_SIZE 16384# endif /* CPU == PPC604 */#endif /* ((CPU == PPC603) || (CPU == PPCEC603) || (CPU == PPC604)) */ DATA_IMPORT(cachePpcReadOrigin) FUNC_IMPORT(cacheErrnoSet)#if (CPU == PPC440) FUNC_IMPORT(cache440Enable) FUNC_IMPORT(cache440Disable)#endif /* PPC440 */#if (CPU == PPC403) DATA_IMPORT(ppc403IccrVal) /* ICCR default cachability states */ DATA_IMPORT(ppc403DccrVal) /* DCCR default cachability states */#endif /* CPU == PPC403 */#if ( (CPU == PPC405F) || (CPU == PPC405) ) DATA_IMPORT(ppc405ICACHE_LINE_NUM) /* comes from BSP */ DATA_IMPORT(ppc405DCACHE_LINE_NUM) /* comes from BSP */ DATA_IMPORT(ppc405CACHE_ALIGN_SIZE)/* comes from BSP*/#endif /* PPC405F || PPC405 */ FUNC_EXPORT(cachePpcEnable) /* enable the data or instr. cache */ FUNC_EXPORT(cachePpcDisable) /* disable the data or instr. cache */ FUNC_EXPORT(cacheArchInvalidate) /* invalidate data or instr. cache */ FUNC_EXPORT(cacheArchFlush) /* flush the data or instr. cache */ FUNC_EXPORT(cacheArchTextUpdate) /* update the instruction cache */ FUNC_EXPORT(cacheArchPipeFlush) /* flush the CPU pipe cache */#if (CPU == PPC85XX) DATA_IMPORT(ppcE500ICACHE_LINE_NUM) /* comes from BSP */ DATA_IMPORT(ppcE500DCACHE_LINE_NUM) /* comes from BSP */ DATA_IMPORT(ppcE500CACHE_ALIGN_SIZE)/* comes from BSP*/ FUNC_EXPORT(cacheE500Enable) /* enable the data or instr. cache */ FUNC_EXPORT(cacheE500Disable) /* disable the data or instr. cache */#include "cacheE500ALib.s"#endif#ifdef _WRS_I_CACHE_TAG_VIRTUAL /* * PPC440 has virtually tagged cache lines. The tag is the * entire virtual address, comprising the 32-bit Effective * Address (EA) concatenated with 8-bit Process ID (PID) and * 1-bit Translation Space (TS). * * The result is that data cached from the same physical memory * location may appear in multiple cache lines... for example, * lines filled during a fetch when MSR[IS] = 0, MSR[IS] = 1, * PID = 0, or PID = 2, or when different EAs map the same * physical memory location, in any combination. If not managed * correctly, these cache lines may have different data contents * cached for the same physical memory location. This is * particularly visible when setting breakpoints * (usrBreakpointSet). * * There are two approaches: one is to clear the entire I-cache * using iccci, or to issue multiple icbi instructions with all * possible combinations of EA, PID, and TS (note: fetches gets * TS from MSR[IS], but icbi gets TS from MSR[DS]). * * Note that the MMU_BASIC library is assumed, it uses PID=0 to * get started, and PID=2 once the MMU library has been * initialized, if the MMU library has been configured. See * mmu440Lib.c and mmu440LibInit(). * * With both I and D MMUs unconfigured, and assuming the same * physical line is not being accessed with multiple EA->PA * translations, then a single icbi with PID=0 and TS=0 is * enough. If either MMU is configured, an additional icbi with * PID=2 and TS=0 is needed. If the I-MMU is configured, then * PID=0, TS=1 and PID=2, TS=1 must be set up for icbi. * * While PID or TS is changed, it is important to not incur any * exceptions, interrupts, or TLB Misses. This is aided by the * fact that icbi gets TS from MSR[DS] instead of MSR[IS], and * we can avoid data accesses that would incur a data TLB Miss. * * Pseudocode for clearing one physical address: * * MMU_TEMP <== mmuPpcSelected * MSR_SAVE <== MSR * MSR[CE,DE,DWE,EE,IS] <== 0 * PID_SAVE <== PID * * PID <== 0; MSR[DS] <== 0; icbi r0, p1 * * if ((MMU_TEMP | (MMU_INST | MMU_DATA)) != 0) * PID <== 2; MSR[DS] <== 0; icbi r0, p1 * if ((MMU_TEMP | MMU_INST) != 0) * PID <== 2; MSR[DS] <== 1; icbi r0, p1 * PID <== 0; MSR[DS] <== 1; icbi r0, p1 * * MSR <== MSR_SAVE * PID <== PID_SAVE * * The same code is needed for both cacheTextUpdate and * cacheArchInvalidate. The code is provided below as a macro, * ICBI. The macro takes these parameters: * * EA_REG - register holding effective address to be icbi'ed * MSR_SAVE - register to save and restore MSR value in * PID_SAVE - register to save and restore PID value in * MMU_TMP - register to use for MMU configuration storage * MSR_TMP - register to use for manipulating MSR contents * TMP_REG - register for general use */# if 1 /* * ICBI for processors with virtual-tagged I-Cache as described * above. */#include <arch/ppc/mmu440Lib.h> DATA_IMPORT(mmuPpcSelected)# define ICBI(EA_REG,MSR_SAVE,PID_SAVE,MMU_TMP,MSR_TMP,TMP_REG) \ \ lis MMU_TMP, HIADJ(mmuPpcSelected) /* load mmuPpcSelected */ ; \ lwz MMU_TMP, LO(mmuPpcSelected)(MMU_TMP) /* MMU_TMP <== */ ; \ \ mfmsr MSR_SAVE /* MSR_SAVE <== orig MSR */ ; \ lis TMP_REG, HI( ~(_PPC_MSR_CE|_PPC_MSR_EE|_PPC_MSR_DE| \ _PPC_MSR_DWE|_PPC_MSR_IS|_PPC_MSR_DS)) ; \ ori TMP_REG, TMP_REG, LO( ~(_PPC_MSR_CE|_PPC_MSR_EE|_PPC_MSR_DE| \ _PPC_MSR_DWE|_PPC_MSR_IS|_PPC_MSR_DS)) ; \ and MSR_TMP, MSR_SAVE, TMP_REG ; \ mtmsr MSR_TMP /* INTS & MMU off */ ; \ isync /* synchronize */ ; \ \ xor TMP_REG,TMP_REG,TMP_REG ; \ mfpid PID_SAVE /* PID_SAVE <== PID */ ; \ mtpid TMP_REG /* PID <== 0 */ ; \ isync /* synchronize */ ; \ icbi r0,EA_REG /* inval for TS 0, PID 0 */ ; \ \ andi. MMU_TMP, MMU_TMP, (MMU_INST | MMU_DATA) /* MMUs off? */ ; \ beq 99f /* if so, skip ahead */ ; \ \ li TMP_REG, 2 ; \ mtpid TMP_REG /* PID <== 2 */ ; \ isync /* synchronize */ ; \ icbi r0,EA_REG /* inval for TS 0 PID 2 */ ; \ \ andi. MMU_TMP, MMU_TMP, (MMU_INST) /* instruction MMU off? */ ; \ beq 99f /* if so, skip ahead */ ; \ \ ori MSR_TMP, MSR_TMP, _PPC_MSR_DS ; \ mtmsr MSR_TMP /* MSR[DS] <== 1 */ ; \ isync /* synchronize */ ; \ icbi r0,EA_REG /* inval for TS 1 PID, 2 */ ; \ \ xor TMP_REG, TMP_REG, TMP_REG ; \ mtpid TMP_REG /* PID <== 0 */ ; \ isync /* synchronize */ ; \ icbi r0,EA_REG /* inval for TS 1, PID 0 */ ; \ \99: \ mtpid PID_SAVE /* restore orig PID */ ; \ isync ; \ mtmsr MSR_SAVE /* restore orig MSR */ ; \ isync# else /* not used */ /* * Alternate ICBI for processors with Virtual-tagged I-cache, * with lowest performance but greatest portability. Will work * on all Book E Processors. All parameters are ignored. */# define ICBI(EA_REG,MSR_SAVE,PID_SAVE,MMU_TMP,MSR_TMP,TMP_REG) \ iccci r0,r0# endif#else /* _WRS_I_CACHE_TAG_VIRTUAL */ /* * Normal ICBI for processors with physically-tagged I-Cache. * All but the first parameter are ignored. */# define ICBI(EA_REG,MSR_SAVE,PID_SAVE,MMU_TMP,MSR_TMP,TMP_REG) \ icbi r0,EA_REG#endif /* _WRS_I_CACHE_TAG_VIRTUAL */ _WRS_TEXT_SEG_START/******************************************************************************** cachePpcEnable - Enable the PowerPC Instruction or Data cache** This routine enables the instruction or data cache as selected by the* <cache> argument.** NOTE:* This routine should never be called by the user application. Only* the cacheArchEnable() can call this routine. If the user application calls* this routine directly the result is unpredictable and can crash the VxWorks* kernel.** RETURNS: OK or ERROR if the cache can not be enabled.** SEE ALSO:*.I "PPC403GA Embedded Controller User's Manual"*.I "PowerPC 601 RISC Microprocessor User's Manual"*.I "PowerPC 603 RISC Microprocessor User's Manual"*.I "PowerPC 604 RISC Microprocessor User's Manual"* STATUS cachePpcEnable* (* CACHE_TYPE cache, /@ cache to enable @/* )*/FUNC_BEGIN(cachePpcEnable)#if (CPU == PPC85XX) b cacheE500Enable/* * This #elif block covers the entire cachePpcEnable function. * All alternatives are marked as just below. */#elif (CPU == PPC601)/* **** cachePpcEnable **** */ /* * PPC601 caches are always on. The only way to disable the caches is * via the MMU. */ b cacheArchOK /* return OK *//* **** cachePpcEnable **** */#elif ( (CPU == PPC403) || (CPU == PPC405F) || (CPU == PPC405) )# if (CPU == PPC403) li p3, 0 /* p3 = multiplication factor */ mfspr p1, PVR /* for _CACHE_LINE_NUM */ rlwinm p1, p1, 24, 24, 31 /* extract CPU ID PVR[16:23] */ cmpwi p1, _PVR_CONF_403GCX bne enableNo403gcx /* 8 for 403GCX which has */ li p3, 3 /* cache 8 times larger */enableNo403gcx:# endif /* PPC403 */ cmpwi p0, _DATA_CACHE /* if _DATA_CACHE then */ beq cachePpc403DataEnable /* enable Data Cache */# if (CPU == PPC403) lis p2, HIADJ(ppc403IccrVal) lwz p2, LO(ppc403IccrVal)(p2) /* load ppc403IccrVal value */# else /* PPC403 */ /* * if the MMU is enabled, the only way to enable the cache is * via the MMU. */ mfmsr p2 rlwinm. p2, p2, 0, _PPC_MSR_BIT_IR, _PPC_MSR_BIT_IR bne cacheArchError /* return ERROR if IR set */ lis p2, HIADJ(ppc405IccrVal) lwz p2, LO(ppc405IccrVal)(p2) /* load ppc405IccrVal value */# endif /* PPC403 */ mfspr p1, ICCR /* move ICCR to p1 */ cmpw p1, p2 /* if instr. cache is already */ beq cacheArchOK /* enabled just return OK */ /* reset the instruction cache */# if ((CPU == PPC405) || (CPU == PPC405F))/* For PPC405 RevE and earlier, disable data MMU to work around errata #15 */ mfmsr p3 /* read msr */ rlwinm p4,p3,0,28,26 /* Turn off DR bit */ mtmsr p4 /* disable data MMU */ iccci r0, r0 /* On the 405, iccci invalidates the entire I CACHE */ mtmsr p3 /* restore data MMU */# else /* CPU == PPC403 */ li p0, 0 /* clear p0 */ li p1, _ICACHE_LINE_NUM /* load number of cache lines */ slw p1, p1, p3 /* adjust with mult. factor */ mtctr p1cachePpc403IInvalidate: iccci r0, p0 addi p0, p0, _CACHE_ALIGN_SIZE /* bump to next line */ bdnz cachePpc403IInvalidate /* go to invalidate */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -