aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/mm.h2
-rw-r--r--mm/memory.c45
2 files changed, 47 insertions, 0 deletions
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 77a76101dcd9..903f3b71f4a7 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -1124,6 +1124,8 @@ unsigned long vmalloc_to_pfn(void *addr);
1124int remap_pfn_range(struct vm_area_struct *, unsigned long addr, 1124int remap_pfn_range(struct vm_area_struct *, unsigned long addr,
1125 unsigned long pfn, unsigned long size, pgprot_t); 1125 unsigned long pfn, unsigned long size, pgprot_t);
1126int vm_insert_page(struct vm_area_struct *, unsigned long addr, struct page *); 1126int vm_insert_page(struct vm_area_struct *, unsigned long addr, struct page *);
1127int vm_insert_pfn(struct vm_area_struct *vma, unsigned long addr,
1128 unsigned long pfn);
1127 1129
1128struct page *follow_page(struct vm_area_struct *, unsigned long address, 1130struct page *follow_page(struct vm_area_struct *, unsigned long address,
1129 unsigned int foll_flags); 1131 unsigned int foll_flags);
diff --git a/mm/memory.c b/mm/memory.c
index 072c1135ad37..8b8f0d2b453d 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -1277,6 +1277,51 @@ int vm_insert_page(struct vm_area_struct *vma, unsigned long addr, struct page *
1277} 1277}
1278EXPORT_SYMBOL(vm_insert_page); 1278EXPORT_SYMBOL(vm_insert_page);
1279 1279
1280/**
1281 * vm_insert_pfn - insert single pfn into user vma
1282 * @vma: user vma to map to
1283 * @addr: target user address of this page
1284 * @pfn: source kernel pfn
1285 *
1286 * Similar to vm_inert_page, this allows drivers to insert individual pages
1287 * they've allocated into a user vma. Same comments apply.
1288 *
1289 * This function should only be called from a vm_ops->fault handler, and
1290 * in that case the handler should return NULL.
1291 */
1292int vm_insert_pfn(struct vm_area_struct *vma, unsigned long addr,
1293 unsigned long pfn)
1294{
1295 struct mm_struct *mm = vma->vm_mm;
1296 int retval;
1297 pte_t *pte, entry;
1298 spinlock_t *ptl;
1299
1300 BUG_ON(!(vma->vm_flags & VM_PFNMAP));
1301 BUG_ON(is_cow_mapping(vma->vm_flags));
1302
1303 retval = -ENOMEM;
1304 pte = get_locked_pte(mm, addr, &ptl);
1305 if (!pte)
1306 goto out;
1307 retval = -EBUSY;
1308 if (!pte_none(*pte))
1309 goto out_unlock;
1310
1311 /* Ok, finally just insert the thing.. */
1312 entry = pfn_pte(pfn, vma->vm_page_prot);
1313 set_pte_at(mm, addr, pte, entry);
1314 update_mmu_cache(vma, addr, entry);
1315
1316 retval = 0;
1317out_unlock:
1318 pte_unmap_unlock(pte, ptl);
1319
1320out:
1321 return retval;
1322}
1323EXPORT_SYMBOL(vm_insert_pfn);
1324
1280/* 1325/*
1281 * maps a range of physical memory into the requested pages. the old 1326 * maps a range of physical memory into the requested pages. the old
1282 * mappings are removed. any references to nonexistent pages results 1327 * mappings are removed. any references to nonexistent pages results