📄 syscache.c
字号:
/* sysCache.c - secondary (L2) cache library for PowerPC 750 *//******************************************************************************* This source and object code has been made available to you by IBM on an AS-IS basis. IT IS PROVIDED WITHOUT WARRANTY OF ANY KIND, INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE OR OF NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL IBM OR ITS LICENSORS BE LIABLE FOR INCIDENTAL, CONSEQUENTIAL OR PUNITIVE DAMAGES. IBM'S OR ITS LICENSOR'S DAMAGES FOR ANY CAUSE OF ACTION, WHETHER IN CONTRACT OR IN TORT, AT LAW OR AT EQUITY, SHALL BE LIMITED TO A MAXIMUM OF $1,000 PER LICENSE. Anyone receiving this source or object code is licensed under IBM copyrights to use it in any way he or she deems fit, including copying it, modifying it, compiling it, and redistributing it either with or without modifications. No license under IBM patents or patent applications is to be implied by the copyright license. Any user of this software should understand that neither IBM nor its licensors will be responsible for any consequences resulting from the use of this software. Any person who transfers this object code or any derivative work must include the IBM copyright notice in the transferred software. COPYRIGHT I B M CORPORATION 1999 LICENSED MATERIAL - PROGRAM PROPERTY OF I B M"*******************************************************************************//* Copyright 1984-2002 Wind River Systems, Inc. *//*modification history--------------------01e,23jan03,jtp SPR 84493 recognize 750FX PVR values 700xxxxx01d,12sep02,pch SPR 80542: recognize 750FX PVR values SPR 81221: add L2 flush & invalidate functions SPR 81212: test entire L2 cache on 750FX01c,27mar01,kab Removed IBM support info per request01b,03nov00,mcg updated for 750CX01a,12apr99,mcg written (from template)*//*DESCRIPTIONThis library provides L2 cache support for the PowerPC 750 processor.The 750 processor has a dedicated L2 cache interface.*/#if defined(INCLUDE_CACHE_SUPPORT) && defined(INCLUDE_CACHE_L2)#ifdef DEBUG_L2_HANDLERint l2_size = 0; /* size of L2 cache */int sysL2flushCount = 0;char * sysL2initStatus = NULL;#elseLOCAL int l2_size = 0; /* size of L2 cache */#endifLOCAL void sysL2CacheEnable (void);LOCAL void sysL2CacheDisable (void);LOCAL void sysL2CacheFlush (void);LOCAL void sysL2CacheInvFunc (void);IMPORT ULONG sysReadL2CR(void); /* assembler function */IMPORT void sysWriteL2CR(ULONG); /* assembler function */IMPORT void sysSync(void); /* assembler function */IMPORT void sysDcbz(void *); /* assembler function */IMPORT void sysDcbf(void *); /* assembler function */IMPORT VOIDFUNCPTR _pSysL2CacheInvFunc;IMPORT VOIDFUNCPTR _pSysL2CacheEnable;IMPORT VOIDFUNCPTR _pSysL2CacheFlush;IMPORT VOIDFUNCPTR _pSysL2CacheDisable;/******************************************************************************** sysL2CacheFlush - flush the L2 cache(s)** This routine flushes the L2 cache(s) if either or both were* previously initialized using sysL2CacheInit().** RETURNS: N/A** SEE ALSO: sysL2CacheInit(), sysL2CacheEnable(), sysL2CacheDisable()*/LOCAL void sysL2CacheFlush ( void ) { int lockKey; register int i; register ULONG tmp; if (l2_size != 0 && (vxHid0Get() & _PPC_HID0_DCE)) { lockKey=intLock();#ifdef DEBUG_L2_HANDLER ++sysL2flushCount;#endif sysSync(); /* * Flush the inline L2 cache, using loads rather than dcbf per * 750CX User's Manual sec. 9.1.1 & 750FX User's Manual sec. 5.2 */ for (i = 2 * l2_size - 32 ; i >= 0 ; i -= 32 ) tmp = *(ULONG *)(RAM_LOW_ADRS + i); sysSync(); intUnlock(lockKey); } }/******************************************************************************** sysL2CacheInvFunc - Invalidate the L2 cache(s)** This routine invalidates the L2 cache(s) if either or both were* previously initialized using sysL2CacheInit(). Calling this* routine invalidates the L2 tag bits.** RETURNS: N/A** SEE ALSO: sysL2CacheInit(), sysL2CacheEnable(), sysL2CacheDisable()*/LOCAL void sysL2CacheInvFunc (void) { int lockKey; lockKey=intLock(); sysSync(); /* Invalidate the L2 */ sysWriteL2CR (sysReadL2CR() | _PPC_L2CR_INVALIDATE); /* spin until L2CR IP bit is cleared */ while (sysReadL2CR() & _PPC_L2CR_INPROGRESS) ; sysSync(); sysWriteL2CR(sysReadL2CR() & ~_PPC_L2CR_INVALIDATE); intUnlock(lockKey); }/******************************************************************************** sysL2CacheDisable - disable the L2 cache** This routine disables the L2 cache if it was previously initialized using* sysL2CacheInit(). Calling this routine invalidates the L2 tag bits.** RETURNS: N/A** SEE ALSO: sysL2CacheInit()*/LOCAL void sysL2CacheDisable ( void ) { sysSync(); sysWriteL2CR (sysReadL2CR() & ~(_PPC_L2CR_ENABLE)); sysSync(); }/******************************************************************************** sysL2CacheEnable - enable the L2 cache** This routine invalidates and enables the L2 cache** RETURNS: N/A** SEE ALSO: sysL2CacheInit(), sysL2CacheDisable()*/LOCAL void sysL2CacheEnable ( void ) { int l2cr; sysSync(); /* Invalidate the L2 */ sysWriteL2CR (sysReadL2CR() | _PPC_L2CR_INVALIDATE); /* spin until L2CR IP bit is cleared */ while (sysReadL2CR() & _PPC_L2CR_INPROGRESS) ; l2cr = sysReadL2CR(); /* * If specified in config.h, use the L2 for data only and not for * instructions. */#ifdef USER_L2_CACHE_DATA_ONLY l2cr |= _PPC_L2CR_DATA_ONLY;#endif sysWriteL2CR((l2cr | _PPC_L2CR_ENABLE) & ~_PPC_L2CR_INVALIDATE); }/******************************************************************************** sysL2CacheInit - initialize the L2 cache** This routine initializes and enables L2 cache support.** RETURNS: OK, or ERROR if cache is not present or not supported.** SEE ALSO: sysL2CacheDisable()**/STATUS sysL2CacheInit ( void ) { int cpu; int family; register int j; register unsigned int * testArea; register unsigned int * testWord; register unsigned int testValue; register unsigned int rvalue; cpu = CPU_TYPE; family = cpu >> 16; l2_size = 0; /* * Continue only if the processor is from the 7xx family * Note 750FX can register a range of values */ if (family == CPU_FAMILY_7XX || (family & 0xfff0) == CPU_FAMILY_750FX) { sysL2CacheDisable (); /* * Is this a 750 or 750L where the L2 is off-chip? */ if ((cpu == CPU_TYPE_740_750) || (cpu == CPU_TYPE_740L_750L) || (cpu == CPU_TYPE_740L_750L_2) || (cpu == CPU_TYPE_740L_750L_3)) { l2_size = L2_CACHE_750_750L_SIZE; /* * The L2 Cache that is available on the 750 and 750L processor * daughter cards has 512KB of L2 cache on board. Set up the L2 * cache control register for 512KB, 2:1 clock ratio, pipelined * burst SRAM. */ /* Note: 2:1 processor to L2 bus interface ratio is not always * correct depending on the processor core speed and the access * parameters of the external SRAMs. */ sysWriteL2CR(_PPC_L2CR_SIZE_512K | _PPC_L2CR_CLKDIV_21 | _PPC_L2CR_RAM_PB ); } else { if (cpu == CPU_TYPE_750FX || ((cpu >> 16) & 0xfff0) == CPU_FAMILY_750FX) l2_size = L2_CACHE_750FX_SIZE; else l2_size = L2_CACHE_750CX_SIZE; } /* * If the L1 Data cache is enabled, don't go any further, just return. */ if (vxHid0Get() & _PPC_HID0_DCE) { _pSysL2CacheEnable = sysL2CacheEnable; _pSysL2CacheFlush = sysL2CacheFlush; _pSysL2CacheDisable = sysL2CacheDisable; _pSysL2CacheInvFunc = sysL2CacheInvFunc;#ifdef DEBUG_L2_HANDLER sysL2initStatus = "_PPC_HID0_DCE was set\n";#endif return(0); } /* * Invalidate L2, turn on test support bit, and turn on data-only bit * for testing the L2. */ sysWriteL2CR(sysReadL2CR() | _PPC_L2CR_INVALIDATE | _PPC_L2CR_TEST_SPRT | _PPC_L2CR_DATA_ONLY); /* * Check L2CR IP bit - it should take 32K core clock cycles to * finish invalidating the L2, upon which the L2CR IP bit is cleared. */ /* spin until L2CR IP bit is cleared */ while (sysReadL2CR() & _PPC_L2CR_INPROGRESS) ; testArea = memalign(32, l2_size); /* Cache line boundary aligned */ if (testArea == NULL) {#ifdef DEBUG_L2_HANDLER sysL2initStatus = "memalign() failed\n";#endif return(ERROR); } /* * Enable L2 and turn off the L2 invalidate bit. */ sysWriteL2CR((sysReadL2CR() | _PPC_L2CR_ENABLE) & ~_PPC_L2CR_INVALIDATE); /* Turn on L1 data cache via the HID0 register for testing the L2. */ sysSync(); vxHid0Set(vxHid0Get() | _PPC_HID0_DCE); /* Zero out testArea (same size as the L2) */ testWord = testArea; while ((unsigned int)testWord < ((unsigned int)testArea + l2_size)) { sysDcbz((void *)testWord); /* Establish a cache line of 0 */ *testWord = 0; /* make the line dirty */ sysDcbf((void *)testWord); /* Flush the line */ testWord += 8; /* the next 8 word L1 cache line */ } /* * Disable the L1 data cache. Then invalidate it. */ sysSync(); vxHid0Set(vxHid0Get() & ~_PPC_HID0_DCE); vxHid0Set(vxHid0Get() | _PPC_HID0_DCFI); /* * Do a simple test to see if the L2 cache is present. With L1 now * disabled and the test support bit set in the L2CR, writes to * testArea should wind up in the L2 if it exists. Note that when the * test support bit is set in L2CR, L2 cache misses are not forwarded * to the 6xx bus interface. This test helps to determine the * difference between a 740 and a 750 at runtime. */ testWord = testArea; *testWord = 0x01234567; *(testWord+1) = 0x89ABCDEF; *(testWord+2) = ~(0x01234567); /* change the data bus */ *(testWord+3) = ~(0x89ABCDEF); /* change the data bus */ if ( ((rvalue = *testWord) != 0x1234567) | ((rvalue = *(testWord+1)) != 0x89ABCDEF)) { sysWriteL2CR(sysReadL2CR() & ~(_PPC_L2CR_ENABLE | _PPC_L2CR_DATA_ONLY | _PPC_L2CR_TEST_SPRT)); free(testArea);#ifdef DEBUG_L2_HANDLER sysL2initStatus = "no L2 found\n";#endif return(0); } /* * We can now assume an L2 cache exists. Now test the L2 SRAM for * for stuck faults by writing "A"s then "5"s then "A"s again. */ testWord = testArea; while ((unsigned int)testWord < ((unsigned int)testArea + l2_size)) { testValue = 0xAAAAAAAA; for (j=0; j<3; j++) { *testWord = testValue; *(testWord+2) = 0x01234567; /* change the data bus */ *(testWord+3) = 0x89ABCDEF; /* change the data bus */ if ( ((rvalue = *testWord) != testValue)) { /* Failure occurred. Disable and invalidate L2 */ sysSync(); sysWriteL2CR((sysReadL2CR() | _PPC_L2CR_INVALIDATE) & ~(_PPC_L2CR_ENABLE | _PPC_L2CR_DATA_ONLY | _PPC_L2CR_TEST_SPRT)); sysSync(); /* spin until L2CR IP bit is cleared */ while (sysReadL2CR() & _PPC_L2CR_INPROGRESS) ; sysWriteL2CR(sysReadL2CR() & ~_PPC_L2CR_INVALIDATE); free(testArea);#ifdef DEBUG_L2_HANDLER sysL2initStatus = "L2 test failed\n";#endif return(ERROR); } testValue = ~testValue; } testWord++; } /* * L2 tests passed. Disable, turn off data only and test support * bits. Turn on the Invalidate bit. */ sysSync(); sysWriteL2CR((sysReadL2CR() | _PPC_L2CR_INVALIDATE) & ~(_PPC_L2CR_ENABLE | _PPC_L2CR_DATA_ONLY | _PPC_L2CR_TEST_SPRT)); /* Wait for the invalidate to complete */ sysSync(); while (sysReadL2CR() & _PPC_L2CR_INPROGRESS) ; /* * Turn off the invalidate bit. L2 cache is ready to be used. */ sysWriteL2CR(sysReadL2CR() & ~_PPC_L2CR_INVALIDATE); free(testArea); _pSysL2CacheEnable = sysL2CacheEnable; _pSysL2CacheFlush = sysL2CacheFlush; _pSysL2CacheDisable = sysL2CacheDisable; _pSysL2CacheInvFunc = sysL2CacheInvFunc;#ifdef DEBUG_L2_HANDLER sysL2initStatus = "finished OK\n"; } else { sysL2initStatus = "not a 750\n";#endif } return (OK); }#endif /* INCLUDE_CACHE_SUPPORT */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -