aboutsummaryrefslogtreecommitdiffstats
path: root/mm
diff options
context:
space:
mode:
Diffstat (limited to 'mm')
-rw-r--r--mm/fremap.c24
-rw-r--r--mm/memory.c122
-rw-r--r--mm/rmap.c2
3 files changed, 115 insertions, 33 deletions
diff --git a/mm/fremap.c b/mm/fremap.c
index f851775e09c2..9f381e58bf44 100644
--- a/mm/fremap.c
+++ b/mm/fremap.c
@@ -55,20 +55,10 @@ int install_page(struct mm_struct *mm, struct vm_area_struct *vma,
55 pgoff_t size; 55 pgoff_t size;
56 int err = -ENOMEM; 56 int err = -ENOMEM;
57 pte_t *pte; 57 pte_t *pte;
58 pmd_t *pmd;
59 pud_t *pud;
60 pgd_t *pgd;
61 pte_t pte_val; 58 pte_t pte_val;
62 spinlock_t *ptl; 59 spinlock_t *ptl;
63 60
64 pgd = pgd_offset(mm, addr); 61 pte = get_locked_pte(mm, addr, &ptl);
65 pud = pud_alloc(mm, pgd, addr);
66 if (!pud)
67 goto out;
68 pmd = pmd_alloc(mm, pud, addr);
69 if (!pmd)
70 goto out;
71 pte = pte_alloc_map_lock(mm, pmd, addr, &ptl);
72 if (!pte) 62 if (!pte)
73 goto out; 63 goto out;
74 64
@@ -110,20 +100,10 @@ int install_file_pte(struct mm_struct *mm, struct vm_area_struct *vma,
110{ 100{
111 int err = -ENOMEM; 101 int err = -ENOMEM;
112 pte_t *pte; 102 pte_t *pte;
113 pmd_t *pmd;
114 pud_t *pud;
115 pgd_t *pgd;
116 pte_t pte_val; 103 pte_t pte_val;
117 spinlock_t *ptl; 104 spinlock_t *ptl;
118 105
119 pgd = pgd_offset(mm, addr); 106 pte = get_locked_pte(mm, addr, &ptl);
120 pud = pud_alloc(mm, pgd, addr);
121 if (!pud)
122 goto out;
123 pmd = pmd_alloc(mm, pud, addr);
124 if (!pmd)
125 goto out;
126 pte = pte_alloc_map_lock(mm, pmd, addr, &ptl);
127 if (!pte) 107 if (!pte)
128 goto out; 108 goto out;
129 109
diff --git a/mm/memory.c b/mm/memory.c
index 9ab206b829a2..5bfa52a98630 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -988,7 +988,7 @@ int get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
988 return i ? : -EFAULT; 988 return i ? : -EFAULT;
989 } 989 }
990 if (pages) { 990 if (pages) {
991 struct page *page = vm_normal_page(vma, start, *pte); 991 struct page *page = vm_normal_page(gate_vma, start, *pte);
992 pages[i] = page; 992 pages[i] = page;
993 if (page) 993 if (page)
994 get_page(page); 994 get_page(page);
@@ -1146,6 +1146,97 @@ int zeromap_page_range(struct vm_area_struct *vma,
1146 return err; 1146 return err;
1147} 1147}
1148 1148
1149pte_t *get_locked_pte(struct mm_struct *mm, unsigned long addr, spinlock_t **ptl)
1150{
1151 pgd_t * pgd = pgd_offset(mm, addr);
1152 pud_t * pud = pud_alloc(mm, pgd, addr);
1153 if (pud) {
1154 pmd_t * pmd = pmd_alloc(mm, pgd, addr);
1155 if (pmd)
1156 return pte_alloc_map_lock(mm, pmd, addr, ptl);
1157 }
1158 return NULL;
1159}
1160
1161/*
1162 * This is the old fallback for page remapping.
1163 *
1164 * For historical reasons, it only allows reserved pages. Only
1165 * old drivers should use this, and they needed to mark their
1166 * pages reserved for the old functions anyway.
1167 */
1168static int insert_page(struct mm_struct *mm, unsigned long addr, struct page *page, pgprot_t prot)
1169{
1170 int retval;
1171 pte_t *pte;
1172 spinlock_t *ptl;
1173
1174 retval = -EINVAL;
1175 if (PageAnon(page) || !PageReserved(page))
1176 goto out;
1177 retval = -ENOMEM;
1178 flush_dcache_page(page);
1179 pte = get_locked_pte(mm, addr, &ptl);
1180 if (!pte)
1181 goto out;
1182 retval = -EBUSY;
1183 if (!pte_none(*pte))
1184 goto out_unlock;
1185
1186 /* Ok, finally just insert the thing.. */
1187 get_page(page);
1188 inc_mm_counter(mm, file_rss);
1189 page_add_file_rmap(page);
1190 set_pte_at(mm, addr, pte, mk_pte(page, prot));
1191
1192 retval = 0;
1193out_unlock:
1194 pte_unmap_unlock(pte, ptl);
1195out:
1196 return retval;
1197}
1198
1199/*
1200 * Somebody does a pfn remapping that doesn't actually work as a vma.
1201 *
1202 * Do it as individual pages instead, and warn about it. It's bad form,
1203 * and very inefficient.
1204 */
1205static int incomplete_pfn_remap(struct vm_area_struct *vma,
1206 unsigned long start, unsigned long end,
1207 unsigned long pfn, pgprot_t prot)
1208{
1209 static int warn = 10;
1210 struct page *page;
1211 int retval;
1212
1213 if (!(vma->vm_flags & VM_INCOMPLETE)) {
1214 if (warn) {
1215 warn--;
1216 printk("%s does an incomplete pfn remapping", current->comm);
1217 dump_stack();
1218 }
1219 }
1220 vma->vm_flags |= VM_INCOMPLETE | VM_IO | VM_RESERVED;
1221
1222 if (start < vma->vm_start || end > vma->vm_end)
1223 return -EINVAL;
1224
1225 if (!pfn_valid(pfn))
1226 return -EINVAL;
1227
1228 retval = 0;
1229 page = pfn_to_page(pfn);
1230 while (start < end) {
1231 retval = insert_page(vma->vm_mm, start, page, prot);
1232 if (retval < 0)
1233 break;
1234 start += PAGE_SIZE;
1235 page++;
1236 }
1237 return retval;
1238}
1239
1149/* 1240/*
1150 * maps a range of physical memory into the requested pages. the old 1241 * maps a range of physical memory into the requested pages. the old
1151 * mappings are removed. any references to nonexistent pages results 1242 * mappings are removed. any references to nonexistent pages results
@@ -1220,6 +1311,9 @@ int remap_pfn_range(struct vm_area_struct *vma, unsigned long addr,
1220 struct mm_struct *mm = vma->vm_mm; 1311 struct mm_struct *mm = vma->vm_mm;
1221 int err; 1312 int err;
1222 1313
1314 if (addr != vma->vm_start || end != vma->vm_end)
1315 return incomplete_pfn_remap(vma, addr, end, pfn, prot);
1316
1223 /* 1317 /*
1224 * Physically remapped pages are special. Tell the 1318 * Physically remapped pages are special. Tell the
1225 * rest of the world about it: 1319 * rest of the world about it:
@@ -1300,8 +1394,15 @@ static inline void cow_user_page(struct page *dst, struct page *src, unsigned lo
1300 */ 1394 */
1301 if (unlikely(!src)) { 1395 if (unlikely(!src)) {
1302 void *kaddr = kmap_atomic(dst, KM_USER0); 1396 void *kaddr = kmap_atomic(dst, KM_USER0);
1303 unsigned long left = __copy_from_user_inatomic(kaddr, (void __user *)va, PAGE_SIZE); 1397 void __user *uaddr = (void __user *)(va & PAGE_MASK);
1304 if (left) 1398
1399 /*
1400 * This really shouldn't fail, because the page is there
1401 * in the page tables. But it might just be unreadable,
1402 * in which case we just give up and fill the result with
1403 * zeroes.
1404 */
1405 if (__copy_from_user_inatomic(kaddr, uaddr, PAGE_SIZE))
1305 memset(kaddr, 0, PAGE_SIZE); 1406 memset(kaddr, 0, PAGE_SIZE);
1306 kunmap_atomic(kaddr, KM_USER0); 1407 kunmap_atomic(kaddr, KM_USER0);
1307 return; 1408 return;
@@ -1332,12 +1433,11 @@ static int do_wp_page(struct mm_struct *mm, struct vm_area_struct *vma,
1332 unsigned long address, pte_t *page_table, pmd_t *pmd, 1433 unsigned long address, pte_t *page_table, pmd_t *pmd,
1333 spinlock_t *ptl, pte_t orig_pte) 1434 spinlock_t *ptl, pte_t orig_pte)
1334{ 1435{
1335 struct page *old_page, *src_page, *new_page; 1436 struct page *old_page, *new_page;
1336 pte_t entry; 1437 pte_t entry;
1337 int ret = VM_FAULT_MINOR; 1438 int ret = VM_FAULT_MINOR;
1338 1439
1339 old_page = vm_normal_page(vma, address, orig_pte); 1440 old_page = vm_normal_page(vma, address, orig_pte);
1340 src_page = old_page;
1341 if (!old_page) 1441 if (!old_page)
1342 goto gotten; 1442 goto gotten;
1343 1443
@@ -1345,7 +1445,7 @@ static int do_wp_page(struct mm_struct *mm, struct vm_area_struct *vma,
1345 int reuse = can_share_swap_page(old_page); 1445 int reuse = can_share_swap_page(old_page);
1346 unlock_page(old_page); 1446 unlock_page(old_page);
1347 if (reuse) { 1447 if (reuse) {
1348 flush_cache_page(vma, address, pfn); 1448 flush_cache_page(vma, address, pte_pfn(orig_pte));
1349 entry = pte_mkyoung(orig_pte); 1449 entry = pte_mkyoung(orig_pte);
1350 entry = maybe_mkwrite(pte_mkdirty(entry), vma); 1450 entry = maybe_mkwrite(pte_mkdirty(entry), vma);
1351 ptep_set_access_flags(vma, address, page_table, entry, 1); 1451 ptep_set_access_flags(vma, address, page_table, entry, 1);
@@ -1365,7 +1465,7 @@ gotten:
1365 1465
1366 if (unlikely(anon_vma_prepare(vma))) 1466 if (unlikely(anon_vma_prepare(vma)))
1367 goto oom; 1467 goto oom;
1368 if (src_page == ZERO_PAGE(address)) { 1468 if (old_page == ZERO_PAGE(address)) {
1369 new_page = alloc_zeroed_user_highpage(vma, address); 1469 new_page = alloc_zeroed_user_highpage(vma, address);
1370 if (!new_page) 1470 if (!new_page)
1371 goto oom; 1471 goto oom;
@@ -1373,7 +1473,7 @@ gotten:
1373 new_page = alloc_page_vma(GFP_HIGHUSER, vma, address); 1473 new_page = alloc_page_vma(GFP_HIGHUSER, vma, address);
1374 if (!new_page) 1474 if (!new_page)
1375 goto oom; 1475 goto oom;
1376 cow_user_page(new_page, src_page, address); 1476 cow_user_page(new_page, old_page, address);
1377 } 1477 }
1378 1478
1379 /* 1479 /*
@@ -1389,7 +1489,7 @@ gotten:
1389 } 1489 }
1390 } else 1490 } else
1391 inc_mm_counter(mm, anon_rss); 1491 inc_mm_counter(mm, anon_rss);
1392 flush_cache_page(vma, address, pfn); 1492 flush_cache_page(vma, address, pte_pfn(orig_pte));
1393 entry = mk_pte(new_page, vma->vm_page_prot); 1493 entry = mk_pte(new_page, vma->vm_page_prot);
1394 entry = maybe_mkwrite(pte_mkdirty(entry), vma); 1494 entry = maybe_mkwrite(pte_mkdirty(entry), vma);
1395 ptep_establish(vma, address, page_table, entry); 1495 ptep_establish(vma, address, page_table, entry);
@@ -1909,6 +2009,8 @@ static int do_no_page(struct mm_struct *mm, struct vm_area_struct *vma,
1909 int anon = 0; 2009 int anon = 0;
1910 2010
1911 pte_unmap(page_table); 2011 pte_unmap(page_table);
2012 BUG_ON(vma->vm_flags & VM_PFNMAP);
2013
1912 if (vma->vm_file) { 2014 if (vma->vm_file) {
1913 mapping = vma->vm_file->f_mapping; 2015 mapping = vma->vm_file->f_mapping;
1914 sequence = mapping->truncate_count; 2016 sequence = mapping->truncate_count;
@@ -1941,7 +2043,7 @@ retry:
1941 page = alloc_page_vma(GFP_HIGHUSER, vma, address); 2043 page = alloc_page_vma(GFP_HIGHUSER, vma, address);
1942 if (!page) 2044 if (!page)
1943 goto oom; 2045 goto oom;
1944 cow_user_page(page, new_page, address); 2046 copy_user_highpage(page, new_page, address);
1945 page_cache_release(new_page); 2047 page_cache_release(new_page);
1946 new_page = page; 2048 new_page = page;
1947 anon = 1; 2049 anon = 1;
diff --git a/mm/rmap.c b/mm/rmap.c
index 491ac350048f..f853c6def159 100644
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -641,7 +641,7 @@ static void try_to_unmap_cluster(unsigned long cursor,
641 continue; 641 continue;
642 642
643 /* Nuke the page table entry. */ 643 /* Nuke the page table entry. */
644 flush_cache_page(vma, address, pfn); 644 flush_cache_page(vma, address, pte_pfn(*pte));
645 pteval = ptep_clear_flush(vma, address, pte); 645 pteval = ptep_clear_flush(vma, address, pte);
646 646
647 /* If nonlinear, store the file page offset in the pte. */ 647 /* If nonlinear, store the file page offset in the pte. */