diff options
author | Jeremie Courreges-Anglas <jca@cvs.openbsd.org> | 2022-11-03 23:30:56 +0000 |
---|---|---|
committer | Jeremie Courreges-Anglas <jca@cvs.openbsd.org> | 2022-11-03 23:30:56 +0000 |
commit | e03883c9aace02589f4bb812d30898f54e217399 (patch) | |
tree | 6a7db08b2054152ae2fb8e5592e3e99eeadc9a92 | |
parent | a7e1cfcc3208b27eb370d6deb1f6acb44300e7de (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.c | 36 |
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(); |