diff options
Diffstat (limited to 'src/ssx/pgp/pgp_cache.S')
-rwxr-xr-x | src/ssx/pgp/pgp_cache.S | 99 |
1 files changed, 99 insertions, 0 deletions
diff --git a/src/ssx/pgp/pgp_cache.S b/src/ssx/pgp/pgp_cache.S new file mode 100755 index 0000000..4208f59 --- /dev/null +++ b/src/ssx/pgp/pgp_cache.S @@ -0,0 +1,99 @@ +// $Id: pgp_cache.S,v 1.1.1.1 2013/12/11 21:03:22 bcbrock Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/pgp_cache.S,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file pgp_cache.S +/// \brief Cache-management specific to PGP + +#include "ssx.h" + +/// \fn void dcache_flush_all() +/// \brief Flush the entire D-Cache by 0-filling and invalidating +/// +/// This API is necessary whenever it is required to change data cacheability +/// after boot. This API operates in an SSX_SUPERCRITICAL critical section. +/// This API always issues a sync() after the flush. +/// +/// This API runs with data translation disabled. This is necessary for +/// correctness, and also obviates the need to check whether a cache entry is +/// valid before flushing the entry. +/// +/// This algorithm works by filling the cache with 0s to displace any dirty +/// lines. Then the cache is invalidated. In PgP the first 16 KB of the +/// 0x80000000 address range are used as the zero-fill range. This memory is +/// not mapped on the OCI so these lines must never escape the D-cache. +/// +/// Note: Our Simics model includes this 16K memory area since Simics does not +/// default to having a cache. Since we run PgP with the MMU enabled and we +/// don't MMU-map this area, memory addressing bugs should not be able to slip +/// through. +#ifdef DOXYGEN_ONLY +void dcache_flush_all(); +#endif +/// \cond + + .global_function dcache_flush_all +dcache_flush_all: + + ## %r3 used as scratch throughout + + ## %r11 holds the original DCCR throughout + ## %r12 holds the original MSR throughout + + ## Enter a super-critical section and go to real mode + + _ssx_critical_section_enter SSX_SUPERCRITICAL, %r12, %r3 + + mfmsr %r3 + _clrbit %r3, %r3, MSR_DR_BIT + mtmsr %r3 + isync + + ## Save the DCCR, and make 0x80000000 cacheable. This is necessary for + ## DCBZ to work. + + mfdccr %r11 + _liwa %r3, PGP_FLUSH_ZERO_DCCR + or %r3, %r3, %r11 + mtdccr %r3 + isync + + ## Fill the cache with 0, displacing any dirty lines + + li %r3, DCACHE_LINES + mtctr %r3 + _liwa %r3, PGP_FLUSH_ZERO_ADDRESS +1: + dcbz %r0, %r3 + addi %r3, %r3, CACHE_LINE_SIZE + bdnz 1b + + sync + + ## Now invalidate the cache + + li %r3, DCACHE_LINES + mtctr %r3 + _liwa %r3, PGP_FLUSH_ZERO_ADDRESS +1: + dcbi %r0, %r3 + addi %r3, %r3, CACHE_LINE_SIZE + bdnz 1b + + ## Restore the DCCR and MSR and return + + mtdccr %r11 + isync + + _ssx_critical_section_exit %r12 + + blr + + .epilogue dcache_flush_all + +/// \endcond + |