summaryrefslogtreecommitdiff
path: root/sys/uvm
diff options
context:
space:
mode:
authorPhilip Guenther <guenther@cvs.openbsd.org>2022-02-01 08:38:54 +0000
committerPhilip Guenther <guenther@cvs.openbsd.org>2022-02-01 08:38:54 +0000
commita2b7b6f4df77e9888bdec5f388a1612903cd1f7f (patch)
tree0662e300f3dd89939cf041fc50f9af2374a262ba /sys/uvm
parent74388c3abd3de66838438f9e0bc1271ec30c0734 (diff)
Attempt to guarantee that on copy-on-write faulting, the new copy
can't be written to while any thread can see the original version of the page via a not-yet-flushed stale TLB entry: pmaps can indicate they do this correctly by defining __HAVE_PMAP_MPSAFE_ENTER_COW; uvm will force the initial CoW fault to be read-only otherwise. Set that on amd64 and fix the problem case in pmap_enter() by putting a read-only mapping in place, shooting the TLB entry, then fixing it to the final read-write entry so this thread can continue without re-faulting. reported by jsing@ from https://github.com/golang/go/issues/34988 assisted by discussion in https://reviews.freebsd.org/D14347 tweaks from jsing@ and kettenis@ ok jsing@ mpi@ kettenis@
Diffstat (limited to 'sys/uvm')
-rw-r--r--sys/uvm/uvm_fault.c14
1 files changed, 13 insertions, 1 deletions
diff --git a/sys/uvm/uvm_fault.c b/sys/uvm/uvm_fault.c
index d54a2b85d75..312ba2b33d6 100644
--- a/sys/uvm/uvm_fault.c
+++ b/sys/uvm/uvm_fault.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uvm_fault.c,v 1.124 2021/12/28 13:16:28 mpi Exp $ */
+/* $OpenBSD: uvm_fault.c,v 1.125 2022/02/01 08:38:53 guenther Exp $ */
/* $NetBSD: uvm_fault.c,v 1.51 2000/08/06 00:22:53 thorpej Exp $ */
/*
@@ -1014,6 +1014,18 @@ uvm_fault_upper(struct uvm_faultinfo *ufi, struct uvm_faultctx *flt,
/* deref: can not drop to zero here by defn! */
oanon->an_ref--;
+#ifndef __HAVE_PMAP_MPSAFE_ENTER_COW
+ /*
+ * If there are multiple threads, either uvm or the
+ * pmap has to make sure no threads see the old RO
+ * mapping once any have seen the new RW mapping.
+ * uvm does it by inserting the new mapping RO and
+ * letting it fault again.
+ */
+ if (P_HASSIBLING(curproc))
+ flt->enter_prot &= ~PROT_WRITE;
+#endif
+
/*
* note: anon is _not_ locked, but we have the sole references
* to in from amap.