linux/arch/arm64/mm
Will Deacon 5e8b53a4db arm64: mm: always take dirty state from new pte in ptep_set_access_flags
commit 0106d456c4 upstream.

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.

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>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
History 2016-06-24 10:18:19 -07:00
..
cache.S arm64: use ENDPIPROC() to annotate position independent assembler routines 2015-10-12 16:19:45 +01:00
context.c arm64: mm: keep reserved ASIDs in sync with mm after multiple rollovers 2015-11-26 15:27:10 +00:00
copypage.c arm64: export __cpu_{clear,copy}_user_page functions 2014-07-08 17:30:51 +01:00
dma-mapping.c arm64: dma-mapping: fix handling of devices registered before arch_initcall 2016-02-25 12:01:20 -08:00
dump.c arm64: Make the kernel page dump utility aware of the CONT bit 2015-10-08 18:39:57 +01:00
extable.c arm64: MMU fault handling and page table management 2012-09-17 13:41:57 +01:00
fault.c arm64: mm: always take dirty state from new pte in ptep_set_access_flags 2016-06-24 10:18:19 -07:00
flush.c arm64: force CONFIG_SMP=y and remove redundant #ifdefs 2015-07-27 11:08:40 +01:00
hugetlbpage.c arm64: hugetlb: remove paragraph about writing to FSF 2015-07-27 11:08:40 +01:00
init.c arm64: vmemmap: use virtual projection of linear region 2016-03-09 15:34:52 -08:00
ioremap.c arm64: add ioremap physical address information 2015-01-23 15:29:06 +00:00
kasan_init.c arm64: kasan: fix issues reported by sparse 2015-10-13 14:54:42 +01:00
Makefile arm64: add KASAN support 2015-10-12 17:46:36 +01:00
mm.h arm64: add better page protections to arm64 2015-01-22 14:54:29 +00:00
mmap.c mm: expose arch_mmap_rnd when available 2015-04-14 16:49:05 -07:00
mmu.c arm64: mm: ensure that the zero page is visible to the page table walker 2016-01-31 11:29:04 -08:00
pageattr.c arm64: mm: avoid calling apply_to_page_range on empty range 2016-02-25 12:01:19 -08:00
pgd.c arm64: move PGD_SIZE definition to pgalloc.h 2015-10-12 17:46:30 +01:00
proc-macros.S arm64: kernel: fix architected PMU registers unconditional access 2016-01-31 11:29:04 -08:00
proc.S arm64: kernel: fix architected PMU registers unconditional access 2016-01-31 11:29:04 -08:00