diff options
Diffstat (limited to 'mm/huge_memory.c')
| -rw-r--r-- | mm/huge_memory.c | 36 | 
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,  	spinlock_t *ptl;  	ptl = pmd_lock(mm, pmd); +	if (!pmd_none(*pmd)) { +		if (write) { +			if (pmd_pfn(*pmd) != pfn_t_to_pfn(pfn)) { +				WARN_ON_ONCE(!is_huge_zero_pmd(*pmd)); +				goto out_unlock; +			} +			entry = pmd_mkyoung(*pmd); +			entry = maybe_pmd_mkwrite(pmd_mkdirty(entry), vma); +			if (pmdp_set_access_flags(vma, addr, pmd, entry, 1)) +				update_mmu_cache_pmd(vma, addr, pmd); +		} + +		goto out_unlock; +	} +  	entry = pmd_mkhuge(pfn_t_pmd(pfn, prot));  	if (pfn_t_devmap(pfn))  		entry = pmd_mkdevmap(entry); @@ -766,11 +781,16 @@ static void insert_pfn_pmd(struct vm_area_struct *vma, unsigned long addr,  	if (pgtable) {  		pgtable_trans_huge_deposit(mm, pmd, pgtable);  		mm_inc_nr_ptes(mm); +		pgtable = NULL;  	}  	set_pmd_at(mm, addr, pmd, entry);  	update_mmu_cache_pmd(vma, addr, pmd); + +out_unlock:  	spin_unlock(ptl); +	if (pgtable) +		pte_free(mm, pgtable);  }  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,  	spinlock_t *ptl;  	ptl = pud_lock(mm, pud); +	if (!pud_none(*pud)) { +		if (write) { +			if (pud_pfn(*pud) != pfn_t_to_pfn(pfn)) { +				WARN_ON_ONCE(!is_huge_zero_pud(*pud)); +				goto out_unlock; +			} +			entry = pud_mkyoung(*pud); +			entry = maybe_pud_mkwrite(pud_mkdirty(entry), vma); +			if (pudp_set_access_flags(vma, addr, pud, entry, 1)) +				update_mmu_cache_pud(vma, addr, pud); +		} +		goto out_unlock; +	} +  	entry = pud_mkhuge(pfn_t_pud(pfn, prot));  	if (pfn_t_devmap(pfn))  		entry = pud_mkdevmap(entry); @@ -830,6 +864,8 @@ static void insert_pfn_pud(struct vm_area_struct *vma, unsigned long addr,  	}  	set_pud_at(mm, addr, pud, entry);  	update_mmu_cache_pud(vma, addr, pud); + +out_unlock:  	spin_unlock(ptl);  } |