[Git][ghc/ghc][wip/supersven/riscv64-ncg] More instruction cache flushing

Sven Tennie (@supersven) gitlab at gitlab.haskell.org
Thu Mar 21 20:15:49 UTC 2024



Sven Tennie pushed to branch wip/supersven/riscv64-ncg at Glasgow Haskell Compiler / GHC


Commits:
f3921041 by Sven Tennie at 2024-03-21T21:14:36+01:00
More instruction cache flushing

Flush in the Linker, which creates code in the PLT. And, cleanup the
link code by using built-ins instead of inline assembly.

- - - - -


8 changed files:

- rts/adjustor/LibffiAdjustor.c
- rts/linker/Elf.c
- rts/linker/elf_reloc.c
- rts/linker/elf_reloc.h
- rts/linker/elf_reloc_aarch64.c
- rts/linker/elf_reloc_aarch64.h
- rts/linker/elf_reloc_riscv64.c
- rts/linker/elf_reloc_riscv64.h


Changes:

=====================================
rts/adjustor/LibffiAdjustor.c
=====================================
@@ -12,6 +12,7 @@
 #include "Adjustor.h"
 
 #include "rts/ghc_ffi.h"
+#include <stdint.h>
 #include <string.h>
 
 // Note that ffi_alloc_prep_closure is a non-standard libffi closure
@@ -189,14 +190,18 @@ createAdjustor (int cconv,
 
 #if defined(riscv64_HOST_ARCH)
     // Synchronize the memory and instruction cache to prevent illegal
-    // instruction exceptions. fence.i works per hart. I'm not sure what happens
-    // when the generated code is called on another hart. Probably, the fence on
-    // read/write is good enough for that. However, if there are illegal
-    // instruction exceptions, this is the place to look at (maybe, that the
-    // fence.i needs to be moved closely before the call.)
-    asm volatile ("fence rw, rw"  : : : "memory");
-    asm volatile ("fence.i" ::: "memory");
+    // instruction exceptions.
+
+    // We expect two instructions for address loading, one for the jump.
+    int instrCount = 3;
+    // On Linux the parameters of __builtin___clear_cache are currently unused.
+    // Add them anyways for future compatibility. (I.e. the parameters couldn't
+    // be checked during development.)
+    __builtin___clear_cache((void *)code,
+                            (void *)code + instrCount * sizeof(uint64_t));
+    // Memory barrier to ensure nothing circumvents the fence.i / cache flush.
+    SEQ_CST_FENCE();
 #endif
 
-    return (void*)code;
+    return (void *)code;
 }


=====================================
rts/linker/Elf.c
=====================================
@@ -2015,6 +2015,8 @@ ocResolve_ELF ( ObjectCode* oc )
 
 #if defined(powerpc_HOST_ARCH)
     ocFlushInstructionCache( oc );
+#elseif defined(riscv64_HOST_ARCH)
+    flushInstructionCache();
 #endif
 
     return ocMprotect_Elf(oc);


=====================================
rts/linker/elf_reloc.c
=====================================
@@ -11,6 +11,11 @@ bool
 relocateObjectCode(ObjectCode * oc) {
     return ADD_SUFFIX(relocateObjectCode)(oc);
 }
+
+
+void flushInstructionCache(){
+   return ADD_SUFFIX(flushInstructionCache)();
+}
 #endif
 
 #endif


=====================================
rts/linker/elf_reloc.h
=====================================
@@ -10,5 +10,5 @@
 bool
 relocateObjectCode(ObjectCode * oc);
 
-
+void flushInstructionCache();
 #endif /* OBJETFORMAT_ELF */


=====================================
rts/linker/elf_reloc_aarch64.c
=====================================
@@ -339,5 +339,10 @@ relocateObjectCodeAarch64(ObjectCode * oc) {
     return EXIT_SUCCESS;
 }
 
+void flushInstructionCacheAarch64() {
+  // Looks like we don't need this on Aarch64.
+  /* no-op */
+}
+
 #endif /* OBJECTFORMAT_ELF */
 #endif /* aarch64_HOST_ARCH */


=====================================
rts/linker/elf_reloc_aarch64.h
=====================================
@@ -7,4 +7,5 @@
 bool
 relocateObjectCodeAarch64(ObjectCode * oc);
 
+void flushInstructionCacheAarch64();
 #endif /* OBJETFORMAT_ELF */


=====================================
rts/linker/elf_reloc_riscv64.c
=====================================
@@ -588,5 +588,25 @@ bool relocateObjectCodeRISCV64(ObjectCode *oc) {
   return EXIT_SUCCESS;
 }
 
+void flushInstructionCacheRISCV64(ObjectCode *oc) {
+  // Synchronize the memory and instruction cache to prevent illegal
+  // instruction exceptions. On Linux the parameters of
+  // __builtin___clear_cache are currently unused. Add them anyways for future
+  // compatibility. (I.e. the parameters couldn't be checked during
+  // development.)
+
+  /* The main object code */
+  void *codeBegin = oc->image + oc->misalignment;
+  __builtin___clear_cache(codeBegin, codeBegin + oc->fileSize);
+
+  /* Jump Islands */
+  __builtin___clear_cache((void *)oc->symbol_extras,
+                          (void *)oc->symbol_extras +
+                              sizeof(SymbolExtra) * oc->n_symbol_extras);
+
+  // Memory barrier to ensure nothing circumvents the fence.i / cache flushes.
+  SEQ_CST_FENCE();
+}
+
 #endif /* OBJECTFORMAT_ELF */
 #endif /* riscv64_HOST_ARCH */


=====================================
rts/linker/elf_reloc_riscv64.h
=====================================
@@ -7,4 +7,5 @@
 bool
 relocateObjectCodeRISCV64(ObjectCode * oc);
 
+void flushInstructionCacheRISCV64();
 #endif /* OBJETFORMAT_ELF */



View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/f39210417bc758abf4b013c5becaa66545184cbc

-- 
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/f39210417bc758abf4b013c5becaa66545184cbc
You're receiving this email because of your account on gitlab.haskell.org.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/ghc-commits/attachments/20240321/d67de9b2/attachment-0001.html>


More information about the ghc-commits mailing list