Skip to content

Commit c6f3c5e

Browse files
kvaneeshtorvalds
authored andcommitted
mm/huge_memory.c: fix modifying of page protection by insert_pfn_pmd()
With some architectures like ppc64, set_pmd_at() cannot cope with a situation where there is already some (different) valid entry present. Use pmdp_set_access_flags() instead to modify the pfn which is built to deal with modifying existing PMD entries. This is similar to commit cae85cb ("mm/memory.c: fix modifying of page protection by insert_pfn()") We also do similar update w.r.t insert_pfn_pud eventhough ppc64 don't support pud pfn entries now. Without this patch we also see the below message in kernel log "BUG: non-zero pgtables_bytes on freeing mm:" Link: http://lkml.kernel.org/r/20190402115125.18803-1-aneesh.kumar@linux.ibm.com Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com> Reported-by: Chandan Rajendra <chandan@linux.ibm.com> Reviewed-by: Jan Kara <jack@suse.cz> Cc: Dan Williams <dan.j.williams@intel.com> Cc: <stable@vger.kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
1 parent 58b6e5e commit c6f3c5e

File tree

1 file changed

+36
-0
lines changed

1 file changed

+36
-0
lines changed

mm/huge_memory.c

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -755,6 +755,21 @@ static void insert_pfn_pmd(struct vm_area_struct *vma, unsigned long addr,
755755
spinlock_t *ptl;
756756

757757
ptl = pmd_lock(mm, pmd);
758+
if (!pmd_none(*pmd)) {
759+
if (write) {
760+
if (pmd_pfn(*pmd) != pfn_t_to_pfn(pfn)) {
761+
WARN_ON_ONCE(!is_huge_zero_pmd(*pmd));
762+
goto out_unlock;
763+
}
764+
entry = pmd_mkyoung(*pmd);
765+
entry = maybe_pmd_mkwrite(pmd_mkdirty(entry), vma);
766+
if (pmdp_set_access_flags(vma, addr, pmd, entry, 1))
767+
update_mmu_cache_pmd(vma, addr, pmd);
768+
}
769+
770+
goto out_unlock;
771+
}
772+
758773
entry = pmd_mkhuge(pfn_t_pmd(pfn, prot));
759774
if (pfn_t_devmap(pfn))
760775
entry = pmd_mkdevmap(entry);
@@ -766,11 +781,16 @@ static void insert_pfn_pmd(struct vm_area_struct *vma, unsigned long addr,
766781
if (pgtable) {
767782
pgtable_trans_huge_deposit(mm, pmd, pgtable);
768783
mm_inc_nr_ptes(mm);
784+
pgtable = NULL;
769785
}
770786

771787
set_pmd_at(mm, addr, pmd, entry);
772788
update_mmu_cache_pmd(vma, addr, pmd);
789+
790+
out_unlock:
773791
spin_unlock(ptl);
792+
if (pgtable)
793+
pte_free(mm, pgtable);
774794
}
775795

776796
vm_fault_t vmf_insert_pfn_pmd(struct vm_area_struct *vma, unsigned long addr,
@@ -821,6 +841,20 @@ static void insert_pfn_pud(struct vm_area_struct *vma, unsigned long addr,
821841
spinlock_t *ptl;
822842

823843
ptl = pud_lock(mm, pud);
844+
if (!pud_none(*pud)) {
845+
if (write) {
846+
if (pud_pfn(*pud) != pfn_t_to_pfn(pfn)) {
847+
WARN_ON_ONCE(!is_huge_zero_pud(*pud));
848+
goto out_unlock;
849+
}
850+
entry = pud_mkyoung(*pud);
851+
entry = maybe_pud_mkwrite(pud_mkdirty(entry), vma);
852+
if (pudp_set_access_flags(vma, addr, pud, entry, 1))
853+
update_mmu_cache_pud(vma, addr, pud);
854+
}
855+
goto out_unlock;
856+
}
857+
824858
entry = pud_mkhuge(pfn_t_pud(pfn, prot));
825859
if (pfn_t_devmap(pfn))
826860
entry = pud_mkdevmap(entry);
@@ -830,6 +864,8 @@ static void insert_pfn_pud(struct vm_area_struct *vma, unsigned long addr,
830864
}
831865
set_pud_at(mm, addr, pud, entry);
832866
update_mmu_cache_pud(vma, addr, pud);
867+
868+
out_unlock:
833869
spin_unlock(ptl);
834870
}
835871

0 commit comments

Comments
 (0)