From 2b5c7b9f336bf2d8eaac3ae9db6272bcf6429029 Mon Sep 17 00:00:00 2001 From: tantricity Date: Sat, 18 Jun 2011 16:05:24 +0000 Subject: [PATCH] patch to make enabling 64B L2 cache optional (tueidj) git-svn-id: https://devkitpro.svn.sourceforge.net/svnroot/devkitpro/trunk/libogc@4666 258c5a1a-4f63-435d-9564-e8f6d34ab52c --- gc/ogc/cache.h | 64 ++++++++++++++++++++++++++++++++--------------------- libogc/cache.c | 38 +++++++++++++++++++++++++++++++ libogc/system_asm.S | 2 +- 3 files changed, 78 insertions(+), 26 deletions(-) diff --git a/gc/ogc/cache.h b/gc/ogc/cache.h index e75ac18..830b5bd 100644 --- a/gc/ogc/cache.h +++ b/gc/ogc/cache.h @@ -33,10 +33,10 @@ distribution. #ifndef __CACHE_H__ #define __CACHE_H__ -/*! \file cache.h +/*! \file cache.h \brief Cache subsystem -*/ +*/ #include @@ -48,7 +48,7 @@ distribution. #endif /* __cplusplus */ -/*! +/*! * \fn void DCEnable() * \brief Enable L1 d-cache * @@ -88,9 +88,9 @@ void DCFreeze(); * \return none */ void DCUnfreeze(); - - -/*! + + +/*! * \fn void DCFlashInvalidate() * \brief Invalidate L1 d-cache. * @@ -102,7 +102,7 @@ void DCUnfreeze(); void DCFlashInvalidate(); -/*! +/*! * \fn void DCInvalidateRange(void *startaddress,u32 len) * \brief Invalidates a given range of the d-cache. * @@ -116,7 +116,7 @@ void DCFlashInvalidate(); void DCInvalidateRange(void *startaddress,u32 len); -/*! +/*! * \fn void DCFlushRange(void *startaddress,u32 len) * \brief Flushes a given range. * @@ -130,7 +130,7 @@ void DCInvalidateRange(void *startaddress,u32 len); */ void DCFlushRange(void *startaddress,u32 len); -/*! +/*! * \fn void DCStoreRange(void *startaddress,u32 len) * \brief Ensures a range of memory is updated with any modified data in the cache. * @@ -144,9 +144,9 @@ void DCFlushRange(void *startaddress,u32 len); void DCStoreRange(void *startaddress,u32 len); -/*! +/*! * \fn void DCFlushRangeNoSync(void *startaddress,u32 len) - * \brief Flushes a given range. + * \brief Flushes a given range. * * If any part of the range hits in the d-cache the corresponding block will be flushed to main memory and invalidated.
* NOTE: This routine does not perform a "sync" to ensure that the range has been flushed to memory. That is, the cache blocks are sent to the bus interface unit for storage to main memory, but by the time this function returns, you are not guaranteed that the blocks have been written to memory. @@ -159,7 +159,7 @@ void DCStoreRange(void *startaddress,u32 len); void DCFlushRangeNoSync(void *startaddress,u32 len); -/*! +/*! * \fn void DCStoreRangeNoSync(void *startaddress,u32 len) * \brief Ensures a range of memory is updated with any modified data in the cache. * @@ -173,7 +173,7 @@ void DCFlushRangeNoSync(void *startaddress,u32 len); void DCStoreRangeNoSync(void *startaddress,u32 len); -/*! +/*! * \fn void DCZeroRange(void *startaddress,u32 len) * \brief Loads a range of memory into cache and zeroes all the cache lines. * @@ -185,7 +185,7 @@ void DCStoreRangeNoSync(void *startaddress,u32 len); void DCZeroRange(void *startaddress,u32 len); -/*! +/*! * \fn void DCTouchRange(void *startaddress,u32 len) * \brief Loads a range of memory into cache. * @@ -197,9 +197,9 @@ void DCZeroRange(void *startaddress,u32 len); void DCTouchRange(void *startaddress,u32 len); -/*! +/*! * \fn void ICSync() - * \brief Performs an instruction cache synchronization. + * \brief Performs an instruction cache synchronization. * * This ensures that all instructions preceding this instruction have completed before this instruction completes. * @@ -208,7 +208,7 @@ void DCTouchRange(void *startaddress,u32 len); void ICSync(); -/*! +/*! * \fn void ICFlashInvalidate() * \brief Invalidate the L1 i-cache. * @@ -220,7 +220,7 @@ void ICSync(); void ICFlashInvalidate(); -/*! +/*! * \fn void ICEnable() * \brief Enable L1 i-cache * @@ -229,7 +229,7 @@ void ICFlashInvalidate(); void ICEnable(); -/*! +/*! * \fn void ICDisable() * \brief Disable L1 i-cache * @@ -238,7 +238,7 @@ void ICEnable(); void ICDisable(); -/*! +/*! * \fn void ICFreeze() * \brief Current contents of the L1 i-cache are locked down and will not be cast out. * @@ -250,7 +250,7 @@ void ICDisable(); void ICFreeze(); -/*! +/*! * \fn void ICUnfreeze() * \brief Undoes actions of ICFreeze(). * @@ -262,9 +262,9 @@ void ICFreeze(); void ICUnfreeze(); -/*! +/*! * \fn void ICBlockInvalidate(void *startaddress) - * \brief Invalidates a block in the i-cache. + * \brief Invalidates a block in the i-cache. * * If the block hits in the i-cache, the corresponding block will be invalidated. * @@ -275,9 +275,9 @@ void ICUnfreeze(); void ICBlockInvalidate(void *startaddress); -/*! +/*! * \fn void ICInvalidateRange(void *startaddress,u32 len) - * \brief Invalidate a range in the L1 i-cache. + * \brief Invalidate a range in the L1 i-cache. * * If any part of the range hits in the i-cache, the corresponding block will be invalidated. * @@ -288,6 +288,20 @@ void ICBlockInvalidate(void *startaddress); */ void ICInvalidateRange(void *startaddress,u32 len); +/*! + * \fn void L2Enhance() + * \brief Turn on extra L2 cache features + * + * Sets the following bits in the HID4 register which affect the L2 cache: + * - L2FM=01 (64-byte fetch mode) + * - BCO=1 (dual 64-byte castout buffers) + * - L2MUM=1 (configured as 2-deep miss-under-miss cache) + * Since these features can't be enabled safely, any HID4 writes in the HBC stub will be removed. + * + * \return none + */ +void L2Enhance(); + void LCEnable(); void LCDisable(); void LCLoadBlocks(void *,void *,u32); diff --git a/libogc/cache.c b/libogc/cache.c index aa84a9d..d3164f2 100644 --- a/libogc/cache.c +++ b/libogc/cache.c @@ -38,6 +38,8 @@ distribution. ((u32)(((u32)(v) >> (s)) & ((0x01 << (w)) - 1))) extern void __LCEnable(); +extern void L2GlobalInvalidate(); +extern void L2Enable(); void LCEnable() { @@ -139,3 +141,39 @@ void LCAllocNoInvalidate(void *addr,u32 bytes) } LCAllocTags(FALSE,addr,cnt); } + +void L2Enhance() +{ + u32 level, hid4; + u32 *stub = (u32*)0x80001800; + _CPU_ISR_Disable(level); + hid4 = mfspr(HID4); + // make sure H4A is set before doing anything + if (hid4 & 0x80000000) { + // There's no easy way to flush only L2, so just flush everything + // L2GlobalInvalidate will take care of syncing + DCFlushRangeNoSync((void*)0x80000000, 0x01800000); +#ifdef HW_RVL + DCFlushRangeNoSync((void*)0x90000000, 0x04000000); +#endif + // Invalidate L2 (this will disable it first) + L2GlobalInvalidate(); + // set bits: L2FM=01, BCO=1, L2MUM=1 + hid4 |= 0x24200000; + mtspr(HID4, hid4); + // Re-enable L2 + L2Enable(); + + // look for HBC stub (STUBHAXX) + if (stub[1]==0x53545542 && stub[2]==0x48415858) { + // look for a HID4 write + for (stub += 3; (u32)stub < 0x80003000; stub++) { + if ((stub[0] & 0xFC1FFFFF)==0x7C13FBA6) { + write32((u32)stub, 0x60000000); + break; + } + } + } + } + _CPU_ISR_Restore(level); +} diff --git a/libogc/system_asm.S b/libogc/system_asm.S index 7e90411..2b8580c 100644 --- a/libogc/system_asm.S +++ b/libogc/system_asm.S @@ -273,7 +273,7 @@ __InitSystem: #if defined(HW_RVL) mfspr r3,HID4 - oris r3,r3,0x25B0 //set additional bits in HID4: L2FM, BCO, SR0(store 0), LPE(PS LE exception), L2MUM, L2CFI(L2 castout prior to L2 inv. flash) + oris r3,r3,0x0190 //set additional bits in HID4: SR0(store 0), LPE(PS LE exception), L2CFI(L2 castout prior to L2 inv. flash) mtspr HID4,r3 isync #endif -- 2.11.4.GIT