On Sat, Sep 04 2021, Jeremie Courreges-Anglas <[email protected]> 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 <[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: 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