diff options
Diffstat (limited to 'src/ssx/ppc405/ppc405_cache_core.c')
-rwxr-xr-x | src/ssx/ppc405/ppc405_cache_core.c | 115 |
1 files changed, 115 insertions, 0 deletions
diff --git a/src/ssx/ppc405/ppc405_cache_core.c b/src/ssx/ppc405/ppc405_cache_core.c new file mode 100755 index 0000000..a03f5e2 --- /dev/null +++ b/src/ssx/ppc405/ppc405_cache_core.c @@ -0,0 +1,115 @@ +// $Id: ppc405_cache_core.c,v 1.1.1.1 2013/12/11 21:03:27 bcbrock Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/ppc405/ppc405_cache_core.c,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file ppc405_cache_core.c +/// \brief Core cache management routines required of any PPC405 configuration +/// of SSX that interacts with DMA devices using cacheable memory. +/// +/// The entry points in this file are considered 'core' routines that will +/// always be present at runtime in any SSX application. +/// +/// \todo The compiler generates wierd assembly language for these cache +/// management APIs - probably due to the "volatile" asm - it may be best to +/// recode them directly in assembler. + +#include "ssx.h" + +/// Invalidate a range of addresses from the D-cache +/// +/// \param p A pointer to the memory area to be invalidated. +/// +/// \param bytes The size (in bytes) of the area to invalidate. +/// +/// The dcache_invalidate() API is used to invalidate an arbitrary range of +/// memory in the cache. Note that invalidation is a destructive operation +/// that may cause the loss of information. This API will invalidate all +/// cache lines from the line containing the address \a p, to the line +/// containing the address \a p + \a size - 1. (If \a size == 0 this call is +/// a NOP.) It is the caller's responsibility to insure that no useful data is +/// inadverdently invalidated. D-cache invalidation is more-or-less a no-op +/// for data either not in the cache or marked as non-cacheable. +/// +/// This API always issues a sync() after the invalidation, even in the event +/// of \a size == 0. +/// +/// \note For invalidating small blocks of data where some alignmment +/// constraints are known it may be more efficient to use +/// dcache_invalidate_line() rather than this API. + +void +dcache_invalidate(void *p, size_t bytes) +{ + size_t lines; + + if (bytes != 0) { + lines = 1; + bytes -= + MIN((CACHE_LINE_SIZE - ((unsigned long)p % CACHE_LINE_SIZE)), + bytes); + lines += bytes / CACHE_LINE_SIZE; + if (!cache_aligned(bytes)) { + lines++; + } + while (lines--) { + dcbi(p); + p += CACHE_LINE_SIZE; + } + } + sync(); +} + + +/// Flush and invalidate a range of addresses from the D-cache +/// +/// \param p A pointer to a memory area to be invalidated. +/// +/// \param bytes The size (in bytes) of the area to invalidate. +/// +/// The dcache_flush() API is used to flush and invalidate an arbitrary range +/// of memory from the D-cache. Note that flushing is not a destructive +/// operation in the sense that no information is lost. This API will flush +/// and invalidate all cache lines from the line containing the address \a p, +/// to the line containing the address \a p + \a size - 1. (If \a size == 0 +/// this call is a NOP.) D-cache flush is more-or-less a no-op for data +/// either not in the cache or marked as non-cacheable. +/// +/// This API always issues a sync() after the flush, even in the event of \a +/// size == 0. +/// +/// \note For flushing small blocks of data where some alignmment constraints +/// are known it may be more efficient to use dcache_flush_line() rather than +/// this API. + + +void +dcache_flush(void *p, size_t bytes) +{ + size_t lines; + + if (bytes != 0) { + lines = 1; + bytes -= + MIN((CACHE_LINE_SIZE - ((unsigned long)p % CACHE_LINE_SIZE)), + bytes); + lines += bytes / CACHE_LINE_SIZE; + if (!cache_aligned(bytes)) { + lines++; + } + while (lines--) { + dcbf(p); + p += CACHE_LINE_SIZE; + } + } + sync(); +} + + + + + + |