On Sat, Sep 04 2021, Jeremie Courreges-Anglas <j...@wxcvbn.org> wrote:
> 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.

Updated diff that builds (one #include was missing) and that appears to
do the right thing.  The diff also includes the compiler-rt change.


Index: gnu/llvm/compiler-rt/lib/builtins/clear_cache.c
===================================================================
RCS file: /cvs/src/gnu/llvm/compiler-rt/lib/builtins/clear_cache.c,v
retrieving revision 1.3
diff -u -p -r1.3 clear_cache.c
--- gnu/llvm/compiler-rt/lib/builtins/clear_cache.c     2 Jan 2021 17:14:13 
-0000       1.3
+++ gnu/llvm/compiler-rt/lib/builtins/clear_cache.c     19 Aug 2021 17:28:40 
-0000
@@ -33,7 +33,7 @@ uintptr_t GetCurrentProcess(void);
 #include <machine/sysarch.h>
 #endif
 
-#if defined(__OpenBSD__) && (defined(__arm__) || defined(__mips__))
+#if defined(__OpenBSD__) && (defined(__arm__) || defined(__mips__) || 
defined(__riscv))
 // clang-format off
 #include <sys/types.h>
 #include <machine/sysarch.h>
@@ -157,6 +157,8 @@ void __clear_cache(void *start, void *en
                    : "=r"(start_reg)
                    : "r"(start_reg), "r"(end_reg), "r"(flags), 
"r"(syscall_nr));
   assert(start_reg == 0 && "Cache flush syscall failed.");
+#elif defined(__riscv) && defined(__OpenBSD__)
+       sysarch(RISCV_SYNC_ICACHE_ALL, NULL);
 #else
 #if __APPLE__
   // On Darwin, sys_icache_invalidate() provides this functionality
Index: sys/arch/riscv64/include/cpufunc.h
===================================================================
RCS file: /cvs/src/sys/arch/riscv64/include/cpufunc.h,v
retrieving revision 1.4
diff -u -p -r1.4 cpufunc.h
--- sys/arch/riscv64/include/cpufunc.h  18 May 2021 09:14:49 -0000      1.4
+++ sys/arch/riscv64/include/cpufunc.h  18 Aug 2021 23:24:59 -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: sys/arch/riscv64/include/sysarch.h
===================================================================
RCS file: sys/arch/riscv64/include/sysarch.h
diff -N sys/arch/riscv64/include/sysarch.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ sys/arch/riscv64/include/sysarch.h  18 Aug 2021 23:24:59 -0000
@@ -0,0 +1,38 @@
+/*     $OpenBSD$       */
+
+/*
+ * Copyright (c) 2021 Jeremie Courreges-Anglas <j...@openbsd.org>
+ *
+ * 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: sys/arch/riscv64/riscv64/cpu.c
===================================================================
RCS file: /cvs/src/sys/arch/riscv64/riscv64/cpu.c,v
retrieving revision 1.11
diff -u -p -r1.11 cpu.c
--- sys/arch/riscv64/riscv64/cpu.c      24 Jul 2021 18:15:13 -0000      1.11
+++ sys/arch/riscv64/riscv64/cpu.c      18 Aug 2021 23:24:59 -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: sys/arch/riscv64/riscv64/machdep.c
===================================================================
RCS file: /cvs/src/sys/arch/riscv64/riscv64/machdep.c,v
retrieving revision 1.25
diff -u -p -r1.25 machdep.c
--- sys/arch/riscv64/riscv64/machdep.c  2 Jul 2021 14:50:18 -0000       1.25
+++ sys/arch/riscv64/riscv64/machdep.c  19 Aug 2021 23:29:41 -0000
@@ -42,8 +42,10 @@
 #include <machine/param.h>
 #include <machine/bootconfig.h>
 #include <machine/bus.h>
+#include <machine/cpufunc.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 +519,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: sys/arch/riscv64/riscv64/pmap.c
===================================================================
RCS file: /cvs/src/sys/arch/riscv64/riscv64/pmap.c,v
retrieving revision 1.19
diff -u -p -r1.19 pmap.c
--- sys/arch/riscv64/riscv64/pmap.c     2 Aug 2021 19:07:29 -0000       1.19
+++ sys/arch/riscv64/riscv64/pmap.c     19 Aug 2021 17:35:45 -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