Here's the diff I've been using for the last bulk build on riscv64.  It
resulted in a single kernel crash:

  cpu1: pool_do_get: pted free list modified: page 0xffffffc22cc0a000; item addr
  0xffffffc22cc0a6d0; offset 0x0=0xa06137b98e6f6767 != 0xa06137b98ed06767

and 5 userland clang crashes.  Yes, that is an improvement over the
18, 27 and 22 clang crashes in the three previous bulk builds.
But it doesn't fix the problem(s) we're still chasing.

The rationale is basically the text from the spec, I added rather
verbose comments quoting said spec, much like what exists in
icache_flush().  But we can make it shorter if wanted.  Maybe just
"SFENCE.VMA orders only the local hart's implicit references to the
memory-management data structures."?

ok?

Bonus: sifive_cip_1200_errata is a remnant, cpu_errata_sifive_cip_1200
is the actual variable used on affected CPUs.  To be committed
separately.


Index: pmap.c
===================================================================
RCS file: /cvs/src/sys/arch/riscv64/riscv64/pmap.c,v
retrieving revision 1.24
diff -u -p -r1.24 pmap.c
--- pmap.c      17 Oct 2022 19:51:54 -0000      1.24
+++ pmap.c      31 Oct 2022 21:15:07 -0000
@@ -42,8 +42,6 @@ pmap_is_active(struct pmap *pm, struct c
 
 #endif
 
-int sifive_cip_1200_errata;
-
 void
 do_tlb_flush_page(pmap_t pm, vaddr_t va)
 {
@@ -59,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);
@@ -81,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();


-- 
jca | PGP : 0x1524E7EE / 5135 92C1 AD36 5293 2BDF  DDCC 0DFA 74AE 1524 E7EE

Reply via email to