linux/Documentation
Jérôme Glisse 0f10851ea4 mm/mmu_notifier: avoid double notification when it is useless
This patch only affects users of mmu_notifier->invalidate_range callback
which are device drivers related to ATS/PASID, CAPI, IOMMUv2, SVM ...
and it is an optimization for those users.  Everyone else is unaffected
by it.

When clearing a pte/pmd we are given a choice to notify the event under
the page table lock (notify version of *_clear_flush helpers do call the
mmu_notifier_invalidate_range).  But that notification is not necessary
in all cases.

This patch removes almost all cases where it is useless to have a call
to mmu_notifier_invalidate_range before
mmu_notifier_invalidate_range_end.  It also adds documentation in all
those cases explaining why.

Below is a more in depth analysis of why this is fine to do this:

For secondary TLB (non CPU TLB) like IOMMU TLB or device TLB (when
device use thing like ATS/PASID to get the IOMMU to walk the CPU page
table to access a process virtual address space).  There is only 2 cases
when you need to notify those secondary TLB while holding page table
lock when clearing a pte/pmd:

  A) page backing address is free before mmu_notifier_invalidate_range_end
  B) a page table entry is updated to point to a new page (COW, write fault
     on zero page, __replace_page(), ...)

Case A is obvious you do not want to take the risk for the device to write
to a page that might now be used by something completely different.

Case B is more subtle. For correctness it requires the following sequence
to happen:
  - take page table lock
  - clear page table entry and notify (pmd/pte_huge_clear_flush_notify())
  - set page table entry to point to new page

If clearing the page table entry is not followed by a notify before setting
the new pte/pmd value then you can break memory model like C11 or C++11 for
the device.

Consider the following scenario (device use a feature similar to ATS/
PASID):

Two address addrA and addrB such that |addrA - addrB| >= PAGE_SIZE we
assume they are write protected for COW (other case of B apply too).

[Time N] -----------------------------------------------------------------
CPU-thread-0  {try to write to addrA}
CPU-thread-1  {try to write to addrB}
CPU-thread-2  {}
CPU-thread-3  {}
DEV-thread-0  {read addrA and populate device TLB}
DEV-thread-2  {read addrB and populate device TLB}
[Time N+1] ---------------------------------------------------------------
CPU-thread-0  {COW_step0: {mmu_notifier_invalidate_range_start(addrA)}}
CPU-thread-1  {COW_step0: {mmu_notifier_invalidate_range_start(addrB)}}
CPU-thread-2  {}
CPU-thread-3  {}
DEV-thread-0  {}
DEV-thread-2  {}
[Time N+2] ---------------------------------------------------------------
CPU-thread-0  {COW_step1: {update page table point to new page for addrA}}
CPU-thread-1  {COW_step1: {update page table point to new page for addrB}}
CPU-thread-2  {}
CPU-thread-3  {}
DEV-thread-0  {}
DEV-thread-2  {}
[Time N+3] ---------------------------------------------------------------
CPU-thread-0  {preempted}
CPU-thread-1  {preempted}
CPU-thread-2  {write to addrA which is a write to new page}
CPU-thread-3  {}
DEV-thread-0  {}
DEV-thread-2  {}
[Time N+3] ---------------------------------------------------------------
CPU-thread-0  {preempted}
CPU-thread-1  {preempted}
CPU-thread-2  {}
CPU-thread-3  {write to addrB which is a write to new page}
DEV-thread-0  {}
DEV-thread-2  {}
[Time N+4] ---------------------------------------------------------------
CPU-thread-0  {preempted}
CPU-thread-1  {COW_step3: {mmu_notifier_invalidate_range_end(addrB)}}
CPU-thread-2  {}
CPU-thread-3  {}
DEV-thread-0  {}
DEV-thread-2  {}
[Time N+5] ---------------------------------------------------------------
CPU-thread-0  {preempted}
CPU-thread-1  {}
CPU-thread-2  {}
CPU-thread-3  {}
DEV-thread-0  {read addrA from old page}
DEV-thread-2  {read addrB from new page}

So here because at time N+2 the clear page table entry was not pair with a
notification to invalidate the secondary TLB, the device see the new value
for addrB before seing the new value for addrA.  This break total memory
ordering for the device.

When changing a pte to write protect or to point to a new write protected
page with same content (KSM) it is ok to delay invalidate_range callback
to mmu_notifier_invalidate_range_end() outside the page table lock.  This
is true even if the thread doing page table update is preempted right
after releasing page table lock before calling
mmu_notifier_invalidate_range_end

Thanks to Andrea for thinking of a problematic scenario for COW.

[jglisse@redhat.com: v2]
  Link: http://lkml.kernel.org/r/20171017031003.7481-2-jglisse@redhat.com
Link: http://lkml.kernel.org/r/20170901173011.10745-1-jglisse@redhat.com
Signed-off-by: Jérôme Glisse <jglisse@redhat.com>
Cc: Andrea Arcangeli <aarcange@redhat.com>
Cc: Nadav Amit <nadav.amit@gmail.com>
Cc: Joerg Roedel <jroedel@suse.de>
Cc: Suravee Suthikulpanit <suravee.suthikulpanit@amd.com>
Cc: David Woodhouse <dwmw2@infradead.org>
Cc: Alistair Popple <alistair@popple.id.au>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Stephen Rothwell <sfr@canb.auug.org.au>
Cc: Andrew Donnellan <andrew.donnellan@au1.ibm.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2017-11-15 18:21:03 -08:00
..
ABI This is the bulk of GPIO changes for the v4.15 kernel cycle: 2017-11-14 17:23:44 -08:00
EDID
PCI
RCU Merge branch 'core-rcu-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip 2017-11-13 12:18:10 -08:00
accounting
acpi ACPI / LPIT: Add Low Power Idle Table (LPIT) support 2017-10-11 15:38:10 +02:00
admin-guide Merge branch 'irq-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip 2017-11-13 17:33:11 -08:00
aoe
arm
arm64 arm64 updates for 4.15 2017-11-15 10:56:56 -08:00
auxdisplay
backlight
blackfin
block block: remove __bio_kmap_atomic 2017-11-10 19:53:25 -07:00
blockdev SCSI misc on 20170907 2017-09-07 21:11:05 -07:00
bus-devices
cdrom documentation: Update ide-cd documentation to reflect CONFIG_BLK_DEV_HD_IDE removal 2017-10-12 11:25:31 -06:00
cgroup-v1
cma
connector
console
core-api A relatively calm cycle for the docs tree again. 2017-11-13 08:25:06 -08:00
cpu-freq cpufreq: stats: Handle the case when trans_table goes beyond PAGE_SIZE 2017-11-08 23:41:25 +01:00
cpuidle
cris
crypto crypto: doc - adapt api sample to use async. op wait 2017-11-03 22:11:23 +08:00
dev-tools docs: dev-tools: correct Coccinelle version number 2017-10-19 12:55:24 -06:00
device-mapper dm raid: fix incorrect status output at the end of a "recover" process 2017-10-05 16:21:30 -04:00
devicetree arm64 updates for 4.15 2017-11-15 10:56:56 -08:00
doc-guide Documentation: fix ref to sphinx/kerneldoc.py 2017-10-19 12:57:10 -06:00
driver-api SCSI misc on 20171114 2017-11-14 16:23:44 -08:00
driver-model driver core: remove DRIVER_ATTR 2017-09-19 09:20:33 +02:00
early-userspace
extcon
fault-injection cpu/hotplug: Get rid of CPU hotplug notifier leftovers 2017-11-13 10:03:53 +01:00
fb documentation: fb: update list of available compiled-in fonts 2017-11-08 03:39:52 -07:00
features Documentation/features/KASAN: mark KASAN as supported only on 64-bit on x86 2017-10-03 14:40:22 -06:00
filesystems Merge branch 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs 2017-11-14 14:13:11 -08:00
firmware_class
fmc
fpga
frv
gpio gpio: Move irq_valid_mask into struct gpio_irq_chip 2017-11-08 14:10:18 +01:00
gpu
hid Documentation: fix input related doc refs 2017-10-12 11:14:06 -06:00
hwmon pmbus: Add driver for Maxim MAX31785 Intelligent Fan Controller 2017-11-05 06:06:33 -08:00
i2c i2c: i801: Add support for Intel Cedar Fork 2017-10-05 14:44:56 +02:00
ia64
ide
iio
infiniband
input Documentation: fix input related doc refs 2017-10-12 11:14:06 -06:00
ioctl
isdn
kbuild DeviceTree for 4.15: 2017-11-14 18:25:40 -08:00
kdump
kernel-hacking
laptops Documentation: fix admin-guide doc refs 2017-10-12 11:13:28 -06:00
leds Documentation: leds: Update 00-INDEX file 2017-10-23 20:17:03 +02:00
lightnvm
livepatch livepatch: add (un)patch callbacks 2017-10-19 10:08:56 +02:00
locking Documentation: fix locking rt-mutex doc refs 2017-10-19 12:56:44 -06:00
m68k
md md-cluster: update document for raid10 2017-11-01 21:32:25 -07:00
media Documentation: fix media related doc refs 2017-10-12 11:15:06 -06:00
memory-devices
metag
mic
mips
misc-devices
mmc
mn10300
mtd
namespaces
netlabel
networking A relatively calm cycle for the docs tree again. 2017-11-13 08:25:06 -08:00
nfc
nios2
nvdimm
nvmem
openrisc Documentation: openrisc: Updates to README 2017-10-30 21:37:53 +09:00
parisc
pcmcia
perf Documentation: perf: hisi: Documentation for HiSilicon SoC PMU driver 2017-10-19 17:06:34 +01:00
phy
platform
power Power management updates for v4.15-rc1 2017-11-13 19:43:50 -08:00
powerpc
pps drivers/pps: aesthetic tweaks to PPS-related content 2017-09-08 18:26:51 -07:00
process A relatively calm cycle for the docs tree again. 2017-11-13 08:25:06 -08:00
pti
ptp
rapidio
s390
scheduler
scsi scsi: smartpqi: correct spelling error in documentation 2017-10-23 04:15:17 -04:00
security Documentation: fix security related doc refs 2017-10-12 11:14:40 -06:00
serial
sh
sound sound updates for 4.15-rc1 2017-11-14 18:01:46 -08:00
sparc
sphinx Documentation/sphinx: fix kernel-doc decode for non-utf-8 locale 2017-08-31 13:36:28 -06:00
sphinx-static
spi
sysctl mm/page-writeback.c: print a warning if the vm dirtiness settings are illogical 2017-11-15 18:21:03 -08:00
target
thermal
timers docs: highres: fix broken urls 2017-09-26 14:58:23 -06:00
trace ftrace/docs: Add documentation on how to use ftrace from within the kernel 2017-11-05 09:55:29 -07:00
translations locking/barriers: Kill lockless_dereference() 2017-10-24 13:17:33 +02:00
usb Documentation: fix usb related doc refs 2017-10-12 11:15:48 -06:00
userspace-api
virtual KVM/ARM Changes for v4.14 2017-09-07 18:22:04 +02:00
vm mm/mmu_notifier: avoid double notification when it is useless 2017-11-15 18:21:03 -08:00
w1
watchdog Documentation: fix selftests related file refs 2017-10-19 12:58:21 -06:00
wimax
x86 Merge branch 'x86-cache-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip 2017-11-13 19:05:19 -08:00
xtensa
.gitignore
00-INDEX
Changes
CodingStyle
DMA-API-HOWTO.txt
DMA-API.txt dma-coherent: remove the DMA_MEMORY_MAP and DMA_MEMORY_IO flags 2017-09-01 11:59:17 +02:00
DMA-ISA-LPC.txt
DMA-attributes.txt
IPMI.txt
IRQ-affinity.txt
IRQ-domain.txt
IRQ.txt
Intel-IOMMU.txt
Makefile Documentation: add script and build target to check for broken file references 2017-10-12 11:07:42 -06:00
SAK.txt
SM501.txt
SubmittingPatches
atomic_bitops.txt
atomic_t.txt
bcache.txt
bt8xxgpio.txt
btmrvl.txt
bus-virt-phys-mapping.txt
cachetlb.txt
cgroup-v2.txt
circular-buffers.txt
clk.txt
conf.py docs-rst: don't require adjustbox anymore 2017-09-08 10:02:55 -06:00
cpu-load.txt
cputopology.txt
crc32.txt
dcdbas.txt
debugging-modules.txt
debugging-via-ohci1394.txt
dell_rbu.txt
digsig.txt
docutils.conf
dontdiff
efi-stub.txt
eisa.txt
errseq.rst
flexible-arrays.txt
futex-requeue-pi.txt
gcc-plugins.txt
highuid.txt
hw_random.txt
hwspinlock.txt
index.rst
intel_txt.txt
io-mapping.txt
io_ordering.txt
iostats.txt
irqflags-tracing.txt
isa.txt
isapnp.txt
kernel-doc-nano-HOWTO.txt
kernel-per-CPU-kthreads.txt
kobject.txt
kprobes.txt kprobes/docs: Remove jprobes related documents 2017-10-20 11:02:55 +02:00
kref.txt
ldm.txt
lockup-watchdogs.txt
logo.gif
logo.txt
lsm.txt
lzo.txt
mailbox.txt
memory-barriers.txt Merge branch 'locking-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip 2017-11-13 12:38:26 -08:00
memory-hotplug.txt
men-chameleon-bus.txt
nommu-mmap.txt
ntb.txt
numastat.txt
padata.txt
parport-lowlevel.txt
percpu-rw-semaphore.txt
phy.txt
pi-futex.txt Documentation: fix locking rt-mutex doc refs 2017-10-19 12:56:44 -06:00
pnp.txt
preempt-locking.txt
printk-formats.txt
pwm.txt
rbtree.txt rbtree: cache leftmost node internally 2017-09-08 18:26:48 -07:00
remoteproc.txt
rfkill.txt
robust-futex-ABI.txt
robust-futexes.txt
rpmsg.txt
rtc.txt
sgi-ioc4.txt
siphash.txt
smsc_ece1099.txt
static-keys.txt
svga.txt
switchtec.txt
sync_file.txt
tee.txt
this_cpu_ops.txt
unaligned-memory-access.txt
vfio-mediated-device.txt
vfio.txt
video-output.txt
xillybus.txt
xz.txt
zorro.txt