summaryrefslogtreecommitdiff
path: root/rts/linker/CacheFlush.c
diff options
context:
space:
mode:
authorBen Gamari <bgamari.foss@gmail.com>2016-11-02 14:58:59 -0400
committerBen Gamari <ben@smart-cactus.org>2016-11-02 15:42:00 -0400
commitf4fb3bc15f49997962e223c4f8c489566d7f5d91 (patch)
tree82dbbaa3320cd4c80c15400754e57411e3a18f8c /rts/linker/CacheFlush.c
parentcc4710af723ca4bbcf77172ff715af22f9ce8419 (diff)
downloadhaskell-f4fb3bc15f49997962e223c4f8c489566d7f5d91.tar.gz
linker: Split out CacheFlush logic
Test Plan: Validate Reviewers: erikd, austin, simonmar Reviewed By: erikd Subscribers: thomie Differential Revision: https://phabricator.haskell.org/D2643
Diffstat (limited to 'rts/linker/CacheFlush.c')
-rw-r--r--rts/linker/CacheFlush.c71
1 files changed, 71 insertions, 0 deletions
diff --git a/rts/linker/CacheFlush.c b/rts/linker/CacheFlush.c
new file mode 100644
index 0000000000..206b2ef7ef
--- /dev/null
+++ b/rts/linker/CacheFlush.c
@@ -0,0 +1,71 @@
+/* Platform-dependent cache flushing logic */
+
+#include "Rts.h"
+#include "linker/CacheFlush.h"
+
+#if defined(arm_HOST_ARCH)
+
+void
+ocFlushInstructionCache( ObjectCode *oc )
+{
+ int i;
+ // Object code
+ for (i=0; i < oc->n_sections; i++) {
+ Section *s = &oc->sections[i];
+ // This is a bit too broad but we don't have any way to determine what
+ // is certainly code
+ if (s->kind == SECTIONKIND_CODE_OR_RODATA)
+ __clear_cache(s->start, (void*) ((uintptr_t) s->start + s->size));
+ }
+
+ // Jump islands
+ // Note the (+1) to ensure that the last symbol extra is covered by the
+ // flush.
+ __clear_cache(oc->symbol_extras, &oc->symbol_extras[oc->n_symbol_extras+1]);
+}
+
+#elif defined(powerpc_HOST_ARCH)
+/*
+ ocFlushInstructionCache
+
+ Flush the data & instruction caches.
+ Because the PPC has split data/instruction caches, we have to
+ do that whenever we modify code at runtime.
+ */
+
+static void
+ocFlushInstructionCacheFrom(void* begin, size_t length)
+{
+ size_t n = (length + 3) / 4;
+ unsigned long* p = begin;
+
+ while (n--)
+ {
+ __asm__ volatile ( "dcbf 0,%0\n\t"
+ "sync\n\t"
+ "icbi 0,%0"
+ :
+ : "r" (p)
+ );
+ p++;
+ }
+ __asm__ volatile ( "sync\n\t"
+ "isync"
+ );
+}
+
+void
+ocFlushInstructionCache( ObjectCode *oc )
+{
+ /* The main object code */
+ ocFlushInstructionCacheFrom(oc->image + oc->misalignment, oc->fileSize);
+
+ /* Jump Islands */
+ ocFlushInstructionCacheFrom(oc->symbol_extras, sizeof(SymbolExtra) * oc->n_symbol_extras);
+}
+
+#else
+
+void ocFlushInstructionCache( ObjectCode *oc STG_UNUSED ) {}
+
+#endif /* powerpc_HOST_ARCH */