[compiler-rt][builtins][RISCV] Port __clear_cache to RISC-V Linux
authorLuís Marques <luismarques@lowrisc.org>
Thu, 5 Mar 2020 16:43:03 +0000 (16:43 +0000)
committerLuís Marques <luismarques@lowrisc.org>
Thu, 5 Mar 2020 16:44:47 +0000 (16:44 +0000)
Implements `__clear_cache` for RISC-V Linux. We can't just use `fence.i` on
Linux, because the Linux thread might be scheduled on another hart, and the
`fence.i` instruction only flushes the icache of the current hart.

compiler-rt/lib/builtins/clear_cache.c

index e83e212..72e02e6 100644 (file)
@@ -147,6 +147,16 @@ void __clear_cache(void *start, void *end) {
 
   for (uintptr_t dword = start_dword; dword < end_dword; dword += dword_size)
     __asm__ volatile("flush %0" : : "r"(dword));
+#elif defined(__riscv) && defined(__linux__)
+#define __NR_riscv_flush_icache (244 + 15)
+  register void *start_reg __asm("a0") = start;
+  const register void *end_reg __asm("a1") = end;
+  const register long flags __asm("a2") = 0;
+  const register long syscall_nr __asm("a7") = __NR_riscv_flush_icache;
+  __asm __volatile("ecall"
+                   : "=r"(start_reg)
+                   : "r"(start_reg), "r"(end_reg), "r"(flags), "r"(syscall_nr));
+  assert(start_reg == 0 && "Cache flush syscall failed.");
 #else
 #if __APPLE__
   // On Darwin, sys_icache_invalidate() provides this functionality