From 98936e098e2e41a52e16e11385d42c67be2f2f88 Mon Sep 17 00:00:00 2001 From: jca Date: Thu, 3 Nov 2022 23:30:55 +0000 Subject: [PATCH] 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@ --- sys/arch/riscv64/riscv64/pmap.c | 36 ++++++++++++++++++++++++++++++--- 1 file 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 @@ -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(); -- 2.20.1