aboutsummaryrefslogtreecommitdiffstats
path: root/mm/memory.c
diff options
context:
space:
mode:
Diffstat (limited to 'mm/memory.c')
-rw-r--r--mm/memory.c36
1 files changed, 5 insertions, 31 deletions
diff --git a/mm/memory.c b/mm/memory.c
index 7135d6b25995..24ff20480bb7 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -3145,50 +3145,24 @@ int follow_phys(struct vm_area_struct *vma,
3145 unsigned long address, unsigned int flags, 3145 unsigned long address, unsigned int flags,
3146 unsigned long *prot, resource_size_t *phys) 3146 unsigned long *prot, resource_size_t *phys)
3147{ 3147{
3148 pgd_t *pgd; 3148 int ret = -EINVAL;
3149 pud_t *pud;
3150 pmd_t *pmd;
3151 pte_t *ptep, pte; 3149 pte_t *ptep, pte;
3152 spinlock_t *ptl; 3150 spinlock_t *ptl;
3153 resource_size_t phys_addr = 0;
3154 struct mm_struct *mm = vma->vm_mm;
3155 int ret = -EINVAL;
3156 3151
3157 if (!(vma->vm_flags & (VM_IO | VM_PFNMAP))) 3152 if (!(vma->vm_flags & (VM_IO | VM_PFNMAP)))
3158 goto out; 3153 goto out;
3159 3154
3160 pgd = pgd_offset(mm, address); 3155 if (follow_pte(vma->vm_mm, address, &ptep, &ptl))
3161 if (pgd_none(*pgd) || unlikely(pgd_bad(*pgd)))
3162 goto out;
3163
3164 pud = pud_offset(pgd, address);
3165 if (pud_none(*pud) || unlikely(pud_bad(*pud)))
3166 goto out;
3167
3168 pmd = pmd_offset(pud, address);
3169 if (pmd_none(*pmd) || unlikely(pmd_bad(*pmd)))
3170 goto out;
3171
3172 /* We cannot handle huge page PFN maps. Luckily they don't exist. */
3173 if (pmd_huge(*pmd))
3174 goto out; 3156 goto out;
3175
3176 ptep = pte_offset_map_lock(mm, pmd, address, &ptl);
3177 if (!ptep)
3178 goto out;
3179
3180 pte = *ptep; 3157 pte = *ptep;
3181 if (!pte_present(pte)) 3158
3182 goto unlock;
3183 if ((flags & FOLL_WRITE) && !pte_write(pte)) 3159 if ((flags & FOLL_WRITE) && !pte_write(pte))
3184 goto unlock; 3160 goto unlock;
3185 phys_addr = pte_pfn(pte);
3186 phys_addr <<= PAGE_SHIFT; /* Shift here to avoid overflow on PAE */
3187 3161
3188 *prot = pgprot_val(pte_pgprot(pte)); 3162 *prot = pgprot_val(pte_pgprot(pte));
3189 *phys = phys_addr; 3163 *phys = (resource_size_t)pte_pfn(pte) << PAGE_SHIFT;
3190 ret = 0;
3191 3164
3165 ret = 0;
3192unlock: 3166unlock:
3193 pte_unmap_unlock(ptep, ptl); 3167 pte_unmap_unlock(ptep, ptl);
3194out: 3168out: