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