aboutsummaryrefslogtreecommitdiffstats
path: root/mm
diff options
context:
space:
mode:
authorMinchan Kim <minchan@kernel.org>2017-01-10 19:57:51 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2017-01-19 14:17:58 -0500
commit8edd365ee94ca4541270ee00b90705c634a085c6 (patch)
treed8cddd0445e5866a6e701c33c135091ee06b9d09 /mm
parent87fa6f37fa29565f13a1db0cdcf8ad2d0eb0f76e (diff)
mm: pmd dirty emulation in page fault handler
commit 20f664aabeb88d582b623a625f83b0454fa34f07 upstream. Andreas reported [1] made a test in jemalloc hang in THP mode in arm64: http://lkml.kernel.org/r/mvmmvfy37g1.fsf@hawking.suse.de The problem is currently page fault handler doesn't supports dirty bit emulation of pmd for non-HW dirty-bit architecture so that application stucks until VM marked the pmd dirty. How the emulation work depends on the architecture. In case of arm64, when it set up pte firstly, it sets pte PTE_RDONLY to get a chance to mark the pte dirty via triggering page fault when store access happens. Once the page fault occurs, VM marks the pmd dirty and arch code for setting pmd will clear PTE_RDONLY for application to proceed. IOW, if VM doesn't mark the pmd dirty, application hangs forever by repeated fault(i.e., store op but the pmd is PTE_RDONLY). This patch enables pmd dirty-bit emulation for those architectures. [1] b8d3c4c3009d, mm/huge_memory.c: don't split THP page when MADV_FREE syscall is called Fixes: b8d3c4c3009d ("mm/huge_memory.c: don't split THP page when MADV_FREE syscall is called") Link: http://lkml.kernel.org/r/1482506098-6149-1-git-send-email-minchan@kernel.org Signed-off-by: Minchan Kim <minchan@kernel.org> Reported-by: Andreas Schwab <schwab@suse.de> Tested-by: Andreas Schwab <schwab@suse.de> Acked-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com> Acked-by: Michal Hocko <mhocko@suse.com> Cc: Jason Evans <je@fb.com> Cc: Will Deacon <will.deacon@arm.com> Cc: Catalin Marinas <catalin.marinas@arm.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'mm')
-rw-r--r--mm/huge_memory.c6
1 files changed, 4 insertions, 2 deletions
diff --git a/mm/huge_memory.c b/mm/huge_memory.c
index d4a6e4001512..8ca40b70beae 100644
--- a/mm/huge_memory.c
+++ b/mm/huge_memory.c
@@ -872,15 +872,17 @@ void huge_pmd_set_accessed(struct fault_env *fe, pmd_t orig_pmd)
872{ 872{
873 pmd_t entry; 873 pmd_t entry;
874 unsigned long haddr; 874 unsigned long haddr;
875 bool write = fe->flags & FAULT_FLAG_WRITE;
875 876
876 fe->ptl = pmd_lock(fe->vma->vm_mm, fe->pmd); 877 fe->ptl = pmd_lock(fe->vma->vm_mm, fe->pmd);
877 if (unlikely(!pmd_same(*fe->pmd, orig_pmd))) 878 if (unlikely(!pmd_same(*fe->pmd, orig_pmd)))
878 goto unlock; 879 goto unlock;
879 880
880 entry = pmd_mkyoung(orig_pmd); 881 entry = pmd_mkyoung(orig_pmd);
882 if (write)
883 entry = pmd_mkdirty(entry);
881 haddr = fe->address & HPAGE_PMD_MASK; 884 haddr = fe->address & HPAGE_PMD_MASK;
882 if (pmdp_set_access_flags(fe->vma, haddr, fe->pmd, entry, 885 if (pmdp_set_access_flags(fe->vma, haddr, fe->pmd, entry, write))
883 fe->flags & FAULT_FLAG_WRITE))
884 update_mmu_cache_pmd(fe->vma, fe->address, fe->pmd); 886 update_mmu_cache_pmd(fe->vma, fe->address, fe->pmd);
885 887
886unlock: 888unlock: