The first problem I was able to diagnose using egdb on riscv was
lang/python/2.7 using libffi and aborting in libcompiler-rt (the
compilerrt_abort() call below).

--8<--
#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
  sys_icache_invalidate(start, end - start);
#else
  compilerrt_abort();
#endif
#endif
}
-->8--

The ususal way we provide this functionality is through sysarch(2).
Since the RISC-V ISA only provides fence.i as an extension, and that
fence.i doesn't support parameters to only act on a specific range,
I figured I would reflect that in the API for the sake of clarity.

If people expect the spec to evolve and new CPUs to ship with
support for finer-grained invalidation, a more forward-looking approach
would be to mimic ARM_SYNC_ICACHE and struct arm_sync_icache_args, and
let the kernel ignore the parameters if appropriate.

In the diff below I'm moving the core of the code to cpu.c since it
doesn't look pmap-specific, but I don't feel strongly about it.
I haven't even built this since I'm still on the way back from k2k21 but
I figured I'd ask for feedback early.  Input welcome.


Index: include/cpufunc.h
===================================================================
RCS file: /d/cvs/src/sys/arch/riscv64/include/cpufunc.h,v
retrieving revision 1.4
diff -u -p -r1.4 cpufunc.h
--- include/cpufunc.h   18 May 2021 09:14:49 -0000      1.4
+++ include/cpufunc.h   4 Sep 2021 08:58:38 -0000
@@ -92,6 +92,7 @@ extern int64_t icache_line_size;
 extern void (*cpu_dcache_wbinv_range)(paddr_t, psize_t);
 extern void (*cpu_dcache_inv_range)(paddr_t, psize_t);
 extern void (*cpu_dcache_wb_range)(paddr_t, psize_t);
+extern void icache_flush(void);
 
 static __inline void
 load_satp(uint64_t val)
Index: include/sysarch.h
===================================================================
RCS file: include/sysarch.h
diff -N include/sysarch.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ include/sysarch.h   4 Sep 2021 09:12:53 -0000
@@ -0,0 +1,38 @@
+/*     $OpenBSD$       */
+
+/*
+ * Copyright (c) 2021 Jeremie Courreges-Anglas <[email protected]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef        _RISCV64_SYSARCH_H_
+#define        _RISCV64_SYSARCH_H_
+
+/*
+ * Architecture specific syscalls (riscv64)
+ */
+
+#define        RISCV_SYNC_ICACHE_ALL   0
+
+#ifndef _KERNEL
+
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+int    sysarch(int, void *);
+__END_DECLS
+
+#endif /* _KERNEL */
+
+#endif /* _RISCV64_SYSARCH_H_ */
Index: riscv64/cpu.c
===================================================================
RCS file: /d/cvs/src/sys/arch/riscv64/riscv64/cpu.c,v
retrieving revision 1.11
diff -u -p -r1.11 cpu.c
--- riscv64/cpu.c       24 Jul 2021 18:15:13 -0000      1.11
+++ riscv64/cpu.c       4 Sep 2021 09:02:09 -0000
@@ -26,6 +26,7 @@
 
 #include <uvm/uvm.h>
 
+#include <machine/cpufunc.h>
 #include <machine/fdt.h>
 #include <machine/sbi.h>
 
@@ -300,6 +301,38 @@ cpu_cache_nop_range(paddr_t pa, psize_t 
 void (*cpu_dcache_wbinv_range)(paddr_t, psize_t) = cpu_cache_nop_range;
 void (*cpu_dcache_inv_range)(paddr_t, psize_t) = cpu_cache_nop_range;
 void (*cpu_dcache_wb_range)(paddr_t, psize_t) = cpu_cache_nop_range;
+
+void
+icache_flush(void)
+{
+#ifdef MULTIPROCESSOR
+       CPU_INFO_ITERATOR cii;
+       struct cpu_info *ci;
+       unsigned long hart_mask = 0;
+#endif
+
+       fence_i();
+
+#ifdef MULTIPROCESSOR
+       CPU_INFO_FOREACH(cii, ci) {
+               if (ci == curcpu())
+                       continue;
+               hart_mask |= (1UL << ci->ci_hartid);
+       }
+
+       /*
+        * From the RISC-V ISA:
+        *
+        * To make a store to instruction memory visible to all RISC-V
+        * harts, the writing hart has to execute a data FENCE before
+        * requesting that all remote RISC-V harts execute a FENCE.I.
+        */
+       if (hart_mask != 0) {
+               membar_sync();
+               sbi_remote_fence_i(&hart_mask);
+       }
+#endif
+}
 
 #ifdef MULTIPROCESSOR
 
Index: riscv64/machdep.c
===================================================================
RCS file: /d/cvs/src/sys/arch/riscv64/riscv64/machdep.c,v
retrieving revision 1.25
diff -u -p -r1.25 machdep.c
--- riscv64/machdep.c   2 Jul 2021 14:50:18 -0000       1.25
+++ riscv64/machdep.c   4 Sep 2021 09:12:45 -0000
@@ -44,6 +44,7 @@
 #include <machine/bus.h>
 #include <machine/riscv64var.h>
 #include <machine/sbi.h>
+#include <machine/sysarch.h>
 
 #include <machine/db_machdep.h>
 #include <ddb/db_extern.h>
@@ -517,6 +518,9 @@ sys_sysarch(struct proc *p, void *v, reg
        int error = 0;
 
        switch (SCARG(uap, op)) {
+       case RISCV_SYNC_ICACHE_ALL:
+               icache_flush();
+               break;
        default:
                error = EINVAL;
                break;
Index: riscv64/pmap.c
===================================================================
RCS file: /d/cvs/src/sys/arch/riscv64/riscv64/pmap.c,v
retrieving revision 1.19
diff -u -p -r1.19 pmap.c
--- riscv64/pmap.c      2 Aug 2021 19:07:29 -0000       1.19
+++ riscv64/pmap.c      4 Sep 2021 09:03:17 -0000
@@ -98,38 +98,6 @@ tlb_flush_page(pmap_t pm, vaddr_t va)
                do_tlb_flush_page(pm, va);
 }
 
-static inline void
-icache_flush(void)
-{
-#ifdef MULTIPROCESSOR
-       CPU_INFO_ITERATOR cii;
-       struct cpu_info *ci;
-       unsigned long hart_mask = 0;
-#endif
-
-       fence_i();
-
-#ifdef MULTIPROCESSOR
-       CPU_INFO_FOREACH(cii, ci) {
-               if (ci == curcpu())
-                       continue;
-               hart_mask |= (1UL << ci->ci_hartid);
-       }
-
-       /*
-        * From the RISC-V ISA:
-        *
-        * To make a store to instruction memory visible to all RISC-V
-        * harts, the writing hart has to execute a data FENCE before
-        * requesting that all remote RISC-V harts execute a FENCE.I.
-        */
-       if (hart_mask != 0) {
-               membar_sync();
-               sbi_remote_fence_i(&hart_mask);
-       }
-#endif
-}
-
 struct pmap kernel_pmap_;
 
 LIST_HEAD(pted_pv_head, pte_desc);


-- 
jca | PGP : 0x1524E7EE / 5135 92C1 AD36 5293 2BDF  DDCC 0DFA 74AE 1524 E7EE

Reply via email to