?? cachearchlib.c
字號:
else { /* Instruction cache */ cacheIInvalidateAll (); /* Invalidate all cache tags */ cacheArchState |= MMUCR_I_ENABLE; /* note turning I-cache on */ } /* * Only actually enable either cache if MMU is already on, else it will * be done later by mmuEnable(), as will the setting of * cacheDataEnabled and the calling of cacheFuncsSet(). * Only change those bits that require setting, relying on the * current state of the MMUCR. */ oldLevel = intIFLock (); if (cacheMmuIsOn ()) { cacheDataEnabled = TRUE; cacheFuncsSet (); mmuModifyCr (cacheArchState, cacheArchState); } intIFUnlock (oldLevel);#endif /* (ARMCACHE == ARMCACHE_940T,946E) */#if ARMCACHE_NEEDS_IMB if (cache == INSTRUCTION_CACHE) /* * If they've asked to enable the I-cache, we'd better flush the * prefetch unit by doing an Instruction Memory Barrier (IMB * instruction). */ cacheIMB ();#endif /* ARMCACHE_NEEDS_IMB */ } /* endif cache not already enabled */ return OK; } /* cacheArchEnable() *//********************************************************************************* cacheArchDisable - disable an ARM cache** This routine flushes, clears and disables the specified ARM instruction or* data cache.** RETURNS: OK, or ERROR if the cache type is invalid or the cache control* is not supported.** NOMANUAL*/LOCAL STATUS cacheArchDisable ( CACHE_TYPE cache /* cache to disable */ ) { if (cacheProbe (cache) != OK) return ERROR; /* invalid cache */ if (cacheIsOn (cache)) /* already off? */ {#if ((ARMCACHE == ARMCACHE_710A) || (ARMCACHE == ARMCACHE_720T) || \ (ARMCACHE == ARMCACHE_740T) || (ARMCACHE == ARMCACHE_810)) /* keep a note that we have disabled the cache */ cacheArchState = 0; /* * Clear (flush and invalidate) D-cache, drain W/Buffer, disable * D-cache, switch off Write Buffer. */ cacheDClearDisable (); cacheDataEnabled = FALSE; /* data cache is off */ cacheFuncsSet (); /* update data function ptrs */#endif /* 710A, 720T, 740T */#if ((ARMCACHE == ARMCACHE_SA110) || (ARMCACHE == ARMCACHE_SA1100) || \ (ARMCACHE == ARMCACHE_SA1500)) if (cache == DATA_CACHE) { /* keep a note that we have disabled the cache */ cacheArchState = 0; /* * Clear (flush and invalidate) D-cache, drain W/Buffer, disable * D-cache, switch off Write Buffer. */ cacheDClearDisable (); cacheDataEnabled = FALSE; /* data cache is off */ cacheFuncsSet (); /* update data function ptrs */ } else /* Instruction cache: disable, flush I-cache and do branch */ cacheIClearDisable ();#endif /* SA110, SA1100, SA1500 */#if ((ARMCACHE == ARMCACHE_920T) || (ARMCACHE == ARMCACHE_926E) || \ (ARMCACHE == ARMCACHE_940T) || (ARMCACHE == ARMCACHE_946E) || \ (ARMCACHE == ARMCACHE_XSCALE) || (ARMCACHE == ARMCACHE_1020E) || \ (ARMCACHE == ARMCACHE_1022E)) if (cache == DATA_CACHE) { /* note that we have disabled the cache. W bit is Should Be One */ cacheArchState &= ~MMUCR_C_ENABLE; /* * Clear (flush and invalidate) D-cache, drain W/Buffer, disable * D-cache. */ cacheDClearDisable (); cacheDataEnabled = FALSE; /* data cache is off */ cacheFuncsSet (); /* update data function ptrs */ } else { /* * Instruction cache: note disabling, disable, flush * I-cache and do branch. On 920T, don't need to keep note * of I-cache setting, only on 940T, where I-cache cannot be * enabled without MMU. */#if ((ARMCACHE == ARMCACHE_940T) || (ARMCACHE == ARMCACHE_946E)) cacheArchState &= ~MMUCR_I_ENABLE;#endif cacheIClearDisable (); }#endif /* 920T, 926E, 940T, 946E, XSCALE, 1020E, 1022E */#if ARMCACHE_NEEDS_IMB if (cache == INSTRUCTION_CACHE) /* * If they've asked to enable the I-cache, we'd better flush the * prefetch unit by doing an Instruction Memory Barrier (IMB * instruction). */ cacheIMB ();#endif /* ARMCACHE_NEEDS_IMB */ } /* endif cache was on */ return OK; } /* cacheArchDisable() *//********************************************************************************* cacheArchFlush - flush entries from an ARM cache** This routine flushes (writes out to memory) some or all entries from the* specified ARM cache and drains write-buffer, if appropriate.** RETURNS: OK, or ERROR if the cache type is invalid or the cache control* is not supported.** NOMANUAL*/LOCAL STATUS cacheArchFlush ( CACHE_TYPE cache, /* cache to flush */ void * address, /* address to flush */ size_t bytes /* bytes to flush */ ) { if (cacheProbe (cache) != OK) return ERROR; /* invalid cache */#if ((ARMCACHE == ARMCACHE_710A) || (ARMCACHE == ARMCACHE_720T) || \ (ARMCACHE == ARMCACHE_740T)) cacheArchPipeFlush (); /* drain W/B */#endif#if ((ARMCACHE == ARMCACHE_810) || (ARMCACHE == ARMCACHE_SA110) || \ (ARMCACHE == ARMCACHE_SA1100) || (ARMCACHE == ARMCACHE_SA1500) || \ (ARMCACHE == ARMCACHE_920T) || (ARMCACHE == ARMCACHE_926E) || \ (ARMCACHE == ARMCACHE_940T) || (ARMCACHE == ARMCACHE_946E) || \ (ARMCACHE == ARMCACHE_XSCALE) || (ARMCACHE == ARMCACHE_1020E) || \ (ARMCACHE == ARMCACHE_1022E)) if (cache == DATA_CACHE) { if ((bytes == ENTIRE_CACHE) ||#if (ARMCACHE == ARMCACHE_810) /* * On 810, to flush an individual address, we actually end up * flushing much more. If the address range corresponds to 8 * segments or more, we might as well do the lot and be done with * it. */ (bytes >= (_CACHE_ALIGN_SIZE * 8)))#endif#if (ARMCACHE == ARMCACHE_940T) /* similar arguments on 940T, for 4 segments or more */ (bytes >= (_CACHE_ALIGN_SIZE * 4)))#endif#if ((ARMCACHE == ARMCACHE_SA110) || (ARMCACHE == ARMCACHE_SA1100) || \ (ARMCACHE == ARMCACHE_SA1500) || (ARMCACHE == ARMCACHE_920T) || \ (ARMCACHE == ARMCACHE_926E) || (ARMCACHE == ARMCACHE_946E) || \ (ARMCACHE == ARMCACHE_XSCALE) || (ARMCACHE == ARMCACHE_1020E) || \ (ARMCACHE == ARMCACHE_1022E)) (bytes >= D_CACHE_SIZE))#endif cacheDFlushAll (); /* also drains W/B */ else { /* not doing all the cache, do the area requested */ bytes += (size_t) address; address = (void *) ((UINT) address & ~(_CACHE_ALIGN_SIZE - 1)); do { cacheDFlush (address); address = (void *) ((UINT) address + _CACHE_ALIGN_SIZE); } while ((size_t) address < bytes); cacheArchPipeFlush (); /* drain write buffer */ } } /* endif data cache */ /* else I-cache. No need to do anything as I-cache is read-only. */#endif return OK; } /* cacheArchFlush() *//********************************************************************************* cacheArchInvalidate - invalidate entries from an ARM cache** This routine invalidates some or all entries from the specified ARM cache.** RETURNS: OK, or ERROR if the cache type is invalid or the cache control* is not supported.** NOMANUAL*/LOCAL STATUS cacheArchInvalidate ( CACHE_TYPE cache, /* cache to clear */ void * address, /* address to clear */ size_t bytes /* bytes to clear */ ) { if (cacheProbe (cache) != OK) return ERROR; /* invalid cache */#if ((ARMCACHE == ARMCACHE_710A) || (ARMCACHE == ARMCACHE_720T) || \ (ARMCACHE == ARMCACHE_740T)) cacheDInvalidateAll (); /* Cannot invalidate individual lines */#endif#if (ARMCACHE == ARMCACHE_810) /* * On 810, to invalidate an individual address, we actually end * up invalidating much more, so we need to flush it first, to avoid * invalidating some dirty data. If the address range corresponds to 8 * segments or more, we might as well do the lot and be done with it. If * the user has actually asked to invalidate all the cache, then we can * actually do an invalidate of all the cache, not a clear. */ if (cache == DATA_CACHE) { if (bytes == ENTIRE_CACHE) cacheDInvalidateAll(); else if (bytes >= (_CACHE_ALIGN_SIZE * 8)) cacheDClearAll(); else { bytes += (size_t) address; address = (void *) ((UINT) address & ~(_CACHE_ALIGN_SIZE - 1)); do { cacheDClear (address); address = (void *) ((UINT) address + _CACHE_ALIGN_SIZE); } while ((size_t) address < bytes); cacheArchPipeFlush (); /* drain write buffer */ } } else { /* Instruction cache */ if (bytes == ENTIRE_CACHE) cacheIMB (); /* Execute IMB to flush Prefetch Unit */ else cacheIMBRange(address, (INSTR *) ((UINT32)address + bytes)); }#endif#if ((ARMCACHE == ARMCACHE_SA110) || \ (ARMCACHE == ARMCACHE_SA1100) || (ARMCACHE == ARMCACHE_SA1500)) if (cache == DATA_CACHE) if (bytes == ENTIRE_CACHE) cacheDInvalidateAll (); else { bytes += (size_t) address; address = (void *) ((UINT) address & ~(_CACHE_ALIGN_SIZE - 1)); do { cacheDInvalidate (address); address = (void *) ((UINT) address + _CACHE_ALIGN_SIZE); } while ((size_t) address < bytes); } else /* I-cache */ cacheIInvalidateAll (); /* Cannot invalidate individual lines */#endif /* * The if (bytes == ENTIRE_CACHE) used to be (== ENTIRE_CACHE) || * (bytes >= D_CACHE_SIZE), which would invalidate unexpected bits of * the cache. Fixes SPR #30698. */#if ((ARMCACHE == ARMCACHE_920T) || (ARMCACHE == ARMCACHE_926E) || \ (ARMCACHE == ARMCACHE_946E) || (ARMCACHE == ARMCACHE_XSCALE) || \ (ARMCACHE == ARMCACHE_1020E) || (ARMCACHE == ARMCACHE_1022E)) if (cache == DATA_CACHE) if (bytes == ENTIRE_CACHE) cacheDInvalidateAll (); else { bytes += (size_t) address; address = (void *) ((UINT) address & ~(cacheArchAlignSize - 1)); do { cacheDInvalidate (address); address = (void *) ((UINT) address + cacheArchAlignSize); } while ((size_t) address < bytes); } else /* I-cache */ if ((bytes == ENTIRE_CACHE) || (bytes >= I_CACHE_SIZE)) cacheIInvalidateAll (); else {#if (ARMCACHE == ARMCACHE_XSCALE) /* visionProbe will not operate correctly with single line flushes*/ cacheIInvalidateAll ();#else bytes += (size_t) address; address = (void *) ((UINT) address & ~(cacheArchAlignSize - 1)); do { cacheIInvalidate (address);#if (ARMCACHE == ARMCACHE_XSCALE) btbInvalidate ();#endif /* (ARMCACHE == ARMCACHE_XSCALE) */ address = (void *) ((UINT) address + cacheArchAlignSize); } while ((size_t) address < bytes);#endif /* (ARMCACHE == XSCALE) */ }#endif /* (ARMCACHE == ARMCACHE_920T,926E,946E,XSCALE,1020E,1022E) */#if (ARMCACHE == ARMCACHE_940T) /* * On 940T, we also end up invalidating much more, so we need to * flush it first, to avoid invalidating some dirty data. If the * address range corresponds to 4 segments or more, we might as well * do the lot and be done with it. If the user has actually asked to * invalidate all the cache, then we can actually do an invalidate of * all the cache, not a clear. */ if (cache == DATA_CACHE) { if (bytes == ENTIRE_CACHE) cacheDInvalidateAll(); else if (bytes >= (_CACHE_ALIGN_SIZE * 4)) cacheDClearAll(); else { bytes += (size_t) address; address = (void *) ((UINT) address & ~(_CACHE_ALIGN_SIZE - 1)); do { cacheDClear (address); address = (void *) ((UINT) address + _CACHE_ALIGN_SIZE); } while ((size_t) address < bytes); cacheArchPipeFlush (); /* drain write buffer */ } } else { /* Instruction cache */ if (bytes == ENTIRE_CACHE) cacheIInvalidateAll(); else if (bytes >= (_CACHE_ALIGN_SIZE * 4)) cacheIInvalidateAll(); else { bytes += (size_t) address; address = (void *) ((UINT) address & ~(_CACHE_ALIGN_SIZE - 1)); do { cacheIInvalidate (address); address = (void *) ((UINT) address + _CACHE_ALIGN_SIZE); } while ((size_t) address < bytes); } }#endif return OK; } /* cacheArchInvalidate() *//*******************************************************************************
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -