linux/arch/arm64/mm
Will Deacon 0106d456c4 arm64: mm: always take dirty state from new pte in ptep_set_access_flags
Commit 66dbd6e61a ("arm64: Implement ptep_set_access_flags() for
hardware AF/DBM") ensured that pte flags are updated atomically in the
face of potential concurrent, hardware-assisted updates. However, Alex
reports that:

 | This patch breaks swapping for me.
 | In the broken case, you'll see either systemd cpu time spike (because
 | it's stuck in a page fault loop) or the system hang (because the
 | application owning the screen is stuck in a page fault loop).

It turns out that this is because the 'dirty' argument to
ptep_set_access_flags is always 0 for read faults, and so we can't use
it to set PTE_RDONLY. The failing sequence is:

  1. We put down a PTE_WRITE | PTE_DIRTY | PTE_AF pte
  2. Memory pressure -> pte_mkold(pte) -> clear PTE_AF
  3. A read faults due to the missing access flag
  4. ptep_set_access_flags is called with dirty = 0, due to the read fault
  5. pte is then made PTE_WRITE | PTE_DIRTY | PTE_AF | PTE_RDONLY (!)
  6. A write faults, but pte_write is true so we get stuck

The solution is to check the new page table entry (as would be done by
the generic, non-atomic definition of ptep_set_access_flags that just
calls set_pte_at) to establish the dirty state.

Cc: <stable@vger.kernel.org> # 4.3+
Fixes: 66dbd6e61a ("arm64: Implement ptep_set_access_flags() for hardware AF/DBM")
Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>
Reported-by: Alexander Graf <agraf@suse.de>
Tested-by: Alexander Graf <agraf@suse.de>
Signed-off-by: Will Deacon <will.deacon@arm.com>
2016-06-08 10:23:44 +01:00
..
cache.S arm64: Fold proc-macros.S into assembler.h 2016-04-28 12:05:45 +01:00
context.c arm64: Add cpu_panic_kernel helper 2016-04-15 18:06:06 +01:00
copypage.c arm64: Defer dcache flush in __cpu_copy_user_page 2015-12-17 11:07:13 +00:00
dma-mapping.c IOMMU Updates for Linux v4.7 2016-05-19 17:07:04 -07:00
dump.c arm64: mm: dump: log span level 2016-06-03 10:16:22 +01:00
extable.c arm64: switch to relative exception tables 2016-02-24 14:57:26 +00:00
fault.c arm64: mm: always take dirty state from new pte in ptep_set_access_flags 2016-06-08 10:23:44 +01:00
flush.c arm64: mm: allow preemption in copy_to_user_page 2016-03-24 16:32:54 +00:00
hugetlbpage.c Revert "arm64: hugetlb: partial revert of 66b3923a1a0f" 2016-05-31 11:00:09 +01:00
init.c arm64: mm: Show bss segment in kernel memory layout 2016-04-19 17:03:31 +01:00
ioremap.c arm64: add ioremap physical address information 2015-01-23 15:29:06 +00:00
kasan_init.c arm64: kasan: Fix zero shadow mapping overriding kernel image shadow 2016-03-11 11:03:35 +00:00
Makefile arm64, numa: Add NUMA support for arm64 platforms. 2016-04-15 18:06:09 +01:00
mm.h arm64: Move unflatten_device_tree() call earlier. 2016-04-15 18:06:08 +01:00
mmap.c arm64: mm: remove unnecessary EXPORT_SYMBOL_GPL 2016-05-05 09:49:38 +01:00
mmu.c arm64: Move unflatten_device_tree() call earlier. 2016-04-15 18:06:08 +01:00
numa.c arm64, numa: Add NUMA support for arm64 platforms. 2016-04-15 18:06:09 +01:00
pageattr.c arm64: Add support for ARCH_SUPPORTS_DEBUG_PAGEALLOC 2016-02-16 15:40:30 +00:00
pgd.c arm64: mm: move pgd_cache initialisation to pgtable_cache_init 2016-01-05 15:43:10 +00:00
proc.S arm64: Change cpu_resume() to enable mmu early then access sleep_sp by va 2016-04-28 12:05:46 +01:00