summaryrefslogtreecommitdiffstats
path: root/src/ssx/pgp/pgp_cache.S
diff options
context:
space:
mode:
Diffstat (limited to 'src/ssx/pgp/pgp_cache.S')
-rwxr-xr-xsrc/ssx/pgp/pgp_cache.S99
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
+
OpenPOWER on IntegriCloud