summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeremie Courreges-Anglas <jca@cvs.openbsd.org>2022-11-03 23:30:56 +0000
committerJeremie Courreges-Anglas <jca@cvs.openbsd.org>2022-11-03 23:30:56 +0000
commite03883c9aace02589f4bb812d30898f54e217399 (patch)
tree6a7db08b2054152ae2fb8e5592e3e99eeadc9a92
parenta7e1cfcc3208b27eb370d6deb1f6acb44300e7de (diff)
riscv64 pmap: flush memory writes before remote sfence.vma
As pointed out by the RISC-V privileged spec. Sadly this is not enough to solve all existing userland or kernel crashes seen on Unmatched (and possibly other?) machines. ok kettenis@
-rw-r--r--sys/arch/riscv64/riscv64/pmap.c36
1 files changed, 33 insertions, 3 deletions
diff --git a/sys/arch/riscv64/riscv64/pmap.c b/sys/arch/riscv64/riscv64/pmap.c
index 7b77db814cb..51ede2aa75a 100644
--- a/sys/arch/riscv64/riscv64/pmap.c
+++ b/sys/arch/riscv64/riscv64/pmap.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pmap.c,v 1.25 2022/11/03 23:26:49 jca Exp $ */
+/* $OpenBSD: pmap.c,v 1.26 2022/11/03 23:30:55 jca Exp $ */
/*
* Copyright (c) 2019-2020 Brian Bamsch <bbamsch@google.com>
@@ -57,8 +57,23 @@ do_tlb_flush_page(pmap_t pm, vaddr_t va)
hart_mask |= (1UL << ci->ci_hartid);
}
- if (hart_mask != 0)
+ /*
+ * From the RISC-V privileged spec:
+ *
+ * SFENCE.VMA orders only the local hart's implicit references
+ * to the memory-management data structures. Consequently, other
+ * harts must be notified separately when the memory-management
+ * data structures have been modified. One approach is to use 1)
+ * a local data fence to ensure local writes are visible
+ * globally, then 2) an interprocessor interrupt to the other
+ * thread, then 3) a local SFENCE.VMA in the interrupt handler
+ * of the remote thread, and finally 4) signal back to
+ * originating thread that operation is complete.
+ */
+ if (hart_mask != 0) {
+ membar_sync();
sbi_remote_sfence_vma(&hart_mask, va, PAGE_SIZE);
+ }
#endif
sfence_vma_page(va);
@@ -79,8 +94,23 @@ do_tlb_flush(pmap_t pm)
hart_mask |= (1UL << ci->ci_hartid);
}
- if (hart_mask != 0)
+ /*
+ * From the RISC-V privileged spec:
+ *
+ * SFENCE.VMA orders only the local hart's implicit references
+ * to the memory-management data structures. Consequently, other
+ * harts must be notified separately when the memory-management
+ * data structures have been modified. One approach is to use 1)
+ * a local data fence to ensure local writes are visible
+ * globally, then 2) an interprocessor interrupt to the other
+ * thread, then 3) a local SFENCE.VMA in the interrupt handler
+ * of the remote thread, and finally 4) signal back to
+ * originating thread that operation is complete.
+ */
+ if (hart_mask != 0) {
+ membar_sync();
sbi_remote_sfence_vma(&hart_mask, 0, -1);
+ }
#endif
sfence_vma();