freebsd-skq/sys/vm
Konstantin Belousov d929ad7f91 Ensure memory consistency on COW.
From the submitter description:
The process is forked transitioning a map entry to COW
Thread A writes to a page on the map entry, faults, updates the pmap to
  writable at a new phys addr, and starts TLB invalidations...
Thread B acquires a lock, writes to a location on the new phys addr, and
  releases the lock
Thread C acquires the lock, reads from the location on the old phys addr...
Thread A ...continues the TLB invalidations which are completed
Thread C ...reads from the location on the new phys addr, and releases
  the lock

In this example Thread B and C [lock, use and unlock] properly and
neither own the lock at the same time.  Thread A was writing somewhere
else on the page and so never had/needed the lock. Thread C sees a
location that is only ever read|modified under a lock change beneath
it while it is the lock owner.

To fix this, perform the two-stage update of the copied PTE.  First,
the PTE is updated with the address of the new physical page with
copied content, but in read-only mode.  The pmap locking and the page
busy state during PTE update and TLB invalidation IPIs ensure that any
writer to the page cannot upgrade the PTE to the writable state until
all CPUs updated their TLB to not cache old mapping.  Then, after the
busy state of the page is lifted, the faults for write can proceed and
do not violate the consistency of the reads.

The change is done in vm_fault because most architectures do need IPIs
to invalidate remote TLBs.  More, I think that hardware guarantees of
atomicity of the remote TLB invalidation are not enough to prevent the
inconsistent reads of non-atomic reads, like multi-word accesses
protected by a lock.  So instead of modifying each pmap invalidation
code, I did it there.

Discovered and analyzed by: Elliott.Rabe@dell.com
Reviewed by:	markj
PR:	225584 (appeared to have the same cause)
Tested by:	Elliott.Rabe@dell.com, emaste, Mike Tancsa <mike@sentex.net>, truckman
Sponsored by:	The FreeBSD Foundation
MFC after:	1 week
Differential revision:	https://reviews.freebsd.org/D14347
2018-02-14 00:31:45 +00:00
..
_vm_radix.h sys: general adoption of SPDX licensing ID tags. 2017-11-27 15:23:17 +00:00
default_pager.c SPDX: wrong license. 2017-11-30 15:45:42 +00:00
device_pager.c sys: further adoption of SPDX licensing ID tags. 2017-11-20 19:43:44 +00:00
memguard.c Eliminate kmem_arena and kmem_object in preparation for further NUMA commits. 2017-11-28 23:40:54 +00:00
memguard.h sys: general adoption of SPDX licensing ID tags. 2017-11-27 15:23:17 +00:00
phys_pager.c sys: general adoption of SPDX licensing ID tags. 2017-11-27 15:23:17 +00:00
pmap.h sys: further adoption of SPDX licensing ID tags. 2017-11-20 19:43:44 +00:00
redzone.c sys: general adoption of SPDX licensing ID tags. 2017-11-27 15:23:17 +00:00
redzone.h sys: general adoption of SPDX licensing ID tags. 2017-11-27 15:23:17 +00:00
sg_pager.c sys: general adoption of SPDX licensing ID tags. 2017-11-27 15:23:17 +00:00
swap_pager.c Make v_wire_count a per-cpu counter(9) counter. This eliminates a 2018-02-12 22:53:00 +00:00
swap_pager.h sys: further adoption of SPDX licensing ID tags. 2017-11-20 19:43:44 +00:00
uma_core.c Fix boot_pages exhaustion on machines with many domains and cores, where 2018-02-09 04:45:39 +00:00
uma_dbg.c sys: general adoption of SPDX licensing ID tags. 2017-11-27 15:23:17 +00:00
uma_dbg.h sys: general adoption of SPDX licensing ID tags. 2017-11-27 15:23:17 +00:00
uma_int.h Fix three miscalculations in amount of boot pages: 2018-02-07 18:32:51 +00:00
uma.h Followup on r302393 by cperciva, improving calculation of boot pages required 2018-02-06 04:16:00 +00:00
vm_domainset.c Move VM_NUMA_ALLOC and DEVICE_NUMA under the single global config option NUMA. 2018-01-14 03:36:03 +00:00
vm_domainset.h Add files for r327895 2018-01-12 22:57:57 +00:00
vm_extern.h Use per-domain locks for vm page queue free. Move paging control from 2018-02-06 22:10:07 +00:00
vm_fault.c Ensure memory consistency on COW. 2018-02-14 00:31:45 +00:00
vm_glue.c Make v_wire_count a per-cpu counter(9) counter. This eliminates a 2018-02-12 22:53:00 +00:00
vm_init.c Fix boot_pages exhaustion on machines with many domains and cores, where 2018-02-09 04:45:39 +00:00
vm_kern.c Use per-domain locks for vm page queue free. Move paging control from 2018-02-06 22:10:07 +00:00
vm_kern.h SPDX: Consider code from Carnegie-Mellon University. 2017-11-30 15:48:35 +00:00
vm_map.c Use per-domain locks for vm page queue free. Move paging control from 2018-02-06 22:10:07 +00:00
vm_map.h Assign map->header values to avoid boundary checks. 2018-01-20 12:19:02 +00:00
vm_meter.c Make v_wire_count a per-cpu counter(9) counter. This eliminates a 2018-02-12 22:53:00 +00:00
vm_mmap.c Make v_wire_count a per-cpu counter(9) counter. This eliminates a 2018-02-12 22:53:00 +00:00
vm_object.c Dequeue wired pages lazily. 2018-02-07 16:57:10 +00:00
vm_object.h Use per-domain locks for vm page queue free. Move paging control from 2018-02-06 22:10:07 +00:00
vm_page.c Make v_wire_count a per-cpu counter(9) counter. This eliminates a 2018-02-12 22:53:00 +00:00
vm_page.h Dequeue wired pages lazily. 2018-02-07 16:57:10 +00:00
vm_pageout.c Dequeue wired pages lazily. 2018-02-07 16:57:10 +00:00
vm_pageout.h Use per-domain locks for vm page queue free. Move paging control from 2018-02-06 22:10:07 +00:00
vm_pagequeue.h Use per-domain locks for vm page queue free. Move paging control from 2018-02-06 22:10:07 +00:00
vm_pager.c SPDX: Consider code from Carnegie-Mellon University. 2017-11-30 15:48:35 +00:00
vm_pager.h sys: further adoption of SPDX licensing ID tags. 2017-11-20 19:43:44 +00:00
vm_param.h SPDX: Consider code from Carnegie-Mellon University. 2017-11-30 15:48:35 +00:00
vm_phys.c Use per-domain locks for vm page queue free. Move paging control from 2018-02-06 22:10:07 +00:00
vm_phys.h Use per-domain locks for vm page queue free. Move paging control from 2018-02-06 22:10:07 +00:00
vm_radix.c Fix boot_pages calculation for machines that don't have UMA_MD_SMALL_ALLOC. 2018-02-06 22:06:59 +00:00
vm_radix.h sys: general adoption of SPDX licensing ID tags. 2017-11-27 15:23:17 +00:00
vm_reserv.c Do not leak rv->psind in some specific situations. 2018-02-13 15:36:28 +00:00
vm_reserv.h Use per-domain locks for vm page queue free. Move paging control from 2018-02-06 22:10:07 +00:00
vm_swapout_dummy.c SPDX: Consider code from Carnegie-Mellon University. 2017-11-30 15:48:35 +00:00
vm_swapout.c Dequeue wired pages lazily. 2018-02-07 16:57:10 +00:00
vm_unix.c ANSIfy function definitions in sys/vm/ 2018-01-12 03:50:44 +00:00
vm.h SPDX: Consider code from Carnegie-Mellon University. 2017-11-30 15:48:35 +00:00
vnode_pager.c Use per-domain locks for vm page queue free. Move paging control from 2018-02-06 22:10:07 +00:00
vnode_pager.h sys: further adoption of SPDX licensing ID tags. 2017-11-20 19:43:44 +00:00