aboutsummaryrefslogtreecommitdiffstats
path: root/mm/huge_memory.c
diff options
context:
space:
mode:
Diffstat (limited to 'mm/huge_memory.c')
-rw-r--r--mm/huge_memory.c36
1 files changed, 36 insertions, 0 deletions
diff --git a/mm/huge_memory.c b/mm/huge_memory.c
index 404acdcd0455..165ea46bf149 100644
--- a/mm/huge_memory.c
+++ b/mm/huge_memory.c
@@ -755,6 +755,21 @@ static void insert_pfn_pmd(struct vm_area_struct *vma, unsigned long addr,
755 spinlock_t *ptl; 755 spinlock_t *ptl;
756 756
757 ptl = pmd_lock(mm, pmd); 757 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
758 entry = pmd_mkhuge(pfn_t_pmd(pfn, prot)); 773 entry = pmd_mkhuge(pfn_t_pmd(pfn, prot));
759 if (pfn_t_devmap(pfn)) 774 if (pfn_t_devmap(pfn))
760 entry = pmd_mkdevmap(entry); 775 entry = pmd_mkdevmap(entry);
@@ -766,11 +781,16 @@ static void insert_pfn_pmd(struct vm_area_struct *vma, unsigned long addr,
766 if (pgtable) { 781 if (pgtable) {
767 pgtable_trans_huge_deposit(mm, pmd, pgtable); 782 pgtable_trans_huge_deposit(mm, pmd, pgtable);
768 mm_inc_nr_ptes(mm); 783 mm_inc_nr_ptes(mm);
784 pgtable = NULL;
769 } 785 }
770 786
771 set_pmd_at(mm, addr, pmd, entry); 787 set_pmd_at(mm, addr, pmd, entry);
772 update_mmu_cache_pmd(vma, addr, pmd); 788 update_mmu_cache_pmd(vma, addr, pmd);
789
790out_unlock:
773 spin_unlock(ptl); 791 spin_unlock(ptl);
792 if (pgtable)
793 pte_free(mm, pgtable);
774} 794}
775 795
776vm_fault_t vmf_insert_pfn_pmd(struct vm_area_struct *vma, unsigned long addr, 796vm_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,
821 spinlock_t *ptl; 841 spinlock_t *ptl;
822 842
823 ptl = pud_lock(mm, pud); 843 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
824 entry = pud_mkhuge(pfn_t_pud(pfn, prot)); 858 entry = pud_mkhuge(pfn_t_pud(pfn, prot));
825 if (pfn_t_devmap(pfn)) 859 if (pfn_t_devmap(pfn))
826 entry = pud_mkdevmap(entry); 860 entry = pud_mkdevmap(entry);
@@ -830,6 +864,8 @@ static void insert_pfn_pud(struct vm_area_struct *vma, unsigned long addr,
830 } 864 }
831 set_pud_at(mm, addr, pud, entry); 865 set_pud_at(mm, addr, pud, entry);
832 update_mmu_cache_pud(vma, addr, pud); 866 update_mmu_cache_pud(vma, addr, pud);
867
868out_unlock:
833 spin_unlock(ptl); 869 spin_unlock(ptl);
834} 870}
835 871